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

Linux Kernel Patch v2.4, patch-2.4.15 (000/115)

129 views
Skip to first unread message

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:36 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part000

lines added deleted
linux/CREDITS : 11 3 1
linux/Documentation/Configure.help : 24221 9382 4615
linux/Documentation/DocBook/via-audio.tmpl : 65 29 9
linux/Documentation/devices.txt : 8 1 1
linux/Documentation/fb/clgenfb.txt : 18 7 0
linux/Documentation/filesystems/proc.txt : 11 5 0
linux/Documentation/i386/boot.txt : 40 8 5
linux/Documentation/memory.txt : 8 1 1
linux/Documentation/networking/8139too.txt : 54 24 3
linux/Documentation/networking/bonding.txt : 524 524 0
linux/Documentation/networking/dl2k.txt : 184 43 36
linux/Documentation/networking/ifenslave.c : 562 562 0
linux/Documentation/networking/multicast.txt : 20 4 0
linux/Documentation/parport.txt : 10 4 0
linux/Documentation/s390/Debugging390.txt : 15 5 1
linux/Documentation/s390/chandev.8 : 17 2 2
linux/Documentation/usb/usb-serial.txt : 336 145 95
linux/MAINTAINERS : 89 38 3
linux/Makefile : 17 3 2
linux/arch/alpha/config.in : 36 15 7
linux/arch/alpha/defconfig : 393 171 12
linux/arch/alpha/kernel/alpha_ksyms.c : 14 2 2
linux/arch/alpha/kernel/entry.S : 6 3 0
linux/arch/alpha/kernel/irq_smp.c : 8 1 1
linux/arch/alpha/kernel/proto.h : 7 0 1
linux/arch/alpha/kernel/semaphore.c : 71 8 8
linux/arch/alpha/kernel/setup.c : 91 38 11
linux/arch/alpha/kernel/signal.c : 7 1 0
linux/arch/alpha/kernel/smp.c : 46 5 14
linux/arch/alpha/kernel/sys_miata.c : 19 13 0
linux/arch/alpha/kernel/time.c : 10 2 2
linux/arch/alpha/kernel/traps.c : 31 16 1
linux/arch/alpha/lib/dec_and_lock.c : 21 6 5
linux/arch/alpha/lib/io.c : 146 22 22
linux/arch/alpha/vmlinux.lds.in : 6 1 1
linux/arch/arm/Makefile : 59 15 4
linux/arch/arm/config.in : 62 35 12
linux/arch/arm/kernel/setup.c : 111 38 42
linux/arch/arm/lib/gcclib.h : 8 1 1
linux/arch/arm/mach-epxa10db/dma.c : 8 1 1
linux/arch/arm/mm/Makefile : 7 1 0
linux/arch/arm/mm/proc-arm1020.S : 762 762 0
linux/arch/arm/mm/proc-arm926.S : 667 667 0
linux/arch/arm/tools/mach-types : 15 4 1
linux/arch/cris/defconfig : 11 3 2
linux/arch/cris/drivers/Config.in : 14 8 0
linux/arch/cris/drivers/axisflashmap.c : 20 6 1
linux/arch/cris/drivers/gpio.c : 203 100 4
linux/arch/cris/drivers/serial.c : 1360 643 188
linux/arch/cris/drivers/serial.h : 15 9 0
linux/arch/cris/kernel/Makefile : 15 4 1
linux/arch/cris/kernel/entry.S : 34 8 2
linux/arch/cris/kernel/head.S : 33 6 3
linux/arch/cris/kernel/kgdb.c : 308 117 114
linux/arch/cris/kernel/ksyms.c : 27 14 0
linux/arch/cris/kernel/process.c : 7 1 0
linux/arch/cris/kernel/setup.c : 105 51 25
linux/arch/cris/kernel/time.c : 39 14 1
linux/arch/cris/kernel/traps.c : 10 2 2
linux/arch/i386/boot/bootsect.S : 15 6 0
linux/arch/i386/boot/compressed/misc.c : 43 5 4
linux/arch/i386/boot/setup.S : 192 121 34
linux/arch/i386/config.in : 10 2 0
linux/arch/i386/defconfig : 53 14 0
linux/arch/i386/kernel/Makefile : 8 1 1
linux/arch/i386/kernel/acpitable.c : 550 550 0
linux/arch/i386/kernel/acpitable.h : 260 260 0
linux/arch/i386/kernel/apic.c : 25 1 4
linux/arch/i386/kernel/apm.c : 8 1 1
linux/arch/i386/kernel/bluesmoke.c : 14 3 3
linux/arch/i386/kernel/dmi_scan.c : 205 88 19
linux/arch/i386/kernel/i386_ksyms.c : 22 5 4
linux/arch/i386/kernel/io_apic.c : 7 0 1
linux/arch/i386/kernel/mpparse.c : 257 143 18
linux/arch/i386/kernel/mtrr.c : 11 2 0
linux/arch/i386/kernel/pci-i386.h : 9 0 3
linux/arch/i386/kernel/pci-pc.c : 228 19 71
linux/arch/i386/kernel/ptrace.c : 19 4 8
linux/arch/i386/kernel/semaphore.c : 19 4 2
linux/arch/i386/kernel/setup.c : 371 166 80
linux/arch/i386/kernel/smpboot.c : 11 1 1
linux/arch/i386/kernel/time.c : 15 2 0
linux/arch/i386/lib/usercopy.c : 17 4 0
linux/arch/i386/math-emu/fpu_proto.h : 8 1 1
linux/arch/i386/mm/init.c : 36 16 0
linux/arch/ia64/Makefile : 55 10 9
linux/arch/ia64/config.in : 131 34 44
linux/arch/ia64/defconfig : 915 672 70
linux/arch/ia64/ia32/binfmt_elf32.c : 250 66 104
linux/arch/ia64/ia32/ia32_entry.S : 434 172 111
linux/arch/ia64/ia32/ia32_ioctl.c : 386 191 164
linux/arch/ia64/ia32/ia32_ldt.c : 81 33 6
linux/arch/ia64/ia32/ia32_signal.c : 992 560 307
linux/arch/ia64/ia32/ia32_support.c : 185 84 27
linux/arch/ia64/ia32/ia32_traps.c : 40 26 1
linux/arch/ia64/ia32/sys_ia32.c : 5859 1951 2626
linux/arch/ia64/kernel/Makefile : 8 1 1
linux/arch/ia64/kernel/acpi.c : 376 222 22
linux/arch/ia64/kernel/efi.c : 68 16 11
linux/arch/ia64/kernel/efi_stub.S : 32 6 6
linux/arch/ia64/kernel/efivars.c : 31 3 3
linux/arch/ia64/kernel/entry.S : 453 58 66
linux/arch/ia64/kernel/entry.h : 30 2 9
linux/arch/ia64/kernel/fw-emu.c : 55 37 5
linux/arch/ia64/kernel/gate.S : 155 51 25
linux/arch/ia64/kernel/head.S : 215 31 32
linux/arch/ia64/kernel/ia64_ksyms.c : 13 2 1
linux/arch/ia64/kernel/iosapic.c : 163 127 2
linux/arch/ia64/kernel/irq.c : 463 184 50
linux/arch/ia64/kernel/irq_ia64.c : 26 10 3
linux/arch/ia64/kernel/ivt.S : 219 30 48
linux/arch/ia64/kernel/mca.c : 2109 1271 373
linux/arch/ia64/kernel/mca_asm.S : 287 54 80
linux/arch/ia64/kernel/pal.S : 104 15 14
linux/arch/ia64/kernel/palinfo.c : 57 13 12
linux/arch/ia64/kernel/pci.c : 62 44 0
linux/arch/ia64/kernel/perfmon.c : 1832 729 388
linux/arch/ia64/kernel/process.c : 110 46 5
linux/arch/ia64/kernel/ptrace.c : 63 11 15
linux/arch/ia64/kernel/sal.c : 74 6 23
linux/arch/ia64/kernel/setup.c : 173 81 48
linux/arch/ia64/kernel/sigframe.h : 23 9 2
linux/arch/ia64/kernel/signal.c : 93 15 22
linux/arch/ia64/kernel/smp.c : 193 8 108
linux/arch/ia64/kernel/smpboot.c : 90 16 8
linux/arch/ia64/kernel/sys_ia64.c : 93 27 18
linux/arch/ia64/kernel/time.c : 9 3 0
linux/arch/ia64/kernel/traps.c : 194 86 37
linux/arch/ia64/kernel/unaligned.c : 142 42 18
linux/arch/ia64/kernel/unwind.c : 8 1 1
linux/arch/ia64/lib/clear_page.S : 6 1 1
linux/arch/ia64/lib/clear_user.S : 83 10 10
linux/arch/ia64/lib/copy_page.S : 6 1 1
linux/arch/ia64/lib/copy_user.S : 383 66 70
linux/arch/ia64/lib/do_csum.S : 89 10 11
linux/arch/ia64/lib/idiv32.S : 6 1 1
linux/arch/ia64/lib/idiv64.S : 6 1 1
linux/arch/ia64/lib/memcpy.S : 126 17 23
linux/arch/ia64/lib/memset.S : 43 6 6
linux/arch/ia64/lib/strlen.S : 68 8 8
linux/arch/ia64/lib/strlen_user.S : 70 9 9
linux/arch/ia64/lib/strncpy_from_user.S : 6 1 1
linux/arch/ia64/lib/strnlen_user.S : 15 2 2
linux/arch/ia64/lib/swiotlb.c : 68 21 9
linux/arch/ia64/mm/fault.c : 107 28 14
linux/arch/ia64/mm/init.c : 58 30 2
linux/arch/ia64/mm/tlb.c : 153 25 96
linux/arch/ia64/sn/sn1/llsc4.c : 24 0 11
linux/arch/ia64/tools/print_offsets.c : 33 4 6
linux/arch/mips/kernel/smp.c : 17 2 2
linux/arch/mips64/sgi-ip27/ip27-init.c : 8 1 1
linux/arch/ppc/8xx_io/micropatch.c : 8 1 1
linux/arch/ppc/config.in : 13 2 1
linux/arch/ppc/kernel/apus_setup.c : 59 13 17
linux/arch/ppc/kernel/chrp_setup.c : 99 17 21
linux/arch/ppc/kernel/gemini_setup.c : 75 15 17
linux/arch/ppc/kernel/m8260_setup.c : 54 11 12
linux/arch/ppc/kernel/m8xx_setup.c : 50 9 10
linux/arch/ppc/kernel/oak_setup.c : 58 10 12
linux/arch/ppc/kernel/pci.c : 46 19 4
linux/arch/ppc/kernel/pmac_setup.c : 152 45 26
linux/arch/ppc/kernel/ppc_ksyms.c : 22 3 1
linux/arch/ppc/kernel/prep_setup.c : 233 65 87
linux/arch/ppc/kernel/setup.c : 296 106 129
linux/arch/ppc/kernel/smp.c : 8 1 1
linux/arch/ppc/kernel/walnut_setup.c : 58 10 12
linux/arch/ppc/lib/Makefile : 16 4 2
linux/arch/ppc/lib/dec_and_lock.c : 46 46 0
linux/arch/s390/config.in : 7 1 0
linux/arch/s390/defconfig : 67 13 1
linux/arch/s390/kernel/entry.S : 31 11 6
linux/arch/s390/kernel/head.S : 15 3 3
linux/arch/s390/kernel/init_task.c : 7 1 0
linux/arch/s390/kernel/s390_ksyms.c : 4 0 1
linux/arch/s390/kernel/setup.c : 90 34 34
linux/arch/s390/kernel/smp.c : 8 1 1
linux/arch/s390/kernel/traps.c : 81 36 5
linux/arch/s390/mm/fault.c : 55 18 4
linux/arch/s390x/defconfig : 43 10 1
linux/arch/s390x/kernel/entry.S : 25 11 1
linux/arch/s390x/kernel/head.S : 15 3 3
linux/arch/s390x/kernel/init_task.c : 7 1 0
linux/arch/s390x/kernel/ioctl32.c : 13 7 0
linux/arch/s390x/kernel/setup.c : 90 34 34
linux/arch/s390x/kernel/smp.c : 8 1 1
linux/arch/s390x/kernel/traps.c : 43 23 0
linux/arch/s390x/kernel/wrapper32.S : 12 4 2
linux/arch/s390x/mm/fault.c : 33 12 2
linux/arch/s390x/mm/init.c : 8 1 1
linux/arch/sh/kernel/setup.c : 66 28 11
linux/arch/sparc/defconfig : 40 8 0
linux/arch/sparc/kernel/ebus.c : 25 7 1
linux/arch/sparc/kernel/entry.S : 29 3 12
linux/arch/sparc/kernel/process.c : 33 3 12
linux/arch/sparc/kernel/setup.c : 111 57 26
linux/arch/sparc/kernel/smp.c : 48 16 13
linux/arch/sparc/kernel/sun4d_smp.c : 8 1 1
linux/arch/sparc/kernel/sun4m_smp.c : 8 1 1
linux/arch/sparc/mm/srmmu.c : 43 13 12
linux/arch/sparc/mm/sun4c.c : 87 27 29
linux/arch/sparc64/config.in : 36 15 4
linux/arch/sparc64/defconfig : 103 34 2
linux/arch/sparc64/kernel/ebus.c : 25 7 1
linux/arch/sparc64/kernel/ioctl32.c : 139 82 3
linux/arch/sparc64/kernel/irq.c : 600 305 89
linux/arch/sparc64/kernel/isa.c : 17 2 2
linux/arch/sparc64/kernel/setup.c : 126 60 36
linux/arch/sparc64/kernel/smp.c : 101 35 23
linux/arch/sparc64/mm/init.c : 60 13 14
linux/arch/sparc64/mm/ultra.S : 27 3 3
linux/drivers/Makefile : 13 1 2
linux/drivers/acpi/os.c : 21 1 7
linux/drivers/acpi/ospm/processor/pr_osl.c : 33 10 7
linux/drivers/atm/Config.in : 12 6 0
linux/drivers/atm/Makefile : 18 5 0
linux/drivers/atm/eni.c : 8 1 1
linux/drivers/atm/firestream.c : 18 4 1
linux/drivers/atm/idt77252.c : 3908 3908 0
linux/drivers/atm/idt77252.h : 818 818 0
linux/drivers/atm/idt77252_tables.h : 780 780 0
linux/drivers/atm/suni.c : 26 5 1
linux/drivers/block/acsi.c : 16 2 8
linux/drivers/block/blkpg.c : 57 13 12
linux/drivers/block/cciss.c : 54 6 10
linux/drivers/block/cpqarray.c : 24 4 5
linux/drivers/block/loop.c : 59 16 8
linux/drivers/block/paride/pd.c : 20 2 8
linux/drivers/block/ps2esdi.c : 34 3 13
linux/drivers/block/rd.c : 9 0 3
linux/drivers/block/xd.c : 20 2 5
linux/drivers/cdrom/cdrom.c : 9 2 1
linux/drivers/char/Config.in : 33 9 5
linux/drivers/char/Makefile : 15 2 0
linux/drivers/char/acpi_serial.c : 203 203 0
linux/drivers/char/agp/agp.h : 107 45 22
linux/drivers/char/agp/agpgart_be.c : 558 356 22
linux/drivers/char/drm/ati_pcigart.h : 26 3 3
linux/drivers/char/drm/drm_agpsupport.h : 9 2 0
linux/drivers/char/drm/drm_vm.h : 32 4 4
linux/drivers/char/esp.c : 68 9 6
linux/drivers/char/hp_keyb.c : 519 519 0
linux/drivers/char/hp_psaux.c : 551 551 0
linux/drivers/char/isicom.c : 87 23 20
linux/drivers/char/joystick/cs461x.c : 17 2 2
linux/drivers/char/joystick/emu10k1-gp.c : 17 2 2
linux/drivers/char/joystick/pcigame.c : 17 2 2
linux/drivers/char/pc_keyb.c : 58 22 18
linux/drivers/char/random.c : 28 2 6
linux/drivers/char/rtc.c : 175 58 15
linux/drivers/char/serial.c : 94 30 10
linux/drivers/char/serial_tx3912.c : 8 1 1
linux/drivers/char/specialix.c : 11 4 1
linux/drivers/char/sx.c : 11 5 0
linux/drivers/char/vt.c : 7 0 1
linux/drivers/hotplug/Config.in : 12 12 0
linux/drivers/hotplug/Makefile : 34 34 0
linux/drivers/hotplug/cpqphp.h : 751 751 0
linux/drivers/hotplug/cpqphp_core.c : 1439 1439 0
linux/drivers/hotplug/cpqphp_ctrl.c : 3047 3047 0
linux/drivers/hotplug/cpqphp_nvram.c : 652 652 0
linux/drivers/hotplug/cpqphp_nvram.h : 57 57 0
linux/drivers/hotplug/cpqphp_pci.c : 1726 1726 0
linux/drivers/hotplug/cpqphp_proc.c : 192 192 0
linux/drivers/hotplug/pci_hotplug.h : 160 160 0
linux/drivers/hotplug/pci_hotplug_core.c : 1135 1135 0
linux/drivers/hotplug/pci_hotplug_util.c : 403 403 0
linux/drivers/i2c/i2c-core.c : 8 1 1
linux/drivers/ide/ide-disk.c : 8 1 1
linux/drivers/ide/ide-geometry.c : 10 2 2
linux/drivers/ide/pdc202xx.c : 7 1 0
linux/drivers/ide/pdcraid.c : 78 12 22
linux/drivers/ieee1394/ieee1394_syms.c : 5 1 0
linux/drivers/ieee1394/pcilynx.c : 9 1 1
linux/drivers/isdn/eicon/eicon_idi.c : 36 6 6
linux/drivers/isdn/eicon/eicon_isa.c : 67 10 10
linux/drivers/isdn/hysdn/boardergo.c : 5 1 1
linux/drivers/isdn/hysdn/hysdn_sched.c : 5 1 1
linux/drivers/isdn/isdn_common.c : 70 8 10
linux/drivers/isdn/isdn_net.c : 94 12 12
linux/drivers/isdn/isdn_ppp.c : 110 27 10
linux/drivers/isdn/isdn_tty.c : 37 5 5
linux/drivers/isdn/isdnloop/isdnloop.c : 27 7 3
linux/drivers/isdn/tpam/tpam.h : 16 3 3
linux/drivers/isdn/tpam/tpam_commands.c : 49 6 6
linux/drivers/isdn/tpam/tpam_hdlc.c : 60 11 11
linux/drivers/md/Makefile : 8 1 1
linux/drivers/md/lvm-fs.c : 623 623 0
linux/drivers/md/lvm-internal.h : 101 101 0
linux/drivers/md/lvm-snap.c : 600 259 160
linux/drivers/md/lvm-snap.h : 47 0 47
linux/drivers/md/lvm.c : 2985 883 1188
linux/drivers/md/multipath.c : 632 80 268
linux/drivers/media/radio/Config.in : 8 1 1
linux/drivers/media/video/Config.in : 9 3 0
linux/drivers/media/video/Makefile : 11 4 1
linux/drivers/media/video/saa7110.c : 7 1 0
linux/drivers/media/video/zr36067.c : 13 7 0
linux/drivers/media/video/zr36120.c : 13 7 0
linux/drivers/mtd/chips/jedec.c : 58 8 7
linux/drivers/mtd/redboot.c : 23 10 2
linux/drivers/net/3c59x.c : 17 2 2
linux/drivers/net/8139cp.c : 59 14 7
linux/drivers/net/8139too.c : 739 59 212
linux/drivers/net/Config.in : 33 7 3
linux/drivers/net/acenic.c : 324 70 51
linux/drivers/net/acenic.h : 21 3 0
linux/drivers/net/appletalk/Config.in : 18 4 4
linux/drivers/net/arcnet/com20020-pci.c : 17 2 2
linux/drivers/net/arlan.c : 10 4 0
linux/drivers/net/bmac.c : 8 1 1
linux/drivers/net/bonding.c : 2177 1885 143
linux/drivers/net/bsd_comp.c : 5 1 1
linux/drivers/net/dl2k.c : 486 213 59
linux/drivers/net/dl2k.h : 115 78 7
linux/drivers/net/dmfe.c : 819 222 168
linux/drivers/net/eepro.c : 1600 382 442
linux/drivers/net/eepro100.c : 88 41 0
linux/drivers/net/fealnx.c : 87 38 8
linux/drivers/net/irda/irda-usb.c : 275 53 49
linux/drivers/net/irda/vlsi_ir.c : 33 4 4
linux/drivers/net/natsemi.c : 310 199 11
linux/drivers/net/ns83820.c : 8 1 1
linux/drivers/net/pcmcia/3c574_cs.c : 219 51 46
linux/drivers/net/pcmcia/3c589_cs.c : 76 19 20
linux/drivers/net/pcmcia/Config.in : 7 1 0
linux/drivers/net/pcmcia/Makefile : 7 1 0
linux/drivers/net/pcmcia/ax8390.h : 193 193 0
linux/drivers/net/pcmcia/axnet_cs.c : 1958 1958 0
linux/drivers/net/pcmcia/fmvj18x_cs.c : 154 33 44
linux/drivers/net/pcmcia/nmclan_cs.c : 59 17 17
linux/drivers/net/pcmcia/pcnet_cs.c : 290 105 33
linux/drivers/net/pcmcia/smc91c92_cs.c : 330 161 26
linux/drivers/net/pcmcia/wavelan_cs.c : 5 1 1
linux/drivers/net/pcmcia/xirc2ps_cs.c : 58 16 4
linux/drivers/net/pcmcia/xircom_cb.c : 8 1 1
linux/drivers/net/pcmcia/xircom_tulip_cb.c : 26 3 3
linux/drivers/net/pcnet32.c : 13 0 7
linux/drivers/net/pppoe.c : 60 12 6
linux/drivers/net/pppox.c : 7 4 0
linux/drivers/net/rrunner.c : 165 78 19
linux/drivers/net/rrunner.h : 7 1 0
linux/drivers/net/sk98lin/skvpd.c : 15 2 0
linux/drivers/net/slhc.c : 5 1 1
linux/drivers/net/strip.c : 8 1 1
linux/drivers/net/tokenring/ibmtr.c : 7 1 0
linux/drivers/net/tokenring/lanstreamer.c : 35 4 4
linux/drivers/net/tokenring/olympic.c : 24 3 3
linux/drivers/net/tulip/21142.c : 34 0 21
linux/drivers/net/tulip/ChangeLog : 28 25 0
linux/drivers/net/tulip/Makefile : 8 1 1
linux/drivers/net/tulip/interrupt.c : 83 16 16
linux/drivers/net/tulip/pnic.c : 17 2 2
linux/drivers/net/tulip/pnic2.c : 407 407 0
linux/drivers/net/tulip/tulip.h : 21 7 1
linux/drivers/net/tulip/tulip_core.c : 303 82 39
linux/drivers/net/via-rhine.c : 229 86 26
linux/drivers/net/wan/dscc4.c : 7 0 1
linux/drivers/net/wan/farsync.c : 17 2 2
linux/drivers/net/wan/z85230.c : 620 160 77
linux/drivers/net/wan/z85230.h : 16 3 0
linux/drivers/net/wireless/airo.c : 24 7 5
linux/drivers/parport/ChangeLog : 12 9 0
linux/drivers/parport/Config.in : 12 6 0
linux/drivers/parport/parport_pc.c : 25 12 0
linux/drivers/parport/parport_serial.c : 7 1 0
linux/drivers/pci/names.c : 8 1 1
linux/drivers/pci/pci.c : 193 45 24
linux/drivers/pci/pci.ids : 37 9 1
linux/drivers/pci/proc.c : 339 141 105
linux/drivers/pci/quirks.c : 58 45 0
linux/drivers/pcmcia/Config.in : 8 1 1
linux/drivers/pcmcia/Makefile : 26 3 3
linux/drivers/pcmcia/cardbus.c : 7 0 1
linux/drivers/pcmcia/cb_enabler.c : 403 0 403
linux/drivers/pcmcia/cistpl.c : 44 4 6
linux/drivers/pcmcia/cs.c : 81 21 14
linux/drivers/pcmcia/ds.c : 52 15 11
linux/drivers/pcmcia/i82092.c : 25 2 3
linux/drivers/pcmcia/i82365.c : 11 0 5
linux/drivers/pcmcia/old-yenta.h : 153 0 153
linux/drivers/pcmcia/pci_socket.c : 44 6 6
linux/drivers/pcmcia/rsrc_mgr.c : 7 0 1
linux/drivers/pcmcia/rsrc_mgr.h : 33 0 33
linux/drivers/pcmcia/smc34c90.h : 52 0 52
linux/drivers/pcmcia/yenta.c : 27 7 0
linux/drivers/pnp/isapnp.c : 108 88 0
linux/drivers/s390/block/dasd.c : 252 57 28
linux/drivers/s390/block/dasd_3990_erp.c : 93 11 11
linux/drivers/s390/block/dasd_eckd.c : 17 2 2
linux/drivers/s390/char/tape34xx.c : 23 7 2
linux/drivers/s390/char/tapechar.c : 36 6 4
linux/drivers/s390/misc/chandev.c : 17 2 2
linux/drivers/s390/s390io.c : 8 1 1
linux/drivers/s390/s390mach.c : 8 1 1
linux/drivers/sbus/char/su.c : 33 6 4
linux/drivers/scsi/3w-xxxx.c : 686 139 104
linux/drivers/scsi/3w-xxxx.h : 147 82 10
linux/drivers/scsi/Config.in : 17 10 1
linux/drivers/scsi/Makefile : 19 6 0
linux/drivers/scsi/README.st : 43 22 1
linux/drivers/scsi/advansys.c : 5 1 1
linux/drivers/scsi/aha152x.c : 11 4 0
linux/drivers/scsi/aic7xxx/aic7xxx_linux.c : 16 2 1
linux/drivers/scsi/aic7xxx/aic7xxx_linux_pci.c : 45 6 2
linux/drivers/scsi/aic7xxx_old.c : 16 2 1
linux/drivers/scsi/dpt_i2o.c : 13 7 0
linux/drivers/scsi/eata.c : 5 1 1
linux/drivers/scsi/gdth.c : 17 11 0
linux/drivers/scsi/i60uscsi.c : 238 14 98
linux/drivers/scsi/i60uscsi.h : 14 0 4
linux/drivers/scsi/ips.c : 10 2 0
linux/drivers/scsi/osst.c : 8 1 1
linux/drivers/scsi/pci2000.c : 8 1 1
linux/drivers/scsi/pci2220i.c : 8 1 1
linux/drivers/scsi/scsi.c : 142 57 22
linux/drivers/scsi/scsi.h : 17 2 2
linux/drivers/scsi/sd.c : 24 4 5
linux/drivers/scsi/st.c : 595 247 158
linux/drivers/scsi/st.h : 39 7 3
linux/drivers/scsi/sym53c8xx_2/ChangeLog.txt : 130 130 0
linux/drivers/scsi/sym53c8xx_2/Documentation.txt : 1149 1149 0
linux/drivers/scsi/sym53c8xx_2/Makefile : 16 16 0
linux/drivers/scsi/sym53c8xx_2/sym53c8xx.h : 370 370 0
linux/drivers/scsi/sym53c8xx_2/sym_conf.h : 329 329 0
linux/drivers/scsi/sym53c8xx_2/sym_defs.h : 957 957 0
linux/drivers/scsi/sym53c8xx_2/sym_fw.c : 617 617 0
linux/drivers/scsi/sym53c8xx_2/sym_fw.h : 232 232 0
linux/drivers/scsi/sym53c8xx_2/sym_fw1.h : 1874 1874 0
linux/drivers/scsi/sym53c8xx_2/sym_fw2.h : 1994 1994 0
linux/drivers/scsi/sym53c8xx_2/sym_glue.c : 3012 3012 0
linux/drivers/scsi/sym53c8xx_2/sym_glue.h : 676 676 0
linux/drivers/scsi/sym53c8xx_2/sym_hipd.c : 6007 6007 0
linux/drivers/scsi/sym53c8xx_2/sym_hipd.h : 1445 1445 0
linux/drivers/scsi/sym53c8xx_2/sym_malloc.c : 418 418 0
linux/drivers/scsi/sym53c8xx_2/sym_misc.c : 336 336 0
linux/drivers/scsi/sym53c8xx_2/sym_misc.h : 311 311 0
linux/drivers/scsi/sym53c8xx_2/sym_nvram.c : 730 730 0
linux/drivers/sound/ac97_codec.c : 48 28 2
linux/drivers/sound/aci.c : 188 48 46
linux/drivers/sound/ad1816.c : 257 58 54
linux/drivers/sound/cmpci.c : 28 12 1
linux/drivers/sound/i810_audio.c : 71 10 6
linux/drivers/sound/maestro3.c : 26 3 3
linux/drivers/sound/trident.c : 30 9 2
linux/drivers/sound/trident.h : 8 1 1
linux/drivers/sound/via82cxxx_audio.c : 891 286 181
linux/drivers/sound/vwsnd.c : 7 1 0
linux/drivers/sound/ymfpci.c : 76 22 2
linux/drivers/usb/bluetooth.c : 12 3 3
linux/drivers/usb/catc.c : 8 1 1
linux/drivers/usb/hid-input.c : 31 6 5
linux/drivers/usb/hid.h : 18 3 2
linux/drivers/usb/hub.c : 106 20 32
linux/drivers/usb/hub.h : 9 2 2
linux/drivers/usb/kaweth.c : 21 4 4
linux/drivers/usb/serial/ftdi_sio.c : 357 92 92
linux/drivers/usb/serial/io_edgeport.c : 475 88 111
linux/drivers/usb/serial/io_tables.h : 415 48 321
linux/drivers/usb/serial/io_usbvend.h : 7 1 0
linux/drivers/usb/serial/ir-usb.c : 84 25 22
linux/drivers/usb/serial/mct_u232.c : 18 4 1
linux/drivers/usb/serial/visor.c : 139 22 42
linux/drivers/usb/serial/visor.h : 7 1 0
linux/drivers/usb/storage/freecom.c : 292 75 70
linux/drivers/usb/storage/isd200.c : 10 2 0
linux/drivers/usb/storage/scsiglue.c : 17 2 2
linux/drivers/usb/storage/sddr09.c : 7 1 1
linux/drivers/usb/storage/transport.c : 7 1 1
linux/drivers/usb/storage/usb.c : 112 47 32
linux/drivers/usb/uhci.c : 35 5 5
linux/drivers/usb/usb-ohci.c : 44 5 5
linux/drivers/usb/usb-skeleton.c : 23 4 1
linux/drivers/usb/usb-uhci.c : 34 4 4
linux/drivers/usb/usb.c : 17 2 2
linux/drivers/usb/usbnet.c : 952 549 175
linux/drivers/video/Config.in : 14 4 4
linux/drivers/video/acornfb.c : 8 1 1
linux/drivers/video/amifb.c : 10 3 1
linux/drivers/video/aty128fb.c : 57 12 4
linux/drivers/video/clgenfb.c : 103 27 10
linux/drivers/video/controlfb.c : 8 1 1
linux/drivers/video/cyberfb.c : 10 3 1
linux/drivers/video/fbmem.c : 11 3 1
linux/drivers/video/fm2fb.c : 8 1 1
linux/drivers/video/hgafb.c : 52 11 11
linux/drivers/video/igafb.c : 8 1 1
linux/drivers/video/imsttfb.c : 26 3 3
linux/drivers/video/macfb.c : 8 1 1
linux/drivers/video/matrox/i2c-matroxfb.c : 35 15 3
linux/drivers/video/matrox/matroxfb_DAC1064.c : 9 2 1
linux/drivers/video/matrox/matroxfb_DAC1064.h : 14 3 1
linux/drivers/video/matrox/matroxfb_base.c : 164 34 16
linux/drivers/video/matrox/matroxfb_base.h : 29 1 15
linux/drivers/video/matrox/matroxfb_crtc2.c : 85 36 11
linux/drivers/video/matrox/matroxfb_g450.c : 134 64 28
linux/drivers/video/matrox/matroxfb_g450.h : 7 1 0
linux/drivers/video/matrox/matroxfb_maven.c : 26 14 1
linux/drivers/video/matrox/matroxfb_misc.c : 7 4 0
linux/drivers/video/platinumfb.c : 8 1 1
linux/drivers/video/radeonfb.c : 28 5 3
linux/drivers/video/retz3fb.c : 10 3 1
linux/drivers/video/riva/fbdev.c : 10 3 1
linux/drivers/video/sa1100fb.c : 8 1 1
linux/drivers/video/sgivwfb.c : 25 4 1
linux/drivers/video/sis/300vtbl.h : 1522 1522 0
linux/drivers/video/sis/310vtbl.h : 2604 2604 0
linux/drivers/video/sis/325vtbl.h : 2318 2318 0
linux/drivers/video/sis/Makefile : 8 1 1
linux/drivers/video/sis/init.c : 3784 3784 0
linux/drivers/video/sis/init.h : 227 227 0
linux/drivers/video/sis/init301.c : 6001 6001 0
linux/drivers/video/sis/init301.h : 223 223 0
linux/drivers/video/sis/initdef.h : 409 271 97
linux/drivers/video/sis/oem300.h : 397 397 0
linux/drivers/video/sis/oem310.h : 204 204 0
linux/drivers/video/sis/osdef.h : 37 37 0
linux/drivers/video/sis/sis.h : 64 0 64
linux/drivers/video/sis/sis_300.c : 1524 0 1524
linux/drivers/video/sis/sis_300.h : 163 0 163
linux/drivers/video/sis/sis_301.c : 2868 0 2868
linux/drivers/video/sis/sis_301.h : 224 0 224
linux/drivers/video/sis/sis_main.c : 4453 2131 1669
linux/drivers/video/sis/sis_main.h : 693 693 0
linux/drivers/video/sis/vgatypes.h : 275 275 0
linux/drivers/video/sis/vstruct.h : 324 324 0
linux/drivers/video/sstfb.c : 8 1 1
linux/drivers/video/tdfxfb.c : 10 3 1
linux/drivers/video/tgafb.c : 8 1 1
linux/drivers/video/valkyriefb.c : 8 1 1
linux/drivers/video/vesafb.c : 42 12 4
linux/drivers/video/vfb.c : 8 1 1
linux/drivers/video/vga16fb.c : 8 1 1
linux/drivers/video/virgefb.c : 18 4 1
linux/fs/Config.in : 42 12 3
linux/fs/Makefile : 31 5 2
linux/fs/affs/super.c : 7 0 1
linux/fs/autofs4/inode.c : 11 3 1
linux/fs/block_dev.c : 19 6 0
linux/fs/buffer.c : 244 113 11
linux/fs/dquot.c : 126 17 27
linux/fs/ext2/ialloc.c : 646 228 269
linux/fs/ext2/inode.c : 19 6 1
linux/fs/ext2/super.c : 11 2 2
linux/fs/ext3/Makefile : 16 16 0
linux/fs/ext3/acl.c : 17 17 0
linux/fs/ext3/balloc.c : 995 995 0
linux/fs/ext3/bitmap.c : 26 26 0
linux/fs/ext3/dir.c : 190 190 0
linux/fs/ext3/file.c : 94 94 0
linux/fs/ext3/fsync.c : 70 70 0
linux/fs/ext3/ialloc.c : 664 664 0
linux/fs/ext3/inode.c : 2672 2672 0
linux/fs/ext3/ioctl.c : 170 170 0
linux/fs/ext3/namei.c : 1125 1125 0
linux/fs/ext3/super.c : 1745 1745 0
linux/fs/ext3/symlink.c : 39 39 0
linux/fs/fat/inode.c : 8 2 0
linux/fs/freevxfs/vxfs_subr.c : 9 2 1
linux/fs/inode.c : 108 15 15
linux/fs/intermezzo/Makefile : 12 12 0
linux/fs/intermezzo/cache.c : 256 256 0
linux/fs/intermezzo/dcache.c : 139 139 0
linux/fs/intermezzo/dir.c : 893 893 0
linux/fs/intermezzo/ext_attr.c : 196 196 0
linux/fs/intermezzo/file.c : 426 426 0
linux/fs/intermezzo/inode.c : 166 166 0
linux/fs/intermezzo/journal.c : 2059 2059 0
linux/fs/intermezzo/journal_ext2.c : 70 70 0
linux/fs/intermezzo/journal_ext3.c : 205 205 0
linux/fs/intermezzo/journal_obdfs.c : 180 180 0
linux/fs/intermezzo/journal_reiserfs.c : 119 119 0
linux/fs/intermezzo/journal_xfs.c : 137 137 0
linux/fs/intermezzo/kml.c : 199 199 0
linux/fs/intermezzo/kml_decode.c : 1017 1017 0
linux/fs/intermezzo/kml_reint.c : 411 411 0
linux/fs/intermezzo/kml_setup.c : 59 59 0
linux/fs/intermezzo/kml_utils.c : 44 44 0
linux/fs/intermezzo/methods.c : 461 461 0
linux/fs/intermezzo/presto.c : 1150 1150 0
linux/fs/intermezzo/psdev.c : 1665 1665 0
linux/fs/intermezzo/super.c : 528 528 0
linux/fs/intermezzo/sysctl.c : 361 361 0
linux/fs/intermezzo/upcall.c : 248 248 0
linux/fs/intermezzo/vfs.c : 2304 2304 0
linux/fs/isofs/compress.c : 9 0 3
linux/fs/jbd/Makefile : 15 15 0
linux/fs/jbd/checkpoint.c : 608 608 0
linux/fs/jbd/commit.c : 701 701 0
linux/fs/jbd/journal.c : 1813 1813 0
linux/fs/jbd/recovery.c : 586 586 0
linux/fs/jbd/revoke.c : 631 631 0
linux/fs/jbd/transaction.c : 2070 2070 0
linux/fs/jffs2/nodelist.c : 44 2 22
linux/fs/minix/file.c : 11 3 1
linux/fs/namespace.c : 283 117 144
linux/fs/nfs/Makefile : 10 2 2
linux/fs/nfs/flushd.c : 187 30 119
linux/fs/nfs/inode.c : 46 12 0
linux/fs/nfs/pagelist.c : 498 498 0
linux/fs/nfs/read.c : 262 71 107
linux/fs/nfs/write.c : 831 153 426
linux/fs/openpromfs/inode.c : 4 1 0
linux/fs/partitions/ldm.c : 186 98 14
linux/fs/partitions/ldm.h : 47 12 6
linux/fs/proc/inode.c : 19 5 7
linux/fs/proc/proc_misc.c : 183 44 63
linux/fs/reiserfs/Makefile : 21 4 4
linux/fs/reiserfs/bitmap.c : 46 11 1
linux/fs/reiserfs/buffer2.c : 26 10 2
linux/fs/reiserfs/do_balan.c : 9 3 0
linux/fs/reiserfs/fix_node.c : 84 17 2
linux/fs/reiserfs/ibalance.c : 8 2 0
linux/fs/reiserfs/journal.c : 104 14 0
linux/fs/reiserfs/namei.c : 9 3 0
linux/fs/reiserfs/objectid.c : 12 3 1
linux/fs/reiserfs/prints.c : 16 1 8
linux/fs/reiserfs/procfs.c : 711 711 0
linux/fs/reiserfs/stree.c : 53 13 3
linux/fs/reiserfs/super.c : 93 26 6
linux/fs/seq_file.c : 295 295 0
linux/fs/super.c : 7 1 0
linux/fs/sysv/ChangeLog : 13 13 0
linux/fs/sysv/dir.c : 57 24 14
linux/fs/sysv/file.c : 17 3 2
linux/fs/sysv/ialloc.c : 7 1 0
linux/fs/sysv/inode.c : 76 4 28
linux/fs/sysv/namei.c : 5 0 1
linux/fs/sysv/super.c : 7 0 1
linux/fs/udf/fsync.c : 7 1 0
linux/fs/ufs/balloc.c : 383 65 75
linux/fs/ufs/cylinder.c : 72 18 22
linux/fs/ufs/dir.c : 432 85 97
linux/fs/ufs/ialloc.c : 122 19 22
linux/fs/ufs/inode.c : 311 47 75
linux/fs/ufs/super.c : 464 132 155
linux/fs/ufs/swab.h : 222 91 95
linux/fs/ufs/truncate.c : 255 30 38
linux/fs/ufs/util.h : 387 175 154
linux/include/asm-alpha/core_apecs.h : 110 15 15
linux/include/asm-alpha/core_cia.h : 202 28 28
linux/include/asm-alpha/core_irongate.h : 92 15 15
linux/include/asm-alpha/core_lca.h : 110 15 15
linux/include/asm-alpha/core_mcpcia.h : 117 15 15
linux/include/asm-alpha/core_polaris.h : 95 15 15
linux/include/asm-alpha/core_t2.h : 118 14 14
linux/include/asm-alpha/core_titan.h : 99 15 15
linux/include/asm-alpha/core_tsunami.h : 98 14 14
linux/include/asm-alpha/core_wildfire.h : 99 15 15
linux/include/asm-alpha/io.h : 82 27 27
linux/include/asm-alpha/jensen.h : 136 16 16
linux/include/asm-alpha/machvec.h : 37 14 14
linux/include/asm-alpha/semaphore.h : 40 4 7
linux/include/asm-alpha/spinlock.h : 67 7 8
linux/include/asm-alpha/unistd.h : 9 3 0
linux/include/asm-arm/arch-epxa10db/hardware.h : 7 0 1
linux/include/asm-arm/arch-integrator/hardware.h : 8 1 1
linux/include/asm-arm/arch-integrator/sizes.h : 52 0 52
linux/include/asm-arm/arch-sa1100/hardware.h : 23 3 3
linux/include/asm-arm/pci.h : 9 3 0
linux/include/asm-arm/proc-fns.h : 14 8 0
linux/include/asm-arm/sizes.h : 52 52 0
linux/include/asm-cris/etraxgpio.h : 15 11 0
linux/include/asm-cris/pgtable.h : 9 5 0
linux/include/asm-cris/system.h : 8 1 1
linux/include/asm-cris/timex.h : 19 13 0
linux/include/asm-cris/uaccess.h : 18 4 1
linux/include/asm-cris/unistd.h : 9 3 0
linux/include/asm-i386/hardirq.h : 8 1 1
linux/include/asm-i386/keyboard.h : 17 3 1
linux/include/asm-i386/mpspec.h : 62 33 0
linux/include/asm-i386/pci.h : 83 23 19
linux/include/asm-i386/pgtable.h : 20 12 0
linux/include/asm-i386/processor.h : 8 1 1
linux/include/asm-i386/system.h : 18 5 0
linux/include/asm-ia64/acpi-ext.h : 25 8 1
linux/include/asm-ia64/ia32.h : 183 87 24
linux/include/asm-ia64/io.h : 39 9 3
linux/include/asm-ia64/iosapic.h : 17 9 0
linux/include/asm-ia64/ipc.h : 31 0 31
linux/include/asm-ia64/keyboard.h : 28 5 4
linux/include/asm-ia64/kregs.h : 15 2 1
linux/include/asm-ia64/machvec.h : 56 10 2
linux/include/asm-ia64/machvec_sn1.h : 15 2 0
linux/include/asm-ia64/mca.h : 53 10 8
linux/include/asm-ia64/mca_asm.h : 96 14 15
linux/include/asm-ia64/mmu_context.h : 7 0 1
linux/include/asm-ia64/module.h : 91 19 21
linux/include/asm-ia64/msgbuf.h : 8 1 1
linux/include/asm-ia64/namei.h : 32 17 8
linux/include/asm-ia64/offsets.h : 46 10 10
linux/include/asm-ia64/page.h : 15 3 0
linux/include/asm-ia64/pal.h : 1089 234 231
linux/include/asm-ia64/pci.h : 39 20 3
linux/include/asm-ia64/perfmon.h : 35 8 3
linux/include/asm-ia64/pgalloc.h : 20 1 6
linux/include/asm-ia64/pgtable.h : 40 21 6
linux/include/asm-ia64/processor.h : 185 78 19
linux/include/asm-ia64/sal.h : 652 391 173
linux/include/asm-ia64/scatterlist.h : 23 10 4
linux/include/asm-ia64/semaphore.h : 8 0 2
linux/include/asm-ia64/sembuf.h : 8 1 1
linux/include/asm-ia64/shmbuf.h : 8 1 1
linux/include/asm-ia64/sigcontext.h : 48 19 4
linux/include/asm-ia64/signal.h : 38 15 5
linux/include/asm-ia64/smp.h : 30 8 2
linux/include/asm-ia64/smplock.h : 34 4 4
linux/include/asm-ia64/spinlock.h : 88 13 11
linux/include/asm-ia64/system.h : 84 10 19
linux/include/asm-ia64/unistd.h : 27 4 3
linux/include/asm-ia64/user.h : 14 3 2
linux/include/asm-parisc/pgtable.h : 9 5 0
linux/include/asm-ppc/machdep.h : 23 4 4
linux/include/asm-ppc/pgtable.h : 11 5 0
linux/include/asm-s390/atomic.h : 8 1 1
linux/include/asm-s390/fcntl.h : 8 1 1
linux/include/asm-s390/gdb-stub.h : 8 1 1
linux/include/asm-s390/irq.h : 8 1 1
linux/include/asm-s390/sigcontext.h : 16 2 2
linux/include/asm-s390/vtoc.h : 8 1 1
linux/include/asm-s390x/atomic.h : 8 1 1
linux/include/asm-s390x/fcntl.h : 8 1 1
linux/include/asm-s390x/irq.h : 8 1 1
linux/include/asm-s390x/s390-regs-common.h : 115 0 115
linux/include/asm-s390x/sigcontext.h : 16 2 2
linux/include/asm-s390x/spinlock.h : 8 1 1
linux/include/asm-s390x/vtoc.h : 144 1 130
linux/include/asm-sh/pgtable.h : 9 5 0
linux/include/asm-sh/string.h : 7 0 3
linux/include/asm-sparc/io.h : 170 62 42
linux/include/asm-sparc/pci.h : 17 4 0
linux/include/asm-sparc/pgtable.h : 26 8 2
linux/include/asm-sparc/smp.h : 11 3 2
linux/include/asm-sparc64/io.h : 313 82 43
linux/include/asm-sparc64/pci.h : 8 2 0
linux/include/asm-sparc64/pgtable.h : 16 6 1
linux/include/linux/ac97_codec.h : 8 2 1
linux/include/linux/acpi_serial.h : 103 103 0
linux/include/linux/agp_backend.h : 12 3 0
linux/include/linux/atm.h : 7 1 0
linux/include/linux/atmapi.h : 16 2 2
linux/include/linux/atmdev.h : 17 11 0
linux/include/linux/atmioc.h : 10 3 1
linux/include/linux/atmppp.h : 24 24 0
linux/include/linux/blk.h : 14 3 1
linux/include/linux/blkdev.h : 20 9 5
linux/include/linux/capability.h : 8 2 0
linux/include/linux/console.h : 7 1 0
linux/include/linux/ethtool.h : 90 35 7
linux/include/linux/ext3_fs.h : 715 715 0
linux/include/linux/ext3_fs_i.h : 78 78 0
linux/include/linux/ext3_fs_sb.h : 77 77 0
linux/include/linux/ext3_jbd.h : 290 290 0
linux/include/linux/fs.h : 106 18 2
linux/include/linux/fsfilter.h : 129 129 0
linux/include/linux/i2o.h : 16 1 2
linux/include/linux/if_bonding.h : 98 82 4
linux/include/linux/intermezzo_fs.h : 729 729 0
linux/include/linux/intermezzo_journal.h : 26 26 0
linux/include/linux/intermezzo_kml.h : 261 261 0
linux/include/linux/intermezzo_psdev.h : 72 72 0
linux/include/linux/intermezzo_upcall.h : 146 146 0
linux/include/linux/irda.h : 7 1 0
linux/include/linux/isapnp.h : 35 15 0
linux/include/linux/jbd.h : 881 881 0
linux/include/linux/journal-head.h : 70 70 0
linux/include/linux/kernel.h : 22 5 3
linux/include/linux/lvm.h : 541 101 225
linux/include/linux/malloc.h : 7 2 0
linux/include/linux/mm.h : 46 8 10
linux/include/linux/module.h : 36 12 4
linux/include/linux/mtd/jedec.h : 16 1 3
linux/include/linux/mtio.h : 25 4 1
linux/include/linux/nfs_flushd.h : 22 2 6
linux/include/linux/nfs_fs.h : 27 9 3
linux/include/linux/nfs_fs_sb.h : 19 6 0
linux/include/linux/nfs_page.h : 135 66 22
linux/include/linux/parport.h : 10 2 2
linux/include/linux/pci.h : 64 13 8
linux/include/linux/pci_ids.h : 89 26 4
linux/include/linux/quota.h : 7 1 0
linux/include/linux/raid/md_k.h : 7 1 0
linux/include/linux/raid/multipath.h : 50 3 19
linux/include/linux/reiserfs_fs.h : 86 64 2
linux/include/linux/reiserfs_fs_sb.h : 83 70 0
linux/include/linux/sched.h : 66 29 3
linux/include/linux/seq_file.h : 55 55 0
linux/include/linux/serial.h : 11 6 0
linux/include/linux/sisfb.h : 199 84 83
linux/include/linux/sockios.h : 15 9 0
linux/include/linux/soundcard.h : 8 1 1
linux/include/linux/swap.h : 45 2 20
linux/include/linux/sysctl.h : 9 2 1
linux/include/linux/sysv_fs.h : 61 0 48
linux/include/linux/sysv_fs_i.h : 7 1 0
linux/include/linux/sysv_fs_sb.h : 15 0 2
linux/include/linux/ufs_fs.h : 27 2 12
linux/include/linux/ufs_fs_i.h : 7 0 1
linux/include/linux/ufs_fs_sb.h : 8 1 1
linux/include/linux/videodev.h : 8 1 1
linux/include/linux/wait.h : 14 2 2
linux/include/linux/watchdog.h : 7 1 0
linux/include/net/dn.h : 6 1 0
linux/include/net/irda/irda-usb.h : 11 5 0
linux/include/net/irda/irda.h : 19 6 0
linux/include/net/irda/irlap_event.h : 15 2 0
linux/include/net/irda/irlmp.h : 15 1 1
linux/include/net/irda/irlmp_event.h : 18 1 4
linux/include/net/irda/irmod.h : 125 10 98
linux/include/net/irda/parameters.h : 21 3 4
linux/include/net/irda/timer.h : 26 4 1
linux/init/main.c : 8 1 1
linux/init/version.c : 6 1 1
linux/kernel/exec_domain.c : 21 5 3
linux/kernel/exit.c : 15 3 2
linux/kernel/fork.c : 8 1 1
linux/kernel/ksyms.c : 7 1 0
linux/kernel/module.c : 130 72 39
linux/kernel/printk.c : 18 12 0
linux/kernel/ptrace.c : 42 36 0
linux/kernel/sched.c : 218 38 66
linux/kernel/signal.c : 8 1 1
linux/lib/brlock.c : 7 1 0
linux/mm/filemap.c : 235 153 9
linux/mm/memory.c : 17 2 2
linux/mm/page_alloc.c : 126 23 19
linux/mm/page_io.c : 22 0 9
linux/mm/shmem.c : 51 4 19
linux/mm/swap.c : 36 8 8
linux/mm/vmscan.c : 58 13 4
linux/net/802/cl2llc.pre : 8 1 1
linux/net/8021q/vlanproc.c : 8 1 1
linux/net/atm/Makefile : 7 1 0
linux/net/atm/common.c : 25 12 0
linux/net/atm/pppoatm.c : 365 365 0
linux/net/atm/resources.c : 19 6 1
linux/net/bluetooth/hci_core.c : 8 1 1
linux/net/bridge/br_stp_bpdu.c : 24 3 1
linux/net/core/dev.c : 40 15 3
linux/net/decnet/af_decnet.c : 37 8 2
linux/net/decnet/dn_nsp_in.c : 9 3 0
linux/net/decnet/dn_route.c : 9 1 1
linux/net/decnet/sysctl_net_decnet.c : 27 7 0
linux/net/ipv4/icmp.c : 17 2 2
linux/net/ipv4/ip_input.c : 26 4 2
linux/net/ipv4/ipconfig.c : 98 21 8
linux/net/ipv4/tcp_input.c : 8 1 1
linux/net/irda/af_irda.c : 90 33 24
linux/net/irda/ircomm/ircomm_param.c : 120 23 23
linux/net/irda/irda_device.c : 48 13 1
linux/net/irda/iriap.c : 16 2 1
linux/net/irda/irlap.c : 66 30 5
linux/net/irda/irlap_event.c : 165 65 28
linux/net/irda/irlap_frame.c : 16 2 1
linux/net/irda/irlmp.c : 203 40 24
linux/net/irda/irlmp_event.c : 183 34 36
linux/net/irda/irlmp_frame.c : 107 10 52
linux/net/irda/irnet/irnet.h : 79 16 8
linux/net/irda/irnet/irnet_irda.c : 427 147 74
linux/net/irda/irnet/irnet_ppp.c : 17 2 2
linux/net/irda/irsyms.c : 37 1 16
linux/net/irda/irttp.c : 245 57 48
linux/net/irda/parameters.c : 76 16 14
linux/net/irda/qos.c : 96 16 15
linux/net/irda/timer.c : 56 14 16
linux/net/netlink/netlink_dev.c : 47 5 8
linux/net/sched/sch_api.c : 11 3 1
linux/scripts/Lindent : 4 2 2
linux/scripts/patch-kernel : 233 150 51

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:37 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part001

#!/bin/sh -x
# 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 001 of a 115 - 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.4.15 ==============
if test -f 'patch-2.4.15' -a X"$1" != X"-c"; then
echo 'x - skipping patch-2.4.15 (File already exists)'
rm -f _shar_wnt_.tmp;
else
> _shar_wnt_.tmp;
echo 'x - extracting patch-2.4.15 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'patch-2.4.15' &&
diff -u --recursive --new-file v2.4.14/linux/CREDITS linux/CREDITS
--- v2.4.14/linux/CREDITS Mon Nov 5 15:55:25 2001
+++ linux/CREDITS Sun Nov 11 10:09:32 2001
@@ -1611,8 +1611,10 @@
X W: http://www.kroah.com/linux-usb/
X D: USB Serial Converter driver framework, USB Handspring Visor driver
X D: ConnectTech WHITEHeat USB driver, Generic USB Serial driver
-D: USB Bluetooth driver
+D: USB I/O Edgeport driver, USB Serial IrDA driver
+D: USB Bluetooth driver, USB Skeleton driver
X D: bits and pieces of USB core code.
+D: PCI Hotplug core, PCI Hotplug Compaq driver modifications
X
X N: Russell Kroll
X E: rkr...@exploits.org
diff -u --recursive --new-file v2.4.14/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.4.14/linux/Documentation/Configure.help Mon Nov 5 15:55:25 2001
+++ linux/Documentation/Configure.help Thu Nov 22 10:52:44 2001
@@ -1,62 +1,71 @@
-# Maintained by Axel Boldt (ax...@uni-paderborn.de)
+# Maintained by:
+# Eric S. Raymond <mailto:e...@thyrsus.com>
+# Steven Cole <mailto:elen...@mesatop.com>
+#
+# Merged version 2.49: Current with 2.4.15-pre1 and 2.4.13-ac8.
X #
X # This version of the Linux kernel configuration help texts
X # corresponds to the kernel versions 2.4.x.
X #
X # Translations of this file available on the WWW:
X #
-# - Japanese, maintained by the JF Project (J...@linux.or.jp), at
-# http://www.linux.or.jp/JF/JFdocs/Configure.help/
-# - Russian, by k...@linux.nevod.perm.su, at
-# http://nevod.perm.su/service/linux/doc/kernel/Configure.help
-# - French, by Pierre Tane (ta...@bigfoot.com), at
-# http://www.traduc.org/kernelfr
-# - Spanish, by Carlos Perelló Marín (fpe...@ehome.encis.es), at
-# http://visar.csustan.edu/~carlos/
-# XXX: Site has moved, new location has no Configure.help trans.
-# - Italian, by Alessandro Rubini (rub...@linux.it), at
-# ftp://ftp-pavia1.linux.it/pub/linux/Configure.help
-# XXX: ftp-pavia1.linux.it: Non-existent host/domain
-# - Polish, by Cezar Cichocki (ce...@cs.net.pl), at
-# http://www.cs.net.pl/~cezar/Kernel
-# - German, by SuSE, at http://www.suse.de/~ke/kernel . This patch
+# - Japanese, maintained by the JF Project <mailto:J...@linux.or.jp>, at
+# <http://www.linux.or.jp/JF/JFdocs/Configure.help/>
+# - Russian, by <mailto:k...@linux.nevod.perm.su>, at
+# <http://nevod.perm.su/service/linux/doc/kernel/Configure.help>
+# - French, by Pierre Tane <mailto:ta...@bigfoot.com>, at
+# <http://www.traduc.org/kernelfr>
+# - Polish, by Dominik Mierzejewski <mailto:dmie...@elka.pw.edu.pl>, at
+# <http://home.elka.pw.edu.pl/~dmierzej/linux/kernel/>
+# - German, by SuSE, at <http://www.suse.de/~ke/kernel>. This patch
X # also includes infrastructure to support different languages.
X #
X # To access a document on the WWW, you need to have a direct Internet
X # connection and a browser program such as netscape or lynx. If you
X # only have email access, you can still use FTP and WWW servers: send
-# an email to mail-...@rtfm.mit.edu with the text
-# send usenet/news.answers/internet-services/access-via-email
+# an email to <mailto:mail-...@rtfm.mit.edu> with the text
+# send usenet/news.answers/internet-services/access-via-email
X # in the body of the message.
X #
X # Information about what a kernel is, what it does, how to patch and
X # compile it and much more is contained in the Kernel-HOWTO, available
-# at http://www.linuxdoc.org/docs.html#howto . Before you start
+# at <http://www.linuxdoc.org/docs.html#howto>. Before you start
X # compiling, make sure that you have the necessary versions of all
X # programs and libraries required to compile and run this kernel; they
-# are listed in the file Documentation/Changes. Make sure to read the
+# are listed in the <file:Documentation/Changes>. Make sure to read the
X # toplevel kernel README file as well.
X #
-# Format of this file: description<nl>variable<nl>help text<nl><nl>. If
-# the question being documented is of type "choice", we list only the
-# first occurring config variable. The help texts may contain empty
-# lines, but every non-empty line must be indented two positions.
-# Order of the help texts does not matter, however, no variable should
-# be documented twice: if it is, only the first occurrence will be
-# used by Configure. We try to keep the help texts of related variables
-# close together. Lines starting with `#' are ignored. To be nice to
-# menuconfig, limit your line length to 70 characters. Use emacs'
+# Format of this file: description<nl>variable<nl>help text<nl><nl>.
+# The help texts may contain empty lines, but every non-empty line must
+# be indented two positions. Order of the help texts does not matter,
+# however, no variable should be documented twice: if it is, only the
+# first occurrence will be used. We try to keep the help texts of related
+# variables close together. Lines starting with `#' are ignored. To be
+# nice to menuconfig, limit your line length to 70 characters. Use emacs'
X # kfill.el to edit and ispell.el to spell check this file or you lose.
X #
+# Comments of the form "# Choice:" followed by a menu name are used
+# internally by the maintainers' consistency-checking tools.
+#
X # If you add a help text to this file, please try to be as gentle as
X # possible. Don't use unexplained acronyms and generally write for the
X # hypothetical ignorant but intelligent user who has just bought a PC,
X # removed Windows, installed Linux and is now recompiling the kernel
-# for the first time. Tell them what to do if they're unsure. Technical
+# for the first time. Tell them what to do if they're unsure. Technical
X # information should go in a README in the Documentation directory.
+#
X # Mention all the relevant READMEs and HOWTOs in the help text.
+# Make them file URLs relative to the top level of the source tree so
+# that help browsers can turn them into hotlinks. All URLs ahould be
+# surrounded by <>.
+#
X # Repetitions are fine since the help texts are not meant to be read
-# in sequence.
+# in sequence. It is good style to include URLs pointing to more
+# detailed technical information, pictures of the hardware, etc.
+#
+# The most important thing to include in a help entry is *motivation*.
+# Explain why someone configuring a kernel might want to select your
+# option.
X #
X # All this was shamelessly stolen from several different sources. Many
X # thanks to all the contributors. Feel free to use these help texts in
@@ -66,21 +75,22 @@
X
X Prompt for development and/or incomplete code/drivers
X CONFIG_EXPERIMENTAL
- Some of the various things that Linux supports (such as network
- drivers, file systems, network protocols, etc.) can be in a state
- of development where the functionality, stability, or the level of
+ Some of the various things that Linux supports (such as network
+ drivers, file systems, network protocols, etc.) can be in a state
+ of development where the functionality, stability, or the level of
X testing is not yet high enough for general use. This is usually
- known as the "alpha-test" phase amongst developers. If a feature is
- currently in alpha-test, then the developers usually discourage
+ known as the "alpha-test" phase among developers. If a feature is
+ currently in alpha-test, then the developers usually discourage
X uninformed widespread use of this feature by the general public to
X avoid "Why doesn't this work?" type mail messages. However, active
X testing and use of these systems is welcomed. Just be aware that it
X may not meet the normal level of reliability or it may fail to work
X in some special cases. Detailed bug reports from people familiar
X with the kernel internals are usually welcomed by the developers
- (before submitting bug reports, please read the documents README,
- MAINTAINERS, REPORTING-BUGS, Documentation/BUG-HUNTING, and
- Documentation/oops-tracing.txt in the kernel source).
+ (before submitting bug reports, please read the documents
+ <file:README>, <file:MAINTAINERS>, <file:REPORTING-BUGS>,
+ <file:Documentation/BUG-HUNTING>, and
+ <file:Documentation/oops-tracing.txt> in the kernel source).
X
X This option will also make obsoleted drivers available. These are
X drivers that have been replaced by something else, and/or are
@@ -89,11 +99,18 @@
X Unless you intend to help test and develop a feature or driver that
X falls into this category, or you have a situation that requires
X using these features, you should probably say N here, which will
- cause this configure script to present you with fewer choices. If
+ cause the configurator to present you with fewer choices. If
X you say Y here, you will be offered the choice of using features or
X drivers that are currently considered to be in the alpha-test phase.
X
-Symmetric Multi Processing
+Prompt for drivers for obsolete features and hardware
+CONFIG_OBSOLETE
+ Obsolete drivers have usually been replaced by more recent software
+ that can talk to the same hardware. Obsolete hardware is things
+ like MGA monitors that you are very unlikely to see on today's
+ systems.
+
+Symmetric Multi-Processing support
X CONFIG_SMP
X This enables support for systems with more than one CPU. If you have
X a system with only one CPU, like most personal computers, say N. If
@@ -114,12 +131,106 @@
X Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
X Management" code will be disabled if you say Y here.
X
- See also the files Documentation/smp.tex, Documentation/smp.txt,
- Documentation/i386/IO-APIC.txt, Documentation/nmi_watchdog.txt and the
- SMP-FAQ on the WWW at http://www.irisa.fr/prive/mentre/smp-faq/ .
-
+ See also the <file:Documentation/smp.tex>,
+ <file:Documentation/smp.txt>, <file:Documentation/i386/IO-APIC.txt>,
+ <file:Documentation/nmi_watchdog.txt> and the SMP-FAQ on the WWW at
+ <http://www.irisa.fr/prive/mentre/smp-faq/>.
+
X If you don't know what to do here, say N.
X
+Intel or compatible 80x86 processor
+CONFIG_X86
+ This is Linux's home port. Linux was originally native to the Intel
+ 386, and runs on all the later x86 processors including the Intel
+ 486, 586, Pentiums, and various instruction-set-compatible chips by
+ AMD, Cyrix, and others.
+
+Alpha processor
+CONFIG_ALPHA
+ The Alpha is a 64-bit general-purpose processor designed and
+ marketed by the Digital Equipment Corporation of blessed memory, now
+ Compaq. Alpha Linux dates from 1995-1996 and was the first non-x86
+ port. The Alpha Linux project has a home page at
+ <http://www.alphalinux.org/>.
+
+32-bit Sun Sparc
+CONFIG_SPARC32
+ SPARC is a family of RISC microprocessors designed and marketed by
+ Sun Microsystems, incorporated. They are very widely found in Sun
+ workstations and clones. This port covers the original 32-bit SPARC;
+ it is old and stable and usually considered one of the "big three"
+ along with the Intel and Alpha ports. The UltraLinux project
+ maintains both the SPARC32 and SPARC64 ports; its web page is
+ available at <http://www.ultralinux.org/>.
+
+64-bit Sun Sparc
+CONFIG_SPARC64
+ SPARC is a family of RISC microprocessors designed and marketed by
+ Sun Microsystems, incorporated. This port covers the newer 64-bit
+ UltraSPARC. The UltraLinux project maintains both the SPARC32 and
+ SPARC64 ports; its web page is available at
+ <http://www.ultralinux.org/>.
+
+Power PC processor
+CONFIG_PPC
+ The PowerPC is a very capable 32-bit RISC processor from Motorola,
+ the successor to their 68000 and 88000 series. It powers recent
+ Macintoshes and also a widely-used series of single-board computers
+ from Motorola. The Linux PowerPC port has a home page at
+ <http://penguinppc.org/>.
+
+Motorola 68K processors
+CONFIG_M68K
+ The Motorola 68K microprocessors are now obsolete, having been
+ superseded by the PowerPC line also from Motorola. But they powered
+ the first wave of workstation hardware in the 1980s, including Sun
+ workstations; they were also the basis of the original Amiga and
+ later Atari personal computers. A lot of this hardware is still
+ around. The m68k project has a home page at
+ <http://www.linux-m68k.org/>.
+
+ARM processors
+CONFIG_ARM
+ The ARM series is a line of low-power-consumption RISC chip designs
+ licensed by ARM ltd and targeted at embedded applications and
+ handhelds such as the Compaq IPAQ. ARM-based PCs are no longer
+ manufactured, but legacy ARM-based PC hardware remains popular in
+ Europe. There is an ARM Linux project with a web page at
+ <http://www.arm.linux.org.uk/>.
+
+SuperH processors
+CONFIG_SUPERH
+ The SuperH is a RISC processor targeted for use in embedded systems
+ and consumer electronics; it was also used in the Sega Dreamcast
+ gaming console. The SuperH port has a home page at
+ <http://www.sh-linux.org/>.
+
+IA64 processors, including Intel Itanium
+CONFIG_IA64
+ The Itanium is Intel's 64-bit successor to the 32-bit X86 line. As
+ of early 2001 it is not yet in widespread production use. The Linux
+ IA-64 project has a home page at <http://www.linuxia64.org/>.
+
+HP PA-RISC processor
+CONFIG_PARISC
+ The PA-RISC microprocessor is a RISC chip designed by
+ Hewlett-Packard and used in their line of workstations. The PA-RISC
+ Linux project has a home page at <www.parisc-linux.org>.
+
+IBM System/390
+CONFIG_S390
+ Linux now runs on the venerable System/390 mainframe from IBM, in a
+ guest partition under VM. In fact, over 40,000 simultaneous Linux
+ images have been run on a single mainframe! The S390 Linux project
+ has a home page at <http://linux.s390.org/>.
+
+Axis Communications ETRAX 100LX embedded network CPU
+CONFIG_CRIS
+ Linux has been ported to run on the Axis Communications ETRAX 100LX
+ CPU and the single-board computers built around it, targeted for
+ network and embedded applications. For more information see the
+ Axis Communication site, <http://developer.axis.com/>.
+
X Multiquad support for NUMA systems
X CONFIG_MULTIQUAD
X This option is used for getting Linux to run on a (IBM/Sequent) NUMA
@@ -127,7 +238,7 @@
X and uses Clustered Logical APIC addressing mode instead of Flat Logical.
X You will need a new lynxer.elf file to flash your firmware with - send
X email to Martin...@us.ibm.com
-
+
X IO-APIC Support on Uniprocessors
X CONFIG_X86_UP_IOAPIC
X An IO-APIC (I/O Advanced Programmable Interrupt Controller) is an
@@ -160,7 +271,7 @@
X a math coprocessor built in, 486SX and 386 do not, unless you added
X a 487DX or 387, respectively. (The messages during boot time can
X give you some hints here ["man dmesg"].) Everyone needs either a
- coprocessor or this emulation.
+ coprocessor or this emulation.
X
X If you don't have a math coprocessor, you need to say Y here; if you
X say Y here even though you have a coprocessor, the coprocessor will
@@ -172,7 +283,7 @@
X intend to use this kernel on different machines.
X
X More information about the internals of the Linux math coprocessor
- emulation can be found in arch/i386/math-emu/README.
+ emulation can be found in <file:arch/i386/math-emu/README>.
X
X If you are not sure, say Y; apart from resulting in a 66 KB bigger
X kernel, it won't hurt.
@@ -211,12 +322,13 @@
X functions. You may choose to use both, but the Timer LED function
X will overrule the CPU usage LED.
X
-Kernel FP software completion (EXPERIMENTAL)
+Kernel FP software completion
X CONFIG_MATHEMU
X This option is required for IEEE compliant floating point arithmetic
X on the Alpha. The only time you would ever not say Y is to say M in
X order to debug the code. Say Y unless you know what you are doing.
X
+# Choice: himem
X High Memory support
X CONFIG_NOHIGHMEM
X Linux can use up to 64 Gigabytes of physical memory on x86 systems.
@@ -248,23 +360,45 @@
X auto detected or can be forced by using a kernel command line option
X such as "mem=256M". (Try "man bootparam" or see the documentation of
X your boot loader (lilo or loadlin) about how to pass options to the
- kernel at boot time.)
+ kernel at boot time.)
X
X If unsure, say "off".
X
+4GB
+CONFIG_HIGHMEM4G
+ Select this if you have a 32-bit processor and between 1 and 4
+ gigabytes of physical RAM.
+
+64GB
+CONFIG_HIGHMEM64G
+ Select this if you have a 32-bit processor and more than 4
+ gigabytes of physical RAM.
+
X Normal PC floppy disk support
X CONFIG_BLK_DEV_FD
X If you want to use the floppy disk drive(s) of your PC under Linux,
X say Y. Information about this driver, especially important for IBM
- Thinkpad users, is contained in Documentation/floppy.txt. That file
- also contains the location of the Floppy driver FAQ as well as
- location of the fdutils package used to configure additional
+ Thinkpad users, is contained in <file:Documentation/floppy.txt>.
+ That file also contains the location of the Floppy driver FAQ as
+ well as location of the fdutils package used to configure additional
X parameters of the driver at run time.
X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).
X The module will be called floppy.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
+
+iSeries Virtual I/O Disk Support
+CONFIG_VIODASD
+ If you are running on an iSeries system and you want to use
+ virtual disks created and managed by OS/400, say Y.
+
+iSeries Virtual I/O Disk IDE Emulation
+CONFIG_VIODASD_IDE
+ This causes the iSeries virtual disks to look like IDE disks.
+ If you have programs or utilities that only support certain
+ kinds of disks, this option will cause iSeries virtual disks
+ to pretend to be IDE disks, which may satisfy the program.
X
X Support for PowerMac floppy
X CONFIG_MAC_FLOPPY
@@ -278,15 +412,15 @@
X write to it and do all the other things that you can do with normal
X block devices (such as hard drives). It is usually used to load and
X store a copy of a minimal root file system off of a floppy into RAM
- during the initial install of Linux.
+ during the initial install of Linux.
X
X Note that the kernel command line option "ramdisk=XX" is now
- obsolete. For details, read Documentation/ramdisk.txt.
+ obsolete. For details, read <file:Documentation/ramdisk.txt>.
X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M and read Documentation/modules.txt. The module will be called
- rd.o.
+ say M and read <file:Documentation/modules.txt>. The module will be
+ called rd.o.
X
X Most normal users won't need the RAM disk functionality, and can
X thus say N here.
@@ -301,15 +435,15 @@
X The initial RAM disk is a RAM disk that is loaded by the boot loader
X (loadlin or lilo) and that is mounted as root before the normal boot
X procedure. It is typically used to load modules needed to mount the
- "real" root file system, etc. See Documentation/initrd.txt for
- details.
+ "real" root file system, etc. See <file:Documentation/initrd.txt>
+ for details.
X
-Loop device support
+Loopback device support
X CONFIG_BLK_DEV_LOOP
X Saying Y here will allow you to use a regular file as a block
X device; you can then create a file system on that block device and
X mount it just as you would mount other block devices such as hard
- drive partitions, CDROM drives or floppy drives. The loop devices
+ drive partitions, CD-ROM drives or floppy drives. The loop devices
X are block special device files with major number 7 and typically
X called /dev/loop0, /dev/loop1 etc.
X
@@ -318,7 +452,7 @@
X writing them to floppy. Furthermore, some Linux distributions avoid
X the need for a dedicated Linux partition by keeping their complete
X root file system inside a DOS FAT file using this loop device
- driver.
+ driver.
X
X The loop device driver can also be used to "hide" a file system in a
X disk partition, floppy, or regular file, either using encryption
@@ -326,58 +460,58 @@
X bits of, say, a sound file). This is also safe if the file resides
X on a remote file server. If you want to do this, you will first have
X to acquire and install a kernel patch from
- ftp://ftp.kerneli.org/pub/kerneli/ , and then you need to
+ <ftp://ftp.kerneli.org/pub/kerneli/>, and then you need to
X say Y to this option.
X
X Note that alternative ways to use encrypted file systems are
X provided by the cfs package, which can be gotten from
- ftp://ftp.kerneli.org/pub/kerneli/net-source/ , and the newer tcfs
- package, available at http://tcfs.dia.unisa.it/ . You do not need to
- say Y here if you want to use one of these. However, using cfs
+ <ftp://ftp.kerneli.org/pub/kerneli/net-source/>, and the newer tcfs
+ package, available at <http://tcfs.dia.unisa.it/>. You do not need
+ to say Y here if you want to use one of these. However, using cfs
X requires saying Y to "NFS file system support" below while using
X tcfs requires applying a kernel patch. An alternative steganography
X solution is provided by StegFS, also available from
- ftp://ftp.kerneli.org/pub/kerneli/net-source/ .
+ <ftp://ftp.kerneli.org/pub/kerneli/net-source/>.
X
X To use the loop device, you need the losetup utility and a recent
X version of the mount program, both contained in the util-linux
X package. The location and current version number of util-linux is
- contained in the file Documentation/Changes.
+ contained in the file <file:Documentation/Changes>.
X
X Note that this loop device has nothing to do with the loopback
X device used for network connections from the machine to itself.
X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be
- called loop.o.
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called loop.o.
X
X Most users will answer N here.
X
-Network Block Device support
+Network block device support
X CONFIG_BLK_DEV_NBD
X Saying Y here will allow your computer to be a client for network
X block devices, i.e. it will be able to use block devices exported by
X servers (mount file systems on them etc.). Communication between
X client and server works over TCP/IP networking, but to the client
X program this is hidden: it looks like a regular local file access to
- a block device special file such as /dev/nd0.
+ a block device special file such as /dev/nd0.
X
X Network block devices also allows you to run a block-device in
X userland (making server and client physically the same computer,
X communicating using the loopback network device).
-
- Read Documentation/nbd.txt for more information, especially about
- where to find the server code, which runs in user space and does not
- need special kernel support.
+
+ Read <file:Documentation/nbd.txt> for more information, especially
+ about where to find the server code, which runs in user space and
+ does not need special kernel support.
X
X Note that this has nothing to do with the network file systems NFS
X or Coda; you can say N here even if you intend to use NFS or Coda.
X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be
- called nbd.o.
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called nbd.o.
X
X If unsure, say N.
X
@@ -385,16 +519,16 @@
X CONFIG_IDE
X If you say Y here, your kernel will be able to manage low cost mass
X storage units such as ATA/(E)IDE and ATAPI units. The most common
- cases are IDE hard drives and ATAPI CDROM drives.
+ cases are IDE hard drives and ATAPI CD-ROM drives.
X
X If your system is pure SCSI and doesn't use these interfaces, you
X can say N here.
-
+
X Integrated Disk Electronics (IDE aka ATA-1) is a connecting standard
X for mass storage units such as hard disks. It was designed by
X Western Digital and Compaq Computer in 1984. It was then named
X ST506. Quite a number of disks use the IDE interface.
-
+
X AT Attachment (ATA) is the superset of the IDE specifications.
X ST506 was also called ATA-1.
X
@@ -407,22 +541,22 @@
X ATA/IDE standards by means of fast DMA controllers.
X
X ATA Packet Interface (ATAPI) is a protocol used by EIDE tape and
- CDROM drives, similar in many respects to the SCSI protocol.
-
+ CD-ROM drives, similar in many respects to the SCSI protocol.
+
X SMART IDE (Self Monitoring, Analysis and Reporting Technology) was
X designed in order to prevent data corruption and disk crash by
X detecting pre hardware failure conditions (heat, access time, and
- the like...). Disks built since June 1995 may follow this
- standard. The kernel itself don't manage this; however there are
- quite a number of user programs such as smart that can query the
- status of SMART parameters disk.
+ the like...). Disks built since June 1995 may follow this standard.
+ The kernel itself don't manage this; however there are quite a
+ number of user programs such as smart that can query the status of
+ SMART parameters disk.
X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be
- called ide.o.
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ide.o.
X
- For further information, please read Documentation/ide.txt.
+ For further information, please read <file:Documentation/ide.txt>.
X
X If unsure, say Y.
X
@@ -436,21 +570,21 @@
X Useful information about large (>540 MB) IDE disks, multiple
X interfaces, what to do if ATA/IDE devices are not automatically
X detected, sound card ATA/IDE ports, module support, and other
- topics, is contained in Documentation/ide.txt. For detailed
+ topics, is contained in <file:Documentation/ide.txt>. For detailed
X information about hard drives, consult the Disk-HOWTO and the
X Multi-Disk-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto .
+ <http://www.linuxdoc.org/docs.html#howto>.
X
X To fine-tune ATA/IDE drive/interface parameters for improved
X performance, look for the hdparm package at
- http://www.ibiblio.org/pub/Linux/system/hardware .
+ <http://www.ibiblio.org/pub/Linux/system/hardware>.
X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt and
- Documentation/ide.txt. The module will be called ide-mod.o. Do not
- compile this driver as a module if your root file system (the one
- containing the directory /) is located on an IDE device.
+ say M here and read <file:Documentation/modules.txt> and
+ <file:Documentation/ide.txt>. The module will be called ide-mod.o.
+ Do not compile this driver as a module if your root file system (the
+ one containing the directory /) is located on an IDE device.
X
X If you have one or more IDE drives, say Y or M here. If your system
X has no IDE drives, or if memory requirements are really tight, you
@@ -467,42 +601,42 @@
X since it lacks the enhanced functionality of the new one. This makes
X it a good choice for systems with very tight memory restrictions, or
X for systems with only older MFM/RLL/ESDI drives. Choosing the old
- driver can save 13 KB or so of kernel memory.
+ driver can save 13 KB or so of kernel memory.
X
X If you are unsure, then just choose the Enhanced IDE/MFM/RLL driver
X instead of this one. For more detailed information, read the
X Disk-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto .
+ <http://www.linuxdoc.org/docs.html#howto>.
X
X Use old disk-only driver on primary interface
X CONFIG_BLK_DEV_HD_IDE
- There are two drivers for MFM/RLL/IDE disks. Most people use just
- the new enhanced driver by itself. This option however installs the
+ There are two drivers for MFM/RLL/IDE disks. Most people use just
+ the new enhanced driver by itself. This option however installs the
X old hard disk driver to control the primary IDE/disk interface in
X the system, leaving the new enhanced IDE driver to take care of only
- the 2nd/3rd/4th IDE interfaces. Doing this will prevent you from
- having an IDE/ATAPI CDROM or tape drive connected to the primary IDE
- interface. Choosing this option may be useful for older systems
+ the 2nd/3rd/4th IDE interfaces. Doing this will prevent you from
+ having an IDE/ATAPI CD-ROM or tape drive connected to the primary
+ IDE interface. Choosing this option may be useful for older systems
X which have MFM/RLL/ESDI controller+drives at the primary port
X address (0x1f0), along with IDE drives at the secondary/3rd/4th port
- addresses.
+ addresses.
X
X Normally, just say N here; you will then use the new driver for all
X 4 interfaces.
X
X Include IDE/ATA-2 DISK support
X CONFIG_BLK_DEV_IDEDISK
- This will include enhanced support for MFM/RLL/IDE hard disks. If
+ This will include enhanced support for MFM/RLL/IDE hard disks. If
X you have a MFM/RLL/IDE disk, and there is no special reason to use
- the old hard disk driver instead, say Y. If you have an SCSI-only
+ the old hard disk driver instead, say Y. If you have an SCSI-only
X system, you can say N here.
X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be
- called ide-disk.o. Do not compile this driver as a module if your
- root file system (the one containing the directory /) is located on
- the IDE disk. If unsure, say Y.
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ide-disk.o. Do not compile this driver as a module
+ if your root file system (the one containing the directory /) is
+ located on the IDE disk. If unsure, say Y.
X
X Use multi-mode by default
X CONFIG_IDEDISK_MULTI_MODE
@@ -513,38 +647,43 @@
X
X If in doubt, say N.
X
-Include IDE/ATAPI CDROM support
+PCMCIA IDE support
+CONFIG_BLK_DEV_IDECS
+ Support for outboard IDE disks, tape drives, and CD-ROM drives
+ connected through a PCMCIA card.
+
+Include IDE/ATAPI CD-ROM support
X CONFIG_BLK_DEV_IDECD
- If you have a CDROM drive using the ATAPI protocol, say Y. ATAPI is
- a newer protocol used by IDE CDROM and TAPE drives, similar to the
- SCSI protocol. Most new CDROM drives use ATAPI, including the
+ If you have a CD-ROM drive using the ATAPI protocol, say Y. ATAPI is
+ a newer protocol used by IDE CD-ROM and TAPE drives, similar to the
+ SCSI protocol. Most new CD-ROM drives use ATAPI, including the
X NEC-260, Mitsumi FX400, Sony 55E, and just about all non-SCSI
X double(2X) or better speed drives.
X
- If you say Y here, the CDROM drive will be identified at boot time
+ If you say Y here, the CD-ROM drive will be identified at boot time
X along with other IDE devices, as "hdb" or "hdc", or something
X similar (check the boot messages with dmesg). If this is your only
- CDROM drive, you can say N to all other CDROM options, but be sure
- to say Y or M to "ISO 9660 CDROM file system support".
+ CD-ROM drive, you can say N to all other CD-ROM options, but be sure
+ to say Y or M to "ISO 9660 CD-ROM file system support".
X
- Read the CDROM-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto and the file
- Documentation/cdrom/ide-cd. Note that older versions of lilo (the
- Linux boot loader) cannot properly deal with IDE/ATAPI CDROMs, so
- install lilo-16 or higher, available from
- ftp://metalab.unc.edu/pub/Linux/system/boot/lilo .
+ Read the CD-ROM-HOWTO, available from
+ <http://www.linuxdoc.org/docs.html#howto> and
+ <file:Documentation/cdrom/ide-cd>. Note that older versions of lilo
+ (the Linux boot loader) cannot properly deal with IDE/ATAPI CD-ROMs,
+ so install lilo-16 or higher, available from
+ <ftp://metalab.unc.edu/pub/Linux/system/boot/lilo>.
X
X If you want to compile the driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be
- called ide-cd.o.
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ide-cd.o.
X
X Include IDE/ATAPI TAPE support
X CONFIG_BLK_DEV_IDETAPE
X If you have an IDE tape drive using the ATAPI protocol, say Y.
- ATAPI is a newer protocol used by IDE tape and CDROM drives, similar
- to the SCSI protocol. If you have an SCSI tape drive however, you
- can say N here.
+ ATAPI is a newer protocol used by IDE tape and CD-ROM drives,
+ similar to the SCSI protocol. If you have an SCSI tape drive
+ however, you can say N here.
X
X You should also say Y if you have an OnStream DI-30 tape drive; this
X will not work with the SCSI protocol, until there is support for the
@@ -553,27 +692,27 @@
X If you say Y here, the tape drive will be identified at boot time
X along with other IDE devices, as "hdb" or "hdc", or something
X similar, and will be mapped to a character device such as "ht0"
- (check the boot messages with dmesg). Be sure to consult the
- drivers/ide/ide-tape.c and Documentation/ide.txt files for usage
- information.
+ (check the boot messages with dmesg). Be sure to consult the
+ <file:drivers/ide/ide-tape.c> and <file:Documentation/ide.txt> files
+ for usage information.
X
X If you want to compile the driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be
- called ide-tape.o.
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ide-tape.o.
X
X Include IDE/ATAPI FLOPPY support
X CONFIG_BLK_DEV_IDEFLOPPY
X If you have an IDE floppy drive which uses the ATAPI protocol,
- answer Y. ATAPI is a newer protocol used by IDE CDROM/tape/floppy
- drives, similar to the SCSI protocol.
+ answer Y. ATAPI is a newer protocol used by IDE CD-ROM/tape/floppy
+ drives, similar to the SCSI protocol.
X
X The LS-120 and the IDE/ATAPI Iomega ZIP drive are also supported by
X this driver. For information about jumper settings and the question
X of when a ZIP drive uses a partition table, see
- http://www.win.tue.nl/~aeb/linux/zip/zip-1.html .
+ <http://www.win.tue.nl/~aeb/linux/zip/zip-1.html>.
X (ATAPI PD-CD/CDR drives are not supported by this driver; support
- for PD-CD/CDR drives is available if you answer Y to
+ for PD-CD/CDR drives is available if you answer Y to
X "SCSI emulation support", below).
X
X If you say Y here, the FLOPPY drive will be identified along with
@@ -582,8 +721,8 @@
X
X If you want to compile the driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be
- called ide-floppy.o.
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ide-floppy.o.
X
X SCSI emulation support
X CONFIG_BLK_DEV_IDESCSI
@@ -625,7 +764,7 @@
X conditions. Say Y here to include code which tries to automatically
X detect and correct the problems under Linux. This option also
X enables access to the secondary IDE ports in some CMD640 based
- systems.
+ systems.
X
X This driver will work automatically in PCI based systems (most new
X systems have PCI slots). But if your system uses VESA local bus
@@ -636,15 +775,15 @@
X
X The CMD640 chip is also used on add-in cards by Acculogic, and on
X the "CSA-6400E PCI to IDE controller" that some people have. For
- details, read Documentation/ide.txt.
+ details, read <file:Documentation/ide.txt>.
X
X CMD640 enhanced support
X CONFIG_BLK_DEV_CMD640_ENHANCED
X This option includes support for setting/autotuning PIO modes and
- prefetch on CMD640 IDE interfaces. For details, read
- Documentation/ide.txt. If you have a CMD640 IDE interface and your
- BIOS does not already do this for you, then say Y here. Otherwise
- say N.
+ prefetch on CMD640 IDE interfaces. For details, read
+ <file:Documentation/ide.txt>. If you have a CMD640 IDE interface
+ and your BIOS does not already do this for you, then say Y here.
+ Otherwise say N.
X
X RZ1000 chipset bugfix/support
X CONFIG_BLK_DEV_RZ1000
@@ -654,14 +793,14 @@
X severe data corruption under many conditions. Say Y here to include
X code which automatically detects and corrects the problem under
X Linux. This may slow disk throughput by a few percent, but at least
- things will operate 100% reliably.
+ things will operate 100% reliably.
X
X Generic PCI IDE chipset support
X CONFIG_BLK_DEV_IDEPCI
X Say Y here for PCI systems which use IDE drive(s).
X This option helps the IDE driver to automatically detect and
X configure all PCI-based IDE interfaces in your system.
-
+
X Support for sharing PCI IDE interrupts
X CONFIG_IDEPCI_SHARE_IRQ
X Some ATA/IDE chipsets have hardware support which allows for
@@ -681,14 +820,14 @@
X for these drives, but you can change that by saying Y to the
X following question "Use DMA by default when available". You can get
X the latest version of the hdparm utility from
- ftp://metalab.unc.edu/pub/Linux/system/hardware/ .
+ <ftp://metalab.unc.edu/pub/Linux/system/hardware/>.
X
- Read the comments at the beginning of drivers/ide/ide-dma.c and
- the file Documentation/ide.txt for more information.
+ Read the comments at the beginning of <file:drivers/ide/ide-dma.c>
+ and the file <file:Documentation/ide.txt> for more information.
X
X It is safe to say Y to this question.
X
-Good-Bad DMA Model-Firmware (EXPERIMENTAL)
+Good-Bad DMA Model-Firmware (WIP)
X CONFIG_IDEDMA_NEW_DRIVE_LISTINGS
X If you say Y here, the model and firmware revision of your drive
X will be compared against a blacklist of buggy drives that claim to
@@ -701,6 +840,16 @@
X
X If in doubt, say N.
X
+Attempt to HACK around Chipsets that TIMEOUT (WIP)
+CONFIG_BLK_DEV_IDEDMA_TIMEOUT
+ If you say Y here, this is a NASTY UGLY HACK!
+
+ We have to issue an abort and requeue the request DMA engine got
+ turned off by a goofy ASIC, and we have to clean up the mess, and
+ here is as good as any. Do it globally for all chipsets.
+
+ If in doubt, say N.
+
X Boot off-board chipsets first support
X CONFIG_BLK_DEV_OFFBOARD
X Normally, IDE controllers built into the motherboard (on-board
@@ -722,7 +871,7 @@
X
X If in doubt, say N.
X
-Use DMA by default when available
+Use PCI DMA by default when available
X CONFIG_IDEDMA_PCI_AUTO
X Prior to kernel version 2.1.112, Linux used to automatically use
X DMA for IDE drives and chipsets which support it. Due to concerns
@@ -738,29 +887,45 @@
X
X IGNORE word93 Validation BITS
X CONFIG_IDEDMA_IVB
- Since various rules were applied and created ... et al. as it relates
- the detection of valid cable signals. This is a result of unclear terms
- in ATA-4 and ATA-5 standards.
+ There are unclear terms is ATA-4 and ATA-5 standards how certain
+ hardware (an 80c ribbon) should be detected. Different interpretations
+ of the standards have been released in hardware. This causes problems:
+ for example, a host with Ultra Mode 4 (or higher) will not run
+ in that mode with an 80c ribbon.
+
+ If you are experiencing compatibility or performance problems, you
+ MAY try to answering Y here. However, it does not necessarily solve
+ any of your problems, it could even cause more of them.
X
X It is normally safe to answer Y; however, the default is N.
X
-Various ATA, Work(s) In Progress (EXPERIMENTAL)
+ATA Work(s) In Progress (EXPERIMENTAL)‹
X CONFIG_IDEDMA_PCI_WIP
X If you enable this you will be able to use and test highly
- developmental projects. If you say N, this configure script will
+ developmental projects. If you say N, the configurator will
X simply skip those options.
X
X It is SAFEST to say N to this question.
X
+Asyncronious DMA support (EXPERIMENTAL)
+CONFIG_BLK_DEV_ADMA
+ Please read the comments at the top of
+ <file:drivers/ide/ide-adma.c>.
+
+Pacific Digital A-DMA support (EXPERIMENTAL)
+CONFIG_BLK_DEV_PDC_ADMA
+ Please read the comments at the top of <file:drivers/ide/pdcadma.c>.
+
X 3ware Hardware ATA-RAID support
X CONFIG_BLK_DEV_3W_XXXX_RAID
X 3ware is the only hardware ATA-Raid product in Linux to date.
X This card is 2,4, or 8 channel master mode support only.
X SCSI support required!!!
X
- http://www.3ware.com/
+ <http://www.3ware.com/>
X
- Please read the comments at the top of drivers/scsi/3w-xxxx.c
+ Please read the comments at the top of
+ <file:drivers/scsi/3w-xxxx.c>.
X
X AEC62XX chipset support
X CONFIG_BLK_DEV_AEC62XX
@@ -774,13 +939,13 @@
X The ATP860 is an UltraDMA 66 chipset base.
X The ATP860M(acintosh) version is an UltraDMA 66 chipset base.
X
- Please read the comments at the top of drivers/ide/aec62xx.c
- If you say Y here, then say Y to "Use DMA by default when available" as
- well.
+ Please read the comments at the top of <file:drivers/ide/aec62xx.c>.
+ If you say Y here, then say Y to "Use DMA by default when available"
+ as well.
X
X AEC62XX Tuning support
X CONFIG_AEC62XX_TUNING
- Please read the comments at the top of drivers/ide/aec62xx.c
+ Please read the comments at the top of <file:drivers/ide/aec62xx.c>.
X If unsure, say N.
X
X ALI M15x3 chipset support
@@ -790,8 +955,8 @@
X normal dual channel support.
X
X If you say Y here, you also need to say Y to "Use DMA by default
- when available", above.
- Please read the comments at the top of drivers/ide/alim15x3.c
+ when available", above. Please read the comments at the top of
+ <file:drivers/ide/alim15x3.c>.
X
X If unsure, say N.
X
@@ -806,20 +971,21 @@
X Using this option can allow WDC drives to run at ATA-4/5 transfer
X rates with only an ATA-2 support structure.
X
- SAY NO!
+ SAY N!
X
-AMD7409 chipset support
-CONFIG_BLK_DEV_AMD7409
- This driver ensures (U)DMA support for the AMD756 Viper chipset.
+AMD Viper support
+CONFIG_BLK_DEV_AMD74XX
+ This driver ensures (U)DMA support for the AMD756/760 Viper
+ chipsets.
X
X If you say Y here, you also need to say Y to "Use DMA by default
X when available", above.
- Please read the comments at the top of drivers/ide/amd7409.c
+ Please read the comments at the top of <file:drivers/ide/amd74xx.c>.
X
X If unsure, say N.
X
-AMD Viper ATA-66 Override support (WIP)
-CONFIG_AMD7409_OVERRIDE
+AMD Viper ATA-66 Override (WIP)
+CONFIG_AMD74XX_OVERRIDE
X This option auto-forces the ata66 flag.
X This effect can be also invoked by calling "idex=ata66"
X If unsure, say N.
@@ -858,8 +1024,8 @@
X HPT34X AUTODMA support (WIP)
X CONFIG_HPT34X_AUTODMA
X This is a dangerous thing to attempt currently! Please read the
- comments at the top of drivers/ide/hpt34x.c If you say Y here,
- then say Y to "Use DMA by default when available" as well.
+ comments at the top of <file:drivers/ide/hpt34x.c>. If you say Y
+ here, then say Y to "Use DMA by default when available" as well.
X
X If unsure, say N.
X
@@ -868,9 +1034,9 @@
X HPT366 is an Ultra DMA chipset for ATA-66.
X HPT368 is an Ultra DMA chipset for ATA-66 RAID Based.
X HPT370 is an Ultra DMA chipset for ATA-100.
-
+
X This driver adds up to 4 more EIDE devices sharing a single
- interrupt.
+ interrupt.
X
X The HPT366 chipset in its current form is bootable. One solution
X for this problem are special LILO commands for redirecting the
@@ -884,21 +1050,22 @@
X ide-probe at boot. It is reported to support DVD II drives, by the
X manufacturer.
X
-NS87415 support (EXPERIMENTAL)
+NS87415 chipset support (EXPERIMENTAL)
X CONFIG_BLK_DEV_NS87415
X This driver adds detection and support for the NS87415 chip
X (used in SPARC64, among others).
X
- Please read the comments at the top of drivers/ide/ns87415.c.
+ Please read the comments at the top of <file:drivers/ide/ns87415.c>.
X
-OPTi 82C621 enhanced support (EXPERIMENTAL)
+OPTi 82C621 chipset enhanced support (EXPERIMENTAL)
X CONFIG_BLK_DEV_OPTI621
X This is a driver for the OPTi 82C621 EIDE controller.
- Please read the comments at the top of drivers/ide/opti621.c.
+ Please read the comments at the top of <file:drivers/ide/opti621.c>.
X
-ServerWorks OSB4 chipset support (EXPERIMENTAL)
-CONFIG_BLK_DEV_OSB4
- This driver adds PIO/DMA support for the Serverworks OSB4 chipset
+ServerWorks OSB4/CSB5 chipset support
+CONFIG_BLK_DEV_SVWKS
+ This driver adds PIO/(U)DMA support for the ServerWorks OSB4/CSB5
+ chipsets.
X
X Intel PIIXn chipsets support
X CONFIG_BLK_DEV_PIIX
@@ -907,7 +1074,7 @@
X PIO 0-4 mode settings, this allows dynamic tuning of the chipset
X via the standard end-user tool 'hdparm'.
X
- Please read the comments at the top of drivers/ide/piix.c.
+ Please read the comments at the top of <file:drivers/ide/piix.c>.
X
X If you say Y here, you should also say Y to "PIIXn Tuning support",
X below.
@@ -926,29 +1093,30 @@
X
X If unsure, say N.
X
-PROMISE PDC20246/PDC20262/PDC20267 support
+PROMISE PDC20246/PDC20262/PDC20265/PDC20267/PDC20268 support
X CONFIG_BLK_DEV_PDC202XX
X Promise Ultra33 or PDC20246
X Promise Ultra66 or PDC20262
- Promise Ultra100 or PDC20265/PDC20267
+ Promise Ultra100 or PDC20265/PDC20267/PDC20268
X
X This driver adds up to 4 more EIDE devices sharing a single
X interrupt. This add-on card is a bootable PCI UDMA controller. Since
X multiple cards can be installed and there are BIOS ROM problems that
X happen if the BIOS revisions of all installed cards (three-max) do
X not match, the driver attempts to do dynamic tuning of the chipset
- at boot-time for max-speed. Ultra33 BIOS 1.25 or newer is required
+ at boot-time for max-speed. Ultra33 BIOS 1.25 or newer is required
X for more than one card. This card may require that you say Y to
- "Special UDMA Feature (EXPERIMENTAL)".
+ "Special UDMA Feature".
X
X If you say Y here, you need to say Y to "Use DMA by default when
X available" as well.
X
- Please read the comments at the top of drivers/ide/pdc202xx.c
+ Please read the comments at the top of
+ <file:drivers/ide/pdc202xx.c>.
X
X If unsure, say N.
X
-Special UDMA Feature (EXPERIMENTAL)
+Special UDMA Feature
X CONFIG_PDC202XX_BURST
X For PDC20246, PDC20262, PDC20265 and PDC20267 Ultra DMA chipsets.
X Designed originally for PDC20246/Ultra33 that has BIOS setup
@@ -956,10 +1124,15 @@
X
X Unknown for PDC20265/PDC20267 Ultra DMA 100.
X
- Please read the comments at the top of drivers/ide/pdc202xx.c
+ Please read the comments at the top of
+ <file:drivers/ide/pdc202xx.c>.
X
X If unsure, say N.
X
+Special FastTrak Feature
+CONFIG_PDC202XX_FORCE
+ For FastTrak enable overriding BIOS.
+
X SiS5513 chipset support
X CONFIG_BLK_DEV_SIS5513
X This driver ensures (U)DMA support for SIS5513 chipset based
@@ -969,20 +1142,21 @@
X If you say Y here, you need to say Y to "Use DMA by default when
X available" as well.
X
- Please read the comments at the top of drivers/ide/sis5513.c
+ Please read the comments at the top of <file:drivers/ide/sis5513.c>.
X
X SLC90E66 chipset support
X CONFIG_BLK_DEV_SLC90E66
X This driver ensures (U)DMA support for Victroy66 SouthBridges for
X SMsC with Intel NorthBridges. This is an Ultra66 based chipset.
X The nice thing about it is that you can mix Ultra/DMA/PIO devices
- and it will handle timing cycles. Since this is an improved look-a-like
- to the PIIX4 it should be a nice addition.
+ and it will handle timing cycles. Since this is an improved
+ look-a-like to the PIIX4 it should be a nice addition.
X
X If you say Y here, you need to say Y to "Use DMA by default when
X available" as well.
X
- Please read the comments at the top of drivers/ide/slc90e66.c
+ Please read the comments at the top of
+ <file:drivers/ide/slc90e66.c>.
X
X Winbond SL82c105 support
X CONFIG_BLK_DEV_SL82C105
@@ -990,35 +1164,34 @@
X special configuration for this chip. This is common on various CHRP
X motherboards, but could be used elsewhere. If in doubt, say Y.
X
-Tekram TRM290 chipset support (EXPERIMENTAL)
+Tekram TRM290 chipset support
X CONFIG_BLK_DEV_TRM290
X This driver adds support for bus master DMA transfers
X using the Tekram TRM290 PCI IDE chip. Volunteers are
X needed for further tweaking and development.
- Please read the comments at the top of drivers/ide/trm290.c.
+ Please read the comments at the top of <file:drivers/ide/trm290.c>.
X
X VIA82CXXX chipset support
X CONFIG_BLK_DEV_VIA82CXXX
X This allows you to configure your chipset for a better use while
- running (U)DMA: it will allow you to enable efficiently the second
- channel dma usage, as it may not be set by BIOS. It allows you to
- pass a kernel command line at boot time in order to set fifo
- config. If no command line is provided, it will try to set fifo
- configuration at its best. It will allow you to get information from
- /proc/ide/via provided you enabled "proc" support.
+ running PIO/(U)DMA, it will allow you to enable efficiently the
+ second channel dma usage, as it may not be set by BIOS. It will try
+ to set fifo configuration at its best. It will allow you to get
+ information from /proc/ide/via provided you enabled "/proc file
+ system" support.
X
- Please read the comments at the top of drivers/ide/via82cxxx.c
+ Please read the comments at the top of
+ <file:drivers/ide/via82cxxx.c>.
X
X If you say Y here, then say Y to "Use DMA by default when available"
X as well.
X
X If unsure, say N.
X
-VIA82CXXX Tuning support (WIP)
-CONFIG_VIA82CXXX_TUNING
- Please read the comments at the top of drivers/ide/via82cxxx.c
-
- If unsure, say N.
+RapIDE interface support
+CONFIG_BLK_DEV_IDE_RAPIDE
+ Say Y here if you want to support the Yellowstone RapIDE controller
+ manufactured for use with Acorn computers.
X
X Other IDE chipset support
X CONFIG_IDE_CHIPSETS
@@ -1030,9 +1203,9 @@
X setting of higher speed I/O rates to improve system performance with
X these chipsets. Most of these also require special kernel boot
X parameters to actually turn on the support at runtime; you can find
- a list of these in the file Documentation/ide.txt.
-
- People with SCSI-only systems can say N here.
+ a list of these in the file <file:Documentation/ide.txt>.
+
+ People with SCSI-only systems can say N here.
X
X Generic 4 drives/port support
X CONFIG_BLK_DEV_4DRIVES
@@ -1045,53 +1218,64 @@
X ALI M14xx support
X CONFIG_BLK_DEV_ALI14XX
X This driver is enabled at runtime using the "ide0=ali14xx" kernel
- boot parameter. It enables support for the secondary IDE interface
+ boot parameter. It enables support for the secondary IDE interface
X of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster
- I/O speeds to be set as well. See the files Documentation/ide.txt
- and drivers/ide/ali14xx.c for more info.
+ I/O speeds to be set as well. See the files
+ <file:Documentation/ide.txt> and <file:drivers/ide/ali14xx.c> for
+ more info.
X
X DTC-2278 support
X CONFIG_BLK_DEV_DTC2278
X This driver is enabled at runtime using the "ide0=dtc2278" kernel
X boot parameter. It enables support for the secondary IDE interface
X of the DTC-2278 card, and permits faster I/O speeds to be set as
- well. See the Documentation/ide.txt and drivers/ide/dtc2278.c
- files for more info.
+ well. See the <file:Documentation/ide.txt> and
+ <file:drivers/ide/dtc2278.c> files for more info.
X
X Holtek HT6560B support
X CONFIG_BLK_DEV_HT6560B
X This driver is enabled at runtime using the "ide0=ht6560b" kernel
X boot parameter. It enables support for the secondary IDE interface
X of the Holtek card, and permits faster I/O speeds to be set as well.
- See the Documentation/ide.txt and drivers/ide/ht6560b.c files for
- more info.
+ See the <file:Documentation/ide.txt> and
+ <file:drivers/ide/ht6560b.c> files for more info.
X
X PROMISE DC4030 support (EXPERIMENTAL)
X CONFIG_BLK_DEV_PDC4030
X This driver provides support for the secondary IDE interface and
- cache of Promise IDE chipsets, e.g. DC4030 and DC5030. This driver
+ cache of Promise IDE chipsets, e.g. DC4030 and DC5030. This driver
X is known to incur timeouts/retries during heavy I/O to drives
- attached to the secondary interface. CDROM and TAPE devices are not
- supported yet. This driver is enabled at runtime using the
- "ide0=dc4030" kernel boot parameter. See the Documentation/ide.txt
- and drivers/ide/pdc4030.c files for more info.
+ attached to the secondary interface. CD-ROM and TAPE devices are
+ not supported yet. This driver is enabled at runtime using the
+ "ide0=dc4030" kernel boot parameter. See the
+ <file:Documentation/ide.txt> and <file:drivers/ide/pdc4030.c> files
+ for more info.
X
+# This is for Linus's tree.
X QDI QD6580 support
X CONFIG_BLK_DEV_QD6580
X This driver is enabled at runtime using the "ide0=qd6580" kernel
- boot parameter. It permits faster I/O speeds to be set. See the
- files Documentation/ide.txt and drivers/ide/qd6580.c for more
- info.
+ boot parameter. It permits faster I/O speeds to be set. See the
+ <file:Documentation/ide.txt> and <file:drivers/ide/qd6580.c> for
+ more info.
+
+# This is for Alan's tree. Note the name difference.
+QDI QD65XX support
+CONFIG_BLK_DEV_QD65XX
+ This driver is enabled at runtime using the "ide0=qd65xx" kernel
+ boot parameter. It permits faster I/O speeds to be set. See the
+ <file:Documentation/ide.txt> and <file:drivers/ide/qd65xx.c> for
+ more info.
X
X UMC 8672 support
X CONFIG_BLK_DEV_UMC8672
X This driver is enabled at runtime using the "ide0=umc8672" kernel
X boot parameter. It enables support for the secondary IDE interface
X of the UMC-8672, and permits faster I/O speeds to be set as well.
- See the files Documentation/ide.txt and drivers/ide/umc8672.c for
- more info.
+ See the files <file:Documentation/ide.txt> and
+ <file:drivers/ide/umc8672.c> for more info.
X
-Amiga builtin Gayle IDE interface support
+Amiga Gayle IDE interface support
X CONFIG_BLK_DEV_GAYLE
X This is the IDE driver for the builtin IDE interface on some Amiga
X models. It supports both the `A1200 style' (used in A600 and A1200)
@@ -1107,11 +1291,11 @@
X disks, CD-ROM drives, etc.) that are connected to the builtin IDE
X interface.
X
-Amiga Buddha/Catweasel IDE interface support (EXPERIMENTAL)
+Amiga Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)
X CONFIG_BLK_DEV_BUDDHA
- This is the IDE driver for the IDE interfaces on the Buddha and
- Catweasel expansion boards. It supports up to two interfaces on the
- Buddha and three on the Catweasel.
+ This is the IDE driver for the IDE interfaces on the Buddha,
+ Catweasel and X-Surf expansion boards. It supports up to two interfaces
+ on the Buddha, three on the Catweasel and two on the X-Surf.
X
X Say Y if you have a Buddha or Catweasel expansion board and want to
X use IDE devices (hard disks, CD-ROM drives, etc.) that are connected
@@ -1131,10 +1315,16 @@
X Say Y if you have an IDE doubler. The driver is enabled at kernel
X runtime using the "ide=doubler" kernel boot parameter.
X
-Support for PowerMac IDE devices (must also enable IDE)
+WarpEngine SCSI support
+CONFIG_WARPENGINE_SCSI
+ Support for MacroSystem Development's WarpEngine Amiga SCSI-2
+ controller. Info at
+ <http://www.lysator.liu.se/amiga/ar/guide/ar310.guide?FEATURE5>.
+
+Builtin PowerMac IDE support
X CONFIG_BLK_DEV_IDE_PMAC
- This driver provides support for the built-in IDE controller on most
- of the recent Apple Power Macintoshes and PowerBooks.
+ This driver provides support for the built-in IDE controller on
+ most of the recent Apple Power Macintoshes and PowerBooks.
X If unsure, say Y.
X
X PowerMac IDE DMA support
@@ -1164,29 +1354,6 @@
X devices (hard disks, CD-ROM drives, etc.) that are connected to the
X builtin IDE interface.
X
-MPC8xx IDE support
-CONFIG_BLK_DEV_MPC8xx_IDE
- This option provides support for IDE on Motorola MPC8xx Systems.
- Please see 'Type of MPC8xx IDE interface' for details.
-
- If unsure, say N.
-
-Type of MPC8xx IDE interface
-CONFIG_IDE_8xx_PCCARD
- Select how the IDE devices are connected to the MPC8xx system:
-
- 8xx_PCCARD uses the 8xx internal PCMCIA interface in combination
- with a PC Card (e.g. ARGOSY portable Hard Disk Adapter),
- ATA PC Card HDDs or ATA PC Flash Cards (example: TQM8xxL
- systems)
-
- 8xx_DIRECT is used for directly connected IDE devices using the 8xx
- internal PCMCIA interface (example: IVMS8 systems)
-
- EXT_DIRECT is used for IDE devices directly connected to the 8xx
- bus using some glue logic, but _not_ the 8xx internal
- PCMCIA interface (example: IDIF860 systems)
-
X ICS IDE interface support
X CONFIG_BLK_DEV_IDE_ICSIDE
X On Acorn systems, say Y here if you wish to use the ICS IDE
@@ -1212,12 +1379,12 @@
X XT hard disk support
X CONFIG_BLK_DEV_XD
X Very old 8 bit hard disk controllers used in the IBM XT computer
- will be supported if you say Y here.
+ will be supported if you say Y here.
X
X If you want to compile the driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
SHAR_EOF
true || echo 'restore of patch-2.4.15 failed'
fi
echo 'End of part 001'
echo 'File patch-2.4.15 is continued in part 002'
echo "002" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:38 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part002

#!/bin/sh -x
# this is part 002 of a 115 - part archive


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

# file patch-2.4.15 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 002; 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.4.15'
else
echo 'x - continuing with patch-2.4.15'


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

- say M here and read Documentation/modules.txt. The module will be

- called xd.o.

+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called xd.o.
X
X It's pretty unlikely that you have one of these: say N.
X
@@ -1225,23 +1392,23 @@
X CONFIG_BLK_DEV_PS2
X Say Y here if you have a PS/2 machine with a MCA bus and an ESDI
X hard disk.
-
+


X If you want to compile the driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called ps2esdi.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called ps2esdi.o.
X
X Mylex DAC960/DAC1100 PCI RAID Controller support
X CONFIG_BLK_DEV_DAC960
X This driver adds support for the Mylex DAC960, AcceleRAID, and
- eXtremeRAID PCI RAID controllers. See the file
- Documentation/README.DAC960 for further information about this
- driver.
+ eXtremeRAID PCI RAID controllers. See the file
+ <file:Documentation/README.DAC960> for further information about
+ this driver.


X
X If you want to compile the driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called DAC960.o.

+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called DAC960.o.
X
X Parallel port IDE device support
X CONFIG_PARIDE
@@ -1249,7 +1416,7 @@
X your computer's parallel port. Most of them are actually IDE devices
X using a parallel port IDE adapter. This option enables the PARIDE
X subsystem which contains drivers for many of these external drives.
- Read Documentation/paride.txt for more information.
+ Read <file:Documentation/paride.txt> for more information.
X
X If you have said Y to the "Parallel-port support" configuration
X option, you may share a single port between your printer and other
@@ -1270,13 +1437,13 @@
X
X Parallel port IDE disks
X CONFIG_PARIDE_PD
- This option enables the high-level driver for IDE-type disk devices
- connected through a parallel port. If you chose to build PARIDE
- support into your kernel, you may answer Y here to build in the
- parallel port IDE driver, otherwise you should answer M to build
- it as a loadable module. The module will be called pd.o. You
- must also have at least one parallel port protocol driver in your
- system. Among the devices supported by this driver are the SyQuest
+ This option enables the high-level driver for IDE-type disk devices
+ connected through a parallel port. If you chose to build PARIDE
+ support into your kernel, you may answer Y here to build in the
+ parallel port IDE driver, otherwise you should answer M to build
+ it as a loadable module. The module will be called pd.o. You
+ must also have at least one parallel port protocol driver in your
+ system. Among the devices supported by this driver are the SyQuest
X EZ-135, EZ-230 and SparQ drives, the Avatar Shark and the backpack
X hard drives from MicroSolutions.
X
@@ -1291,8 +1458,8 @@
X system. Among the devices supported by this driver are the
X MicroSolutions backpack CD-ROM drives and the Freecom Power CD. If
X you have such a CD-ROM drive, you should also say Y or M to "ISO
- 9660 CDROM file system support" below, because that's the file
- system used on CDROMs.
+ 9660 CD-ROM file system support" below, because that's the file
+ system used on CD-ROMs.
X
X Parallel port ATAPI disks
X CONFIG_PARIDE_PF
@@ -1322,7 +1489,7 @@
X This option enables a special high-level driver for generic ATAPI
X devices connected through a parallel port. The driver allows user
X programs, such as cdrecord, to send ATAPI commands directly to a
- device.
+ device.
X
X If you chose to build PARIDE support into your kernel, you may
X answer Y here to build in the parallel port generic ATAPI driver,
@@ -1333,10 +1500,10 @@
X your system.
X
X This driver implements an API loosely related to the generic SCSI
- driver. See include/linux/pg.h for details.
+ driver. See <file:include/linux/pg.h>. for details.
X
X You can obtain the most recent version of cdrecord from
- ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ . Versions 1.6.1a3 and
+ <ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/>. Versions 1.6.1a3 and
X later fully support this driver.
X
X ATEN EH-100 protocol
@@ -1352,39 +1519,40 @@
X
X Micro Solutions BACKPACK Series 5 protocol
X CONFIG_PARIDE_BPCK
- This option enables support for the Micro Solutions BACKPACK parallel
- port Series 5 IDE protocol. (Most BACKPACK drives made before 1999 were
- Series 5) Series 5 drives will NOT always have the Series noted on the
- bottom of the drive. Series 6 drivers will.
+ This option enables support for the Micro Solutions BACKPACK
+ parallel port Series 5 IDE protocol. (Most BACKPACK drives made
+ before 1999 were Series 5) Series 5 drives will NOT always have the
+ Series noted on the bottom of the drive. Series 6 drivers will.
X
X In other words, if your BACKPACK drive dosen't say "Series 6" on the
X bottom, enable this option.
X
- If you chose to build PARIDE support into your kernel, you may answer Y
- here to build in the protocol driver, otherwise you should answer M to
- build it as a loadable module. The module will be called bpck.o. You
- must also have a high-level driver for the type of device that you want
- to support.
+ If you chose to build PARIDE support into your kernel, you may
+ answer Y here to build in the protocol driver, otherwise you should
+ answer M to build it as a loadable module. The module will be
+ called bpck.o. You must also have a high-level driver for the type
+ of device that you want to support.
X
X Micro Solutions BACKPACK Series 6 protocol
X CONFIG_PARIDE_BPCK6
- This option enables support for the Micro Solutions BACKPACK parallel
- port Series 6 IDE protocol. (Most BACKPACK drives made after 1999 were
- Series 6) Series 6 drives will have the Series noted on the bottom of
- the drive. Series 5 drivers don't always have it noted.
+ This option enables support for the Micro Solutions BACKPACK
+ parallel port Series 6 IDE protocol. (Most BACKPACK drives made
+ after 1999 were Series 6) Series 6 drives will have the Series noted
+ on the bottom of the drive. Series 5 drivers don't always have it
+ noted.
X
- In other words, if your BACKPACK drive says "Series 6" on the bottom,
- enable this option.
+ In other words, if your BACKPACK drive says "Series 6" on the
+ bottom, enable this option.
X
- If you chose to build PARIDE support into your kernel, you may answer Y
- here to build in the protocol driver, otherwise you should answer M to
- build it as a loadable module. The module will be called bpck6.o. You
- must also have a high-level driver for the type of device that you want
- to support.
+ If you chose to build PARIDE support into your kernel, you may
+ answer Y here to build in the protocol driver, otherwise you should
+ answer M to build it as a loadable module. The module will be
+ called bpck6.o. You must also have a high-level driver for the type
+ of device that you want to support.
X
X DataStor Commuter protocol
X CONFIG_PARIDE_COMM
- This option enables support for the Commuter parallel port IDE
+ This option enables support for the Commuter parallel port IDE
X protocol from DataStor. If you chose to build PARIDE support
X into your kernel, you may answer Y here to build in the protocol
X driver, otherwise you should answer M to build it as a loadable
@@ -1393,7 +1561,7 @@
X
X DataStor EP-2000 protocol
X CONFIG_PARIDE_DSTR
- This option enables support for the EP-2000 parallel port IDE
+ This option enables support for the EP-2000 parallel port IDE
X protocol from DataStor. If you chose to build PARIDE support
X into your kernel, you may answer Y here to build in the protocol
X driver, otherwise you should answer M to build it as a loadable
@@ -1412,7 +1580,7 @@
X have a high-level driver for the type of device that you want to
X support.
X
-Shuttle EPAT c7/c8 extension
+Shuttle EPAT c7/c8 extension
X CONFIG_PARIDE_EPATC8
X This option enables support for the newer Shuttle EP1284 (aka c7 and
X c8) chip. You need this if you are using any recent Imation SuperDisk
@@ -1453,12 +1621,12 @@
X Freecom IQ ASIC-2 protocol
X CONFIG_PARIDE_FRIQ
X This option enables support for version 2 of the Freecom IQ parallel
- port IDE adapter. This adapter is used by the Maxell Superdisk
+ port IDE adapter. This adapter is used by the Maxell Superdisk
X drive. If you chose to build PARIDE support into your kernel, you
X may answer Y here to build in the protocol driver, otherwise you
X should answer M to build it as a loadable module. The module will be
X called friq.o. You must also have a high-level driver for the type
- of device that you want to support.
+ of device that you want to support.
X
X FreeCom power protocol
X CONFIG_PARIDE_FRPW
@@ -1493,12 +1661,12 @@
X
X OnSpec 90c20 protocol
X CONFIG_PARIDE_ON20
- This option enables support for the (obsolete) 90c20 parallel port
+ This option enables support for the (obsolete) 90c20 parallel port
X IDE protocol from OnSpec (often marketed under the ValuStore brand
- name). If you chose to build PARIDE support into your kernel, you
- may answer Y here to build in the protocol driver, otherwise you
- should answer M to build it as a loadable module. The module will
- be called on20.o. You must also have a high-level driver for the
+ name). If you chose to build PARIDE support into your kernel, you
+ may answer Y here to build in the protocol driver, otherwise you
+ should answer M to build it as a loadable module. The module will
+ be called on20.o. You must also have a high-level driver for the
X type of device that you want to support.
X
X OnSpec 90c26 protocol
@@ -1522,13 +1690,19 @@
X to new capacity needs. Logical volumes are accessed as block
X devices named /dev/VolumeGroupName/LogicalVolumeName.
X
- For details see Documentation/LVM-HOWTO. You will need supporting
- user space software; location is in Documentation/Changes.
+ For details see <file:Documentation/LVM-HOWTO>. You will need
+ supporting user space software; location is in
+ <file:Documentation/Changes>.
X
X If you want to compile this support as a module ( = code which can
X be inserted in and removed from the running kernel whenever you
- want), say M here and read Documentation/modules.txt. The module
- will be called lvm-mod.o.
+ want), say M here and read <file:Documentation/modules.txt>. The
+ module will be called lvm-mod.o.
+
+Multiple devices driver support (RAID and LVM)
+CONFIG_MD
+ Support multiple physical spindles through a single logical device.
+ Required for RAID and logical volume management (LVM).
X
X Multiple devices driver support
X CONFIG_BLK_DEV_MD
@@ -1543,7 +1717,7 @@
X
X More information about Software RAID on Linux is contained in the
X Software-RAID mini-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . There you will also
+ <http://www.linuxdoc.org/docs.html#howto>. There you will also
X learn where to get the supporting user space utilities raidtools.


X
X If unsure, say N.

@@ -1552,12 +1726,12 @@
X CONFIG_MD_LINEAR
X If you say Y here, then your multiple devices driver will be able to
X use the so-called linear mode, i.e. it will combine the hard disk
- partitions by simply appending one to the other.
+ partitions by simply appending one to the other.


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt. The module will be

- called linear.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called linear.o.


X
X If unsure, say Y.
X

@@ -1567,40 +1741,40 @@
X use the so-called raid0 mode, i.e. it will combine the hard disk
X partitions into one logical device in such a fashion as to fill them
X up evenly, one chunk here and one chunk there. This will increase
- the throughput rate if the partitions reside on distinct disks.
+ the throughput rate if the partitions reside on distinct disks.
X
X Information about Software RAID on Linux is contained in the
X Software-RAID mini-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . There you will also
+ <http://www.linuxdoc.org/docs.html#howto>. There you will also
X learn where to get the supporting user space utilities raidtools.


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt. The module will be

- called raid0.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called raid0.o.


X
X If unsure, say Y.
X

X RAID-1 (mirroring) mode
X CONFIG_MD_RAID1
X A RAID-1 set consists of several disk drives which are exact copies
- of each other. In the event of a mirror failure, the RAID driver
+ of each other. In the event of a mirror failure, the RAID driver
X will continue to use the operational mirrors in the set, providing
X an error free MD (multiple device) to the higher levels of the
- kernel. In a set with N drives, the available space is the capacity
+ kernel. In a set with N drives, the available space is the capacity
X of a single drive, and the set protects against a failure of (N - 1)
- drives.
+ drives.
X
X Information about Software RAID on Linux is contained in the
X Software-RAID mini-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . There you will also
+ <http://www.linuxdoc.org/docs.html#howto>. There you will also
X learn where to get the supporting user space utilities raidtools.
X
X If you want to use such a RAID-1 set, say Y. This code is also
X available as a module called raid1.o ( = code which can be inserted
- in and removed from the running kernel whenever you want). If you
+ in and removed from the running kernel whenever you want). If you
X want to compile it as a module, say M here and read
- Documentation/modules.txt.
+ <file:Documentation/modules.txt>.


X
X If unsure, say Y.
X

@@ -1616,41 +1790,92 @@
X
X Information about Software RAID on Linux is contained in the
X Software-RAID mini-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . There you will also
+ <http://www.linuxdoc.org/docs.html#howto>. There you will also
X learn where to get the supporting user space utilities raidtools.
X
X If you want to use such a RAID-4/RAID-5 set, say Y. This code is
X also available as a module called raid5.o ( = code which can be


X inserted in and removed from the running kernel whenever you want).

X If you want to compile it as a module, say M here and read
- Documentation/modules.txt.
+ <file:Documentation/modules.txt>.


X
X If unsure, say Y.
X

+Multipath I/O support
+CONFIG_MD_MULTIPATH
+ Multipath-IO is the ability of certain devices to address the same
+ physical disk over multiple 'IO paths'. The code ensures that such
+ paths can be defined and handled at runtime, and ensures that a
+ transparent failover to the backup path(s) happens if a IO errors
+ arrives on the primary path.
+
+ If unsure, say N.
+
+# AC tree only
+Support for IDE Raid controllers
+CONFIG_BLK_DEV_ATARAID
+ Say Y or M if you have an IDE Raid controller and want linux
+ to use its softwareraid feature. You must also select an
+ appropriate for your board low-level driver below.
+
+ Note, that Linux does not use the Raid implemetation in BIOS, and
+ the main purpose for this feature is to retain compatibility and
+ data integrity with other OS-es, using the same disk array. Linux
+ has its own Raid drivers, which you should use if you need better
+ performance.
+
+# AC tree only
+Support Promise software RAID (Fasttrak(tm))
+CONFIG_BLK_DEV_ATARAID_PDC
+ Say Y or M if you have a Promise Fasttrak (tm) Raid controller
+ and want linux to use the softwareraid feature of this card.
+ This driver uses /dev/ataraid/dXpY (X and Y numbers) as device
+ names.
+
+ If you choose to compile this as a module, the module will be called
+ pdcraid.o.
+
+# AC tree only
+Highpoint 370 software RAID
+CONFIG_BLK_DEV_ATARAID_HPT
+ Say Y or M if you have a Highpoint HPT 370 Raid controller
+ and want linux to use the softwareraid feature of this card.
+ This driver uses /dev/ataraid/dXpY (X and Y numbers) as device
+ names.
+
+ If you choose to compile this as a module, the module will be called
+ hptraid.o.
+
X Support for Acer PICA 1 chipset
X CONFIG_ACER_PICA_61
X This is a machine with a R4400 133/150 MHz CPU. To compile a Linux
X kernel that runs on these, say Y here. For details about Linux on
X the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
- http://oss.sgi.com/mips .
+ <http://oss.sgi.com/mips>.
X
X Support for Algorithmics P4032 (EXPERIMENTAL)
X CONFIG_ALGOR_P4032
- This is an evaluation board of the British company Algorithmics. The
- board uses the R4300 and a R5230 CPUs. For more information about
- this board see http://www.algor.co.uk .
+ This is an evaluation board of the British company Algorithmics.
+ The board uses the R4300 and a R5230 CPUs. For more information
+ about this board see <http://www.algor.co.uk>.
X
X Support for BAGET MIPS series
X CONFIG_BAGET_MIPS
- This enables support for the Baget, a Russian embedded system. For
- more details about the Baget see the Linux/MIPS FAQ on
- http://oss.sgi.com/mips .
+ This enables support for the Baget, a Russian embedded system. For
+ more details about the Baget see the Linux/MIPS FAQ on
+ <http://oss.sgi.com/mips>.
+
+Baget AMD LANCE support
+CONFIG_BAGETLANCE
+ Say Y to enable kernel support for AMD Lance Ethernet cards on the
+ MIPS-32-based Baget embedded system. This chipset is better known
+ via the NE2100 cards.
X
X Support for DECstations
X CONFIG_DECSTATION
X This enables support for DEC's MIPS based workstations. For details
- see the Linux/MIPS FAQ on http://oss.sgi.com/mips and the
- DECstation porting pages on http://decstation.unix-ag.org .
+ see the Linux/MIPS FAQ on <http://oss.sgi.com/mips> and the
+ DECstation porting pages on <http://decstation.unix-ag.org>.
X
X If you have one of the following DECstation Models you definitely
X want to choose R4xx0 for the CPU Type:
@@ -1662,6 +1887,25 @@
X
X otherwise choose R3000.
X
+Support for Cobalt Micro Server
+CONFIG_COBALT_MICRO_SERVER
+ Support for MIPS-based Cobalt boxes (they have been bought by Sun
+ and are now the "Server Appliance Business Unit") including the 2700
+ series -- versions 1 of the Qube and Raq. To compile a Linux kernel
+ for this hardware, say Y here.
+
+Support for Cobalt 2800
+CONFIG_COBALT_28
+ Support for the second generation of MIPS-based Cobalt boxes (they
+ have been bought by Sun and are now the "Server Appliance Business
+ Unit") including the 2800 series -- versions 2 of the Qube and Raq.
+ To compile a Linux kernel for this hardware, say Y here.
+
+Support for the Momentum Computer Ocelot SBC
+CONFIG_MOMENCO_OCELOT
+ The Ocelot is a MIPS-based Single Board Computer (SBC) made by
+ Momentum Computer <http://www.momenco.com>.
+
X Support for NEC DDB Vrc-5074
X CONFIG_DDB5074
X This enables support for the VR5000-based NEC DDB Vrc-5074
@@ -1673,10 +1917,18 @@
X evaluation board.
X
X Features : kernel debugging, serial terminal, NFS root fs, on-board
- ether port (with a patch to tulip driver), IDE controller, PS2 keyboard
- PS2 mouse, etc.
+ ether port (Need an additional patch at <http://linux.junsun.net>),
+ USB, AC97, PCI, PCI VGA card & framebuffer console, IDE controller,
+ PS2 keyboard, PS2 mouse, etc.
+
+Support for NEC DDB Vrc-5477
+CONFIG_DDB5477
+ This enables support for the R5432-based NEC DDB Vrc-5477
+ evaluation board.
X
- TODO : USB, Compact-PCI interface.
+ Features : kernel debugging, serial terminal, NFS root fs, on-board
+ ether port (Need an additional patch at <http://linux.junsun.net>),
+ USB, AC97, PCI, etc.
X
X Support for MIPS Atlas board
X CONFIG_MIPS_ATLAS
@@ -1688,19 +1940,39 @@
X This enables support for the VR5000-based MIPS Malta evaluation
X board.
X
+Support for Galileo Evaluation board or CoSine Orion
+CONFIG_ORION
+ Say Y if configuring for the Galileo evaluation board
+ or CoSine Orion. More information is available at
+ <http://tochna.technion.ac.il/project/linux/html/linux.html>.
+
+ Otherwise, say N.
+
X Support for Mips Magnum 4000
X CONFIG_MIPS_MAGNUM_4000
X This is a machine with a R4000 100 MHz CPU. To compile a Linux
X kernel that runs on these, say Y here. For details about Linux on
X the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
- http://oss.sgi.com/mips.
+ <http://oss.sgi.com/mips>.
+
+Enable Qtronix 990P Keyboard Support
+CONFIG_QTRONIX_KEYBOARD
+ Images of Qtronix keyboards are at
+ <http://www.qtronix.com/keyboard.html>.
X
X Support for Olivetti M700
X CONFIG_OLIVETTI_M700
X This is a machine with a R4000 100 MHz CPU. To compile a Linux
X kernel that runs on these, say Y here. For details about Linux on
X the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
- http://oss.sgi.com/mips.
+ <http://oss.sgi.com/mips>.
+
+Support for SNI RM200 PCI
+CONFIG_SNI_RM200_PCI
+ The SNI RM200 PCI was a MIPS-based platform manufactured by Siemens
+ Nixdorf Informationssysteme (SNI), parent company of Pyramid
+ Technology and now in turn merged with Fujitsu. Say Y here to
+ support this machine type.
X
X Support for SGI IP22
X CONFIG_SGI_IP22
@@ -1709,6 +1981,7 @@
X that runs on these, say Y here.
X
X Support for SGI IP27
+CONFIG_SGI_IP27
X This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics
X workstations. To compile a Linux kernel that runs on these, say Y
X here.
@@ -1731,11 +2004,49 @@
X 4000, Acer PICA, Olivetti M700-10 and a few other identical OEM
X systems.
X
+MIPS GT96100 support
+CONFIG_MIPS_GT96100
+ Say Y here to support the Galileo Technology GT96100 communications
+ controller card. There is a web page at <http://www.galileot.com/>.
+
+MIPS GT96100 Ethernet support
+CONFIG_MIPS_GT96100ETH
+ Say Y here to support the Ethernet subsystem on your GT96100 card.
+
+Zalon SCSI support
+CONFIG_SCSI_ZALON
+ The Zalon is an interface chip that sits between the PA-RISC
+ processor and the NCR 53c720 SCSI controller on K-series PA-RISC
+ boards (these are used, among other places, on some HP 780
+ workstations). Say Y here to make sure it gets initialized
+ correctly before the Linux kernel tries to talk to the controller.
+
X Kernel floating-point instruction emulation
X CONFIG_MIPS_FPU_EMULATOR
- This option enables the MIPS software floatingpoint support. Due to the
- way floatingpoint works you should always enable this option unless
- you exactly know what you're doing.
+ This option enables the MIPS software floatingpoint support. Due to
+ the way floating point works you should always enable this option
+ unless you exactly know what you're doing.
+
+SGI PROM Console Support
+CONFIG_SGI_PROM_CONSOLE
+ Say Y here to set up the boot console on serial port 0.
+
+DZ11 Serial Support
+CONFIG_DZ
+ DZ11-family serial controllers for VAXstations, including the
+ DC7085, M7814, and M7819.
+
+
+TURBOchannel support
+CONFIG_TC
+ TurboChannel is a DEC (now Compaq) bus for Alpha and MIPS processors.
+ Documentation on writing device drivers for TurboChannel is available at:
+ <http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PS3HD-TET1_html/TITLE.html>.
+
+Z85C30 Serial Support
+CONFIG_ZS
+ Documentation on the Zilog 85C350 serial communications controller
+ is downloadable at <http://www.zilog.com/pdfs/serial/z85c30.pdf>.
X
X PCMCIA SCSI adapter support
X CONFIG_SCSI_PCMCIA
@@ -1744,9 +2055,30 @@
X size devices often used with laptops.
X
X Note that the answer to this question won't directly affect the
- kernel: saying N will just cause this configure script to skip all
+ kernel: saying N will just cause the configurator to skip all
X the questions PCMCIA SCSI host adapters.
X
+Adaptec APA1480 CardBus support
+CONFIG_PCMCIA_APA1480
+ Say Y here if you intend to attach this type of CardBus SCSI host
+ adapter to your computer.
+
+ This driver is also available as a module called apa1480_cb.o ( =
+ 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 <file:Documentation/modules.txt>.
+
+NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support
+CONFIG_PCMCIA_NINJA_SCSI
+ If you intend to attach this type of PCMCIA SCSI host adapter to
+ your computer, say Y here and read
+ <file:Documentation/README.nsp_cs>.
+
+ This driver is also available as a module called nsp_cs.o ( =
+ 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 <file:Documentation/modules.txt>.
+
X Adaptec AHA152X PCMCIA support
X CONFIG_PCMCIA_AHA152X
X Say Y here if you intend to attach this type of PCMCIA SCSI host
@@ -1755,7 +2087,7 @@
X This driver is also available as a module called aha152x_cs.o ( =
X code which can be inserted in and removed from the running kernel
X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X
X Qlogic PCMCIA support
X CONFIG_PCMCIA_QLOGIC
@@ -1764,8 +2096,8 @@
X
X This driver is also available as a module called qlogic_cs.o ( =
X 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.
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
X
X Future Domain PCMCIA support
X CONFIG_PCMCIA_FDOMAIN
@@ -1774,27 +2106,96 @@
X
X This driver is also available as a module called fdomain_cs.o ( =
X 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.
-
-Adaptec APA1480 CardBus support
-CONFIG_PCMCIA_APA1480
- Say Y here if you intend to attach this type of CardBus SCSI host
- adapter to your computer.
-
- This driver is also available as a module called apa1480_cb.o ( =
- 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.
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
X
+# Choice: mipstype
X CPU type
X CONFIG_CPU_R3000
X Please make sure to pick the right CPU type. Linux/MIPS is not
X designed to be generic, i.e. Kernels compiled for R3000 CPUs will
- *not* work on R4000 Machines and vice versa.
- However, since most the supported Machines have an R4000 (or
- similar) CPU, R4xx0 might be a safe bet.
- If the resulting Kernel does not work try to recompile with R3000.
+ *not* work on R4000 machines and vice versa. However, since most
+ of the supported machines have an R4000 (or similar) CPU, R4x00
+ might be a safe bet. If the resulting kernel does not work,
+ try to recompile with R3000.
+
+ R3000 MIPS Technologies R3000-series processors,
+ including the 3041, 3051, and 3081.
+
+ R6000 MIPS Technologies R6000-series processors,
+ including the 64474, 64475, 64574 and 64575.
+
+ R4300 MIPS Technologies R4300-series processors.
+
+ R4x00 MIPS Technologies R4000-series processors other than 4300,
+ including the 4640, 4650, and 4700.
+
+ R5000 MIPS Technologies R5000-series processors other than the
+ Nevada.
+
+ R52xx MIPS Technologies R52xx-series ("Nevada") processors.
+
+ R10000 MIPS Technologies R10000-series processors.
+
+R6000
+CONFIG_CPU_R6000
+ MIPS Technologies R6000-series processors, including the 64474,
+ 64475, 64574 and 64575.
+
+R4300
+CONFIG_CPU_R4300
+ MIPS Technologies R4300-series processors.
+
+R4x00
+CONFIG_CPU_R4X00
+ MIPS Technologies R4000-series processors other than 4300, including
+ the 4640, 4650, and 4700.
+
+R5000
+CONFIG_CPU_R5000
+ MIPS Technologies R5000-series processors other than the Nevada.
+
+R52x0
+CONFIG_CPU_NEVADA
+ MIPS Technologies R52x0-series ("Nevada") processors.
+
+R8000
+CONFIG_CPU_R8000
+ MIPS Technologies R8000-series processors.
+
+R10000
+CONFIG_CPU_R10000
+ MIPS Technologies R10000-series processors.
+
+Discontiguous Memory Support
+CONFIG_DISCONTIGMEM
+ Say Y to upport efficient handling of discontiguous physical memory,
+ for architectures which are either NUMA (Non-Uniform Memory Access)
+ or have huge holes in the physical address space for other reasons.
+ See <file:Documentation/vm/numa> for more.
+
+Mapped kernel support
+CONFIG_MAPPED_KERNEL
+ Change the way a Linux kernel is loaded unto memory on a MIPS64
+ machine. This is required in order to support text replication and
+ NUMA. If you need to undersatand it, read the source code.
+
+Kernel text replication support
+CONFIG_REPLICATE_KTEXT
+ Say Y here to enable replicating the kernel text across multiple
+ nodes in a NUMA cluster. This trades memory for speed.
+
+Exception handler replication support
+CONFIG_REPLICATE_EXHANDLERS
+ Say Y here to enable replicating the kernel exception handlers
+ across multiple nodes in a NUMA cluster. This trades memory for
+ speed.
+
+NUMA support?
+CONFIG_NUMA
+ Say Y to compile the kernel to support NUMA (Non-Uniform Memory
+ Access). This option is for configuring high-end multiprocessor
+ server machines. If in doubt, say N.
X
X CPU type
X CONFIG_CPU_VR41XX
@@ -1805,14 +2206,18 @@
X
X CPU feature configuration
X CONFIG_CPU_ADVANCED
- Saying yes here allows you to select support for various features your
- CPU may or may not have. Most people should say N here.
+ Saying yes here allows you to select support for various features
+ your CPU may or may not have. Most people should say N here.
X
-ll and sc instructions
+ll/sc Instructions available
X CONFIG_CPU_HAS_LLSC
- Say Y here if your CPU has the ll and sc instructions. Say Y here for
- better performance, N if you don't know. You must say Y here for
- multiprocessor machines.
+ MIPS R4000 series and later provide the Load Linked (ll)
+ and Store Conditional (sc) instructions. More information is
+ available at <http://www.go-ecs.com/mips/miptek1.htm>.
+
+ Say Y here if your CPU has the ll and sc instructions. Say Y here
+ for better performance, N if you don't know. You must say Y here
+ for multiprocessor machines.
X
X lld and scd instructions
X CONFIG_CPU_HAS_LLDSCD
@@ -1820,7 +2225,7 @@
X equivalents of ll and sc. Say Y here for better performance, N if
X you don't know. You must say Y here for multiprocessor machines.
X
-Support for writebuffer flushing
+Writeback Buffer available
X CONFIG_CPU_HAS_WB
X Say N here for slightly better performance. You must say Y here for
X machines which require flushing of write buffers in software. Saying
@@ -1840,6 +2245,12 @@
X byte order. These modes require different kernels. Say Y if your
X machine is little endian, N if it's a big endian machine.
X
+Use power LED as a heartbeat
+CONFIG_HEARTBEAT
+ Use the power-on LED on your machine as a load meter. The exact
+ behavior is platform-dependent, but normally the flash frequency is
+ a hyperbolic function of the 5-minute load average.
+
X Networking support
X CONFIG_NET
X Unless you really know what you are doing, you should say Y here.
@@ -1849,27 +2260,28 @@
X should consider updating your networking tools too because changes
X in the kernel and the tools often go hand in hand. The tools are
X contained in the package net-tools, the location and version number
- of which are given in Documentation/Changes.
+ of which are given in <file:Documentation/Changes>.
X
X For a general introduction to Linux networking, it is highly
X recommended to read the NET-3-HOWTO, available from

X Socket filtering
X CONFIG_FILTER
X The Linux Socket Filter is derived from the Berkeley Packet Filter.
X If you say Y here, user-space programs can attach a filter to any
X socket and thereby tell the kernel that it should allow or disallow
- certain types of data to get through the socket. Linux Socket
- Filtering works on all socket types except TCP for now. See the text
- file Documentation/networking/filter.txt for more information.
+ certain types of data to get through the socket. Linux Socket
+ Filtering works on all socket types except TCP for now. See the
+ text file <file:Documentation/networking/filter.txt> for more
+ information.
X
X You need to say Y here if you want to use PPP packet filtering
X (see the CONFIG_PPP_FILTER option below).


X
X If unsure, say N.
X

-Network packet filtering
+Network packet filtering (replaces ipchains)
X CONFIG_NETFILTER
X Netfilter is a framework for filtering and mangling network packets
X that pass through your Linux box.
@@ -1912,21 +2324,21 @@
X Various modules exist for netfilter which replace the previous
X masquerading (ipmasqadm), packet filtering (ipchains), transparent
X proxying, and portforwarding mechanisms. Please see
- Documentation/Changes under "iptables" for the location of these
- packages.
-
+ <file:Documentation/Changes> under "iptables" for the location of
+ these packages.
+
X Make sure to say N to "Fast switching" below if you intend to say Y
X here, as Fast switching currently bypasses netfilter.
-
+
X Chances are that you should say Y here if you compile a kernel which
X will run as a router and N for regular hosts. If unsure, say N.
-
+
X Network packet filtering debugging
X CONFIG_NETFILTER_DEBUG
X You can say Y here if you want to get additional messages useful in
- debugging the netfilter code.
+ debugging the netfilter code.
X
-IP: connection tracking (required for masq/NAT)
+Connection tracking (required for masq/NAT)
X CONFIG_IP_NF_CONNTRACK
X Connection tracking keeps a record of what packets have passed
X through your machine, in order to figure out how they are related
@@ -1938,7 +2350,7 @@
X below).
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X IRC Send/Chat support
X CONFIG_IP_NF_IRC
@@ -1961,17 +2373,17 @@
X of Network Address Translation on them.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `Y'.
+ <file:Documentation/modules.txt>. If unsure, say `Y'.
X
-IP: user space queueing via NETLINK (EXPERIMENTAL)
+User space queueing via NETLINK
X CONFIG_IP_NF_QUEUE
X Netfilter has the ability to queue packets to user space: the
X netlink device can be used to access them using this driver.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
-IP: ip tables support (required for filtering/masq/NAT)
+IP tables support (required for filtering/masq/NAT)
X CONFIG_IP_NF_IPTABLES
X iptables is a general, extensible packet identification framework.
X The packet filtering and full NAT (masquerading, port forwarding,
@@ -1979,41 +2391,7 @@
X either of those.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
-CONFIG_IP6_NF_MATCH_LIMIT
- limit matching allows you to control the rate at which a rule can be
- matched: mainly useful in combination with the LOG target ("LOG
- target support", below) and to avoid some Denial of Service attacks.
-
- If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
-
-MAC address match support
-CONFIG_IP6_NF_MATCH_MAC
- mac matching allows you to match packets based on the source
- ethernet address of the packet.
-
- If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
-
-Multiple port match support
-CONFIG_IP6_NF_MATCH_MULTIPORT
- Multiport matching allows you to match TCP or UDP packets based on
- a series of source or destination ports: normally a rule can only
- match a single range of ports.
-
- If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
-
-Owner match support (EXPERIMENTAL)
-CONFIG_IP6_NF_MATCH_OWNER
- Packet owner matching allows you to match locally-generated packets
- based on who created them: the user, group, process or session.
-
- If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
-
-
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X limit match support
X CONFIG_IP_NF_MATCH_LIMIT
@@ -2022,24 +2400,24 @@
X target support", below) and to avoid some Denial of Service attacks.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X MAC address match support
X CONFIG_IP_NF_MATCH_MAC
- mac matching allows you to match packets based on the source
- ethernet address of the packet.
+ MAC matching allows you to match packets based on the source
+ Ethernet address of the packet.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
-netfilter mark match support
+Netfilter MARK match support
X CONFIG_IP_NF_MATCH_MARK
X Netfilter mark matching allows you to match packets based on the
X `nfmark' value in the packet. This can be set by the MARK target
X (see below).
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X Multiple port match support
X CONFIG_IP_NF_MATCH_MULTIPORT
@@ -2048,7 +2426,7 @@
X match a single range of ports.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X TTL match support
X CONFIG_IP_NF_MATCH_TTL
@@ -2064,7 +2442,7 @@
X specific value or range of values.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X TOS match support
X CONFIG_IP_NF_MATCH_TOS
@@ -2072,7 +2450,7 @@
X Service fields of the IP packet.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X Connection state match support
X CONFIG_IP_NF_MATCH_STATE
@@ -2081,23 +2459,23 @@
X is a powerful tool for packet classification.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
-Unclean match support (EXPERIMENTAL)
+Unclean match support
X CONFIG_IP_NF_MATCH_UNCLEAN
X Unclean packet matching matches any strange or invalid packets, by
X looking at a series of fields in the IP, TCP, UDP and ICMP headers.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
-Owner match support (EXPERIMENTAL)
+Owner match support
X CONFIG_IP_NF_MATCH_OWNER
X Packet owner matching allows you to match locally-generated packets
X based on who created them: the user, group, process or session.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X Packet filtering
X CONFIG_IP_NF_FILTER
@@ -2106,7 +2484,7 @@
X local output. See the man page for iptables(8).
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X REJECT target support
X CONFIG_IP_NF_TARGET_REJECT
@@ -2115,24 +2493,24 @@
X than silently being dropped.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
-MIRROR target support (EXPERIMENTAL)
+MIRROR target support
X CONFIG_IP_NF_TARGET_MIRROR
X The MIRROR target allows a filtering rule to specify that an
X incoming packet should be bounced back to the sender.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
-Full NAT
+Full NAT (Network Address Translation)
X CONFIG_IP_NF_NAT
X The Full NAT option allows masquerading, port forwarding and other
X forms of full Network Address Port Translation. It is controlled by
X the `nat' table in iptables: see the man page for iptables(8).
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X MASQUERADE target support
X CONFIG_IP_NF_TARGET_MASQUERADE
@@ -2143,21 +2521,21 @@
X address will be different on next dialup).
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X Basic SNMP-ALG support
X CONFIG_IP_NF_NAT_SNMP_BASIC
X
- This module implements an Application Layer Gateway (ALG) for
- SNMP payloads. In conjunction with NAT, it allows a network
- management system to access multiple private networks with
- conflicting addresses. It works by modifying IP addresses
+ This module implements an Application Layer Gateway (ALG) for
+ SNMP payloads. In conjunction with NAT, it allows a network
+ management system to access multiple private networks with
+ conflicting addresses. It works by modifying IP addresses
X inside SNMP payloads to match IP-layer NAT mapping.
-
+
X This is the "basic" form of SNMP-ALG, as described in RFC 2962
-
+
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X REDIRECT target support
X CONFIG_IP_NF_TARGET_REDIRECT
@@ -2167,7 +2545,7 @@
X useful for transparent proxies.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X Packet mangling
X CONFIG_IP_NF_MANGLE
@@ -2176,7 +2554,7 @@
X which can effect how the packet is routed.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X TOS target support
X CONFIG_IP_NF_TARGET_TOS
@@ -2185,19 +2563,19 @@
X packet prior to routing.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X MARK target support
X CONFIG_IP_NF_TARGET_MARK
X This option adds a `MARK' target, which allows you to create rules
X in the `mangle' table which alter the netfilter mark (nfmark) field
- associated with the packet packet prior to routing. This can change
- the routing method (see `IP: use netfilter MARK value as routing
+ associated with the packet prior to routing. This can change
+ the routing method (see `Use netfilter MARK value as routing
X key') and can also be used by other subsystems to change their
X behavior.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X TCPMSS target support
X CONFIG_IP_NF_TARGET_TCPMSS
@@ -2222,16 +2600,16 @@
X -j TCPMSS --clamp-mss-to-pmtu
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
-tcpmss match support
+TCPMSS match support
X CONFIG_IP_NF_MATCH_TCPMSS
X This option adds a `tcpmss' match, which allows you to examine the
X MSS value of TCP SYN packets, which control the maximum packet size
X for that connection.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X LOG target support
X CONFIG_IP_NF_TARGET_LOG
@@ -2239,7 +2617,7 @@
X any iptables table which records the packet header to the syslog.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X ipchains (2.2-style) support
X CONFIG_IP_NF_COMPAT_IPCHAINS
@@ -2250,7 +2628,7 @@
X the ipchains tool exactly as in 2.2 kernels.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X ipfwadm (2.0-style) support
X CONFIG_IP_NF_COMPAT_IPFWADM
@@ -2261,51 +2639,24 @@
X the ipfwadm tool exactly as in 2.0 kernels.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
-
-IP6 tables support (required for filtering/masq/NAT)
-CONFIG_IP6_NF_IPTABLES
- ip6tables is a general, extensible packet identification framework.
- Currently only the packet filtering and packet mangling subsystem
- for IPv6 use this, but connection tracking is going to follow.
- Say 'Y' or 'M' here if you want to use either of those.
-
- If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
-
-IPv6 limit match support
-CONFIG_IP6_NF_MATCH_LIMIT
- limit matching allows you to control the rate at which a rule can be
- matched: mainly useful in combination with the LOG target ("LOG
- target support", below) and to avoid some Denial of Service attacks.
-
- If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X MAC address match support
X CONFIG_IP6_NF_MATCH_MAC
X mac matching allows you to match packets based on the source
- ethernet address of the packet.
+ Ethernet address of the packet.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
-netfilter mark match support
+Netfilter MARK match support
X CONFIG_IP6_NF_MATCH_MARK
X Netfilter mark matching allows you to match packets based on the
X `nfmark' value in the packet. This can be set by the MARK target
X (see below).
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
-
-LOG target support
-CONFIG_IP6_NF_TARGET_LOG
- This option adds a `LOG' target, which allows you to create rules in
- any ip6tables table which records the packet header to the syslog.
-
- If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X Packet filtering
X CONFIG_IP6_NF_FILTER
@@ -2314,7 +2665,7 @@
X local output. See the man page for iptables(8).
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X Packet mangling
X CONFIG_IP6_NF_MANGLE
@@ -2323,38 +2674,38 @@
X which can effect how the packet is routed.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X MARK target support
X CONFIG_IP6_NF_TARGET_MARK
X This option adds a `MARK' target, which allows you to create rules
X in the `mangle' table which alter the netfilter mark (nfmark) field
X associated with the packet packet prior to routing. This can change
- the routing method (see `IP: use netfilter MARK value as routing
+ the routing method (see `Use netfilter MARK value as routing
X key') and can also be used by other subsystems to change their
X behavior.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X TCP Explicit Congestion Notification support
X CONFIG_INET_ECN
X Explicit Congestion Notification (ECN) allows routers to notify
X clients about network congestion, resulting in fewer dropped packets
- and increased network performance. This option adds ECN support to the
- Linux kernel, as well as a sysctl (/proc/sys/net/ipv4/tcp_ecn) which
- allows ECN support to be disabled at runtime.
+ and increased network performance. This option adds ECN support to
+ the Linux kernel, as well as a sysctl (/proc/sys/net/ipv4/tcp_ecn)
+ which allows ECN support to be disabled at runtime.
X
X Note that, on the Internet, there are many broken firewalls which
X refuse connections from ECN-enabled machines, and it may be a while
- before these firewalls are fixed. Until then, to access a site behind
- such a firewall (some of which are major sites, at the time of this
- writing) you will have to disable this option, either by saying N now
- or by using the sysctl.
+ before these firewalls are fixed. Until then, to access a site
+ behind such a firewall (some of which are major sites, at the time
+ of this writing) you will have to disable this option, either by
+ saying N now or by using the sysctl.


X
X If in doubt, say N.
X

-IP6 tables support (required for filtering/masq/NAT)
+IPv6 tables support (required for filtering/masq/NAT)
X CONFIG_IP6_NF_IPTABLES
X ip6tables is a general, extensible packet identification framework.
X Currently only the packet filtering and packet mangling subsystem
@@ -2362,7 +2713,7 @@
X Say 'Y' or 'M' here if you want to use either of those.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X IPv6 limit match support
X CONFIG_IP6_NF_MATCH_LIMIT
@@ -2371,54 +2722,7 @@
X target support", below) and to avoid some Denial of Service attacks.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
-
-MAC address match support
-CONFIG_IP6_NF_MATCH_MAC
- mac matching allows you to match packets based on the source
- ethernet address of the packet.
-
- If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
-
-netfilter mark match support
-CONFIG_IP6_NF_MATCH_MARK
- Netfilter mark matching allows you to match packets based on the
- `nfmark' value in the packet. This can be set by the MARK target
- (see below).
-
- If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
-
-Packet filtering
-CONFIG_IP6_NF_FILTER
- Packet filtering defines a table `filter', which has a series of
- rules for simple packet filtering at local input, forwarding and
- local output. See the man page for iptables(8).
-
- If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
-
-Packet mangling
-CONFIG_IP6_NF_MANGLE
- This option adds a `mangle' table to iptables: see the man page for
- iptables(8). This table is used for various packet alterations
- which can effect how the packet is routed.
-
- If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
-
-MARK target support
-CONFIG_IP6_NF_TARGET_MARK
- This option adds a `MARK' target, which allows you to create rules
- in the `mangle' table which alter the netfilter mark (nfmark) field
- associated with the packet packet prior to routing. This can change
- the routing method (see `IP: use netfilter MARK value as routing
- key') and can also be used by other subsystems to change their
- behavior.
-
- If you want to compile it as a module, say M here and read
- Documentation/modules.txt. If unsure, say `N'.
+ <file:Documentation/modules.txt>. If unsure, say `N'.
X
X SYN flood protection
X CONFIG_SYN_COOKIES
@@ -2434,8 +2738,7 @@
X continue to connect, even when your machine is under attack. There
X is no need for the legitimate users to change their TCP/IP software;
X SYN cookies work transparently to them. For technical information
- about SYN cookies, check out
- ftp://koobera.math.uic.edu/syncookies.html .
+ about SYN cookies, check out <http://cr.yp.to/syncookies.html>.
X
X If you are SYN flooded, the source address reported by the kernel is
X likely to have been forged by the attacker; it is only reported as
@@ -2450,12 +2753,21 @@
X you can enable them by saying Y to "/proc file system support" and
X "Sysctl support" below and executing the command
X
- echo 1 >/proc/sys/net/ipv4/tcp_syncookies
+ echo 1 >/proc/sys/net/ipv4/tcp_syncookies
X
X at boot time after the /proc file system has been mounted.
-
- If unsure, say Y.
X
+ If unsure, say N.
+
+HCI EMU (virtual device) driver
+CONFIG_BLUEZ_HCIEMU
+ Bluetooth Virtual HCI device driver.
+ This driver is required if you want to use HCI Emulation software.
+
+ Say Y here to compile support for Virtual HCI devices into the
+ kernel or say M to compile it as module (hci_usb.o).
+
+# Choice: alphatype
X Alpha system type
X CONFIG_ALPHA_GENERIC
X This is the system type of your hardware. A "generic" kernel will
@@ -2464,7 +2776,7 @@
X
X To find out what type of Alpha system you have, you may want to
X check out the Linux/Alpha FAQ, accessible on the WWW from
- http://www.alphalinux.org . In summary:
+ <http://www.alphalinux.org>. In summary:
X
X Alcor/Alpha-XLT AS 600
X Alpha-XL XL-233, XL-266
@@ -2476,7 +2788,7 @@
X EB64+ EB64+ 21064 evaluation board
X EB66 EB66 21066 evaluation board
X EB66+ EB66+ 21066 evaluation board
- Jensen DECpc 150, DEC 2000 model 300,
+ Jensen DECpc 150, DEC 2000 model 300,
X DEC 2000 model 500
X LX164 AlphaPC164-LX
X Miata Personal Workstation 433a, 433au, 500a,
@@ -2496,21 +2808,160 @@
X
X If you don't know what to do, choose "generic".
X
-EV5 CPU daughtercard
+# Most of the information on these variants is from
+# <http://www.alphalinux.org/docs/alpha-howto.html>
+Alcor/Alpha-XLT
+CONFIG_ALPHA_ALCOR
+ For systems using the Digital ALCOR chipset: 5 chips (4, 64-bit data
+ slices (Data Switch, DSW) - 208-pin PQFP and 1 control (Control, I/O
+ Address, CIA) - a 383 pin plastic PGA). It provides a DRAM
+ controller (256-bit memory bus) and a PCI interface. It also does
+ all the work required to support an external Bcache and to maintain
+ memory coherence when a PCI device DMAs into (or out of) memory.
+
+Alpha-XL
+CONFIG_ALPHA_XL
+ XL-233 and XL-266-based Alpha systems.
+
+AlphaBook1
+CONFIG_ALPHA_BOOK1
+ Dec AlphaBook1/Burns Alpha-based laptops.
+
+Avanti
+CONFIG_ALPHA_AVANTI
+ Avanti AS 200, AS 205, AS 250, AS 255, AS 300, and AS 400-based
+ Alphas. Info at
+ <http://www.unix-ag.org/Linux-Alpha/Architectures/Avanti.html>.
+
+Cabriolet
+CONFIG_ALPHA_CABRIOLET
+ Cabriolet AlphaPC64, AlphaPCI64 systems. Derived from EB64+ but now
+ baby-AT with Flash boot ROM, no on-board SCSI or Ethernet. 3 ISA
+ slots, 4 PCI slots (one pair are on a shared slot), uses plug-in
+ Bcache SIMMs. Requires power supply with 3.3V output.
+
+DP264
+CONFIG_ALPHA_DP264
+ Various 21264 systems with the tsunami core logic chipset.
+ API Networks: 264DP, UP2000(+), CS20;
+ Compaq: DS10(E,L), XP900, XP1000, DS20(E), ES40.
+
+EB164
+CONFIG_ALPHA_EB164
+ EB164 21164 evaluation board from DEC. Uses 21164 and ALCOR. Has
+ ISA and PCI expansion (3 ISA slots, 2 64-bit PCI slots (one is
+ shared with an ISA slot) and 2 32-bit PCI slots. Uses plus-in
+ Bcache SIMMs. I/O sub-system provides SuperI/O (2S, 1P, FD), KBD,
+ MOUSE (PS2 style), RTC/NVRAM. Boot ROM is Flash. PC-AT-sized
+ motherboard. Requires power supply with 3.3V output.
+
+EB64+
+CONFIG_ALPHA_EB64P
+ Uses 21064 or 21064A and APECs. Has ISA and PCI expansion (3 ISA,
+ 2 PCI, one pair are on a shared slot). Supports 36-bit DRAM SIMs.
+ ISA bus generated by Intel SaturnI/O PCI-ISA bridge. On-board SCSI
+ (NCR 810 on PCI) Ethernet (Digital 21040), KBD, MOUSE (PS2 style),


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

echo 'End of part 002'
echo 'File patch-2.4.15 is continued in part 003'
echo "003" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:53 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part017

#!/bin/sh -x
# this is part 017 of a 115 - part archive


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

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

- The default behavior is to show both the upper and lower bound in
+ The default behavior is to show both the upper and lower bound in
X /proc/cpuinfo. If the range is large, the temperature is either changing
- a lot, or the TAU hardware is broken (likely on some G4's). If the range
- is small (around 4 degrees), the temperature is relatively stable.
-
-Support for CUDA based PowerMacs
-CONFIG_ADB_CUDA
- This provides support for CUDA based Power Macintosh systems. This
- includes most OldWorld PowerMacs, the first generation iMacs, the
- Blue&White G3 and the Yikes G4 (PCI Graphics). All later models
- should use CONFIG_ADB_PMU instead.
-
- If unsure say Y.
-
-Support for PMU based PowerMacs
-CONFIG_ADB_PMU
- This provides support for PMU based Power Macintosh systems. This
- includes all PowerBooks and all AGP-based machines.
-
- If unsure say Y.
+ a lot, or the TAU hardware is broken (likely on some G4's). If the range
+ is small (around 4 degrees), the temperature is relatively stable.
X
X Power management support for PowerBooks
X CONFIG_PMAC_PBOOK
@@ -17710,7 +20667,7 @@
X must get the power management daemon, pmud, to make it work and you
X must have the /dev/pmu device (see the pmud README).
X
- Get pmud from ftp://linuxcare.com.au/pub/ppclinux/pmud/
+ Get pmud from <ftp://ftp.samba.org/pub/ppclinux/pmud/>.
X
X If you have a PowerBook, you should say Y.
X
@@ -17718,33 +20675,218 @@
X have it autoloaded. The act of removing the module shuts down the
X sound hardware for more power savings.
X
+Backlight control for LCD screens
+CONFIG_PMAC_BACKLIGHT
+ Say Y here to build in code to manage the LCD backlight on a
+ Macintosh PowerBook. With this code, the backlight will be turned
+ on and off appropriately on power-management and lid-open/lid-closed
+ events; also, the PowerBook button device will be enabled so you can
+ change the screen brightness.
+
+# Choice: ppc8xxtype
+RPX-Lite
+CONFIG_RPXLITE
+ Single-board computers based around the PowerPC MPC8xx chips and
+ intended for embedded applications. The following types are
+ supported:
+
+ RPX-Lite -- PC104 form-factor SBC based on the MPC823
+ RPX-Classic -- Credit-card-size SBC based on the MPC 860
+ BSE-IP -- Bright Star Engineering BSE-IP SBC
+ TQM823L -- TQM823L SBC from TQ Components
+ TQM850L -- TQM850L SBC from TQ Components
+ TQM855L -- TQM855L SBC from TQ Components
+ TQM860L -- TQM860L SBC from TQ Components
+ FPS850L -- FingerPrint Sensor from TQ Components
+ TQM860 -- TQM860 SBC from IKENDI AG
+ SPD823TS -- Speech Design TeleServer from Speech Design
+ IVMS8 -- Integrated VoiceMail SBC from Speech Design
+ SM850 -- Service Module 850 from Dependable Computer Systems
+ MBX -- MBX821 and MBX860 SBCs
+ Wincept -- Wincept SBCs for thin-client machines
+
+RPX-Classic
+CONFIG_RPXCLASSIC
+ The RPX-Classic is a single-board computer based on the Motorola
+ MPC860. It features 16MB of DRAM and a variable amount of flash,
+ I2C EEPROM, thermal monitoring, a PCMCIA slot, a DIP switch and two
+ LEDs. Variants with Ethernet ports exist. Say Y here to support it
+ directly.
+
+BSE-IP
+CONFIG_BSEIP
+ Say Y here to support the Bright Star Engineering ipEngine SBC.
+ This is a credit-card-sized device featuring a MPC823 processor,
+ 26MB DRAM, 4MB flash, Ethernet, a 16K-gate FPGA, USB, an LCD/video
+ controller, and two RS232 ports.
+
+TQM823L
+CONFIG_TQM823L
+ Say Y here to support the TQM823L, one of an MPC8xx-based family of
+ mini SBCs (half credit-card size) from TQ Components first released
+ in late 1999. Technical references are at
+ <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
+ <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
+ <http://www.denx.de/embedded-ppc-en.html>.
+
+TQM850L
+CONFIG_TQM850L
+ Say Y here to support the TQM850L, one of an MPC8xx-based family of
+ mini SBCs (half credit-card size) from TQ Components first released
+ in late 1999. Technical references are at
+ <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
+ <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
+ <http://www.denx.de/embedded-ppc-en.html>.
+
+TQM855L
+CONFIG_TQM855L
+ Say Y here to support the TQM855L, one of an MPC8xx-based family of
+ mini SBCs (half credit-card size) from TQ Components first released
+ in late 1999. Technical references are at
+ <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
+ <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
+ <http://www.denx.de/embedded-ppc-en.html>.
+
+TQM860L
+CONFIG_TQM860L
+ Say Y here to support the TQM860L, one of an MPC8xx-based family of
+ mini SBCs (half credit-card size) from TQ Components first released
+ in late 1999. Technical references are at
+ <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
+ <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
+ <http://www.denx.de/embedded-ppc-en.html>.
+
+FPS850
+CONFIG_FPS850
+ Say Y here to support the FingerPrint Sensor from AKENDI IG, based
+ on the TQ Components TQM850L module, released November 1999 and
+ discontinued a year later.
+
+TQM860
+CONFIG_TQM860
+ Say Y here to support the TQM860, one of an MPC8xx-based family of
+ SBCs (credit-card size) from TQ Components first released in
+ mid-1999 and discontinued mid-2000.
+
+SM850
+CONFIG_SM850
+ Say Y here to support the Service Module 850 from Dependable
+ Computer Systems, an SBC based on the TQM850L module by TQ
+ Components. This board is no longer in production. The
+ manufacturer's website is at <http://www.decomsys.com/>.
+
+SPD823TS
+CONFIG_SPD823TS
+ Say Y here to support the Speech Design 823 Tele-Server from Speech
+ Design, released in 2000. The manufacturer's website is at
+ <http://www.speech-design.de/>.
+
+IVMS8
+CONFIG_IVMS8
+ Say Y here to support the Integrated Voice-Mail Small 8-channel SBC
+ from Speech Design, released March 2001. The manufacturer's website
+ is at <http://www.speech-design.de/>.
+
+# IVML24 is not yet active
+IVML24
+CONFIG_IVML24
+ Say Y here to support the Integrated Voice-Mail Large 24-channel SBC
+ from Speech Design, released March 2001. The manufacturer's website
+ is at <http://www.speech-design.de/>.
+
+MBX
+CONFIG_MBX
+ MBX is a line of Motorola single-board computer based around the
+ MPC821 and MPC860 processors, and intended for embedded-controller
+ applications. Say Y here to support these boards directly.
+
+WinCept
+CONFIG_WINCEPT
+ The Wincept 100/110 is a Motorola single-board computer based on the
+ MPC821 PowerPC, introduced in 1998 and designed to be used in
+ thin-client machines. Say Y to support it directly.
+
+# More systems that will be supported soon, according to
+# Wolfgang Denk <w...@denx.de>:
+#
+# TQM8260:
+# MPC8260 based module
+#
+# Manufacturer: TQ Components, www.tq-group.de
+# Date of Release: June 2001
+# End of Life: not yet :-)
+# URL: <http://www.denx.de/PDF/TQM82xx_SPEC_Rev003.pdf>
+#
+# IP860:
+# VMEBus IP (Industry Pack) carrier board with MPC860
+#
+# Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
+# Date of Release: ?
+# End of life: -
+# URL: <http://www.microsys.de/html/ip860.html>
+#
+# CU824:
+# VMEBus Board with PCI extension with MPC8240 CPU
+#
+# Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
+# Date of Release: early 2001 (?)
+# End of life: -
+# URL: <http://www.microsys.de/html/cu824.html
+#
+# PM826:
+# Modular system with MPC8260 CPU
+#
+# Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
+# Date of Release: mid 2001
+# End of life: -
+# URL: <http://www.microsys.de/html/pm826.html>
+#
+# PCU_E:
+# PCU = Peripheral Controller Unit; E = extended (?)
+#
+# Mfr: Siemens AG, ICN (Information and Communication Networks)
+# <http://www.siemens.de/page/1,3771,224315-1-999_2_226207-0,00.html>
+# Date of Release: April 2001
+# End of life: -
+# URL: n. a.o
+
+Support for EST8260
+CONFIG_EST8260
+ The EST8260 is a single-board computer manufactured by Wind River
+ Systems, Inc. (formerly Embedded Support Tools Corp.) and based on
+ the MPC8260. Wind River Systems has a website at
+ <http://www.windriver.com/>, but the EST8260 cannot be found on it
+ and has probably been discontinued or rebadged.
+
X ADB raw keycode support
X CONFIG_MAC_ADBKEYCODES
X This provides support for sending raw ADB keycodes to console
X devices. This is the default up to 2.4.0, but in future this may be
- phased out in favor of generic Linux keycodes. If you say Y here, you
- can dynamically switch via the
+ phased out in favor of generic Linux keycodes. If you say Y here,
+ you can dynamically switch via the
X /proc/sys/dev/mac_hid/keyboard_sends_linux_keycodes
- sysctl and with the "keyboard_sends_linux_keycodes=" kernel argument.
-
+ sysctl and with the "keyboard_sends_linux_keycodes=" kernel
+ argument.
+
X If unsure, say Y here.
X
X Mouse button 2+3 emulation support
X CONFIG_MAC_EMUMOUSEBTN
X This provides generic support for emulating the 2nd and 3rd mouse
- button with keypresses. If you say Y here, the emulation is still
- disabled by default. The emulation is controlled by these sysctl entries:
+ button with keypresses. If you say Y here, the emulation is still
+ disabled by default. The emulation is controlled by these sysctl
+ entries:
X /proc/sys/dev/mac_hid/mouse_button_emulation
X /proc/sys/dev/mac_hid/mouse_button2_keycode
X /proc/sys/dev/mac_hid/mouse_button3_keycode
X
-Enhanced Real Time Clock Support
+Enhanced Real Time Clock Support (/dev/rtc)
X CONFIG_PPC_RTC
X If you say Y here and create a character special file /dev/rtc with
X major number 10 and minor number 135 using mknod ("man mknod"), you
- will get access to the real time clock (or hardware clock) built
+ will get access to the real time clock (or hardware clock) built
X into your computer.
-
+
X If unsure, say Y here.
X
X Support for Open Firmware device tree in /proc
@@ -17753,27 +20895,27 @@
X an image of the device tree that the kernel copies from Open
X Firmware. If unsure, say Y here.
X
-RTAS proc interface
+RTAS (RunTime Abstraction Services) in /proc
X CONFIG_PPC_RTAS
X When you use this option, you will be able to use RTAS from
- userspace.
-
+ userspace.
+
X RTAS stands for RunTime Abstraction Services and should
X provide a portable way to access and set system information. This is
- commonly used on RS/6000 (pSeries) computers.
-
- You can access RTAS via the special proc filesystem entry rtas.
+ commonly used on RS/6000 (pSeries) computers.
+
+ You can access RTAS via the special proc file system entry rtas.
X Don't confuse this rtas entry with the one in /proc/device-tree/rtas
X which is readonly.
-
+
X If you don't know if you can use RTAS look into
X /proc/device-tree/rtas. If there are some entries, it is very likely
X that you will be able to use RTAS.
X
X You can do cool things with rtas. To print out information about
- various sensors in the system, just do a
+ various sensors in the system, just do a
X
- $ cat /proc/rtas/sensors
+ $ cat /proc/rtas/sensors
X
X or if you power off your machine at night but want it running when
X you enter your office at 7:45 am, do a
@@ -17782,7 +20924,7 @@
X
X and shutdown.
X
- If unsure, say Y
+ If unsure, say Y.
X
X MESH (Power Mac internal SCSI) support
X CONFIG_SCSI_MESH
@@ -17792,9 +20934,9 @@
X adaptor. This driver is also available as a module called mesh.o
X ( = code which can be inserted in and removed from the running
X kernel whenever you want). If you want to compile it as a module,


- say M here and read Documentation/modules.txt.

+ say M here and read <file:Documentation/modules.txt>.

X
-Maximum synchronous transfer rate
+Maximum synchronous transfer rate (MB/s) (0 = async)
X CONFIG_SCSI_MESH_SYNC_RATE
X On Power Macintoshes (and clones) where the MESH SCSI bus adaptor
X drives a bus which is entirely internal to the machine (such as the
@@ -17810,12 +20952,12 @@
X On Power Macintoshes (and clones) with two SCSI buses, the external
X SCSI bus is usually controlled by a 53C94 SCSI bus adaptor. Older
X machines which only have one SCSI bus, such as the 7200, also use
- the 53C94. Say Y to include support for the 53C94.
+ the 53C94. Say Y to include support for the 53C94.
X
X This driver is also available as a module called mac53c94.o ( = code
X which can be inserted in and removed from the running kernel


X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

X MACE (Power Mac Ethernet) support
X CONFIG_MACE
@@ -17826,7 +20968,7 @@
X This driver is also available as a module called mace.o ( = code
X which can be inserted in and removed from the running kernel


X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

X Use AAUI port instead of TP by default
X CONFIG_MACE_AAUI_PORT
@@ -17835,53 +20977,52 @@
X instead of an 8-pin RJ45 connector for twisted-pair ethernet. Say
X Y here if you have such a machine. If unsure, say N.
X The driver will default to AAUI on ANS anyway, and if you use it as
- a module, you can provide the port_aaui=0|1 to force the driver
- setting.
+ a module, you can provide the port_aaui=0|1 to force the driver.
X
-BMAC (G3 ethernet) support
+BMAC (G3 Ethernet) support
X CONFIG_BMAC
X Say Y for support of BMAC Ethernet interfaces. These are used on G3
- computers.
+ computers.
X
X This driver is also available as a module called bmac.o ( = code
X which can be inserted in and removed from the running kernel


X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

-GMAC (G4/iBook ethernet) support
+GMAC (G4/iBook Ethernet) support
X CONFIG_GMAC
X Say Y for support of GMAC Ethernet interfaces. These are used on G4
- and iBook computers.
+ and iBook computers.
X
X This driver is also available as a module called gmac.o ( = code
X which can be inserted in and removed from the running kernel


X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

-National DP83902AV (Oak ethernet) support
+National DP83902AV (Oak Ethernet) support
X CONFIG_OAKNET
X Say Y if your machine has this type of Ethernet network card.
X
X This driver is also available as a module called oaknet.o ( = code
X which can be inserted in and removed from the running kernel


X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

X Video For Linux
X CONFIG_VIDEO_DEV
X Support for audio/video capture and overlay devices and FM radio
X cards. The exact capabilities of each device vary. User tools for
X this are available from
- ftp://ftp.uk.linux.org/pub/linux/video4linux .
+ <ftp://ftp.uk.linux.org/pub/linux/video4linux>.
X
X If you are interested in writing a driver for such an audio/video
X device or user software interacting with such a driver, please read
- the file Documentation/video4linux/API.html.
+ the file <file:Documentation/video4linux/API.html>.
X
X This driver is also available as a module called videodev.o ( = code
X which can be inserted in and removed from the running kernel


X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

X Video For Linux /proc file system information
X CONFIG_VIDEO_PROC_FS
@@ -17897,122 +21038,121 @@
X in the port address below.
X
X Note that newer AIMSlab RadioTrack cards have a different chipset
- and are not supported by this driver. For these cards, use the
+ and are not supported by this driver. For these cards, use the
X RadioTrack II driver below.
X
X If you have a GemTeks combined (PnP) sound- and radio card you must
- use this driver as a module and setup the card with isapnptools. You
- must also pass the module a suitable io parameter, 0x248 has been
- reported to be used by these cards.
+ use this driver as a module and setup the card with isapnptools.
+ You must also pass the module a suitable io parameter, 0x248 has
+ been reported to be used by these cards.
X
X In order to control your radio card, you will need to use programs
- that are compatible with the Video for Linux API. Information on
+ that are compatible with the Video For Linux API. Information on
X this API and pointers to "v4l" programs may be found on the WWW at
- http://roadrunner.swansea.uk.linux.org/v4l.shtml . More information
- is contained in the file Documentation/video4linux/radiotrack.txt.
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>. More
+ information is contained in the file
+ <file:Documentation/video4linux/radiotrack.txt>.
X
X If you want to compile this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called radio-aimslab.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called radio-aimslab.o.
X
-RadioTrack i/o port
+RadioTrack I/O port
X CONFIG_RADIO_RTRACK_PORT
- Enter either 0x30f or 0x20f here. The card default is 0x30f, if you
+ Enter either 0x30f or 0x20f here. The card default is 0x30f, if you
X haven't changed the jumper setting on the card.
X
X AIMSlab RadioTrack II support
X CONFIG_RADIO_RTRACK2
- Choose Y here if you have this FM radio card, and then fill in the
+ Choose Y here if you have this FM radio card, and then fill in the
X port address below.
X
X In order to control your radio card, you will need to use programs
- that are compatible with the Video for Linux API. Information on
+ that are compatible with the Video For Linux API. Information on
X this API and pointers to "v4l" programs may be found on the WWW at
- http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
X
X If you want to compile this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called radio-rtrack2.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called radio-rtrack2.o.
X
-RadioTrack II i/o port
+RadioTrack II I/O port
X CONFIG_RADIO_RTRACK2_PORT
- Enter either 0x30c or 0x20c here. The card default is 0x30c, if you
+ Enter either 0x30c or 0x20c here. The card default is 0x30c, if you
X haven't changed the jumper setting on the card.
X
X Aztech/Packard Bell Radio
X CONFIG_RADIO_AZTECH
X Choose Y here if you have one of these FM radio cards, and then fill
X in the port address below.
-
+
X In order to control your radio card, you will need to use programs
- that are compatible with the Video for Linux API. Information on
+ that are compatible with the Video For Linux API. Information on
X this API and pointers to "v4l" programs may be found on the WWW at
- http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
X
X If you want to compile this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called radio-aztech.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called radio-aztech.o.
X
-Aztech/Packard Bell radio card i/o port
+Aztech/Packard Bell radio card I/O port
X CONFIG_RADIO_AZTECH_PORT
- Enter either 0x350 or 0x358 here. The card default is 0x350, if you
- haven't changed the setting of jumper JP3 on the card. Removing the
+ Enter either 0x350 or 0x358 here. The card default is 0x350, if you
+ haven't changed the setting of jumper JP3 on the card. Removing the
X jumper sets the card to 0x358.
X
X ADS Cadet AM/FM Radio Tuner Card
X CONFIG_RADIO_CADET
X Choose Y here if you have one of these AM/FM radio cards, and then
X fill in the port address below.
-
+
X In order to control your radio card, you will need to use programs
- that are compatible with the Video for Linux API. Information on
+ that are compatible with the Video For Linux API. Information on
X this API and pointers to "v4l" programs may be found on the WWW at
- http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
X
X Further documentation on this driver can be found on the WWW at
- http://linux.blackhawke.net/cadet.html .
+ <http://linux.blackhawke.net/cadet.html>.
X
X If you want to compile this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called radio-cadet.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called radio-cadet.o.
X
X SF16FMI Radio
X CONFIG_RADIO_SF16FMI
- Choose Y here if you have one of these FM radio cards, and then fill
- in the port address below.
+ Choose Y here if you have one of these FM radio cards. If you
+ compile the driver into the kernel and your card is not PnP one, you
+ have to add "sf16fm=<io>" to the kernel command line (I/O address is
+ 0x284 or 0x384).
X
X In order to control your radio card, you will need to use programs
- that are compatible with the Video for Linux API. Information on
+ that are compatible with the Video For Linux API. Information on
X this API and pointers to "v4l" programs may be found on the WWW at
- http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
X
X If you want to compile this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called radio-sf16fmi.o
-
-SF16FMI I/O port (0x284 or 0x384)
-CONFIG_RADIO_SF16FMI_PORT
- Enter the I/O port of your SF16FMI radio card.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called radio-sf16fmi.o.
X
-Typhoon Radio
+Typhoon Radio (a.k.a. EcoRadio)
X CONFIG_RADIO_TYPHOON
X Choose Y here if you have one of these FM radio cards, and then fill
X in the port address and the frequency used for muting below.
X
X In order to control your radio card, you will need to use programs
- that are compatible with the Video for Linux API. Information on
+ that are compatible with the Video For Linux API. Information on
X this API and pointers to "v4l" programs may be found on the WWW at
- http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
X
X If you want to compile this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called radio-typhoon.o


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called radio-typhoon.o.
X
X Support for /proc/radio-typhoon
X CONFIG_RADIO_TYPHOON_PROC_FS
@@ -18041,88 +21181,132 @@
X in the port address below.
X
X In order to control your radio card, you will need to use programs
- that are compatible with the Video for Linux API. Information on
+ that are compatible with the Video For Linux API. Information on
X this API and pointers to "v4l" programs may be found on the WWW at
- http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
X
X If you want to compile this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called radio-zoltrix.o


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called radio-zoltrix.o.
X
X ZOLTRIX I/O port (0x20c or 0x30c)
X CONFIG_RADIO_ZOLTRIX_PORT
X Enter the I/O port of your Zoltrix radio card.
X
-IIC on parallel port
+I2C on parallel port
X CONFIG_I2C_PARPORT
X I2C is a simple serial bus system used in many micro controller
- applications. Saying Y here will allow you to use your parallel port
- as an I2C interface.
+ applications. Saying Y here will allow you to use your parallel
+ port as an I2C interface.
X
X If you want to compile this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called i2c-parport.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called i2c-parport.o.
X
X miroSOUND PCM20 radio
X CONFIG_RADIO_MIROPCM20
- Choose Y here if you have this sound card. You also need to say Y
+ Choose Y here if you have this FM radio card. You also need to say Y
X to "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio)" (in "Sound")
X for this to work.
X
X In order to control your radio card, you will need to use programs
- that are compatible with the Video for Linux API. Information on
+ that are compatible with the Video For Linux API. Information on
X this API and pointers to "v4l" programs may be found on the WWW at
- http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
X
X If you want to compile this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called miropcm20.o


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called miropcm20.o.
X
X miroSOUND PCM20 radio RDS user interface (EXPERIMENTAL)
X CONFIG_RADIO_MIROPCM20_RDS
- Choose Y here if you want to see RDS/RBDS information like RadioText,
- Programme Service name, Clock Time and date, Programme TYpe and
- Traffic Announcement/Programme identification. You also need to say
- Y to "miroSOUND PCM20 radio" and devfs!
+ Choose Y here if you want to see RDS/RBDS information like
+ RadioText, Programme Service name, Clock Time and date, Programme
+ TYpe and Traffic Announcement/Programme identification. You also
+ need to say Y to "miroSOUND PCM20 radio" and devfs!
X
X It's not possible to read the raw RDS packets from the device, so
- the driver cant provide an V4L interface for this. But the
- availability of RDS is reported over V4L by the basic driver already.
- Here RDS can be read from files in /dev/v4l/rds.
+ the driver cant provide an V4L interface for this. But the
+ availability of RDS is reported over V4L by the basic driver
+ already. Here RDS can be read from files in /dev/v4l/rds.
X
X As module the driver will be called miropcm20-rds.o.
X
-GemTek Radio Card
+Maestro on board radio
+CONFIG_RADIO_MAESTRO
+ Say Y here to directly support the on-board radio tuner on the
+ Maestro 2 or 2E sound card.
+
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux API. Information on
+ this API and pointers to "v4l" programs may be found on the WWW at
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called radio-maestro.o.
+
+Guillemot MAXI Radio FM 2000 Radio Card
+CONFIG_RADIO_MAXIRADIO
+ Choose Y here if you have this radio card. This card may also be
+ found as Gemtek PCI FM.
+
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux API. Information on
+ this API and pointers to "v4l" programs may be found on the WWW at
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called radio-maxiradio.o.
+
+GemTek Radio Card support
X CONFIG_RADIO_GEMTEK
- Choose Y here if you have this FM radio card, and then fill in the
+ Choose Y here if you have this FM radio card, and then fill in the
X port address below.
X
X In order to control your radio card, you will need to use programs
- that are compatible with the Video for Linux API. Information on
+ that are compatible with the Video For Linux API. Information on
X this API and pointers to "v4l" programs may be found on the WWW at
- http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
X
X If you want to compile this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called radio-gemtek.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called radio-gemtek.o.
X
-GemTek i/o port
+GemTek I/O port
X CONFIG_RADIO_GEMTEK_PORT
X Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is
X 0x34c, if you haven't changed the jumper setting on the card. On
- Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the i/o
+ Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O
X port is 0x28c.
X
+Gemtek PCI Radio
+CONFIG_RADIO_GEMTEK_PCI
+ Choose Y here if you have this PCI FM radio card.
+
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video for Linux API. Information on
+ this API and pointers to "v4l" programs may be found on the WWW at
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called radio-gemtek-pci.o.
+
X PlanB Video-In for PowerMacs
X CONFIG_VIDEO_PLANB
X PlanB is the V4L driver for the PowerMac 7x00/8x00 series video
X input hardware. If you want to experiment with this, say Y.
X Otherwise, or if you don't understand a word, say N.
- See http://www.cpu.lu/~mlan/planb.html for more info.
+ See <http://www.cpu.lu/~mlan/planb.html> for more info.
X
X Saying M will compile this driver as a module (planb.o).
X
@@ -18131,34 +21315,27 @@
X Choose Y here if you have this FM radio card, and then fill in the
X port address below. (TODO)
X
- Note: This driver is in its early stages. Right now volume and
+ Note: This driver is in its early stages. Right now volume and
X frequency control and muting works at least for me, but
- unfortunately i have not found anybody who wants to use this card
- with Linux. So if it is this what YOU are trying to do right now,
- PLEASE DROP ME A NOTE!! Rolf Offermanns (ro...@offermanns.de)
-
+ unfortunately I have not found anybody who wants to use this card
+ with Linux. So if it is this what YOU are trying to do right now,
+ PLEASE DROP ME A NOTE!! Rolf Offermanns (ro...@offermanns.de)
+
X In order to control your radio card, you will need to use programs
- that are compatible with the Video for Linux API. Information on
+ that are compatible with the Video For Linux API. Information on
X this API and pointers to "v4l" programs may be found on the WWW at
- http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
X
X If you want to compile this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called radio-terratec.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called radio-terratec.o.
X
-Terratec i/o port (normally 0x590)
+Terratec I/O port (normally 0x590)
X CONFIG_RADIO_TERRATEC_PORT
- Fill in the i/o port of your TerraTec FM radio card. If unsure, go
+ Fill in the I/O port of your TerraTec FM radio card. If unsure, go
X with the default.
X
-### Add these
-# Zoran ZR36057/36060 support
-# CONFIG_VIDEO_ZORAN
-
-# Include support for Iomega Buz
-# CONFIG_VIDEO_BUZ
-
X Trust FM radio card
X CONFIG_RADIO_TRUST
X This is a driver for the Trust FM radio cards. Say Y if you have
@@ -18167,38 +21344,76 @@
X This driver is also available as a module called radio-trust.o ( =


X code which can be inserted in and removed from the running kernel
X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

-Trust i/o port (usually 0x350 or 0x358)
+Trust I/O port (usually 0x350 or 0x358)
X CONFIG_RADIO_TRUST_PORT
- Enter the i/o port of your Trust FM radio card. If unsure, try the
+ Enter the I/O port of your Trust FM radio card. If unsure, try the
X values "0x350" or "0x358".
X
X BT848 Video For Linux
X CONFIG_VIDEO_BT848
X Support for BT848 based frame grabber/overlay boards. This includes
X the Miro, Hauppauge and STB boards. Please read the material in
- Documentation/video4linux/bttv for more information.
+ <file:Documentation/video4linux/bttv> for more information.
X
X If you say Y or M here, you need to say Y or M to "I2C support" and
X "I2C bit-banging interfaces" in the character device section.
-
+
X This driver is available as a module called bttv.o ( = code
X which can be inserted in and removed from the running kernel


X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.

+
+BT878 Audio DMA
+CONFIG_SOUND_BT878
+ Audio DMA support for bt878 based grabber boards. As you might have
+ already noticed, bt878 is listed with two functions in /proc/pci.
+ Function 0 does the video stuff (bt848 compatible), function 1 does
+ the same for audio data. This is a driver for the audio part of
+ the chip. If you say 'Y' here you get a oss-compatible dsp device
+ where you can record from. If you want just watch TV you probably
+ don't need this driver as most TV cards handle sound with a short
+ cable from the TV card to your sound card's line-in.
+
+ This driver is available as a module called btaudio.o ( = 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 <file:Documentation/modules.txt>.
+

+SGI Vino Video For Linux
+CONFIG_VIDEO_VINO
+ Say Y here to build in support for the Vino video input system found
+ on SGI Indy machines.
+
+Stradis 4:2:2 MPEG-2 video driver
+CONFIG_VIDEO_STRADIS
+ Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video
+ driver for PCI. There is a product page at
+ <http://www.stradis.com/decoder.html>.
+
+Zoran ZR36057/36060 Video For Linux
+CONFIG_VIDEO_ZORAN
+ Say Y here to include support for video cards based on the Zoran
+ ZR36057/36060 encoder/decoder chip (including the Iomega Buz and the
+ Miro DC10 and DC30 video capture cards).
+
+Include support for Iomega Buz
+CONFIG_VIDEO_BUZ
+ Say Y here to include support for the Iomega Buz video card. There
+ is a Buz/Linux homepage at <http://www.lysator.liu.se/~gz/buz/>.
X
-ZR36120/36125 Video for Linux
+Zoran ZR36120/36125 Video For Linux
X CONFIG_VIDEO_ZR36120
X Support for ZR36120/ZR36125 based frame grabber/overlay boards.
X This includes the Victor II, WaveWatcher, Video Wonder, Maxi-TV,
X and Buster boards. Please read the material in
- Documentation/video4linux/zr36120.txt for more information.
+ <file:Documentation/video4linux/zr36120.txt> for more information.
X
X This driver is also available as a module called zr36120.o ( = code
X which can be inserted in and removed from the running kernel


X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

X SAA5249 Teletext processor
X CONFIG_VIDEO_SAA5249
@@ -18208,26 +21423,37 @@
X This driver is also available as a module called saa5249.o ( = code
X which can be inserted in and removed from the running kernel


X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

-Quickcam BW Video For Linux
+QuickCam BW Video For Linux
X CONFIG_VIDEO_BWQCAM
X Say Y have if you the black and white version of the QuickCam
- camera. See the next option for the color version.
+ camera. See the next option for the color version.
X
X This driver is also available as a module called bw-qcam.o ( = code
X which can be inserted in and removed from the running kernel


X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

-Colour QuickCam Video For Linux
+QuickCam Colour Video For Linux
X CONFIG_VIDEO_CQCAM
X This is the video4linux driver for the colour version of the
- Connectix Quickcam. If you have one of these cameras, say Y here,
- otherwise say N. This driver does not work with the original
- monochrome Quickcam, Quickcam VC or QuickClip. It is also available
- as a module (c-qcam.o). Read Documentation/video4linux/CQcam.txt for
- more information.
+ Connectix QuickCam. If you have one of these cameras, say Y here,
+ otherwise say N. This driver does not work with the original
+ monochrome QuickCam, QuickCam VC or QuickClip. It is also available
+ as a module (c-qcam.o).
+ Read <file:Documentation/video4linux/CQcam.txt> for more information.
+
+Winbond W9966CF Webcam Video For Linux
+CONFIG_VIDEO_W9966
+ Video4linux driver for Winbond's w9966 based Webcams.
+ Currently tested with the LifeView FlyCam Supra.
+ If you have one of these cameras, say Y here
+ otherwise say N.
+ This driver is also available as a module (w9966.o).
+
+ Check out <file:Documentation/video4linux/w9966.txt> and
+ <file:Documentation/video4linux/w9966.c> for more information.
X
X CPiA Video For Linux
X CONFIG_VIDEO_CPIA
@@ -18236,10 +21462,10 @@
X Blaster Webcam II. If you have one of these cameras, say Y here
X and select parallel port and/or USB lowlevel support below,
X otherwise say N. This will not work with the Creative Webcam III.
-
- Please read Documentation/video4linux/README.cpia for more
+
+ Please read <file:Documentation/video4linux/README.cpia> for more
X information.
-
+
X This driver is also available as a module (cpia.o).
X
X CPiA Parallel Port Lowlevel Support
@@ -18260,11 +21486,13 @@
X
X Mediavision Pro Movie Studio Video For Linux
X CONFIG_VIDEO_PMS
- Say Y if you have such a thing. This driver is also available as a
+ Say Y if you have such a thing. This driver is also available as a
X module called pms.o ( = 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.
+ from the running kernel whenever you want). If you want to compile
+ it as a module, say M here and read


+ <file:Documentation/modules.txt>.
X

+Sony Vaio Picturebook Motion Eye Video for Linux
X CONFIG_VIDEO_MEYE
X This is the video4linux driver for the Motion Eye camera found
X in the Vaio Picturebook laptops. Please read the material in
@@ -18285,20 +21513,20 @@
X s390-compiler released by IBM (based on gcc-2.95.1) before.
X
X Merge some code into the kernel to make the image IPLable
-CONFIG_IPLABLE
+CONFIG_IPL
X If you want to use the produced kernel to IPL directly from a
X device, you have to merge a bootsector specific to the device
X into the first bytes of the kernel. You will have to select the
- IPL device on another question, that pops up, when you select
- CONFIG_IPLABE.
+ IPL device.
X
-IPL from a /390 tape unit
+# Choice: s390_ipl
+IPL from a S/390 tape unit
X CONFIG_IPL_TAPE
X Select this option if you want to IPL the image from a Tape.
X
X IPL from a virtual card reader emulated by VM/ESA
X CONFIG_IPL_RDR_VM
- Select this option if you are running under VM/ESA and want
+ Select this option if you are running under VM/ESA and want
X to IPL the image from the emulated card reader.
X
X IPL from a real card reader
@@ -18307,7 +21535,7 @@
X card reader. Maybe you still got one and want to try. We didn't
X test.
X
-IBMs S/390 Harddisks (DASDs)
+Support for DASD hard disks
X CONFIG_DASD
X Enable this option if you want to access DASDs directly utilizing
X S/390s channel subsystem commands. This is necessary for running
@@ -18340,6 +21568,163 @@
X CONFIG_DASD_FBA
X FBA devices are currently unsupported.
X
+Merge some code into the kernel to make the image IPLable
+CONFIG_IPLABLE
+ If you want to use the produced kernel to IPL directly from a
+ device, you have to merge a bootsector specific to the device
+ into the first bytes of the kernel. You will have to select the
+ IPL device on another question, that pops up, when you select
+ CONFIG_IPLABE.
+
+Support for 3215 line mode terminal
+CONFIG_3215
+ Include support for IBM 3215 line-mode terminals. Can't be used
+ if 3270 console support is chosen.
+
+Support for console on 3215 line mode terminal
+CONFIG_3215_CONSOLE
+ Include support for using an IBM 3215 line-mode terminal as the
+ Linux system console. Can't be used if 3270 console support is
+ chosen.
+
+Support for 3270 line mode terminal
+CONFIG_3270
+ Include support for IBM 3270 line-mode terminals.
+
+Support for console on 3270 line mode terminal
+CONFIG_3270_CONSOLE
+ Include support for using an IBM 3270 line-mode terminal as the
+ Linux system console. Excludes using 3215s. Available only if 3270
+ support is compiled in statically.
+
+Support for HWC line mode terminal
+CONFIG_HWC
+ Include support for IBM HWC line-mode terminals.
+
+Console on HWC line mode terminal
+CONFIG_HWC_CONSOLE
+ Include support for using an IBM HWC line-mode terminal as the Linux
+ system console.
+
+S/390 tape device support
+CONFIG_S390_TAPE
+ Select this option if you want to access channel-attached tape
+ devices on IBM S/390 or zSeries.
+ If you select this option you will also want to select at
+ least one of the tape interface options and one of the tape
+ hardware options in order to access a tape device.
+ This option is also available as a module. The module will be
+ called tape390.o and include all selected interfaces and
+ hardware drivers.
+
+Support for tape character devices
+CONFIG_S390_TAPE_CHAR
+ Select this option if you want to access your channel-attached
+ tape devices using the character device interface.
+ This interface is similar to other Linux tape devices like
+ SCSI-Tapes (st) and the floppy tape device (ftape).
+ If unsure, say "Y".
+
+Support for tape block devices
+CONFIG_S390_TAPE_BLOCK
+ Select this option if you want to access your channel-attached tape
+ devices using the block device interface. This interface is similar
+ to CD-ROM devices on other platforms. The tapes can only be
+ accessed read-only when using this interface. Have a look at
+ Documentation/s390/TAPE for further information about creating
+ volumes for and using this interface. It is safe to say "Y" here.
+
+Support for 3490 tape hardware
+CONFIG_S390_TAPE_3490
+ Select this option if you want to access IBM 3480 magnetic
+ tape subsystems and 100% compatibles.
+ It is safe to say "Y" here.
+
+Support for 3480 tape hardware
+CONFIG_S390_TAPE_3480
+ Select this option if you want to access IBM 3490 magnetic
+ tape subsystems and 100% compatibles.
+
+CTC device support
+CONFIG_CTC
+ Select this option if you want to use channel-to-channel networking
+ on IBM S/390 or zSeries. This device driver supports real CTC
+ coupling using ESCON. It also supports virtual CTCs when running
+ under VM. It will use the channel device configuration if this is
+ available. This option is also available as a module which will be
+ called ctc.o. If you do not know what it is, it's safe to say "Y".
+
+Support for DIAG access to CMS reserved Disks
+CONFIG_DASD_DIAG
+ Select this option if you want to use CMS reserved Disks under VM
+ with the Diagnose250 command. If you are not running under VM or
+ unsure what it is, say "N".
+
+XPRAM disk support
+CONFIG_BLK_DEV_XPRAM
+ Select this option if you want to use your expanded storage on S/390
+ or zSeries as a disk. This is useful as a _fast_ swap device if you
+ want to access more than 2G of memory when running in 31 bit mode.
+ This option is also available as a module which will be called
+ xpram.o. If unsure, say "N".
+
+Fast IRQ handling
+CONFIG_FAST_IRQ
+ Select this option in order to get the interrupts processed faster
+ on your S/390 or zSeries machine. If selected, after an interrupt
+ is processed, the channel subsystem will be asked for other pending
+ interrupts which will also be processed before leaving the interrupt
+ context. This speeds up the I/O a lot. Say "Y".
+
+IUCV device support (VM only)
+CONFIG_IUCV
+ Select this option if you want to use inter-user communication
+ vehicle networking under VM or VIF. This option is also available
+ as a module which will be called iucv.o. If unsure, say "Y".
+
+Kernel support for 31 bit ELF binaries
+CONFIG_S390_SUPPORT
+ Select this option if you want to enable your system kernel to
+ handle system-calls from ELF binaries for 31 bit ESA. This option
+ (and some other stuff like libraries and such) is needed for
+ executing 31 bit applications. It is safe to say "Y".
+
+Channel Device Configuration
+CONFIG_CHANDEV
+ The channel device layer is a layer to provide a consistent
+ interface for configuration & default machine check (devices
+ appearing & disappearing) handling on Linux for s/390 & z/Series
+ channel devices.
+
+ s/390 & z/Series channel devices include among others
+
+ lcs (the most common ethernet/token ring/fddi standard on
+ zSeries)
+ ctc/escon hi speed like serial link standard on zSeries
+ claw used to talk to cisco routers.
+ qeth gigabit ethernet.
+
+ These devices use two channels one read & one write for
+ configuration & communication (& a third channel, the data
+ channel the case of gigabit ethernet). The motivation
+ behind developing this layer was that there was a lot of
+ duplicate code among the channel device drivers for
+ configuration.
+
+ Also the lcs & ctc drivers tended to fight over
+ 3088/08's & 3088/1F's which could be either 2216/3172
+ channel attached lcs compatible devices or escon/ctc pipes
+ had to be configured separately as they couldn't autodetect,
+ this is now simplified by doing the configuration in a single
+ place (the channel device layer).
+
+ This layer isn't invasive & it is quite okay to use channel
+ drivers which don't use the channel device layer in
+ conjunction with drivers which do.
+
+ For more info see the chandev manpage usually distributed in
+ <file:Documentation/s390/chandev.8> in the Linux source tree.
+
X SAB3036 tuner support
X CONFIG_TUNER_3036
X Say Y here to include support for Philips SAB3036 compatible tuners.
@@ -18347,15 +21732,24 @@
X
X Compaq SMART2 support
X CONFIG_BLK_CPQ_DA
- This is the driver for Compaq Smart Array controllers.
- Everyone using these boards should say Y here.
- See the file Documentation/cpqarray.txt for the current list of
- boards supported by this driver, and for further information
- on the use of this driver.
+ This is the driver for Compaq Smart Array controllers. Everyone
+ using these boards should say Y here. See the file
+ <file:Documentation/cpqarray.txt> for the current list of boards
+ supported by this driver, and for further information on the use of
+ this driver.
+
+Show crashed user process info
+CONFIG_PROCESS_DEBUG
+ Say Y to print all process fault locations to the console. This is
+ a debugging option; you probably do not want to set it unless you
+ are an S390 port maintainer.
X
X #
X # ARM options
X #
+# CML2 transition note: CML1 asks ARCH_ARCA5K, then has ARCH_A5K and ARCH_ARK
+# as subquestions. CML2 asks the subquestions in the armtype menu and makes
+# ARCH_ARCA5K a derived symbol.
X ARM System type
X CONFIG_ARCH_ARCA5K
X This selects what ARM system you wish to build the kernel for. It
@@ -18363,110 +21757,224 @@
X to set this option to, please consult any information supplied with
X your system.
X
+# Choice: armtype
+A5000
+CONFIG_ARCH_A5K
+ Say Y here to to support the Acorn A5000. Linux can support the
+ internal IDE disk and CD-ROM interface, serial and parallel port,
+ and the floppy drive. Note that on some A5000s the floppy is
+ plugged into the wrong socket on the motherboard.
+
+Archimedes
+CONFIG_ARCH_ARC
+ The Acorn Archimedes was an personal computer based on an 8K ARM2
+ processor, released in 1987. It supported 512K of RAM and 2 800K
+ floppy disks. Picture and more detailed specifications at
+ <http://www.computingmuseum.com/museum/archi.htm>.
+
+EBSA-110
+CONFIG_ARCH_EBSA110
+ This is an evaluation board for the StrongARM processor available
+ from Digital. It has limited hardware on-board, including an onboard
+ Ethernet interface, two PCMCIA sockets, two serial ports and a
+ parallel port.
+
+RiscPC
+CONFIG_ARCH_RPC
+ On the Acorn Risc-PC, Linux can support the internal IDE disk and
+ CD-ROM interface, serial and parallel port, and the floppy drive.
+
X 2MB physical memory
X CONFIG_PAGESIZE_16
X Say Y here if your Archimedes or A5000 system has only 2MB of
X memory, otherwise say N. The resulting kernel will not run on a
X machine with 4MB of memory.
X
-Include support for the CATS
+CATS
X CONFIG_ARCH_CATS
X Say Y here if you intend to run this kernel on the CATS.
X
X Saying N will reduce the size of the Footbridge kernel.
X
-Include support for the EBSA285
+EBSA285 (addin mode)
+CONFIG_ARCH_EBSA285_ADDIN
+ Say Y here if you intend to run this kernel on the EBSA285 card
+ in addin mode.
+
+ Saying N will reduce the size of the Footbridge kernel.
+
+EBSA285 (host mode)
X CONFIG_ARCH_EBSA285_HOST
X Say Y here if you intend to run this kernel on the EBSA285 card
X in host ("central function") mode.
X
X Saying N will reduce the size of the Footbridge kernel.
X
-Include support for the LinkUp Systems L7200 SDB
+LinkUp Systems L7200 SDB
X CONFIG_ARCH_L7200
X Say Y here if you intend to run this kernel on a LinkUp Systems
X L7200 Software Development Board which uses an ARM720T processor.
X Information on this board can be obtained at:
X
- http://www.linkupsys.com/
+ <http://www.linkupsys.com/>
X
X If you have any questions or comments about the Linux kernel port
- to this board, send e-mail to sjh...@cotw.com
+ to this board, send e-mail to sjh...@cotw.com.
X
-Include support for the NetWinder
+NetWinder
X CONFIG_ARCH_NETWINDER
X Say Y here if you intend to run this kernel on the Rebel.COM
X NetWinder. Information about this machine can be found at:
X
- http://www.netwinder.org/
+ <http://www.netwinder.org/>
X
X Saying N will reduce the size of the Footbridge kernel.
X
-Include support for the Compaq Personal Server
+P720T
+CONFIG_ARCH_P720T
+ Say Y here if you intend to run this kernel on the ARM Prospector
+ 720T.
+
+Compaq Personal Server
X CONFIG_ARCH_PERSONAL_SERVER
X Say Y here if you intend to run this kernel on the Compaq
X Personal Server.
-
+
X Saying N will reduce the size of the Footbridge kernel.
X
- The Compaq Personal Server is not available for purchase.
+ The Compaq Personal Server is not available for purchase.
X There are no product plans beyond the current research
X prototypes at this time. Information is available at:
-
- http://crl.research.compaq.com/projects/personalserver
-
+
+ <http://crl.research.compaq.com/projects/personalserver>
+
X If you have any questions or comments about the Compaq Personal
- Server, send e-mail to sk...@crl.dec.com
+ Server, send e-mail to sk...@crl.dec.com.
X
-Include support for Assabet
+Assabet
X CONFIG_SA1100_ASSABET
X Say Y here if you are using the Intel(R) StrongARM(R) SA-1110
X Microprocessor Development Board (also known as the Assabet).
X
-Include support for Neponset
+Neponset
X CONFIG_ASSABET_NEPONSET
X Say Y here if you are using the Intel(R) StrongARM(R) SA-1110
X Microprocessor Development Board (Assabet) with the SA-1111
X Development Board (Nepon).
X
-Include support for the Compaq iPAQ H3600 (Bitsy)
-CONFIG_SA1100_BITSY
- Say Y here if you intend to run this kernel on the Compaq iPAQ
+Compaq iPAQ H3600
+CONFIG_SA1100_H3600
+ Say Y here if you intend to run this kernel on the Compaq iPAQ
X H3600 handheld computer. Information about this machine and the
X Linux port to this machine can be found at:
X
- http://www.handhelds.org/Compaq/index.html#iPAQ_H3600
- http://www.compaq.com/products/handhelds/pocketpc/
+ <http://www.handhelds.org/Compaq/index.html#iPAQ_H3600>
+ <http://www.compaq.com/products/handhelds/pocketpc/>
X
-Include support for Brutus
+Brutus
X CONFIG_SA1100_BRUTUS
X Say Y here if you are using the Intel(R) StrongARM(R) SA-1100
X Microprocessor Development Board (also known as the Brutus).
X
-Include support for LART
+LART
X CONFIG_SA1100_LART
X Say Y here if you are using the Linux Advanced Radio Terminal
- (also known as the LART). See http://www.lart.tudelft.nl/ for
+ (also known as the LART). See <http://www.lart.tudelft.nl/> for
X information on the LART.
X
-Include support for GraphicsClient
+GraphicsClient
X CONFIG_SA1100_GRAPHICSCLIENT
X Say Y here if you are using an Applied Data Systems Intel(R)
X StrongARM(R) SA-1100 based Graphics Client SBC. See
- http://www.flatpanels.com/ for information on this system.
+ <http://www.flatpanels.com/> for information on this system.
+
+CerfBoard
+CONFIG_SA1100_CERF
+ The Intrinsyc CerfBoard is based on the StrongARM 1110.
+ More information is available at:
+ <http://www.intrinsyc.com/products/referenceplatforms/cerfboard.html>.
+
+ Say Y if configuring for an Intrinsyc CerfBoard.
+ Say N otherwise.
+
+nanoEngine
+CONFIG_SA1100_NANOENGINE
+ The nanoEngine is a StrongARM 1110-based single board computer
+ from Bright Star Engineering. More information is available at:
+ <http://www.brightstareng.com/arm/nanoeng.htm>.
+
+ Say Y if configuring for a nanoEngine.
+ Say N otherwise.
+
+Pangolin
+CONFIG_SA1100_PANGOLIN
+ Pangolin is a StrongARM 1110-based evaluation platform produced
+ by Dialogue Technology. It has EISA slots for ease of configuration
+ with SDRAM/Flash memory card, USB/Serial/Audio card, Compact Flash
+ card, and TFT-LCD card.
+
+ Say Y if configuring for a Pangolin.
+ Say N otherwise.
X
-Include support for Victor
+Victor
X CONFIG_SA1100_VICTOR
X Say Y here if you are using a Visu Aide Intel(R) StrongARM(R)
X SA-1100 based Victor Digital Talking Book Reader. See
- http://www.visuaide.com/pagevictor.en.html for information on
+ <http://www.visuaide.com/pagevictor.en.html> for information on
X this system.
X
-Load kernel using Angel Debug Monitor
-CONFIG_ANGELBOOT
- Say Y if you plan to load the kernel using Angel, ARM Ltd's target
- debug stub. If you are not using Angel, you must say N. It is
- important to get this setting correct.
+Support ARM610 processor
+CONFIG_CPU_ARM610
+ The ARM610 is the successor to the ARM3 processor
+ and was produced by VLSI Technology Inc.
+
+ Say Y if you want support for the ARM610 processor.


+ Otherwise, say N.
+

+Support ARM710 processor
+CONFIG_CPU_ARM710
+ A 32-bit RISC microprocessor based on the ARM7 processor core
+ designed by Advanced RISC Machines Ltd. The ARM710 is the
+ successor to the ARM610 processor. It was released in
+ July 1994 by VLSI Technology Inc.
+
+ Say Y if you want support for the ARM710 processor.


+ Otherwise, say N.
+

+Support ARM720T processor
+CONFIG_CPU_ARM720T
+ A 32-bit RISC processor with 8kByte Cache, Write Buffer and
+ MMU built around an ARM7TDMI core.
+
+ Say Y if you want support for the ARM720T processor.


+ Otherwise, say N.
+

+Support ARM920T processor
+CONFIG_CPU_ARM920T
+ The ARM920T is licensed to be produced by numerous vendors,
+ and is used in the Maverick EP9312. More information at
+ <http://linuxdevices.com/products/PD2382866068.html>.
+
+ Say Y if you want support for the ARM920T processor.


+ Otherwise, say N.
+

+Support ARM1020 processor
+CONFIG_CPU_ARM1020
+ The ARM1020 is the cached version of the ARM10 processor,
+ with an addition of a floating-point unit.
+
+ Say Y if you want support for the ARM1020 processor.


+ Otherwise, say N.
+

+Support StrongARM SA-110 processor
+CONFIG_CPU_SA110
+ The Intel StrongARM(R) SA-110 is a 32-bit microprocessor and


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

echo 'End of part 017'
echo 'File patch-2.4.15 is continued in part 018'
echo "018" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:55 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part019

#!/bin/sh -x
# this is part 019 of a 115 - part archive


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

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

@@ -19109,8 +23422,8 @@
X Enable Itanium A-step specific code
X CONFIG_ITANIUM_ASTEP_SPECIFIC
X Select this option to build a kernel for an Itanium prototype system
- with an A-step CPU. You have an A-step CPU if the "revision" field in
- /proc/cpuinfo is 0.
+ with an A-step CPU. You have an A-step CPU if the "revision" field
+ in /proc/cpuinfo is 0.
X
X Enable Itanium B-step specific code
X CONFIG_ITANIUM_BSTEP_SPECIFIC
@@ -19120,9 +23433,33 @@
X
X Enable Itanium B0-step specific code
X CONFIG_ITANIUM_B0_SPECIFIC
- Select this option to bild a kernel for an Itanium prototype system
- with a B0-step CPU. You have a B0-step CPU if the "revision" field in
- /proc/cpuinfo is 1.
+ Select this option to build a kernel for an Itanium prototype system
+ with a B0-step CPU. You have a B0-step CPU if the "revision" field
+ in /proc/cpuinfo is 1.
+
+Enable Itanium C-step specific code
+CONFIG_ITANIUM_CSTEP_SPECIFIC
+ Select this option to build a kernel for an Itanium prototype system
+ with a C-step CPU. You have a C-step CPU if the "revision" field in
+ /proc/cpuinfo is in the range of 5 to 8.
+
+Enable Itanium B1-step specific code
+CONFIG_ITANIUM_B1_SPECIFIC
+ Select this option to build a kernel for an Itanium prototype system
+ with a B1-step CPU. You have a B1-step CPU if the "revision" field
+ in /proc/cpuinfo is 2.
+
+Enable Itanium B2-step specific code
+CONFIG_ITANIUM_B2_SPECIFIC
+ Select this option to build a kernel for an Itanium prototype system
+ with a B2-step CPU. You have a B2-step CPU if the "revision" field
+ in /proc/cpuinfo is 3.
+
+Enable Itanium C0-step specific code
+CONFIG_ITANIUM_C0_SPECIFIC
+ Select this option to build a kernel for an Itanium prototype system
+ with a C0-step CPU. You have a C0-step CPU if the "revision" field
+ in /proc/cpuinfo is 5.
X
X Force interrupt redirection
X CONFIG_IA64_HAVE_IRQREDIR
@@ -19130,38 +23467,56 @@
X redirect interrupts to different CPUs. Select N here if you're
X unsure.
X
-Enable use of global TLB purge instruction (ptc.g)
-CONFIG_ITANIUM_PTCG
- Say Y here if you want the kernel to use the IA-64 "ptc.g"
- instruction to flush the TLB on all CPUs. Select N here if
- you're unsure.
-
-Enable SoftSDV hacks
-CONFIG_IA64_SOFTSDV_HACKS
- Say Y here to enable hacks to make the kernel work on the Intel
- SoftSDV simulator. Select N here if you're unsure.
-
-Enable AzusA hacks
-CONFIG_IA64_AZUSA_HACKS
- Say Y here to enable hacks to make the kernel work on the NEC
- AzusA platform. Select N here if you're unsure.
-
-Force socket buffers below 4GB?
-CONFIG_SKB_BELOW_4GB
- Most of today's network interface cards (NICs) support DMA to
- the low 32 bits of the address space only. On machines with
- more then 4GB of memory, this can cause the system to slow
- down if there is no I/O TLB hardware. Turning this option on
- avoids the slow-down by forcing socket buffers to be allocated
- from memory below 4GB. The downside is that your system could
- run out of memory below 4GB before all memory has been used up.
- If you're unsure how to answer this question, answer Y.
-
X Enable IA-64 Machine Check Abort
X CONFIG_IA64_MCA
X Say Y here to enable machine check support for IA-64. If you're
X unsure, answer Y.
X
+Disable IA-64 Virtual Hash Page Table
+CONFIG_DISABLE_VHPT
+ The Virtual Hash Page Table (VHPT) enhances virtual address
+ translation performance. Normally you want the VHPT active but you
+ can select this option to disable the VHPT for debugging. If you're
+ unsure, answer N.
+
+Enable McKinley A-step specific code
+CONFIG_MCKINLEY_ASTEP_SPECIFIC
+ Select this option to build a kernel for an IA64 McKinley system
+ with any A-stepping CPU.
+
+Enable McKinley A0/A1-step specific code
+CONFIG_MCKINLEY_A0_SPECIFIC
+ Select this option to build a kernel for an IA64 McKinley system
+ with an A0 or A1 stepping CPU.
+
+Turn on compare-and-exchange bug checking (slow!)
+CONFIG_IA64_DEBUG_CMPXCHG
+ Selecting this option turns on bug checking for the IA64
+ compare-and-exchange instructions. This is slow! Itaniums
+ from step B3 or later don't have this problem. If you're unsure,
+ select N.
+
+IA64 IRQ bug checking
+CONFIG_IA64_DEBUG_IRQ
+ Selecting this option turns on bug checking for the IA64 irq_save
+ and restore instructions. It's useful for tracking down spinlock
+ problems, but slow! If you're unsure, select N.
+
+Early printk support (requires VGA!)
+CONFIG_IA64_EARLY_PRINTK
+ Selecting this option uses the VGA screen for printk() output before
+ the consoles are initialised. It is useful for debugging problems
+ early in the boot process, but only if you have a VGA screen
+ attached. If you're unsure, select N.
+
+Print possible IA64 hazards to console
+CONFIG_IA64_PRINT_HAZARDS
+ Selecting this option prints more information for Illegal Dependency
+ Faults, that is, for Read after Write, Write after Write or Write
+ after Read violations. This option is ignored if you are compiling
+ for an Itanium A step processor (CONFIG_ITANIUM_ASTEP_SPECIFIC). If
+ you're unsure, select Y.
+
X Performance monitor support
X CONFIG_PERFMON
X Selects whether support for the IA-64 performance monitor hardware
@@ -19179,12 +23534,416 @@
X To use this option, you have to check that the "/proc file system
X support" (CONFIG_PROC_FS) is enabled, too.
X
+Kernel support for IA-32 emulation
+CONFIG_IA32_SUPPORT
+ IA64 processors can run IA32 (that is, x86) binaries by emulating
+ the IA32 instruction set. Say Y here to build in kernel support for
+ this. If in doubt, say Y.
+
+/proc/efi/vars support
+CONFIG_IA64_EFIVARS
+ If you say Y here, you are able to get EFI (Extensible Firmware
+ Interface) variable information in /proc/efi/vars. You may read,
+ write, create, and destroy EFI variables through this interface.
+
+ To use this option, you have to check that the "/proc file system
+ support" (CONFIG_PROC_FS) is enabled, too.
+
+Directly Connected Compact Flash support
+CONFIG_CF_ENABLER
+ Compact Flash is a small, removable mass storage device introduced
+ in 1994 originally as a PCMCIA device. If you say `Y' here, you
+ compile in support for Compact Flash devices directly connected to
+ a SuperH processor. A Compact Flash FAQ is available at
+ <http://www.compactflash.org/faqs/faq.htm>.
+
+ If your board has "Directly Connected" CompactFlash at area 5 or 6,
+ you may want to enable this option. Then, you can use CF as
+ primary IDE drive (only tested for SanDisk).
+
+ If in doubt, select 'N'.
+
+Kernel debugging
+CONFIG_DEBUG_KERNEL
+ Say Y here if you are developing drivers or trying to debug and
+ identify kernel problems.
+
+Debug memory allocations
+CONFIG_DEBUG_SLAB
+ Say Y here to have the kernel do limited verification on memory
+ allocation as well as poisoning memory on free to catch use of freed
+ memory.
+
+Memory mapped I/O debug support
+CONFIG_DEBUG_IOVIRT
+ Say Y here to get warned whenever an attempt is made to do I/O on
+ obviously invalid addresses such as those generated when ioremap()
+ calls are forgotten. Memory mapped I/O will go through an extra
+ check to catch access to unmapped ISA addresses, an access method
+ that can still be used by old drivers that are being ported from
+ 2.0/2.2.
+
+Spinlock debugging
+CONFIG_DEBUG_SPINLOCK
+ Say Y here and build SMP to catch missing spinlock initialization
+ and certain other kinds of spinlock errors commonly made. This is
+ best used in conjunction with the NMI watchdog so that spinlock
+ deadlocks are also debuggable.
+
+Verbose BUG() reporting (adds 70K)
+CONFIG_DEBUG_BUGVERBOSE
+ Say Y here to make BUG() panics output the file name and line number
+ of the BUG call as well as the EIP and oops trace. This aids
+ debugging but costs about 70-100K of memory.
+
+Include kgdb kernel debugger
+CONFIG_KGDB
+ Include in-kernel hooks for kgdb, the Linux kernel source level
+ debugger. This project has a web page at
+ <http://kgdb.sourceforge.net/>.
+
+Include xmon kernel debugger
+CONFIG_XMON
+ Include in-kernel hooks for the xmon kernel monitor/debugger
+ supported by the PPC port.
+
+Include kgdb kernel debugger
+CONFIG_KWDB
+ Include in-kernel hooks for kdb, the source level debugger for the
+ PA-RISC port.
+
+IODC console
+CONFIG_IODC_CONSOLE
+ IODC is HP's pre-PCI standard for device identification (a la PCI
+ vendor, device IDs), detection, configuration, initialization and so
+ on. It also can provide firmware function to do the actual IO,
+ which are slow, not really defined for runtime usage and generally
+ not desirable.
+
+ See <http://www.linuxhq.com/kernel/v2.4/doc/parisc/IODC.txt.html>
+ for the gory details.
+
+ Say Y here to enable use of the IODC firmware functions for console
+ I/O. This is only useful on older PA-RISC workstations. If in
+ doubt, say Y.
+
+U2/Uturn I/O MMU
+CONFIG_IOMMU_CCIO
+ Say Y here to enable DMA management routines for the first
+ generation of PA-RISC cache-coherent machines. Programs the
+ U2/Uturn chip in "Virtual Mode" and use the I/O MMU.
+
+LBA/Elroy PCI support
+CONFIG_PCI_LBA
+ Say Y here to give the PA-RISC kernel access to PCI configuration
+ and IO-port space on PA-RISC workstations equipped with a Lower Bus
+ Adapter (LBA). This includes A, B, C, J, L, and N-class machines
+ with 4-digit model numbers, also the A300.
+
+LASI I/O support
+CONFIG_GSC_LASI
+ Say Y here to directly support the LASI controller chip found on
+ PA-RISC workstations. Linux-oriented documentation for this chip
+ can be found at <http://www.parisc-linux.org/documentation/>.
+
+LASI/ASP builtin parallel-port
+CONFIG_PARPORT_GSC
+ Say Y here to build in low-level parallel-support for PC-style
+ hardware integrated in the LASI-Controller (on the GSC Bus) for
+ HP-PARISC workstations.
+
+Fujitsu Vendor Specific
+CONFIG_BLK_DEV_IDEDISK_FUJITSU
+ Enable vendor-specific code for Fujitsu IDE disks. Unless you are
+ the IDE maintainer, you probably do not want to mess with this.
+
+IBM Vendor Specific
+CONFIG_BLK_DEV_IDEDISK_IBM
+ Enable vendor-specific code for IBM IDE disks. Unless you are the
+ IDE maintainer, you probably do not want to mess with this.
+
+Maxtor Vendor Specific
+CONFIG_BLK_DEV_IDEDISK_MAXTOR
+ Enable vendor-specific code for Maxtor IDE disks. Unless you are
+ the IDE maintainer, you probably do not want to mess with this.
+
+Quantum Vendor Specific
+CONFIG_BLK_DEV_IDEDISK_QUANTUM
+ Enable vendor-specific code for Quantum IDE disks. Unless you are
+ the IDE maintainer, you probably do not want to mess with this.
+
+Seagate Vendor Specific
+CONFIG_BLK_DEV_IDEDISK_SEAGATE
+ Enable vendor-specific code for Seagate IDE disks. Unless you are
+ the IDE maintainer, you probably do not want to mess with this.
+
+Western Digital Vendor Specific
+CONFIG_BLK_DEV_IDEDISK_WD
+ Enable vendor-specific code for Western Digital IDE disks. Unless
+ you are the IDE maintainer, you probably do not want to mess with
+ this.
+
+TiVo Commerial Application Specific
+CONFIG_BLK_DEV_TIVO
+ Enable vendor-specific code for TiVo IDE disks. Unless you are the
+ IDE maintainer, you probably do not want to mess with this.
+
+# Choice: superhsys
+Generic
+CONFIG_SH_GENERIC
+ Select Generic if configuring for a generic SuperH system.
+ The "generic" option compiles in *all* the possible hardware
+ support and relies on the sh_mv= kernel commandline option to choose
+ at runtime which routines to use. "MV" stands for "machine vector";
+ each of the machines below is described by a machine vector.
+
+ Select SolutionEngine if configuring for a Hitachi SH7709
+ or SH7750 evalutation board.
+
+ Select Overdrive if configuring for a ST407750 Overdrive board.
+ More information at
+ <http://linuxsh.sourceforge.net/docs/7750overdrive.php3>.
+
+ Select HP620 if configuring for a HP Jornada HP620.
+ More information (hardware only) at
+ <http://www.hp.com/jornada>.
+
+ Select HP680 if configuring for a HP Jornada HP680.
+ More information (hardware only) at
+ <http://www.hp.com/jornada/products/680>.
+
+ Select HP690 if configuring for a HP Jornada HP690.
+ More information (hardware only) at
+ <http://www.hp.com/jornada/products/680>.
+
+ Select CqREEK if configuring for a CqREEK SH7708 or SH7750.
+ More information at
+ <http://sources.redhat.com/ecos/hardware.html#SuperH>.
+
+ Select DMIDA if configuring for a DataMyte 4000 Industrial
+ Digital Assistant. More information at <http://www.dmida.com>.
+
+ Select EC3104 if configuring for a system with an Eclipse
+ International EC3104 chip, e.g. the Harris AD2000.
+
+ Select Dreamcast if configuring for a SEGA Dreamcast.
+ More information at
+ <http://www.m17n.org/linux-sh/dreamcast>. There is a
+ Dreamcast project is at <http://linuxdc.sourceforge.net/>.
+
+ Select BareCPU if you know what this means, and it applies
+ to your system.
+
+SolutionEngine
+CONFIG_SH_SOLUTION_ENGINE
+ Select SolutionEngine if configuring for a Hitachi SH7709
+ or SH7750 evalutation board.
+
+7751 SolutionEngine
+CONFIG_SH_7751_SOLUTION_ENGINE
+ Select 7751 SolutionEngine if configuring for a Hitachi SH7751
+ evalutation board.
+
+Overdrive
+CONFIG_SH_OVERDRIVE
+ Select Overdrive if configuring for a ST407750 Overdrive board.
+ More information at
+ <http://linuxsh.sourceforge.net/docs/7750overdrive.php3>.
+
+HP620
+CONFIG_SH_HP620
+ Select HP620 if configuring for a HP jornada HP620.
+ More information (hardware only) at
+ <http://www.hp.com/jornada>.
+
+HP680
+CONFIG_SH_HP680
+ Select HP680 if configuring for a HP Jornada HP680.
+ More information (hardware only) at
+ <http://www.hp.com/jornada/products/680>.
+
+HP690
+CONFIG_SH_HP690
+ Select HP690 if configuring for a HP Jornada HP690.
+ More information (hardware only)
+ at <http://www.hp.com/jornada/products/680>.
+
+CqREEK
+CONFIG_SH_CQREEK
+ Select CqREEK if configuring for a CqREEK SH7708 or SH7750.
+ More information at
+ <http://sources.redhat.com/ecos/hardware.html#SuperH>.
+
+DMIDA
+CONFIG_SH_DMIDA
+ Select DMIDA if configuring for a DataMyte 4000 Industrial
+ Digital Assistant. More information at <http://www.dmida.com>.
+
+EC3104
+CONFIG_SH_EC3104
+ Select EC3104 if configuring for a system with an Eclipse
+ International EC3104 chip, e.g. the Harris AD2000.
+
+Dreamcast
+CONFIG_SH_DREAMCAST
+ Select Dreamcast if configuring for a SEGA Dreamcast.
+ More information at
+ <http://www.m17n.org/linux-sh/dreamcast>. There is a
+ Dreamcast project is at <http://linuxdc.sourceforge.net/>.
+
+BareCPU
+CONFIG_SH_UNKNOWN
+ "Bare CPU" aka "unknown" means an SH-based system which is not one
+ of the specific ones mentioned above, which means you need to enter
+ all sorts of stuff like CONFIG_MEMORY_START because the config
+ system doesn't already know what it is. You get a machine vector
+ without any platform-specific code in it, so things like the RTC may
+ not work.
+
+ This option is for the early stages of porting to a new machine.
+
+# Choice: superhtype
+SH7707
+CONFIG_CPU_SUBTYPE_SH7707
+ Select the type of SuperH processor you have.
+
+ Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU.
+
+ Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or
+ if you have a 100 Mhz SH-3 HD6417708R CPU.
+
+ Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU.
+
+ Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU.
+
+SH7708
+CONFIG_CPU_SUBTYPE_SH7708
+ Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or
+ if you have a 100 Mhz SH-3 HD6417708R CPU.
+
+SH7709
+CONFIG_CPU_SUBTYPE_SH7709
+ Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU.
+
+SH7750
+CONFIG_CPU_SUBTYPE_SH7750
+ Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU.
+
+Physical memory start address
+CONFIG_MEMORY_START
+ The physical memory start address will be automatically
+ set to 08000000, unless you selected one of the following
+ processor types: SolutionEngine, Overdrive, HP620, HP680, HP690,
+ in which case the start address will be set to 0c000000.
+
+ Tweak this only when porting to a new machine which is not already
+ known by the config system. Changing it from the known correct
+ value on any of the known systems will only lead to disaster.
+
+Hitachi HD64461 companion chip support
+CONFIG_HD64461
+ The Hitachi HD64461 provides an interface for
+ the SH7709 CPU, supporting a LCD controller,
+ CRT color controller, IrDA up to 4 Mbps, and a
+ PCMCIA controller supporting 2 slots.
+


+ More information is available at

+ <http://semiconductor.hitachi.com/windowsce/superh/sld013.htm>.
+
+ Say Y if you want support for the HD64461.


+ Otherwise, say N.
+

+HD64461 PCMCIA enabler
+CONFIG_HD64461_ENABLER
+ Say Y here if you want to enable PCMCIA support
+ via the HD64461 companion chip.


+ Otherwise, say N.
+

+HD64461 virtualized IRQ number
+CONFIG_HD64461_IRQ
+ The default setting of the HD64461 IRQ is 36.
+
+ Do not change this unless you know what you are doing.
+
+Hitachi HD64465 companion chip support
+CONFIG_HD64465
+ The Hitachi HD64465 provides an interface for
+ the SH7750 CPU, supporting a LCD controller,
+ CRT color controller, IrDA, USB, PCMCIA,
+ keyboard controller, and a printer interface.
+


+ More information is available at

+ <http://global.hitachi.com/New/cnews/E/1998/981019B.html>.
+
+ Say Y if you want support for the HD64465.


+ Otherwise, say N.
+

+HD64465 virtualized IRQ number
+CONFIG_HD64465_IRQ
+ The default setting of the HD64465 IRQ is 5.
+
+ Do not change this unless you know what you are doing.
+
+HD64465 start address
+CONFIG_HD64465_IOBASE
+ The default setting of the HD64465 IO base address is 0xb0000000.
+
+ Do not change this unless you know what you are doing.
+
+Early printk support
+CONFIG_SH_EARLY_PRINTK
+ Say Y here to redirect kernel messages to the serial port
+ used by the SH-IPL bootloader, starting very early in the boot
+ process and ending when the kernel's serial console is initialised.
+ This option is only useful porting the kernel to a new machine,
+ when the kernel may crash or hang before the serial console is
+ initialised.
+
+SuperH SCI (serial) support
+CONFIG_SH_SCI
+ Selecting this option will allow the Linux kernel to transfer data
+ over SCI (Serial Communication Interface) and/or SCIF (Serial
+ Communication Interface with FIFO) which are built into the Hitachi
+ SuperH processor. The option provides 1 to 3 (depending
+ on the CPU model) standard Linux tty devices, /dev/ttySC[012]; one
+ of these is normally used as the system console.
+
+ If in doubt, press "y".
+
+Use LinuxSH standard BIOS
+CONFIG_SH_STANDARD_BIOS
+ Say Y here if your target has the gdb-sh-stub
+ package from www.m17n.org (or any conforming standard LinuxSH BIOS)
+ in FLASH or EPROM. The kernel will use standard BIOS calls during
+ boot for various housekeeping tasks (including calls to read and
+ write characters to a system console, get a MAC address from an
+ on-board Ethernet interface, and shut down the hardware). Note this
+ does not work with machines with an existing operating system in
+ mask ROM and no flash (WindowsCE machines fall in this category).


+ If unsure, say N.
+

+GDB Stub kernel debug
+CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
+ If you say Y here, it will be possible to remotely debug the SuperH
+ kernel using gdb, if you have the gdb-sh-stub package from
+ www.m17n.org (or any conforming standard LinuxSH BIOS) in FLASH or
+ EPROM. This enlarges your kernel image disk size by several
+ megabytes but allows you to load, run and debug the kernel image
+ remotely using gdb. This is only useful for kernel hackers. If
+ unsure, say N.
+
+Console output to GDB
+CONFIG_GDB_CONSOLE
+ If you are using GDB for remote debugging over a serial port and
+ would like kernel messages to be formatted into GDB $O packets so
+ that GDB prints them as program output, say 'Y'.
+
X #
X # A couple of things I keep forgetting:
-# capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
-# Intel, IRQ, ISDN, Linux, MSDOS, NetWare, NetWinder,
+# capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
+# Intel, IRQ, ISDN, Linux, MSDOS, NetWare, NetWinder,
X # NFS, PCI, SCSI, SPARC
-# two words: file system, hard drive, hard disk, home page,
+# two words: file system, hard drive, hard disk, home page,
X # user space, web site
X # other: it's safe to save; daemon; use --, not - or ---;
X # use KB for 1024 bytes, not kB or K.
@@ -19195,13 +23954,13 @@
X # LocalWords: CONFIG coprocessor DX Pentium SX lilo loadlin HOWTO ftp metalab
X # LocalWords: unc edu docs emu README kB BLK DEV FD Thinkpad fd MFM RLL IDE gz
X # LocalWords: cdrom diskless netboot nfs xzvf ATAPI MB ide pavia rubini pl pd
-# LocalWords: HD CDROMs IDECD NEC MITSUMI filesystem XT XD PCI BIOS cezar ATEN
+# LocalWords: HD CD-ROMs IDECD NEC MITSUMI filesystem XT XD PCI BIOS cezar ATEN
X # LocalWords: ISA EISA Microchannel VESA BIOSes IPC SYSVIPC ipc Ctrl dmesg hlt
X # LocalWords: BINFMT Linkable http ac uk jo html GCC SPARC AVANTI CABRIOLET EB
X # LocalWords: netscape gcc LD CC toplevel MODVERSIONS insmod rmmod modprobe IP
-# LocalWords: genksyms INET loopback gatewaying ethernet PPP ARP Arp MEMSIZE
+# LocalWords: genksyms INET loopback gatewaying Ethernet PPP ARP Arp MEMSIZE
X # LocalWords: howto multicasting MULTICAST MBONE firewalling ipfw ACCT resp ip
-# LocalWords: proc acct IPIP encapsulator decapsulator klogd PCTCP RARP EXT PS
+# LocalWords: proc acct IPIP encapsulator decapsulator klogd RARP EXT PS
X # LocalWords: telnetting subnetted NAGLE rlogin NOSR ttyS TGA techinfo mbone nl
X # LocalWords: Mb SKB IPX Novell dosemu DDP ATALK vmalloc visar ehome
X # LocalWords: SD CHR scsi thingy SG CD LUNs LUN jukebox Adaptec BusLogic EATA
@@ -19255,11 +24014,11 @@
X # LocalWords: FC DC dc PPA IOMEGA's ppa RNFS FMV Fujitsu ARPD arpd loran layes
X # LocalWords: FRAD indiana framerelay DLCI DCLIs Sangoma SDLA mrouted sync sec
X # LocalWords: Starmode Metricom MosquitoNet mosquitonet kbit nfsroot Digiboard
-# LocalWords: DIGI Xe Xeve digiboard UMISC touchscreens mtu ethernets HBAs MEX
+# LocalWords: DIGI Xe Xeve digiboard UMISC touchscreens mtu Ethernets HBAs MEX
X # LocalWords: Shifflett netcom js jshiffle WIC DECchip ELCP EtherPower dst RTC
X # LocalWords: rtc SMP lp Digi Intl RightSwitch DGRS dgrs AFFS Amiga UFS SDL AP
X # LocalWords: Solaris RISCom riscom syncPPP PCBIT pcbit sparc anu au artoo MFB
-# LocalWords: hitchcock Crynwr cnam pktdrvr NCSA's CyDROM CyCDROM FreeBSD NeXT
+# LocalWords: hitchcock Crynwr cnam pktdrvr NCSA's CyDROM CyCD-ROM FreeBSD NeXT
X # LocalWords: NeXTstep disklabel disklabels SMD FFS tm AmigaOS diskfiles Un IQ
X # LocalWords: Bernd informatik rwth aachen uae affs multihosting bytecode java
X # LocalWords: applets applet JDK ncsa cabi SNI Alphatronix readme LANs scarab
@@ -19275,7 +24034,7 @@
X # LocalWords: mgetty sendfax gert greenie muc lowlevel Lasermate LanManager io
X # LocalWords: OOPSes trackball binghamton mobileip ncr IOMAPPED settags ns ser
X # LocalWords: setsync NEGO MPARITY autotuning prefetch PIIX cdwrite utils rc
-# LocalWords: PCWATCHDOG berkprod bitgate boldt ucsb jf kyoto jp euc Tetsuyasu
+# LocalWords: PCWATCHDOG berkprod bitgate boldt ucsb jf kyoto jp euc Tetsuyasu
X # LocalWords: YAMADA tetsu cauchy nslab ntt nevod perm su doc kaf kheops wsc
X # LocalWords: traduc Bourgin dbourgin menuconfig kfill READMEs HOWTOs Virge WA
X # LocalWords: IDEDISK IDEFLOPPY EIDE firewalls QMAGIC ZMAGIC LocalWords opti
@@ -19338,7 +24097,7 @@
X # LocalWords: prio Micom xIO dwmw rimi OMIRR omirr omirrd unicode ntfs cmu NIC
X # LocalWords: Braam braam Schmidt's freiburg nls codepages codepage Romanian
X # LocalWords: Slovak Slovenian Sorbian Nordic iso Catalan Faeroese Galician SZ
-# LocalWords: Valencian Slovene Esperanto Estonian Latvian Byelorussian KOI mt
+# LocalWords: Valencian Slovene Esperanto Estonian Latvian Belarusian KOI mt
X # LocalWords: charset Inuit Greenlandic Sami Lappish koi Alexey Kuznetsov's sa
X # LocalWords: Specialix specialix DTR RTS RTSCTS cycladesZ Exabyte ftape's inr
X # LocalWords: Iomega's LBFM claus ZFTAPE VFS zftape zft William's lzrw DFLT kb
@@ -19404,7 +24163,7 @@
X # LocalWords: uit dagb irda LSAP IrLMP RR's IrLAP IR alloc skb's kfree skb's
X # LocalWords: GZIP IrLAN NetbeamIR ESI JetEye IrOBEX IrCOMM TTY's minicom dti
X # LocalWords: ircomm ircomm pluto thiguchi IrTTY Linux's bps NetWinder MIR NSC
-# LocalWords: ACTiSYS Dongle dongle dongles esi actisys IrMate tekram BVM MVME
+# LocalWords: ACTiSYS dongle dongles esi actisys IrMate tekram BVM MVME
X # LocalWords: BVME BVME WRITETHROUGH copyback writethrough fwmark syncookie tu
X # LocalWords: alphalinux GOBIOS csn chemnitz nat ACARD AMI MegaRAID megaraid
X # LocalWords: QNXFS ISI isicom xterms Apollos VPN RCPCI rcpci sgi visws pcmcia
@@ -19416,7 +24175,7 @@
X # LocalWords: SKMC USB UHCI OHCI intel compaq usb ohci HCD Virt Compaq's hcd
X # LocalWords: VROOTHUB KBD ARRs MCRs NWBUTTON nwbutton NUM WaveArtist APNE cpu
X # LocalWords: apne blackhawke PlanB lu mlan planb NWFPE FPA nwfpe unbootable
-# LocalWords: FPEmulator ds vmlinux initialisation discardable pgtable PGT mdw
+# LocalWords: FPEmulator ds vmlinux initialization discardable pgtable PGT mdw
X # LocalWords: quicklist pagetable arthur StrongARM podule podules Autodetect
X # LocalWords: dodgy IrPORT irport Litelink litelink SuSE rtfm internet hda CY
X # LocalWords: multmode DriveReady SeekComplete DriveStatusError miscompile AEC
@@ -19445,7 +24204,7 @@
X # LocalWords: VWSND eg ESSSOLO CFU CFNR scribed eiconctrl eicon hylafax KFPU
X # LocalWords: EXTRAPREC fpu mainboards KHTTPD kHTTPd khttpd Xcelerator SBNI tw
X # LocalWords: LOGIBUSMOUSE Granch granch sbni Raylink NOHIGHMEM Athlon SIM sim
-# LocalWords: hpl Tourrilhes DuraLAN starfile Davicom davicom dmfe auk tms tr
+# LocalWords: hpl Tourrilhes DuraLAN starfire Davicom davicom dmfe auk tms tr
X # LocalWords: TokenExpress Belkin Peracom eTek DVDs infradead Cxxx Adlib AV ZX
X # LocalWords: NeoMagic CPi CPt Celeron decapsulation Undeletion BFS bfs nVidia
X # LocalWords: OnStream Irongate Riva phonedev QuickNet LineJack PhoneJack IXJ
@@ -19465,7 +24224,7 @@
X # LocalWords: DEVS FireWire PCILynx pcilynx LOCALRAM miro's DV RAWIO GRED Mk
X # LocalWords: Diffserv DSMARK Ingress Qdisc TCINDEX TMSPCI tmspci Ringode JE
X # LocalWords: MADGEMC madgemc TokenRing SMCTR TokenCard smctr Wacom Graphire
-# LocalWords: WMFORCE mousedev ConnectTech HandSpring Xirlink IBMCAM ibmcam SN
+# LocalWords: mousedev ConnectTech HandSpring Xirlink IBMCAM ibmcam SN
X # LocalWords: DEVICEFS yyy Cymraeg Dwave SIMM JSFLASH JavaStation's multilink
X # LocalWords: nsc ircc DDB Vrc CMN TB PROMs Vino rivafb DDC Matroxes MGA TVO
X # LocalWords: MAVEN fbdev crtc maven matroxset NTSC PCA SBA AAL SKFP DAS SAS
@@ -19495,3 +24254,11 @@
X # LocalWords: DMX Domex dmx wellington ftdi sio Accton Billington Corega FEter
X # LocalWords: MELCO LUA PNA Linksys SNC chkdsk AWACS Webcam RAMFS Ramfs ramfs
X # LocalWords: ramfiles MAKEDEV pty WDTPCI APA apa
+#
+# The following sets edit modes for GNU EMACS
+# Local Variables:
+# case-fold-search:nil
+# fill-prefix:" "
+# adaptive-fill:nil
+# fill-column:70
+# End:
diff -u --recursive --new-file v2.4.14/linux/Documentation/DocBook/via-audio.tmpl linux/Documentation/DocBook/via-audio.tmpl
--- v2.4.14/linux/Documentation/DocBook/via-audio.tmpl Wed Jul 25 17:10:16 2001
+++ linux/Documentation/DocBook/via-audio.tmpl Fri Nov 9 13:45:35 2001
@@ -68,7 +68,7 @@
X support are not yet available.
X </para>
X <para>
- This driver supports any Linux kernel version after 2.3.50.
+ This driver supports any Linux kernel version after 2.4.10.
X </para>
X <para>
X Please send bug reports to the mailing list <email>linu...@gtf.org</email>.
@@ -157,14 +157,6 @@
X </para>
X </listitem></varlistentry>
X
- <varlistentry><term>RealPlayer trouble</term>
- <listitem>
- <para>
- RealPlayer output very scratchy. Workaround: use esd, and
- configure RealPlayer to output to esd.
- </para>
- </listitem></varlistentry>
-
X </variablelist>
X
X </para>
@@ -191,6 +183,9 @@
X MMAP support, and several other notable fixes that resulted from
X his hard work and testing.
X </para>
+ <para>
+ Thomas Sailer for further bugfixes.
+ </para>
X </chapter>
X
X <chapter id="notes">
@@ -233,6 +228,31 @@
X
X <chapter id="changelog">
X <title>Driver ChangeLog</title>
+
+<sect1 id="version191"><title>
+Version 1.9.1
+</title>
+ <itemizedlist spacing=compact>
+ <listitem>
+ <para>
+ DSP read/write bugfixes from Thomas Sailer.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Add new PCI id for single-channel use of Via 8233.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Other bug fixes, tweaks, new ioctls.
+ </para>
+ </listitem>
+
+ </itemizedlist>
+</sect1>
X
X <sect1 id="version1115"><title>
X Version 1.1.15
diff -u --recursive --new-file v2.4.14/linux/Documentation/devices.txt linux/Documentation/devices.txt
--- v2.4.14/linux/Documentation/devices.txt Mon Aug 27 12:41:37 2001
+++ linux/Documentation/devices.txt Wed Nov 7 14:46:01 2001
@@ -971,7 +971,7 @@
X 0 = /dev/rd/c0d0 First disk, whole disk
X 8 = /dev/rd/c0d1 Second disk, whole disk
X ...
- 248 = /dev/rd/c0d15 32nd disk, whole disk
+ 248 = /dev/rd/c0d31 32nd disk, whole disk
X
X For partitions add:
X 0 = /dev/rd/c?d? Whole disk
diff -u --recursive --new-file v2.4.14/linux/Documentation/fb/clgenfb.txt linux/Documentation/fb/clgenfb.txt
--- v2.4.14/linux/Documentation/fb/clgenfb.txt Thu Jan 6 10:23:46 2000
+++ linux/Documentation/fb/clgenfb.txt Mon Nov 19 15:19:42 2001
@@ -35,11 +35,18 @@
X At the moment, there are two kernel command line arguments supported:
X
X mode:640x480
+mode:800x600
X or
X mode:1024x768
X
X Full support for startup video modes (modedb) will be integrated soon.
X
+Version 1.9.9.1
+---------------
+* Fix memory detection for 512kB case
+* 800x600 mode
+* Fixed timings
+* Hint for AXP: Use -accel false -vyres -1 when changing resolution
X
X
X Version 1.9.4.4
diff -u --recursive --new-file v2.4.14/linux/Documentation/filesystems/proc.txt linux/Documentation/filesystems/proc.txt
--- v2.4.14/linux/Documentation/filesystems/proc.txt Fri Apr 6 10:42:48 2001
+++ linux/Documentation/filesystems/proc.txt Wed Nov 7 14:39:36 2001
@@ -471,6 +471,11 @@
X ...] 1375103 17405 0 0 0 0 0 0
X ...] 1703981 5535 0 0 0 3 0 0
X
+In addition, each Channel Bond interface has it's own directory. For
+example, the bond0 device will have a directory called /proc/net/bond0/.
+It will contain information that is specific to that bond, such as the
+current slaves of the bond, the link status of the slaves, and how
+many times the slaves link has failed.
X
X 1.5 SCSI info
X -------------
diff -u --recursive --new-file v2.4.14/linux/Documentation/i386/boot.txt linux/Documentation/i386/boot.txt
--- v2.4.14/linux/Documentation/i386/boot.txt Wed Apr 11 18:50:25 2001
+++ linux/Documentation/i386/boot.txt Wed Nov 7 14:46:01 2001
@@ -2,7 +2,7 @@
X ----------------------------
X
X H. Peter Anvin <h...@zytor.com>
- Last update 2000-07-27
+ Last update 2000-10-29
X
X On the i386 platform, the Linux kernel uses a rather complicated boot
X convention. This has evolved partially due to historical aspects, as
@@ -145,6 +145,9 @@
X most of the fields in the header. The following fields should be
X filled out, however:
X
+ vid_mode:
+ Please see the section on SPECIAL COMMAND LINE OPTIONS.
+
X type_of_loader:
X If your boot loader has an assigned id (see table below), enter
X 0xTV here, where T is an identifier for the boot loader and V is
@@ -319,8 +322,8 @@
X
X mem=<size>
X <size> is an integer in C notation optionally followed by K, M
- or G (meaning << 10, << 20 or << 30). This specifies to the
- kernel the memory size. This affects the possible placement
+ or G (meaning << 10, << 20 or << 30). This specifies the end
+ of memory to the kernel. This affects the possible placement
X of an initrd, since an initrd should be placed near end of
X memory. Note that this is an option to *both* the kernel and
X the bootloader!
@@ -392,8 +395,8 @@
X appropriate time. The use of these hooks should probably be
X considered an absolutely last resort!
X
-IMPORTANT: All the hooks are required to preserve %ebp, %esi and %edi
-across invocation.
+IMPORTANT: All the hooks are required to preserve %esp, %ebp, %esi and
+%edi across invocation.
X
X realmode_swtch:
X A 16-bit real mode far subroutine invoked immediately before
diff -u --recursive --new-file v2.4.14/linux/Documentation/memory.txt linux/Documentation/memory.txt
--- v2.4.14/linux/Documentation/memory.txt Tue Dec 22 08:31:07 1998
+++ linux/Documentation/memory.txt Fri Nov 9 13:58:02 2001
@@ -37,7 +37,7 @@
X * Not overclocking your CPU.
X
X * Having the memory tested in a memory tester or exchanged
- with the vendor.
+ with the vendor. Consider testing it with memtest86 yourself.
X
X * Exchanging your CPU, cache, or motherboard for one that works.
X
diff -u --recursive --new-file v2.4.14/linux/Documentation/networking/8139too.txt linux/Documentation/networking/8139too.txt
--- v2.4.14/linux/Documentation/networking/8139too.txt Mon Nov 5 15:55:25 2001
+++ linux/Documentation/networking/8139too.txt Fri Nov 9 13:45:35 2001
@@ -82,7 +82,7 @@
X
X (overwrite 8139too driver in kernel tree with different version)
X 1) cp 8139too.c $my_source_tree/drivers/net/8139too.c
-
+
X OPTION 2: Build outside kernel tree
X
X Use the included Makefile.
@@ -139,7 +139,7 @@
X
X Submitting Bug Reports
X ----------------------
-Obtain and compile the modified rtl8139-diag source code from the
+Obtain and compile the modified rtl8139-diag source code from the
X 8139too driver Web site, http://sourceforge.net/projects/gkernel/
X This diagnostics programs, originally from Donald Becker, has been
X modified to display all registers on your RTL8139 chip, not just the
@@ -181,6 +181,27 @@
X Change History
X --------------
X
+Version 0.9.22 - November 8, 2001
+
+* Additional retries before aborting Tx
+* Do not write other TxConfig bits when writing clear-abort bit.
+* Ack TxErr intr status after each Tx abort, too.
+
+
+Version 0.9.21 - November 1, 2001
+
+* Disable early Rx, it hurts performance and creates races.
+* Remove DPRINTK macro function tracing.
+* Better interrupt sharing behavior.
+* Acknowledge PCI errors.
+* Remove early-Rx acknowledgement, unnecessary
+* Remove code for uncommon case where Tx packets are
+ properly aligned, and do not need to be copied.
+ Tx packets are now always copied into a static DMA buffer,
+ which is allocated at interface open.
+* Fix problems with kernel thread exit.
+
+
X Version 0.9.20 - October 18, 2001
X
X * Print out notice when 8139C+ chip is detected
@@ -212,7 +233,7 @@
X Version 0.9.17 - May 7, 2001
X
X * Fix chipset wakeup bug which prevent media connection for 8139B
-* Print out "media is unconnected..." instead of
+* Print out "media is unconnected..." instead of
X "partner ability 0000"
X
X
diff -u --recursive --new-file v2.4.14/linux/Documentation/networking/bonding.txt linux/Documentation/networking/bonding.txt
--- v2.4.14/linux/Documentation/networking/bonding.txt Wed Dec 31 16:00:00 1969
+++ linux/Documentation/networking/bonding.txt Wed Nov 7 14:39:36 2001
@@ -0,0 +1,524 @@
+
+ Linux Ethernet Bonding Driver mini-howto
+
+Initial release : Thomas Davis <tadavis at lbl.gov>
+Corrections, HA extensions : 2000/10/03-15 :
+ - Willy Tarreau <willy at meta-x.org>
+ - Constantine Gavrilov <const-g at xpert.com>
+ - Chad N. Tindel <ctindel at ieee dot org>
+ - Janice Girouard <girouard at us dot ibm dot com>
+
+Note :
+------
+The bonding driver originally came from Donald Becker's beowulf patches for
+kernel 2.0. It has changed quite a bit since, and the original tools from
+extreme-linux and beowulf sites will not work with this version of the driver.
+
+For new versions of the driver, patches for older kernels and the updated
+userspace tools, please follow the links at the end of this file.
+
+Installation
+============
+
+1) Build kernel with the bonding driver
+---------------------------------------
+For the latest version of the bonding driver, use kernel 2.4.12 or above
+(otherwise you will need to apply a patch).
+
+Configure kernel with `make menuconfig/xconfig/config', and select
+"Bonding driver support" in the "Network device support" section. It is
+recommended to configure the driver as module since it is currently the only way
+to pass parameters to the driver and configure more than one bonding device.
+
+Build and install the new kernel and modules.
+
+2) Get and install the userspace tools
+--------------------------------------
+This version of the bonding driver requires updated ifenslave program. The
+original one from extreme-linux and beowulf will not work. Kernels 2.4.12
+and above include the updated version of ifenslave.c in Documentation/network
+directory. For older kernels, please follow the links at the end of this file.
+
+IMPORTANT!!! If you are running on Redhat 7.1 or greater, you need
+to be careful because /usr/include/linux is no longer a symbolic link
+to /usr/src/linux/include/linux. If you build ifenslave while this is
+true, ifenslave will appear to succeed but your bond won't work. The purpose
+of the -I option on the ifenslave compile line is to make sure it uses
+/usr/src/linux/include/linux/if_bonding.h instead of the version from
+/usr/include/linux.
+
+To install ifenslave.c, do:
+ # gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave
+ # cp ifenslave /sbin/ifenslave
+
+3) Configure your system
+------------------------
+Also see the following section on the module parameters. You will need to add
+at least the following line to /etc/conf.modules (or /etc/modules.conf):
+
+ alias bond0 bonding
+
+Use standard distribution techniques to define bond0 network interface. For
+example, on modern RedHat distributions, create ifcfg-bond0 file in
+/etc/sysconfig/network-scripts directory that looks like this:
+
+DEVICE=bond0
+IPADDR=192.168.1.1
+NETMASK=255.255.255.0
+NETWORK=192.168.1.0
+BROADCAST=192.168.1.255
+ONBOOT=yes
+BOOTPROTO=none
+USERCTL=no
+
+(put the appropriate values for you network instead of 192.168.1).
+
+All interfaces that are part of the trunk, should have SLAVE and MASTER
+definitions. For example, in the case of RedHat, if you wish to make eth0 and
+eth1 (or other interfaces) a part of the bonding interface bond0, their config
+files (ifcfg-eth0, ifcfg-eth1, etc.) should look like this:
+
+DEVICE=eth0
+USERCTL=no
+ONBOOT=yes
+MASTER=bond0
+SLAVE=yes
+BOOTPROTO=none
+
+(use DEVICE=eth1 for eth1 and MASTER=bond1 for bond1 if you have configured
+second bonding interface).
+
+Restart the networking subsystem or just bring up the bonding device if your
+administration tools allow it. Otherwise, reboot. (For the case of RedHat
+distros, you can do `ifup bond0' or `/etc/rc.d/init.d/network restart'.)
+
+If the administration tools of your distribution do not support master/slave
+notation in configuration of network interfaces, you will need to configure
+the bonding device with the following commands manually:
+
+ # /sbin/ifconfig bond0 192.168.1.1 up
+ # /sbin/ifenslave bond0 eth0
+ # /sbin/ifenslave bond0 eth1
+
+(substitute 192.168.1.1 with your IP address and add custom network and custom
+netmask to the arguments of ifconfig if required).
+
+You can then create a script with these commands and put it into the appropriate
+rc directory.
+
+If you specifically need that all your network drivers are loaded before the
+bonding driver, use one of modutils' powerful features : in your modules.conf,
+tell that when asked for bond0, modprobe should first load all your interfaces :
+
+probeall bond0 eth0 eth1 bonding
+
+Be careful not to reference bond0 itself at the end of the line, or modprobe will
+die in an endless recursive loop.
+
+4) Module parameters.
+---------------------
+The following module parameters can be passed:
+
+ mode=
+
+Possible values are 0 (round robin policy, default) and 1 (active backup
+policy), and 2 (XOR). See question 9 and the HA section for additional info.
+
+ miimon=
+
+Use integer value for the frequency (in ms) of MII link monitoring. Zero value
+is default and means the link monitoring will be disabled. A good value is 100
+if you wish to use link monitoring. See HA section for additional info.
+
+ downdelay=
+
+Use integer value for delaying disabling a link by this number (in ms) after
+the link failure has been detected. Must be a multiple of miimon. Default
+value is zero. See HA section for additional info.
+
+ updelay=
+
+Use integer value for delaying enabling a link by this number (in ms) after
+the "link up" status has been detected. Must be a multiple of miimon. Default
+value is zero. See HA section for additional info.
+
+ arp_interval=
+
+Use integer value for the frequency (in ms) of arp monitoring. Zero value
+is default and means the arp monitoring will be disabled. See HA section
+for additional info. This field is value in active_backup mode only.
+
+ arp_ip_target=
+
+An ip address to use when arp_interval is > 0. This is the target of the
+arp request sent to determine the health of the link to the target.
+Specify this value in ddd.ddd.ddd.ddd format.
+
+If you need to configure several bonding devices, the driver must be loaded
+several times. I.e. for two bonding devices, your /etc/conf.modules must look
+like this:
+
+alias bond0 bonding
+alias bond1 bonding
+
+options bond0 miimon=100
+options bond1 -o bonding1 miimon=100
+
+5) Testing configuration
+------------------------
+You can test the configuration and transmit policy with ifconfig. For example,
+for round robin policy, you should get something like this:
+
+[root]# /sbin/ifconfig
+bond0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4
+ inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0
+ UP BROADCAST RUNNING MASTER MULTICAST MTU:1500 Metric:1
+ RX packets:7224794 errors:0 dropped:0 overruns:0 frame:0
+ TX packets:3286647 errors:1 dropped:0 overruns:1 carrier:0
+ collisions:0 txqueuelen:0
+
+eth0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4
+ inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0
+ UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1
+ RX packets:3573025 errors:0 dropped:0 overruns:0 frame:0
+ TX packets:1643167 errors:1 dropped:0 overruns:1 carrier:0
+ collisions:0 txqueuelen:100
+ Interrupt:10 Base address:0x1080
+
+eth1 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4
+ inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0
+ UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1
+ RX packets:3651769 errors:0 dropped:0 overruns:0 frame:0
+ TX packets:1643480 errors:0 dropped:0 overruns:0 carrier:0
+ collisions:0 txqueuelen:100
+ Interrupt:9 Base address:0x1400
+
+Questions :
+===========
+
+1. Is it SMP safe?
+
+ Yes. The old 2.0.xx channel bonding patch was not SMP safe.
+ The new driver was designed to be SMP safe from the start.
+
+2. What type of cards will work with it?
+
+ Any Ethernet type cards (you can even mix cards - a Intel
+ EtherExpress PRO/100 and a 3com 3c905b, for example).
+ You can even bond together Gigabit Ethernet cards!
+
+3. How many bonding devices can I have?
+
+ One for each module you load. See section on module parameters for how
+ to accomplish this.
+
+4. How many slaves can a bonding device have?
+
+ Limited by the number of network interfaces Linux supports and the
+ number of cards you can place in your system.
+
+5. What happens when a slave link dies?
+
+ If your ethernet cards support MII status monitoring and the MII
+ monitoring has been enabled in the driver (see description of module
+ parameters), there will be no adverse consequences. This release
+ of the bonding driver knows how to get the MII information and
+ enables or disables its slaves according to their link status.
+ See section on HA for additional information.
+
+ For ethernet cards not supporting MII status, or if you wish to
+ verify that packets have been both send and received, you may
+ configure the arp_interval and arp_ip_target. If packets have
+ not been sent or received during this interval, an arp request
+ is sent to the target to generate send and receive traffic.
+ If after this interval, either the successful send and/or
+ receive count has not incremented, the next slave in the sequence
+ will become the active slave.
+
+ If neither mii_monitor and arp_interval is configured, the bonding
+ driver will not handle this situation very well. The driver will
+ continue to send packets but some packets will be lost. Retransmits
+ will cause serious degradation of performance (in the case when one
+ of two slave links fails, 50% packets will be lost, which is a serious
+ problem for both TCP and UDP).
+
+6. Can bonding be used for High Availability?
+
+ Yes, if you use MII monitoring and ALL your cards support MII link
+ status reporting. See section on HA for more information.
+
+7. Which switches/systems does it work with?
+
+ In round-robin mode, it works with systems that support trunking:
+
+ * Cisco 5500 series (look for EtherChannel support).
+ * SunTrunking software.
+ * Alteon AceDirector switches / WebOS (use Trunks).
+ * BayStack Switches (trunks must be explicitly configured). Stackable
+ models (450) can define trunks between ports on different physical
+ units.
+ * Linux bonding, of course !
+
+ In Active-backup mode, it should work with any Layer-II switches.
+
+8. Where does a bonding device get its MAC address from?
+
+ If not explicitly configured with ifconfig, the MAC address of the
+ bonding device is taken from its first slave device. This MAC address
+ is then passed to all following slaves and remains persistent (even if
+ the the first slave is removed) until the bonding device is brought
+ down or reconfigured.
+
+ If you wish to change the MAC address, you can set it with ifconfig:
+
+ # ifconfig bond0 ha ether 00:11:22:33:44:55
+
+ The MAC address can be also changed by bringing down/up the device
+ and then changing its slaves (or their order):
+
+ # ifconfig bond0 down ; modprobe -r bonding
+ # ifconfig bond0 .... up
+ # ifenslave bond0 eth...
+
+ This method will automatically take the address from the next slave
+ that will be added.
+
+ To restore your slaves' MAC addresses, you need to detach them
+ from the bond (`ifenslave -d bond0 eth0'), set them down
+ (`ifconfig eth0 down'), unload the drivers (`rmmod 3c59x', for
+ example) and reload them to get the MAC addresses from their
+ eeproms. If the driver is shared by several devices, you need
+ to turn them all down. Another solution is to look for the MAC
+ address at boot time (dmesg or tail /var/log/messages) and to
+ reset it by hand with ifconfig :
+
+ # ifconfig eth0 down
+ # ifconfig eth0 hw ether 00:20:40:60:80:A0
+
+9. Which transmit polices can be used?
+
+ Round robin, based on the order of enslaving, the output device
+ is selected base on the next available slave. Regardless of
+ the source and/or destination of the packet.
+
+ XOR, based on (src hw addr XOR dst hw addr) % slave cnt. This
+ selects the same slave for each destination hw address.
+
+ Active-backup policy that ensures that one and only one device will
+ transmit at any given moment. Active-backup policy is useful for
+ implementing high availability solutions using two hubs (see
+ section on HA).
+
+High availability
+=================
+
+To implement high availability using the bonding driver, you need to
+compile the driver as module because currently it is the only way to pass
+parameters to the driver. This may change in the future.
+
+High availability is achieved by using MII status reporting. You need to
+verify that all your interfaces support MII link status reporting. On Linux
+kernel 2.2.17, all the 100 Mbps capable drivers and yellowfin gigabit driver
+support it. If your system has an interface that does not support MII status
+reporting, a failure of its link will not be detected!
+
+The bonding driver can regularly check all its slaves links by checking the
+MII status registers. The check interval is specified by the module argument
+"miimon" (MII monitoring). It takes an integer that represents the
+checking time in milliseconds. It should not come to close to (1000/HZ)
+(10 ms on i386) because it may then reduce the system interactivity. 100 ms
+seems to be a good value. It means that a dead link will be detected at most
+100 ms after it goes down.
+
+Example:
+
+ # modprobe bonding miimon=100
+
+Or, put in your /etc/modules.conf :
+
+ alias bond0 bonding
+ options bond0 miimon=100
+
+There are currently two policies for high availability, depending on whether
+a) hosts are connected to a single host or switch that support trunking
+b) hosts are connected to several different switches or a single switch that
+ does not support trunking.
+
+1) HA on a single switch or host - load balancing
+-------------------------------------------------
+It is the easiest to set up and to understand. Simply configure the
+remote equipment (host or switch) to aggregate traffic over several
+ports (Trunk, EtherChannel, etc.) and configure the bonding interfaces.
+If the module has been loaded with the proper MII option, it will work
+automatically. You can then try to remove and restore different links
+and see in your logs what the driver detects. When testing, you may
+encounter problems on some buggy switches that disable the trunk for a
+long time if all ports in a trunk go down. This is not Linux, but really
+the switch (reboot it to ensure).
+
+Example 1 : host to host at double speed
+
+ +----------+ +----------+
+ | |eth0 eth0| |
+ | Host A +--------------------------+ Host B |
+ | +--------------------------+ |
+ | |eth1 eth1| |
+ +----------+ +----------+
+
+ On each host :
+ # modprobe bonding miimon=100
+ # ifconfig bond0 addr
+ # ifenslave bond0 eth0 eth1
+
+Example 2 : host to switch at double speed
+
+ +----------+ +----------+
+ | |eth0 port1| |
+ | Host A +--------------------------+ switch |
+ | +--------------------------+ |
+ | |eth1 port2| |
+ +----------+ +----------+
+
+ On host A : On the switch :
+ # modprobe bonding miimon=100 # set up a trunk on port1
+ # ifconfig bond0 addr and port2
+ # ifenslave bond0 eth0 eth1
+
+2) HA on two or more switches (or a single switch without trunking support)
+---------------------------------------------------------------------------
+This mode is more problematic because it relies on the fact that there
+are multiple ports and the host's MAC address should be visible on one
+port only to avoid confusing the switches.
+
+If you need to know which interface is the active one, and which ones are
+backup, use ifconfig. All backup interfaces have the NOARP flag set.
+
+To use this mode, pass "mode=1" to the module at load time :
+
+ # modprobe bonding miimon=100 mode=1
+
+Or, put in your /etc/modules.conf :
+
+ alias bond0 bonding
+ options bond0 miimon=100 mode=1
+
+Example 1: Using multiple host and multiple switches to build a "no single
+point of failure" solution.
+
+
+ | |
+ |port3 port3|
+ +-----+----+ +-----+----+
+ | |port7 ISL port7| |
+ | switch A +--------------------------+ switch B |
+ | +--------------------------+ |
+ | |port8 port8| |
+ +----++----+ +-----++---+
+ port2||port1 port1||port2
+ || +-------+ ||
+ |+-------------+ host1 +---------------+|
+ | eth0 +-------+ eth1 |
+ | |
+ | +-------+ |
+ +--------------+ host2 +----------------+
+ eth0 +-------+ eth1
+
+In this configuration, there are an ISL - Inter Switch Link (could be a trunk),
+several servers (host1, host2 ...) attached to both switches each, and one or
+more ports to the outside world (port3...). One an only one slave on each host
+is active at a time, while all links are still monitored (the system can
+detect a failure of active and backup links).
+
+Each time a host changes its active interface, it sticks to the new one until
+it goes down. In this example, the hosts are not too much affected by the
+expiration time of the switches' forwarding tables.
+
+If host1 and host2 have the same functionality and are used in load balancing
+by another external mechanism, it is good to have host1's active interface
+connected to one switch and host2's to the other. Such system will survive
+a failure of a single host, cable, or switch. The worst thing that may happen
+in the case of a switch failure is that half of the hosts will be temporarily
+unreachable until the other switch expires its tables.
+
+Example 2: Using multiple ethernet cards connected to a switch to configure
+ NIC failover (switch is not required to support trunking).
+
+
+ +----------+ +----------+
+ | |eth0 port1| |
+ | Host A +--------------------------+ switch |
+ | +--------------------------+ |
+ | |eth1 port2| |
+ +----------+ +----------+
+
+ On host A : On the switch :
+ # modprobe bonding miimon=100 mode=1 # (optional) minimize the time
+ # ifconfig bond0 addr # for table expiration
+ # ifenslave bond0 eth0 eth1
+
+Each time the host changes its active interface, it sticks to the new one until
+it goes down. In this example, the host is strongly affected by the expiration
+time of the switch forwarding table.
+
+3) Adapting to your switches' timing
+------------------------------------
+If your switches take a long time to go into backup mode, it may be
+desirable not to activate a backup interface immediately after a link goes
+down. It is possible to delay the moment at which a link will be
+completely disabled by passing the module parameter "downdelay" (in
+milliseconds, must be a multiple of miimon).
+
+When a switch reboots, it is possible that its ports report "link up" status
+before they become usable. This could fool a bond device by causing it to
+use some ports that are not ready yet. It is possible to delay the moment at
+which an active link will be reused by passing the module parameter "updelay"
+(in milliseconds, must be a multiple of miimon).
+
+A similar situation can occur when a host re-negotiates a lost link with the
+switch (a case of cable replacement).
+
+A special case is when a bonding interface has lost all slave links. Then the
+driver will immediately reuse the first link that goes up, even if updelay
+parameter was specified. (If there are slave interfaces in the "updelay" state,
+the interface that first went into that state will be immediately reused.) This
+allows to reduce down-time if the value of updelay has been overestimated.
+
+Examples :
+
+ # modprobe bonding miimon=100 mode=1 downdelay=2000 updelay=5000
+ # modprobe bonding miimon=100 mode=0 downdelay=0 updelay=5000
+
+4) Limitations
+--------------
+The main limitations are :
+ - only the link status is monitored. If the switch on the other side is
+ partially down (e.g. doesn't forward anymore, but the link is OK), the link
+ won't be disabled. Another way to check for a dead link could be to count
+ incoming frames on a heavily loaded host. This is not applicable to small
+ servers, but may be useful when the front switches send multicast
+ information on their links (e.g. VRRP), or even health-check the servers.
+ Use the arp_interval/arp_ip_target parameters to count incoming/outgoing
+ frames.
+
+Resources and links
+===================
+
+Current developement on this driver is posted to:
+ - http://www.sourceforge.net/projects/bonding/
+
+Donald Becker's Ethernet Drivers and diag programs may be found at :
+ - http://www.scyld.com/network/
+
+You will also find a lot of information regarding Ethernet, NWay, MII, etc. at
+www.scyld.com.
+
+For new versions of the driver, patches for older kernels and the updated
+userspace tools, take a look at Willy Tarreau's site :
+ - http://wtarreau.free.fr/pub/bonding/


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

echo 'End of part 019'
echo 'File patch-2.4.15 is continued in part 020'
echo "020" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:39 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part003

#!/bin/sh -x
# this is part 003 of a 115 - part archive


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

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

+ SuperI/O (2S, 1P, FD), RTC/NVRAM. Boot ROM is EPROM. PC-AT size.
+ Runs from standard PC power supply.
+
+EB66
+CONFIG_ALPHA_EB66
+ A Digital DS group board. Uses 21066 or 21066A. I/O sub-system is
+ identical to EB64+. Baby PC-AT size. Runs from standard PC power
+ supply. The EB66 schematic was published as a marketing poster
+ advertising the 21066 as "the first microprocessor in the world with
+ embedded PCI".
+
+EB66+
+CONFIG_ALPHA_EB66P
+ Later variant of the EB66 board.
+
+Eiger
+CONFIG_ALPHA_EIGER
+ Apparently an obscure OEM single-board computer based on the
+ Typhoon/Tsunami chipset family. Information on it is scanty.
+
+Jensen
+CONFIG_ALPHA_JENSEN
+ DEC PC 150 AXP (aka Jensen): This is a very old Digital system - one
+ of the first-generation Alpha systems. A number of these systems
+ seem to be available on the second- hand market. The Jensen is a
+ floor-standing tower system which originally used a 150MHz 21064 It
+ used programmable logic to interface a 486 EISA I/O bridge to the
+ CPU.
+
+LX164
+CONFIG_ALPHA_LX164
+ A technical overview of this board is available at
+ <http://www.unix-ag.org/Linux-Alpha/Architectures/LX164.html>.
+
+Miata
+CONFIG_ALPHA_MIATA
+ The Digital PersonalWorkStation (PWS 433a, 433au, 500a, 500au, 600a,
+ or 600au). There is an Installation HOWTO for this hardware at
+ <http://members.brabant.chello.nl/~s.vandereijk/miata.html>.
+
+Mikasa
+CONFIG_ALPHA_MIKASA
+ AlphaServer 1000-based Alpha systems.
+
+Nautilus
+CONFIG_ALPHA_NAUTILUS
+ Alpha systems based on the AMD 751 & ALI 1543C chipsets.
+
+Noname
+CONFIG_ALPHA_NONAME
+ The AXPpci33 (aka NoName), is based on the EB66 (includes the Multia
+ UDB). This design was produced by Digital's Technical OEM (TOEM)
+ group. It uses the 21066 processor running at 166MHz or 233MHz. It
+ is a baby-AT size, and runs from a standard PC power supply. It has
+ 5 ISA slots and 3 PCI slots (one pair are a shared slot). There are
+ 2 versions, with either PS/2 or large DIN connectors for the
+ keyboard.
+
+Noritake
+CONFIG_ALPHA_NORITAKE
+ AlphaServer 1000A, AlphaServer 600A, and AlphaServer 800-based
+ systems.
+
+Rawhide
+CONFIG_ALPHA_RAWHIDE
+ AlphaServer 1200, AlphaServer 4000 and AlphaServer 4100 machines.
+ See HOWTO at
+ <http://www.alphalinux.org/docs/rawhide/4100_install.shtml>.
+
+Ruffian
+CONFIG_ALPHA_RUFFIAN
+ Samsung APC164UX. There is a page on known problems and workarounds
+ at <http://www.alphalinux.org/faq/FAQ-11.html>.
+
+Sable
+CONFIG_ALPHA_SABLE
+ Digital AlphaServer 2000 and 2100-based systems.
+
+Takara
+CONFIG_ALPHA_TAKARA
+ Alpha 11164-based OEM single-board computer.
+
+Wildfire
+CONFIG_ALPHA_WILDFIRE
+ AlphaServer GS 40/80/160/320 SMP based on the EV67 core.
+
+EV5 CPU daughtercard (model 5/xxx)
X CONFIG_ALPHA_PRIMO
X Say Y if you have an AS 1000 5/xxx or an AS 1000A 5/xxx.
X
-EV5 CPU(s)
+EV5 CPU(s) (model 5/xxx)
X CONFIG_ALPHA_GAMMA
X Say Y if you have an AS 2000 5/xxx or an AS 2100 5/xxx.
X
-Using SRM as bootloader
+Use SRM as bootloader
X CONFIG_ALPHA_SRM
X There are two different types of booting firmware on Alphas: SRM,
X which is command line driven, and ARC, which uses menus and arrow
X keys. Details about the Linux/Alpha booting process are contained in
X the Linux/Alpha FAQ, accessible on the WWW from
- http://www.alphalinux.org .
+ <http://www.alphalinux.org>.
X
X The usual way to load Linux on an Alpha machine is to use MILO
X (a bootloader that lets you pass command line parameters to the
@@ -2521,7 +2972,7 @@
X here. If MILO doesn't work on your system (true for Jensen
X motherboards), you can bypass it altogether and boot Linux directly
X from an SRM console; say Y here in order to do that. Note that you
- won't be able to boot from an IDE disk using SRM.
+ won't be able to boot from an IDE disk using SRM.


X
X If unsure, say N.
X

@@ -2530,20 +2981,20 @@
X The 2.4 kernel changed the kernel start address from 0x310000
X to 0x810000 to make room for the Wildfire's larger SRM console.
X
- If you're using aboot 0.7 or later, the bootloader will examine
- the ELF headers to determine where to transfer control. Unfortunately,
- most older bootloaders -- APB or MILO -- hardcoded the kernel
- start address rather than examining the ELF headers, and the result
- is a hard lockup.
+ If you're using aboot 0.7 or later, the bootloader will examine the
+ ELF headers to determine where to transfer control. Unfortunately,
+ most older bootloaders -- APB or MILO -- hardcoded the kernel start
+ address rather than examining the ELF headers, and the result is a
+ hard lockup.
X
- Say Y if you have a broken bootloader. Say N if you do not, or
- if you wish to run on Wildfire.
+ Say Y if you have a broken bootloader. Say N if you do not, or if
+ you wish to run on Wildfire.
X
X Large VMALLOC support
X CONFIG_ALPHA_LARGE_VMALLOC
- Process creation and other aspects of virtual memory management
- can be streamlined if we restrict the kernel to one PGD for all
- vmalloc allocations. This equates to about 8GB.
+ Process creation and other aspects of virtual memory management can
+ be streamlined if we restrict the kernel to one PGD for all vmalloc
+ allocations. This equates to about 8GB.
X
X Under normal circumstances, this is so far and above what is needed
X as to be laughable. However, there are certain applications (such
@@ -2559,11 +3010,11 @@
X This includes intelligent serial boards such as Cyclades,
X Digiboards, etc. These are usually used for systems that need many
X serial ports because they serve many terminals or dial-in
- connections.
+ connections.


X
X Note that the answer to this question won't directly affect the
- kernel: saying N will just cause this configure script to skip all

- the questions about non-standard serial boards.

+ kernel: saying N will just cause the configurator to skip all

+ the questions about non-standard serial boards.
X
X Most people can say N here.
X
@@ -2572,10 +3023,10 @@
X If you wish to use any non-standard features of the standard "dumb"
X driver, say Y here. This includes HUB6 support, shared serial
X interrupts, special multiport support, support for more than the
- four COM 1/2/3/4 boards, etc.
+ four COM 1/2/3/4 boards, etc.


X
X Note that the answer to this question won't directly affect the
- kernel: saying N will just cause this configure script to skip all
+ kernel: saying N will just cause the configurator to skip all

X the questions about serial driver options. If unsure, say N.
X
X Support more than 4 serial ports
@@ -2583,22 +3034,30 @@
X Say Y here if you have dumb serial boards other than the four
X standard COM 1/2/3/4 ports. This may happen if you have an AST
X FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
- from http://www.linuxdoc.org/docs.html#howto ), or other custom
+ from <http://www.linuxdoc.org/docs.html#howto>), or other custom
X serial port hardware which acts similar to standard serial port
X hardware. If you only use the standard COM 1/2/3/4 ports, you can
X say N here to save some memory. You can also say Y if you have an
X "intelligent" multiport card such as Cyclades, Digiboards, etc.
X
+Support for serial ports defined by ACPI tables
+CONFIG_SERIAL_ACPI
+ Legacy free machines may not have serial ports at the legacy COM1,
+ COM2 etc addresses. Serial ports on such machines are described by
+ the ACPI tables SPCR (Serial Port Console Redirection) table and
+ DBGP (Debug Port) table. Say Y here if you want to include support
+ for these serial ports.
+
X Support for sharing serial interrupts
X CONFIG_SERIAL_SHARE_IRQ
X Some serial boards have hardware support which allows multiple dumb
X serial ports on the same board to share a single IRQ. To enable
X support for this in the serial driver, say Y here.
X
-Auto detect IRQ on standard ports (unsafe)
+Auto-detect IRQ on standard ports (unsafe)
X CONFIG_SERIAL_DETECT_IRQ
X Say Y here if you want the kernel to try to guess which IRQ
- to use for your serial port.
+ to use for your serial port.
X
X This is considered unsafe; it is far better to configure the IRQ in
X a boot script using the setserial command.
@@ -2612,16 +3071,12 @@
X servicing. Say Y here to enable the serial driver to take advantage
X of those special I/O ports.
X
-SGI PROM Console Support
-CONFIG_ARC_CONSOLE
- Say Y here if you want to use the PROMs for console I/O.
-
X SGI Zilog85C30 serial support
X CONFIG_SGI_SERIAL
X If you want to use your SGI's built-in serial ports under Linux,
X answer Y.
X
-SGI Newport Graphics support (EXPERIMENTAL)
+SGI Newport Graphics support
X CONFIG_SGI_NEWPORT_GFX
X If you have an SGI machine and you want to compile the graphics
X drivers, say Y here. This will include the code for the
@@ -2651,14 +3106,14 @@
X CONFIG_PCMCIA_SERIAL_CS
X Say Y here to enable support for 16-bit PCMCIA serial devices,
X including serial port cards, modems, and the modem functions of
- multi-function ethernet/modem cards. (PCMCIA- or PC-cards are
+ multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are
X credit-card size devices often used with laptops.)
X
X This driver is also available as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want).

- The module will be called serial_cs.o. If you want to compile it as
- a module, say M here and read Documentation/modules.txt. If unsure,
- say N.
+ The module will be called serial_cs.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.


+ If unsure, say N.

X
X ACP Modem (Mwave) support
X CONFIG_MWAVE
@@ -2685,17 +3140,14 @@
X The module will be called mwave.o. If you want to compile it as
X a module, say M here and read Documentation/modules.txt.
X
-/dev/agpgart (AGP Support) (EXPERIMENTAL)
+/dev/agpgart (AGP Support)
X CONFIG_AGP
X AGP (Accelerated Graphics Port) is a bus system mainly used to
- connect graphics cards to the rest of the system.
+ connect graphics cards to the rest of the system.
X
X If you have an AGP system and you say Y here, it will be possible to
X use the AGP features of your 3D rendering video card. This code acts
- as a sort of "AGP driver" for the motherboard's chipset. The glx
- module will then be able to program the GART (graphics aperture
- relocation table) registers with appropriate values to transfer
- commands to the card.
+ as a sort of "AGP driver" for the motherboard's chipset.
X
X If you need more texture memory than you can get with the AGP GART
X (theoretically up to 256 MB, but in practice usually 64 or 128 MB
@@ -2706,47 +3158,42 @@
X write-combining with MTRR support on the AGP bus. Without it, OpenGL
X direct rendering will be a lot slower but still faster than PIO.
X
- For the moment, you should probably say N, unless you want to test
- the GLX component for XFree86 3.3.6, which can be downloaded from
- http://utah-glx.sourceforge.net/ , or need to use the 810 Xserver in
- XFree 3.3.6.
-
- This driver is available as a module. If you want to compile it as a
- module, say M here and read Documentation/modules.txt. The module
- will be called agpgart.o.
+ You should say Y here if you use XFree86 3.3.6 or 4.x and want to
+ use GLX or DRI. If unsure, say N.
+
+ This driver is available as a module. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>. The
+ module will be called agpgart.o.
X
-Intel 440LX/BX/GX/815/830M/840/850 support
+Intel 440LX/BX/GX/815/820/830/840/845/850/860 support
X CONFIG_AGP_INTEL
X This option gives you AGP support for the GLX component of the
- XFree86 4.x on Intel 440LX/BX/GX, 815, 830M, 840 and 850 chipsets.
+ XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850 and 860 chipsets.
X
- For the moment, you should probably say N, unless you want to test
- the GLX component for XFree86 3.3.6, which can be downloaded from
- http://utah-glx.sourceforge.net/ .
+ You should say Y here if you use XFree86 3.3.6 or 4.x and want to
+ use GLX or DRI. If unsure, say N.
X
-Intel I810/I810 DC100/I810e support
+Intel I810/I815 DC100/I810e support
X CONFIG_AGP_I810
- This option gives you AGP support for the Xserver on the Intel 810,
- 830M and 815 chipset boards for their on-board integrated graphics.
- This is required to do any useful video modes with these boards.
+ This option gives you AGP support for the Xserver on the Intel 810
+ 815 and 830m chipset boards for their on-board integrated graphics. This
+ is required to do any useful video modes with these boards.
X
X VIA chipset support
X CONFIG_AGP_VIA
X This option gives you AGP support for the GLX component of the
X XFree86 4.x on VIA MPV3/Apollo Pro chipsets.
X
- For the moment, you should probably say N, unless you want to test
- the GLX component for XFree86 3.3.6, which can be downloaded from
- http://utah-glx.sourceforge.net/ .
+ You should say Y here if you use XFree86 3.3.6 or 4.x and want to
+ use GLX or DRI. If unsure, say N.
X
X AMD Irongate, 761, and 762 support
X CONFIG_AGP_AMD
X This option gives you AGP support for the GLX component of the
X XFree86 4.x on AMD Irongate, 761, and 762 chipsets.
X
- For the moment, you should probably say N, unless you want to test
- the GLX component for XFree86 3.3.6, which can be downloaded from
- http://utah-glx.sourceforge.net/ .
+ You should say Y here if you use XFree86 3.3.6 or 4.x and want to
+ use GLX or DRI. If unsure, say N.
X
X Generic SiS support
X CONFIG_AGP_SIS
@@ -2756,33 +3203,47 @@
X
X Note that 5591/5592 AGP chipsets are NOT supported.
X
- For the moment, you should probably say N, unless you want to test
- the GLX component for XFree86 3.3.6, which can be downloaded from
- http://utah-glx.sourceforge.net/ .
+ You should say Y here if you use XFree86 3.3.6 or 4.x and want to
+ use GLX or DRI. If unsure, say N.
X
-ALI M1541 support
+Serverworks LE/HE support
+CONFIG_AGP_SWORKS
+ Say Y here to support the Serverworks AGP card. See
+ <http://www.serverworks.com/> for product descriptions and images.
+
+ALI chipset support
X CONFIG_AGP_ALI
X This option gives you AGP support for the GLX component of the
- XFree86 4.x on the ALi M1541 chipset.
+ XFree86 4.x on the following ALi chipsets. The supported chipsets
+ include M1541, M1621, M1631, M1632, M1641,M1647,and M1651.
+ For the ALi-chipset question, ALi suggests you refer to
+ <http://www.ali.com.tw/eng/support/index.shtml>.
X
- This chipset can do AGP 1x and 2x, but note that there is an
+ The M1541 chipset can do AGP 1x and 2x, but note that there is an
X acknowledged incompatibility with Matrox G200 cards. Due to
X timing issues, this chipset cannot do AGP 2x with the G200.
X This is a hardware limitation. AGP 1x seems to be fine, though.
X
- For the moment, you should probably say N, unless you want to test
- the GLX component for XFree86 3.3.6, which can be downloaded from
- http://utah-glx.sourceforge.net/ .
+ You should say Y here if you use XFree86 3.3.6 or 4.x and want to
+ use GLX or DRI. If unsure, say N.
X
-PCI support
+Support for ISA-bus hardware
+CONFIG_ISA
+ Find out whether you have ISA slots on your motherboard. ISA is the
+ name of a bus system, i.e. the way the CPU talks to the other stuff
+ inside your box. Other bus systems are PCI, EISA, MicroChannel
+ (MCA) or VESA. ISA is an older system, now being displaced by PCI;
+ newer boards don't support it. If you have ISA, say Y, otherwise N.
+
+Support for PCI bus hardware
X CONFIG_PCI
X Find out whether you have a PCI motherboard. PCI is the name of a
X bus system, i.e. the way the CPU talks to the other stuff inside
- your box. Other bus systems are ISA, EISA, Microchannel (MCA) or
- VESA. If you have PCI, say Y, otherwise N.
+ your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
+ VESA. If you have PCI, say Y, otherwise N.
X
X The PCI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto , contains valuable
+ <http://www.linuxdoc.org/docs.html#howto>, contains valuable
X information about which PCI hardware does work under Linux and which
X doesn't.
X
@@ -2790,11 +3251,11 @@
X CONFIG_PCI_INTEGRATOR
X Find out whether you have a PCI motherboard. PCI is the name of a
X bus system, i.e. the way the CPU talks to the other stuff inside
- your box. Other bus systems are ISA, EISA, Microchannel (MCA) or
- VESA. If you have PCI, say Y, otherwise N.
+ your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
+ VESA. If you have PCI, say Y, otherwise N.
X
X The PCI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto , contains valuable
+ <http://www.linuxdoc.org/docs.html#howto>, contains valuable
X information about which PCI hardware does work under Linux and which
X doesn't.
X
@@ -2802,14 +3263,15 @@
X CONFIG_PCI_QSPAN
X Find out whether you have a PCI motherboard. PCI is the name of a
X bus system, i.e. the way the CPU talks to the other stuff inside
- your box. Other bus systems are ISA, EISA, Microchannel (MCA) or
- VESA. If you have PCI, say Y, otherwise N.
+ your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
+ VESA. If you have PCI, say Y, otherwise N.
X
X The PCI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto , contains valuable
+ <http://www.linuxdoc.org/docs.html#howto>, contains valuable
X information about which PCI hardware does work under Linux and which
X doesn't.
X
+# Choice: pci_access
X PCI access mode
X CONFIG_PCI_GOBIOS
X On PCI systems, the BIOS can be used to detect the PCI devices and
@@ -2838,22 +3300,56 @@
X
X When in doubt, say Y.
X
+PCI Hotplug support
+CONFIG_HOTPLUG_PCI
+ Say Y here if you have a motherboard with a PCI Hotplug controller.
+ This allows you to add and remove PCI cards while the machine is
+ powered up and running. The file system pcihpfs must be mounted
+ in order to interact with any PCI Hotplug controllers.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called pci_hotplug.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+ When in doubt, say N.
+
+PCI Compaq Hotplug controller
+CONFIG_HOTPLUG_PCI_COMPAQ
+ Say Y here if you have a motherboard with a Compaq PCI Hotplug
+ controller.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called cpqphp.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+ When in doubt, say N.
+
+PCI Compaq Hotplug controller NVRAM support
+CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM
+ Say Y here if you have a Compaq server that has a PCI Hotplug
+ controller. This will allow the PCI Hotplug driver to store the PCI
+ system configuration options in NVRAM.
+
+ When in doubt, say N.
+
X MCA support
X CONFIG_MCA
X MicroChannel Architecture is found in some IBM PS/2 machines and
- laptops. It is a bus system similar to PCI or ISA. See
- Documentation/mca.txt (and especially the web page given there)
- before attempting to build an MCA bus kernel.
+ laptops. It is a bus system similar to PCI or ISA. See
+ <file:Documentation/mca.txt> (and especially the web page given
+ there) before attempting to build an MCA bus kernel.
X
-EISA support
+Support for EISA-bus hardware
X CONFIG_EISA
X The Extended Industry Standard Architecture (EISA) bus was
X developed as an open alternative to the IBM MicroChannel bus.
X
X The EISA bus provided some of the features of the IBM MicroChannel
X bus while maintaining backward compatibility with cards made for
- the older ISA bus. The EISA bus saw limited use between 1988 and 1995
- when it was made obsolete by the PCI bus.
+ the older ISA bus. The EISA bus saw limited use between 1988 and
+ 1995 when it was made obsolete by the PCI bus.
X
X Say Y here if you are building a kernel for an EISA-based machine.
X
@@ -2866,7 +3362,7 @@
X Say Y here to create a kernel to run on the SGI 320 or 540.
X A kernel compiled for the Visual Workstation will not run on other
X PC boards and vice versa.
- See Documentation/sgi-visws.txt for more.
+ See <file:Documentation/sgi-visws.txt> for more.
X
X SGI Visual Workstation framebuffer support
X CONFIG_FB_SGIVW
@@ -2891,8 +3387,8 @@
X This support is also available as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want).
X If you want to compile it as a module, say M here and read

- Documentation/modules.txt. You will get modules called i2o_core.o
- and i2o_config.o.
+ <file:Documentation/modules.txt>. You will get modules called
+ i2o_core.o and i2o_config.o.


X
X If unsure, say N.
X

@@ -2904,7 +3400,7 @@
X This support is also available as a module called i2o_pci.o ( = code
X which can be inserted in and removed from the running kernel


X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

X I2O Block OSM
X CONFIG_I2O_BLOCK
@@ -2914,7 +3410,7 @@
X This support is also available as a module called i2o_block.o ( =


X code which can be inserted in and removed from the running kernel
X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

X I2O LAN OSM
X CONFIG_I2O_LAN
@@ -2925,7 +3421,7 @@
X This support is also available as a module called i2o_lan.o ( = code
X which can be inserted in and removed from the running kernel


X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

X I2O SCSI OSM
X CONFIG_I2O_SCSI
@@ -2936,7 +3432,7 @@
X This support is also available as a module called i2o_scsi.o ( =


X code which can be inserted in and removed from the running kernel
X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

X I2O /proc support
X CONFIG_I2O_PROC
@@ -2947,7 +3443,7 @@
X This support is also available as a module called i2o_proc.o ( =


X code which can be inserted in and removed from the running kernel
X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X

X Plug and Play support
X CONFIG_PNP
@@ -2959,24 +3455,41 @@
X
X Say Y here if you would like Linux to configure your Plug and Play
X devices. You should then also say Y to "ISA Plug and Play support",
- below. Alternatively, you can say N here and configure your PnP
+ below. Alternatively, you can say N here and configure your PnP
X devices using the user space utilities contained in the isapnptools
X package.
-
+
X This support is also available as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want).
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt.
+ <file:Documentation/modules.txt>.
X

X ISA Plug and Play support
X CONFIG_ISAPNP
X Say Y here if you would like support for ISA Plug and Play devices.
- Some information is in Documentation/isapnp.txt.
-
+ Some information is in <file:Documentation/isapnp.txt>.
+
X This support is also available as a module called isapnp.o ( =


X code which can be inserted in and removed from the running kernel
X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.

+
+ If unsure, say Y.
+
+PNPBIOS support
+CONFIG_PNPBIOS
+ Linux uses the PNPBIOS as defined in "Plug and Play BIOS
+ Specification Version 1.0A May 5, 1994" to autodetect built-in
+ mainboard resources (e.g. parallel port resources).
+
+ Other features (e.g. change resources, ESCD, event notification,
+ Docking station information, ISAPNP services) are not used.
+
+ Note: ACPI is expected to supersede PNPBIOS some day, currently it
+ co-exists nicely.
+
+ See latest pcmcia-cs (stand-alone package) for a nice "lspnp" tools,
+ or have a look at /proc/bus/pnp.


X
X If unsure, say Y.
X

@@ -2992,50 +3505,55 @@
X example, used on modern desktops as well as laptops, is USB.
X
X Enable HOTPLUG and KMOD, and build a modular kernel. Get agent
- software (at http://linux-hotplug.sourceforge.net) and install it.
+ software (at <http://linux-hotplug.sourceforge.net>) and install it.
X Then your kernel will automatically call out to a user mode "policy
X agent" (/sbin/hotplug) to load modules and set up software needed
X to use devices as you hotplug them.
X
-PCMCIA/Cardbus support
+PCMCIA/CardBus support
X CONFIG_PCMCIA
X Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
- computer. These are credit-card size devices such as network cards,
- modems or hard drives often used with laptops computers. There are
+ computer. These are credit-card size devices such as network cards,
+ modems or hard drives often used with laptops computers. There are
X actually two varieties of these cards: the older 16 bit PCMCIA cards
- and the newer 32 bit CardBus cards. If you want to use CardBus
+ and the newer 32 bit CardBus cards. If you want to use CardBus
X cards, you need to say Y here and also to "CardBus support" below.
X
- To use your PC-cards, you will need supporting software from David
- Hinds' pcmcia-cs package (see the file Documentation/Changes for
- location). Please also read the PCMCIA-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto
+ To use your PC-cards, you will need supporting software from David
+ Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
+ for location). Please also read the PCMCIA-HOWTO, available from

X This driver is also available as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want).

X When compiled this way, there will be modules called pcmcia_core.o
X and ds.o. If you want to compile it as a module, say M here and
- read Documentation/modules.txt.
+ read <file:Documentation/modules.txt>.
X
-CardBus support
+CardBus card and (Yenta) bridge support
X CONFIG_CARDBUS
- CardBus is a bus mastering architecture for PC-cards, which allows
- for 32 bit PC-cards (the original PCMCIA standard specifies only
+ CardBus is a bus mastering architecture for PC-cards, which allows
+ for 32 bit PC-cards (the original PCMCIA standard specifies only
X a 16 bit wide bus). Many newer PC-cards are actually CardBus cards.
X
- To use your PC-cards, you will need supporting software from David
- Hinds' pcmcia-cs package (see the file Documentation/Changes for
- location).
+ This option enables support for CardBus PC Cards, as well as support
+ for CardBus host bridges. Virtually all modern PCMCIA bridges are
+ CardBus compatible. A "bridge" is the hardware inside your computer
+ that PCMCIA cards are plugged into.
+
+ To use your PC-cards, you will need supporting software from David
+ Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
+ for location).


X
X If unsure, say Y.
X

-i82365/Yenta compatible bridge support
+i82365 compatible host bridge support
X CONFIG_I82365
- Say Y here to include support for PCMCIA and CardBus host bridges
- that are register compatible with the Intel i82365 and/or the Yenta
- specification: this includes virtually all modern PCMCIA bridges.
- "Bridge" is the name used for the hardware inside your computer that
- PCMCIA cards are plugged into. If unsure, say Y.
+ Say Y here to include support for ISA-bus PCMCIA host bridges that
+ are register compatible with the Intel i82365. These are found on
+ older laptops and ISA-bus card readers for desktop systems. A
+ "bridge" is the hardware inside your computer that PCMCIA cards are
+ plugged into. If unsure, say N.
X
X Databook TCIC host bridge support
X CONFIG_TCIC
@@ -3052,60 +3570,67 @@
X and some programs won't run unless you say Y here. In particular, if
X you want to run the DOS emulator dosemu under Linux (read the
X DOSEMU-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto ), you'll need to say Y
+ <http://www.linuxdoc.org/docs.html#howto>), you'll need to say Y
X here.
-
+
X You can find documentation about IPC with "info ipc" and also in
X section 6.4 of the Linux Programmer's Guide, available from
- http://www.linuxdoc.org/docs.html#guide .
+ <http://www.linuxdoc.org/docs.html#guide>.
X
X BSD Process Accounting
X CONFIG_BSD_PROCESS_ACCT
X If you say Y here, a user level program will be able to instruct the
X kernel (via a special system call) to write process accounting
X information to a file: whenever a process exits, information about
- that process will be appended to the file by the kernel. The
+ that process will be appended to the file by the kernel. The
X information includes things such as creation time, owning user,
X command name, memory usage, controlling terminal etc. (the complete
- list is in the struct acct in include/linux/acct.h). It is up to the
- user level program to do useful things with this information. This
- is generally a good idea, so say Y.
-
+ list is in the struct acct in <file:include/linux/acct.h>). It is
+ up to the user level program to do useful things with this
+ information. This is generally a good idea, so say Y.
+
X Sysctl support
X CONFIG_SYSCTL
X The sysctl interface provides a means of dynamically changing
X certain kernel parameters and variables on the fly without requiring
- a recompile of the kernel or reboot of the system. The primary
+ a recompile of the kernel or reboot of the system. The primary
X interface consists of a system call, but if you say Y to "/proc
X file system support", a tree of modifiable sysctl entries will be
X generated beneath the /proc/sys directory. They are explained in the
- files in Documentation/sysctl/. Note that enabling this option will
- enlarge the kernel by at least 8 KB.
+ files in <file:Documentation/sysctl/>. Note that enabling this
+ option will enlarge the kernel by at least 8 KB.
X
X As it is generally a good thing, you should say Y here unless
X building a kernel for install/rescue disks or your system is very
X limited in memory.
X
+# Choice: kcore
X Kernel core (/proc/kcore) format
X CONFIG_KCORE_ELF
- If you enabled support for /proc file system then the file
- /proc/kcore will contain the kernel core image. This can be used
+ If you enabled support for /proc file system then the file
+ /proc/kcore will contain the kernel core image. This can be used
X in gdb:
X
X $ cd /usr/src/linux ; gdb vmlinux /proc/kcore
X
- You have two choices here: ELF and A.OUT. Selecting ELF will make
+ You have two choices here: ELF and A.OUT. Selecting ELF will make
X /proc/kcore appear in ELF core format as defined by the Executable
X and Linking Format specification. Selecting A.OUT will choose the
X old "a.out" format which may be necessary for some old versions
X of binutils or on some architectures.
X
- This is especially useful if you have compiled the kernel with the
- "-g" option to preserve debugging information. It is mainly used
- for examining kernel data structures on the live kernel so if you
- don't understand what this means or are not a kernel hacker, just
+ This is especially useful if you have compiled the kernel with the
+ "-g" option to preserve debugging information. It is mainly used
+ for examining kernel data structures on the live kernel so if you
+ don't understand what this means or are not a kernel hacker, just
X leave it at its default value ELF.
X
+# Choice: kcore
+Select a.out format for /proc/kcore
+CONFIG_KCORE_AOUT
+ Not necessary unless you're using a very out-of-date binutils
+ version. You probably want KCORE_ELF.
+
X Kernel support for ELF binaries
X CONFIG_BINFMT_ELF
X ELF (Executable and Linkable Format) is a format for libraries and
@@ -3120,21 +3645,21 @@
X want to say Y here.
X
X Information about ELF is contained in the ELF HOWTO available from

X If you find that after upgrading from Linux kernel 1.2 and saying Y
X here, you still can't run any ELF binaries (they just crash), then
X you'll have to install the newest ELF runtime libraries, including
- ld.so (check the file Documentation/Changes for location and latest
- version).
+ ld.so (check the file <file:Documentation/Changes> for location and
+ latest version).


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called binfmt_elf.o. Saying M or N here is dangerous because some
- crucial programs on your system might be in ELF format.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called binfmt_elf.o. Saying M or N here is dangerous because
+ some crucial programs on your system might be in ELF format.
X
-Kernel support for A.OUT binaries
+Kernel support for a.out binaries
X CONFIG_BINFMT_AOUT
X A.out (Assembler.OUTput) is a set of formats for libraries and
X executables used in the earliest versions of UNIX. Linux used the
@@ -3162,12 +3687,17 @@
X this to work, you need to have the emulator /usr/bin/em86 in place.
X
X You can get the same functionality by saying N here and saying Y to
- "Kernel support for MISC binaries".
+ "Kernel support for MISC binaries".
X
X You may answer M to compile the emulation support as a module and
X later load the module when you want to use a Linux/Intel binary. The
X module will be called binfmt_em86.o. If unsure, say Y.
X
+Kernel support for SOM binaries
+CONFIG_BINFMT_SOM
+ SOM is a binary executable format inherited from HP/UX. Say Y here
+ to be able to load and execute SOM binaries directly.
+
X Kernel support for MISC binaries
X CONFIG_BINFMT_MISC
X If you say Y here, it will be possible to plug wrapper-driven binary
@@ -3175,15 +3705,15 @@
X programs that need an interpreter to run like Java, Python or
X Emacs-Lisp. It's also useful if you often run DOS executables under
X the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto ). Once you have
+ <http://www.linuxdoc.org/docs.html#howto>). Once you have
X registered such a binary class with the kernel, you can start one of
X those programs simply by typing in its name at a shell prompt; Linux
X will automatically feed it to the correct interpreter.
X
X You can do other nice things, too. Read the file
- Documentation/binfmt_misc.txt to learn how to use this feature, and
- Documentation/java.txt for information about how to include Java
- support.
+ <file:Documentation/binfmt_misc.txt> to learn how to use this
+ feature, and <file:Documentation/java.txt> for information about how
+ to include Java support.
X
X You must say Y to "/proc file system support" (CONFIG_PROC_FS) to
X use this part of the kernel.
@@ -3192,16 +3722,33 @@
X you have use for it; the module is called binfmt_misc.o. If you
X don't know what to answer at this point, say Y.
X
-Solaris binary emulation (EXPERIMENTAL)
+Kernel support for JAVA binaries
+CONFIG_BINFMT_JAVA
+ If you say Y here, the kernel will load and execute Java J-code
+ binaries directly. Note: this option is obsolete and scheduled for
+ removal, use CONFIG_BINFMT_MISC instead.
+
+Solaris binary emulation
X CONFIG_SOLARIS_EMUL
X This is experimental code which will enable you to run (many)
- Solaris binaries on your SPARC Linux machine.
+ Solaris binaries on your SPARC Linux machine.
X
X This code is also available as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want).

X The module will be called solaris.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
+
+SUN SME environment monitoring
+CONFIG_ENVCTRL
+ Kernel support for temperature and fan monitoring on Sun SME
+ machines.
X
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called envctrl.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+# Choice: x86
X Processor family
X CONFIG_M386
X This is the processor type of your CPU. This information is used for
@@ -3215,17 +3762,17 @@
X
X Here are the settings recommended for greatest speed:
X - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI
- 486DLC/DLC2, UMC 486SX-S and NexGen Nx586. Only "386" kernels will
- run on a 386 class machine.
+ 486DLC/DLC2, UMC 486SX-S and NexGen Nx586. Only "386" kernels
+ will run on a 386 class machine.
X - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or
X SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S.
- - "586" for generic Pentium CPUs, possibly lacking the TSC
+ - "586" for generic Pentium CPUs, possibly lacking the TSC
X (time stamp counter) register.
X - "Pentium-Classic" for the Intel Pentium.
X - "Pentium-MMX" for the Intel Pentium MMX.
X - "Pentium-Pro" for the Intel Pentium Pro/Celeron/Pentium II.
X - "Pentium-III" for the Intel Pentium III
- and Celerons based on the coppermine core.
+ and Celerons based on the Coppermine core.
X - "Pentium-4" for the Intel Pentium 4.
X - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D).
X - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird).
@@ -3237,18 +3784,54 @@
X
X If you don't know what to do, choose "386".
X
+486
+CONFIG_M486
+ Select this for a x486 processor, ether Intel or one of the
+ compatible processors from AMD, Cyrix, IBM, or Intel. Includes DX,
+ DX2, and DX4 variants; also SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or
+ U5S.
+
+586/K5/5x86/6x86/6x86MX
+CONFIG_M586
+ Select this for an x586 or x686 processor such as the AMD K5, the
+ Intel 5x86 or 6x86, or the Intel 6x86MX. This choice does not
+ assume the RDTSC instruction.
+
+Pentium Classic
+CONFIG_M586TSC
+ Select this for a Pentium Classic processor with the RDTSC (Read
+ Time Stamp Counter) instruction for benchmarking.
+
+32-bit PDC
+CONFIG_PDC_NARROW
+ Saying Y here will allow developers with a C180, C200, C240, C360,
+ J200, J210, and/or a J2240 to test 64-bit kernels by providing a
+ wrapper for the 32-bit PDC calls. Since the machines which require
+ this option do not support over 4G of RAM, this option is targeted
+ for developers of these machines wishing to test changes on both
+ 32-bit and 64-bit configurations.


+
+ If unsure, say N.
+

X VGA text console
X CONFIG_VGA_CONSOLE
X Saying Y here will allow you to use Linux in text mode through a
X display that complies with the generic VGA standard. Virtually
- everyone wants that.
+ everyone wants that.
X
X The program SVGATextMode can be used to utilize SVGA video cards to
X their full potential in text mode. Download it from
- ftp://metalab.unc.edu/pub/Linux/utils/console .
+ <ftp://metalab.unc.edu/pub/Linux/utils/console>.
X
X Say Y.
X
+Distribute interrupts on all CPUs by default
+CONFIG_IRQ_ALL_CPUS
+ This option gives the kernel permission to distribute IRQs across
+ multiple CPUs. Saying N here will route all IRQs to the first
+ CPU. Generally SMP PowerMacs can answer Y. SMP IBM CHRP boxes or
+ Power3 boxes should say N for now.
+
X Video mode selection support
X CONFIG_VIDEO_SELECT
X This enables support for text mode selection on kernel startup. If
@@ -3260,16 +3843,16 @@
X "man bootparam" or see the documentation of your boot loader about
X how to pass options to the kernel.)
X
- Read the file Documentation/svga.txt for more information about the
- Video mode selection support. If unsure, say N.
+ Read the file <file:Documentation/svga.txt> for more information
+ about the Video mode selection support. If unsure, say N.
X
-Support for frame buffer devices (EXPERIMENTAL)
+Support for frame buffer devices
X CONFIG_FB
X The frame buffer device provides an abstraction for the graphics
X hardware. It represents the frame buffer of some video hardware and
X allows application software to access the graphics hardware through
X a well-defined interface, so the software doesn't need to know
- anything about the low-level (hardware register) stuff.
+ anything about the low-level (hardware register) stuff.
X
X Frame buffer devices work identically across the different
X architectures supported by Linux and make the implementation of
@@ -3277,14 +3860,14 @@
X server exists which uses the frame buffer device exclusively.
X On several non-X86 architectures, the frame buffer device is the
X only way to use the graphics hardware.
-
+
X The device is accessed through special device nodes, usually located
X in the /dev directory, i.e. /dev/fb*.
X
X You need an utility program called fbset to make full use of frame
- buffer devices. Please read Documentation/fb/framebuffer.txt and the
- Framebuffer-HOWTO at
- http://www.tahallah.demon.co.uk/programming/prog.html for more
+ buffer devices. Please read <file:Documentation/fb/framebuffer.txt>
+ and the Framebuffer-HOWTO at
+ <http://www.tahallah.demon.co.uk/programming/prog.html> for more
X information.
X
X Say Y here and to the driver for your graphics board below if you
@@ -3302,6 +3885,27 @@
X hardware found in Acorn RISC PCs and other ARM-based machines. If
X unsure, say N.
X
+Permedia2 support
+CONFIG_FB_PM2
+ This is the frame buffer device driver for the Permedia2 AGP frame
+ buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a
+ product page at
+ <http://www.ask.com.hk/product/Permedia%202/permedia2.htm>.
+
+Enable FIFO disconnect feature
+CONFIG_FB_PM2_FIFO_DISCONNECT
+ Support the Permedia2 FIFOI disconnect feature (see CONFIG_FB_PM2).
+
+Generic Permedia2 PCI board support
+CONFIG_FB_PM2_PCI
+ Say Y to enable support for Permedia2 AGP frame buffer card from
+ 3Dlabs (aka `Graphic Blaster Exxtreme') on the PCI bus.
+
+Phase5 CVisionPPC/BVisionPPC support
+CONFIG_FB_PM2_CVPPC
+ Say Y to enable support for the Amiga Phase 5 CVisionPPC BVisionPPC
+ framebuffer cards. Phase 5 is no longer with us, alas.
+
X Amiga native chipset support
X CONFIG_FB_AMIGA
X This is the frame buffer device driver for the builtin graphics
@@ -3310,7 +3914,7 @@
X The driver is also available as a module ( = code which can be
X inserted and removed from the running kernel whenever you want). The
X module will be called amifb.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X
X Amiga OCS chipset support
X CONFIG_FB_AMIGA_OCS
@@ -3348,7 +3952,7 @@
X Say Y if you have a NetWinder or a graphics card containing this
X device, otherwise say N.
X
-Amiga CyberVision3D support (EXPERIMENTAL)
+Amiga CyberVision3D support
X CONFIG_FB_VIRGE
X This enables support for the Cybervision 64/3D graphics card from
X Phase5. Please note that its use is not all that intuitive (i.e. if
@@ -3357,13 +3961,13 @@
X kernel. Please note that this driver DOES NOT support the older
X Cybervision 64 card, as they use incompatible video chips.
X
-Amiga RetinaZ3 support (EXPERIMENTAL)
+Amiga RetinaZ3 support
X CONFIG_FB_RETINAZ3
X This enables support for the Retina Z3 graphics card. Say N unless
X you have a Retina Z3 or plan to get one before you next recompile
X the kernel.
X
-Cirrus Logic generic driver (EXPERIMENTAL)
+Cirrus Logic generic driver
X CONFIG_FB_CLGEN
X This enables support for Cirrus Logic GD542x/543x based boards on
X Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum.
@@ -3371,21 +3975,17 @@
X If you have a PCI-based system, this enables support for these
X chips: GD-543x, GD-544x, GD-5480.
X
- Please read the file Documentation/fb/clgenfb.txt.
+ Please read the file <file:Documentation/fb/clgenfb.txt>.
X
X Say N unless you have such a graphics board or plan to get one
X before you next recompile the kernel.
X
-Permedia2 support (EXPERIMENTAL)
-CONFIG_FB_PM2
- Say Y here if this is your graphics board.
-
X Apollo support
X CONFIG_APOLLO
X Say Y here if you want to run Linux on an MC680x0-based Apollo
X Domain workstation such as the DN3500.
X
-Apollo 3c505 support
+Apollo 3c505 "EtherLink Plus" support
X CONFIG_APOLLO_ELPLUS
X Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card.
X If you don't have one made for Apollos, you can use one from a PC,
@@ -3397,16 +3997,21 @@
X This is the frame buffer device driver for the builtin graphics
X chipset found in Ataris.
X
-Open Firmware frame buffer device support
+Amiga FrameMaster II/Rainbow II support
+CONFIG_FB_FM2
+ This is the frame buffer device driver for the Amiga FrameMaster
+ card from BSC (exhibited 1992 but not shipped as a CBM product).
+
+Open Firmware frame buffer device support
X CONFIG_FB_OF
X Say Y if you want support with Open Firmware for your graphics
X board.
X
-S3 Trio frame buffer device support
+S3 Trio frame buffer device support
X CONFIG_FB_S3TRIO
- If you have a S3 Trio say Y. Say N for S3 Virge.
+ If you have a S3 Trio say Y. Say N for S3 Virge.
X
-3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)
+3Dfx Banshee/Voodoo3 display support
X CONFIG_FB_3DFX
X This driver supports graphics boards with the 3Dfx Banshee/Voodoo3
X chips. Say Y if you have such a graphics board.
@@ -3414,9 +4019,9 @@
X The driver is also available as a module ( = code which can be
X inserted and removed from the running kernel whenever you want). The
X module will be called tdfxfb.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X
-nVidia Riva support (EXPERIMENTAL)
+nVidia Riva support
X CONFIG_FB_RIVA
X This driver supports graphics boards with the nVidia Riva/Geforce
X chips.
@@ -3425,9 +4030,9 @@
X The driver is also available as a module ( = code which can be
X inserted and removed from the running kernel whenever you want). The
X module will be called rivafb.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X
-ATI Mach64 display support (EXPERIMENTAL)
+ATI Mach64 display support
X CONFIG_FB_ATY
X This driver supports graphics boards with the ATI Mach64 chips.
X Say Y if you have such a graphics board.
@@ -3435,30 +4040,54 @@
X The driver is also available as a module ( = code which can be
X inserted and removed from the running kernel whenever you want). The
X module will be called atyfb.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.
-
-ATI Mach64 GX display support (EXPERIMENTAL)
-CONFIG_FB_ATY_GX
- This options adds support for the first generation ATI Mach64
- graphics chips, i.e. the Mach64 GX and CX. Note that this support is
- limited.
-
-ATI Mach64 CT/VT/GT/LT display support (EXPERIMENTAL)
-CONFIG_FB_ATY_CT
- This option adss support for ATI Mach64 graphics chips starting
- with the Mach64 CT family. This includes the Mach64 VT (limited
- support), GT (3D RAGE family), and LT.
+ module, say M here and read <file:Documentation/modules.txt>.
X
-ATI Rage128 display support (EXPERIMENTAL)
+ATI Rage128 display support
X CONFIG_FB_ATY128
X This driver supports graphics boards with the ATI Rage128 chips.
X Say Y if you have such a graphics board and read
- Documentation/fb/aty128fb.txt.
+ <file:Documentation/fb/aty128fb.txt>.
X
X The driver is also available as a module ( = code which can be
X inserted and removed from the running kernel whenever you want). The
X module will be called aty128fb.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.


+
+# AC tree only

+Maxine (Personal DECstation) onboard framebuffer support
+CONFIG_FB_MAXINE
+ Say Y here to directly support the on-board framebuffer in the
+ Maxine (5000/20, /25, /33) version of the DECstation. There is a
+ page dedicated to Linux on DECstations at <http://decstation.unix-ag.org/>.


+
+# AC tree only

+PMAG-BA TURBOchannel framebuffer support
+CONFIG_FB_PMAG_BA
+ Say Y here to directly support the on-board PMAG-BA framebuffer in
+ the 5000/1xx versions of the DECstation. There is a page dedicated
+ to Linux on DECstations at <http://decstation.unix-ag.org/>.


+
+# AC tree only

+PMAGB-B TURBOchannel framebuffer support
+CONFIG_FB_PMAGB_B
+ Say Y here to directly support the on-board PMAGB-B framebuffer in
+ the 5000/1xx versions of the DECstation. There is a page dedicated
+ to Linux on DECstations at <http://decstation.unix-ag.org/>.
+
+FutureTV PCI card
+CONFIG_ARCH_FTVPCI
+ Say Y here if you intend to run this kernel on a FutureTV (nee Nexus
+ Electronics) StrongARM PCI card.
+


+P720T
+CONFIG_ARCH_P720T
+ Say Y here if you intend to run this kernel on the ARM Prospector
+ 720T.
+

+Link-Up Systems LCD support
+CONFIG_FB_L7200
+ This driver supports the L7200 Color LCD.
+ Say Y if you want graphics support.
X
X PowerMac "control" frame buffer device support
X CONFIG_FB_CONTROL
@@ -3490,13 +4119,13 @@
X This is the frame buffer device driver for generic VESA 2.0
X compliant graphic cards. The older VESA 1.2 cards are not supported.
X You will get a boot time penguin logo at no additional cost. Please
- read Documentation/fb/vesafb.txt. If unsure, say Y.
+ read <file:Documentation/fb/vesafb.txt>. If unsure, say Y.
X
X VGA 16-color planar support
X CONFIG_FBCON_VGA_PLANES
X This low level frame buffer console driver enable the kernel to use
X the 16-color planar modes of the old VGA cards where the bits of
- each pixel are separated into 4 planes.
+ each pixel are separated into 4 planes.
X
X Only answer Y here if you have a (very old) VGA card that isn't VESA
X 2 compatible.
@@ -3509,7 +4138,29 @@
X This code is also available as a module. If you want to compile it
X as a module ( = code which can be inserted in and removed from the
X running kernel whenever you want), say M here and read
- Documentation/modules.txt. The module will be called vga16fb.o.
+ <file:Documentation/modules.txt>. The module will be called
+ vga16fb.o.
+
+Generic STI frame buffer device support
+CONFIG_FB_STI
+ STI refers to the HP "Standard Text Interface" which is a set of
+ BIOS routines contained in a ROM chip in HP PA-RISC based machines.
+ Enabling this option will implement the linux framebuffer device and
+ an fbcon color text console using calls to the STI BIOS routines.
+ The HP framebuffer device is usually planar, uses a strange memory
+ layout, and changing the plane mask to create colored pixels
+ requires a call to the STI routines, so do not expect /dev/fb to
+ actually be useful. However, it is the best we have as far as
+ graphics on the HP chipsets due to lack of hardware level
+ documentation for the various on-board HP chipsets used in these
+ systems. It is sufficient for basic text console functions,
+ including fonts.
+
+ You should probably enable this option, unless you are having
+ trouble getting video when booting the kernel (make sure it isn't
+ just that you are running the console on the serial port, though).
+ Really old HP boxes may not have STI, and must use the PDC BIOS
+ console or the IODC BIOS.
X
X Select other compiled-in fonts
X CONFIG_FBCON_FONTS
@@ -3517,7 +4168,7 @@
X your frame buffer console usually use.


X
X Note that the answer to this question won't directly affect the
- kernel: saying N will just cause this configure script to skip all
+ kernel: saying N will just cause the configurator to skip all

X the questions about foreign fonts.
X
X If unsure, say N (the default choices are safe).
@@ -3549,14 +4200,29 @@
X VGA 8x8 font
X CONFIG_FONT_8x8
X This is the "high resolution" font for the VGA frame buffer (the one
- provided by the text console 80x50 (and higher) modes).
+ provided by the text console 80x50 (and higher) modes).
X
X Note that this is a poor quality font. The VGA 8x16 font is quite a
- lot more readable.
+ lot more readable.
X
X Given the resolution provided by the frame buffer device, answer N
X here is safe.
X
+Mac console 6x11 font (not supported by all drivers)
+CONFIG_FONT_6x11
+ Small console font with Macintosh-style high-half glyphs. Some Mac
+ framebuffer drivers don't support this one at all.
+
+Pearl (old m68k) console 8x8 font
+CONFIG_FONT_PEARL_8x8
+ Small console font with PC-style control-character and high-half
+ glyphs.
+
+Acorn console 8x8 font
+CONFIG_FONT_ACORN_8x8
+ Small console font with PC-style control characters and high-half
+ glyphs.
+
X Backward compatibility mode for Xpmac
X CONFIG_FB_COMPAT_XPMAC
X If you use the Xpmac X server (common with mklinux), you'll need to
@@ -3564,35 +4230,61 @@
X includes a server that supports the frame buffer device directly
X (XF68_FBDev).
X
-HGA monochrome support (EXPERIMENTAL)
+Hercules (HGA) mono graphics support
X CONFIG_FB_HGA
X Say Y here if you have a Hercules mono graphics card.
X
X This driver is also available as a module ( = code which can be
X inserted and removed from the running kernel whenever you want).
X The module will be called hgafb.o. If you want to compile it as
- a module, say M here and read Documentation/modules.txt.
+ a module, say M here and read <file:Documentation/modules.txt>.
X
X As this card technology is 15 years old, most people will answer N
X here.
X
+Epson 1355 framebuffer support
+CONFIG_FB_E1355
+ Build in support for the SED1355 Epson Research Embedded RAMDAC
+ LCD/CRT Controller (since redesignated as the S1D13505) as a
+ framebuffer. Product specs at
+ <http://www.erd.epson.com/vdc/html/products.htm>.
+
+Dreamcast Frame Buffer support
+CONFIG_FB_DC
+ Say Y here to enable support for the framebuffer on the Sega
+ Dreamcast. This driver is also available as a module, dcfb.o.
+
+Register Base Address
+CONFIG_E1355_REG_BASE
+ Epson SED1355/S1D13505 LCD/CRT controller register base address.
+ See the manuals at
+ <http://www.erd.epson.com/vdc/html/contents/S1D13505.htm> for
+ discussion.
+
+Framebuffer Base Address
+CONFIG_E1355_FB_BASE
+ Epson SED1355/S1D13505 LCD/CRT controller memory base address. See
+ the manuals at
+ <http://www.erd.epson.com/vdc/html/contents/S1D13505.htm> for
+ discussion.
+
X NEC PowerVR 2 display support
X CONFIG_FB_PVR2
- Say Y here if you have a PowerVR 2 card in your box. If you plan to
- run linux on your Dreamcast, you will have to say Y here. This driver
- may or may not work on other PowerVR 2 cards, but is totally untested.
- Use at your own risk. If unsure, say N.
+ Say Y here if you have a PowerVR 2 card in your box. If you plan to
+ run linux on your Dreamcast, you will have to say Y here.
+ This driver may or may not work on other PowerVR 2 cards, but is
+ totally untested. Use at your own risk. If unsure, say N.
X
X This driver is also available as a module ( = code which can be
X inserted and removed from the running kernel whenever you want).
- The module will be called pvr2fb.o. If you want to compile it as
- a module, say M here and read Documentation/modules.txt.
+ The module will be called pvr2fb.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
X
X You can pass several parameters to the driver at boot time or at
- module load time. The parameters look like "video=pvr2:XXX", where
+ module load time. The parameters look like "video=pvr2:XXX", where
X the meaning of XXX can be found at the end of the main source file
- (drivers/video/pvr2fb.c). Please see the file
- Documentation/fb/pvr2fb.txt.
+ (<file:drivers/video/pvr2fb.c>). Please see the file
+ <file:Documentation/fb/pvr2fb.txt>.
X
X Debug pvr2fb
X CONFIG_FB_PVR2_DEBUG
@@ -3600,26 +4292,26 @@
X messages. Most people will want to say N here. If unsure, you will
X also want to say N.
X
-Matrox unified accelerated driver (EXPERIMENTAL)
+Matrox unified accelerated driver
X CONFIG_FB_MATROX
X Say Y here if you have a Matrox Millennium, Matrox Millennium II,
X Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
X Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video,
- Matrox G400 or G450 card in your box. At this time, support for the G100
- is untested and support for G450 is highly experimental.
+ Matrox G400 or G450 card in your box. At this time, support for the
+ G100 is untested and support for G450 is highly experimental.
X
X This driver is also available as a module ( = code which can be
X inserted and removed from the running kernel whenever you want).
X The module will be called matroxfb.o. If you want to compile it as


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

echo 'End of part 003'
echo 'File patch-2.4.15 is continued in part 004'
echo "004" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:56 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part020

#!/bin/sh -x
# this is part 020 of a 115 - part archive


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

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

+ - http://www-miaif.lip6.fr/willy/pub/bonding/
+
+To get latest informations about Linux Kernel development, please consult
+the Linux Kernel Mailing List Archives at :
+ http://boudicca.tux.org/hypermail/linux-kernel/latest/
+
+-- END --
diff -u --recursive --new-file v2.4.14/linux/Documentation/networking/dl2k.txt linux/Documentation/networking/dl2k.txt
--- v2.4.14/linux/Documentation/networking/dl2k.txt Sun Sep 23 11:40:54 2001
+++ linux/Documentation/networking/dl2k.txt Mon Nov 19 15:19:42 2001
@@ -1,7 +1,7 @@
X
X D-Link DL2000-based Gigabit Ethernet Adapter Installation
X for Linux
- July 5, 2001
+ Nov 12, 2001
X
X Contents
X ========
@@ -14,20 +14,22 @@
X - Troubleshooting
X
X
-Compatiblity List
+Compatibility List
X =================
X Adapter Support:
X
X D-Link DGE-550T Gigabit Ethernet Adapter.
+D-Link DGE-550SX Gigabit Ethernet Adapter.
X D-Link DL2000-based Gigabit Ethernet Adapter.
X
X
-The driver support Linux kernal 2.4.x later. We had tested it
+The driver support Linux kernel 2.4.7 later. We had tested it
X on the environments below.
X
- . Red Hat v6.2 (update to kernel 2.4.4)
- . Red Hat v7.0 (update to kernel 2.4.4)
- . Red Hat v7.1 (kernel 2.4.2-2)
+ . Red Hat v6.2 (update kernel to 2.4.7)
+ . Red Hat v7.0 (update kernel to 2.4.7)
+ . Red Hat v7.1 (kernel 2.4.7)
+ . Red Hat v7.2 (kernel 2.4.7-10)
X
X
X Quick Install
@@ -35,16 +37,16 @@
X Install linux driver as following command:
X
X 1. make all
-2. insmod dl2x.o
+2. insmod dl2k.o
X 3. ifconfig eth0 up 10.xxx.xxx.xxx netmask 255.0.0.0
X ^^^^^^^^^^^^^^^\ ^^^^^^^^\
X IP NETMASK
-Now eth0 bring up, you can test it by "ping" or get more information by
-"ifconfig". If test ok, then continue next step.
+Now eth0 should active, you can test it by "ping" or get more information by
+"ifconfig". If tested ok, continue the next step.
X
-4. cp dl2x.o /lib/modules/`uname -r`/kernel/drivers/net
+4. cp dl2k.o /lib/modules/`uname -r`/kernel/drivers/net
X 5. Add the following lines to /etc/modules.conf:
- alias eth0 dl2x
+ alias eth0 dl2k
X 6. Run "netconfig" or "netconf" to create configuration script ifcfg-eth0
X located at /etc/sysconfig/network-scripts or create it manually.
X [see - Configuration Script Sample]
@@ -61,10 +63,10 @@
X better reliability since a precompiled driver might depend on libraries or
X kernel features that are not present in a given Linux installation.
X
-The 3 files necessary to build Linux device driver are dl2x.c, dl2x.h and
+The 3 files necessary to build Linux device driver are dl2k.c, dl2k.h and
X Makefile. To compile, the Linux installation must include the gcc compiler,
X the kernel source, and the kernel headers. The Linux driver supports Linux
-Kernels 2.4.x. Copy the files to a directory and enter the following command
+Kernels 2.4.7. Copy the files to a directory and enter the following command
X to compile and link the driver:
X
X CD-ROM drive
@@ -73,21 +75,21 @@
X [root@XXX /] mkdir cdrom
X [root@XXX /] mount -r -t iso9660 -o conv=auto /dev/cdrom /cdrom
X [root@XXX /] cd root
-[root@XXX /root] mkdir dl2x
-[root@XXX /root] cd dl2x
-[root@XXX dl2x] cp /cdrom/linux/dl2x.tgz /root/dl2x
-[root@XXX dl2x] tar xfvz dl2x.tgz
-[root@XXX dl2x] make all
+[root@XXX /root] mkdir dl2k
+[root@XXX /root] cd dl2k
+[root@XXX dl2k] cp /cdrom/linux/dl2k.tgz /root/dl2k
+[root@XXX dl2k] tar xfvz dl2k.tgz
+[root@XXX dl2k] make all
X
X Floppy disc drive
X -----------------
X
X [root@XXX /] cd root
-[root@XXX /root] mkdir dl2x
-[root@XXX /root] cd dl2x
-[root@XXX dl2x] mcopy a:/linux/dl2x.tgz /root/dl2x
-[root@XXX dl2x] tar xfvz dl2x.tgz
-[root@XXX dl2x] make all
+[root@XXX /root] mkdir dl2k
+[root@XXX /root] cd dl2k
+[root@XXX dl2k] mcopy a:/linux/dl2k.tgz /root/dl2k
+[root@XXX dl2k] tar xfvz dl2k.tgz
+[root@XXX dl2k] make all
X
X Installing the Driver
X =====================
@@ -98,17 +100,16 @@
X to a protocol stack in order to establish network connectivity. To load a
X module enter the command:
X
- insmod dl2x.o
-
+ insmod dl2k.o
X
X or
X
- insmod dl2x.o <optional parameter> ; add parameter
+ insmod dl2k.o <optional parameter> ; add parameter
X
X ===============================================================
- example: insmod dl2x.o media=100mbps_hd
- or insmod dl2x.o media=3
- or insmod dl2x.o media=3 2 ; for 2 cards
+ example: insmod dl2k.o media=100mbps_hd
+ or insmod dl2k.o media=3
+ or insmod dl2k.o media=3,2 ; for 2 cards
X ===============================================================
X
X Please reference the list of the command line parameters supported by
@@ -133,7 +134,7 @@
X
X ifdown eth0
X ifconfig eth0 down
- rmmod dl2x.o
+ rmmod dl2k.o
X
X The following are the commands to list the currently loaded modules and
X to see the current network configuration.
@@ -151,13 +152,13 @@
X
X Red Hat v6.x/v7.x
X -----------------
- 1. Copy dl2x.o to the network modules directory, typically
+ 1. Copy dl2k.o to the network modules directory, typically
X /lib/modules/2.x.x-xx/net or /lib/modules/2.x.x/kernel/drivers/net.
X 2. Locate the boot module configuration file, most commonly modules.conf
X or conf.modules in the /etc directory. Add the following lines:
X
- alias ethx dl2x
- options dl2x <optional parameters>
+ alias ethx dl2k
+ options dl2k <optional parameters>
X
X where ethx will be eth0 if the NIC is the only ethernet adapter, eth1 if
X one other ethernet adapter is installed, etc. Refer to the table in the
@@ -187,12 +188,19 @@
X 10mbps_fd 10Mbps full duplex.
X 100mbps_hd 100Mbps half duplex.
X 100mbps_fd 100Mbps full duplex.
+ 1000mbps_fd 1000Mbps full duplex.
+ 1000mbps_hd 1000Mbps half duplex.
X 0 Autosensing active media.
X 1 10Mbps half duplex.
X 2 10Mbps full duplex.
X 3 100Mbps half duplex.
X 4 100Mbps full duplex.
+ 5 1000Mbps full duplex.
+ 6 1000Mbps half duplex.
+
X By default, the NIC operates at autosense.
+ Note that only 1000mbps_fd and 1000mbps_hd
+ types are available for fiber adapter.
X
X vlan=x - Specifies the VLAN ID. If vlan=0, the
X Virtual Local Area Network (VLAN) function is
@@ -208,9 +216,8 @@
X int_timeout - Rx DMA wait time for an interrupt. Proper
X values of int_count and int_timeout bring
X a conspicuous performance in the fast machine.
- For P4 1.5GHz systems, a setting of
- int_count=5 and int_timeout=750 is
- recommendable.
+ Ex. int_count=5 and int_timeout=750
+
X Configuration Script Sample
X ===========================
X Here is a sample of a simple configuration script:
diff -u --recursive --new-file v2.4.14/linux/Documentation/networking/ifenslave.c linux/Documentation/networking/ifenslave.c
--- v2.4.14/linux/Documentation/networking/ifenslave.c Wed Dec 31 16:00:00 1969
+++ linux/Documentation/networking/ifenslave.c Wed Nov 7 14:39:36 2001
@@ -0,0 +1,562 @@
+/* Mode: C;
+ * ifenslave.c: Configure network interfaces for parallel routing.
+ *
+ * This program controls the Linux implementation of running multiple
+ * network interfaces in parallel.
+ *
+ * Usage: ifenslave [-v] master-interface < slave-interface [metric <N>] > ...
+ *
+ * Author: Donald Becker <bec...@cesdis.gsfc.nasa.gov>
+ * Copyright 1994-1996 Donald Becker
+ *
+ * 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.
+ *
+ * The author may be reached as bec...@CESDIS.gsfc.nasa.gov, or C/O
+ * Center of Excellence in Space Data and Information Sciences
+ * Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+ *
+ * Changes :
+ * - 2000/10/02 Willy Tarreau <willy at meta-x.org> :
+ * - few fixes. Master's MAC address is now correctly taken from
+ * the first device when not previously set ;
+ * - detach support : call BOND_RELEASE to detach an enslaved interface.
+ * - give a mini-howto from command-line help : # ifenslave -h
+ *
+ * - 2001/02/16 Chad N. Tindel <ctindel at ieee dot org> :
+ * - Master is now brought down before setting the MAC address. In
+ * the 2.4 kernel you can't change the MAC address while the device is
+ * up because you get EBUSY.
+ *
+ * - 2001/09/13 Takao Indoh <indou dot takao at jp dot fujitsu dot com>
+ * - Added the ability to change the active interface on a mode 1 bond
+ * at runtime.
+ *
+ * - 2001/10/23 Chad N. Tindel <ctindel at ieee dot org> :
+ * - No longer set the MAC address of the master. The bond device will
+ * take care of this itself
+ * - Try the SIOC*** versions of the bonding ioctls before using the
+ * old versions
+ */
+
+static char *version =
+"ifenslave.c:v0.07 9/9/97 Donald Becker (bec...@cesdis.gsfc.nasa.gov).\n"
+"detach support added on 2000/10/02 by Willy Tarreau (willy at meta-x.org).\n"
+"2.4 kernel support added on 2001/02/16 by Chad N. Tindel (ctindel at ieee dot org.\n";
+
+static const char *usage_msg =
+"Usage: ifenslave [-adfrvVh] <master-interface> < <slave-if> [metric <N>] > ...\n"
+" ifenslave -c master-interface slave-if\n";
+
+static const char *howto_msg =
+"Usage: ifenslave [-adfrvVh] <master-interface> < <slave-if> [metric <N>] > ...\n"
+" ifenslave -c master-interface slave-if\n"
+"\n"
+" To create a bond device, simply follow these three steps :\n"
+" - ensure that the required drivers are properly loaded :\n"
+" # modprobe bonding ; modprobe <3c59x|eepro100|pcnet32|tulip|...>\n"
+" - assign an IP address to the bond device :\n"
+" # ifconfig bond0 <addr> netmask <mask> broadcast <bcast>\n"
+" - attach all the interfaces you need to the bond device :\n"
+" # ifenslave bond0 eth0 eth1 eth2\n"
+" If bond0 didn't have a MAC address, it will take eth0's. Then, all\n"
+" interfaces attached AFTER this assignment will get the same MAC addr.\n"
+"\n"
+" To detach a dead interface without setting the bond device down :\n"
+" # ifenslave -d bond0 eth1\n"
+"\n"
+" To set the bond device down and automatically release all the slaves :\n"
+" # ifconfig bond0 down\n"
+"\n"
+" To change active slave :\n"
+" # ifenslave -c bond0 eth0\n"
+"\n";
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <linux/if.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/if_bonding.h>
+#include <linux/sockios.h>
+
+struct option longopts[] = {
+ /* { name has_arg *flag val } */
+ {"all-interfaces", 0, 0, 'a'}, /* Show all interfaces. */
+ {"force", 0, 0, 'f'}, /* Force the operation. */
+ {"help", 0, 0, '?'}, /* Give help */
+ {"howto", 0, 0, 'h'}, /* Give some more help */
+ {"receive-slave", 0, 0, 'r'}, /* Make a receive-only slave. */
+ {"verbose", 0, 0, 'v'}, /* Report each action taken. */
+ {"version", 0, 0, 'V'}, /* Emit version information. */
+ {"detach", 0, 0, 'd'}, /* Detach a slave interface. */
+ {"change-active", 0, 0, 'c'}, /* Change the active slave. */
+ { 0, 0, 0, 0 }
+};
+
+/* Command-line flags. */
+unsigned int
+opt_a = 0, /* Show-all-interfaces flag. */
+opt_f = 0, /* Force the operation. */
+opt_r = 0, /* Set up a Rx-only slave. */
+opt_d = 0, /* detach a slave interface. */
+opt_c = 0, /* change-active-slave flag. */
+verbose = 0, /* Verbose flag. */
+opt_version = 0,
+opt_howto = 0;
+int skfd = -1; /* AF_INET socket for ioctl() calls. */
+
+static void if_print(char *ifname);
+
+int
+main(int argc, char **argv)
+{
+ struct ifreq ifr2, if_hwaddr, if_ipaddr, if_metric, if_mtu, if_dstaddr;
+ struct ifreq if_netmask, if_brdaddr, if_flags;
+ int goterr = 0;
+ int c, errflag = 0;
+ sa_family_t master_family;
+ char **spp, *master_ifname, *slave_ifname;
+ int hwaddr_notset;
+
+ while ((c = getopt_long(argc, argv, "acdfrvV?h", longopts, 0)) != EOF)
+ switch (c) {
+ case 'a': opt_a++; break;
+ case 'f': opt_f++; break;
+ case 'r': opt_r++; break;
+ case 'd': opt_d++; break;
+ case 'c': opt_c++; break;
+ case 'v': verbose++; break;
+ case 'V': opt_version++; break;
+ case 'h': opt_howto++; break;
+ case '?': errflag++;
+ }
+
+ /* option check */
+ if (opt_c)
+ if(opt_a || opt_f || opt_r || opt_d || verbose || opt_version ||
+ opt_howto || errflag ) {
+ fprintf(stderr, usage_msg);
+ return 2;
+ }
+
+ if (errflag) {
+ fprintf(stderr, usage_msg);
+ return 2;
+ }
+
+ if (opt_howto) {
+ fprintf(stderr, howto_msg);
+ return 0;
+ }
+
+ if (verbose || opt_version) {
+ printf(version);
+ if (opt_version)
+ exit(0);
+ }
+
+ /* Open a basic socket. */
+ if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
+ perror("socket");
+ exit(-1);
+ }
+
+ if (verbose)
+ fprintf(stderr, "DEBUG: argc=%d, optind=%d and argv[optind] is %s.\n",
+ argc, optind, argv[optind]);
+
+ /* No remaining args means show all interfaces. */
+ if (optind == argc) {
+ if_print((char *)NULL);
+ (void) close(skfd);
+ exit(0);
+ }
+
+ /* Copy the interface name. */
+ spp = argv + optind;
+ master_ifname = *spp++;
+ slave_ifname = *spp++;
+
+ /* Check command line. */
+ if (opt_c) {
+ char **tempp = spp;
+ if ((master_ifname == NULL)||(slave_ifname == NULL)||(*tempp++ != NULL)) {
+ fprintf(stderr, usage_msg);
+ return 2;
+ }
+ }
+
+ /* A single args means show the configuration for this interface. */
+ if (slave_ifname == NULL) {
+ if_print(master_ifname);
+ (void) close(skfd);
+ exit(0);
+ }
+
+ /* Get the vitals from the master interface. */
+ {
+ struct ifreq *ifra[7] = { &if_ipaddr, &if_mtu, &if_dstaddr,
+ &if_brdaddr, &if_netmask, &if_flags,
+ &if_hwaddr };
+ const char *req_name[7] = {
+ "IP address", "MTU", "destination address",
+ "broadcast address", "netmask", "status flags",
+ "hardware address" };
+ const int ioctl_req_type[7] = {
+ SIOCGIFADDR, SIOCGIFMTU, SIOCGIFDSTADDR,
+ SIOCGIFBRDADDR, SIOCGIFNETMASK, SIOCGIFFLAGS,
+ SIOCGIFHWADDR };
+ int i;
+
+ for (i = 0; i < 7; i++) {
+ strncpy(ifra[i]->ifr_name, master_ifname, IFNAMSIZ);
+ if (ioctl(skfd, ioctl_req_type[i], ifra[i]) < 0) {
+ fprintf(stderr,
+ "Something broke getting the master's %s: %s.\n",
+ req_name[i], strerror(errno));
+ }
+ }
+
+ hwaddr_notset = 1; /* assume master's address not set yet */
+ for (i = 0; hwaddr_notset && (i < 6); i++) {
+ hwaddr_notset &= ((unsigned char *)if_hwaddr.ifr_hwaddr.sa_data)[i] == 0;
+ }
+
+ /* The family '1' is ARPHRD_ETHER for ethernet. */
+ if (if_hwaddr.ifr_hwaddr.sa_family != 1 && !opt_f) {
+ fprintf(stderr, "The specified master interface '%s' is not"
+ " ethernet-like.\n This program is designed to work"
+ " with ethernet-like network interfaces.\n"
+ " Use the '-f' option to force the operation.\n",
+ master_ifname);
+
+ exit (1);
+ }
+ master_family = if_hwaddr.ifr_hwaddr.sa_family;
+ if (verbose) {
+ unsigned char *hwaddr = (unsigned char *)if_hwaddr.ifr_hwaddr.sa_data;
+ printf("The current hardware address (SIOCGIFHWADDR) of %s is type %d "
+ "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", master_ifname,
+ if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
+ hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
+ }
+ }
+
+
+ /* do this when enslaving interfaces */
+ do {
+ if (opt_d) { /* detach a slave interface from the master */
+ strncpy(if_flags.ifr_name, master_ifname, IFNAMSIZ);
+ strncpy(if_flags.ifr_slave, slave_ifname, IFNAMSIZ);
+ if ((ioctl(skfd, SIOCBONDRELEASE, &if_flags) < 0) &&
+ (ioctl(skfd, BOND_RELEASE_OLD, &if_flags) < 0)) {
+ fprintf(stderr, "SIOCBONDRELEASE: cannot detach %s from %s. errno=%s.\n",
+ slave_ifname, master_ifname, strerror(errno));
+ }
+ else { /* we'll set the interface down to avoid any conflicts due to
+ same IP/MAC */
+ strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ);
+ if (ioctl(skfd, SIOCGIFFLAGS, &ifr2) < 0) {
+ int saved_errno = errno;
+ fprintf(stderr, "SIOCGIFFLAGS on %s failed: %s\n", slave_ifname,
+ strerror(saved_errno));
+ }
+ else {
+ ifr2.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
+ if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
+ int saved_errno = errno;
+ fprintf(stderr, "Shutting down interface %s failed: %s\n",
+ slave_ifname, strerror(saved_errno));
+ }
+ }
+ }
+ }
+ else { /* attach a slave interface to the master */
+ /* two possibilities :
+ - if hwaddr_notset, do nothing. The bond will assign the
+ hwaddr from it's first slave.
+ - if !hwaddr_notset, assign the master's hwaddr to each slave
+ */
+
+ if (hwaddr_notset) { /* we do nothing */
+
+ }
+ else { /* we'll assign master's hwaddr to this slave */
+ strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ);
+ if (ioctl(skfd, SIOCGIFFLAGS, &ifr2) < 0) {
+ int saved_errno = errno;
+ fprintf(stderr, "SIOCGIFFLAGS on %s failed: %s\n", slave_ifname,
+ strerror(saved_errno));
+ return 1;
+ }
+
+ if (ifr2.ifr_flags & IFF_UP) {
+ ifr2.ifr_flags &= ~IFF_UP;
+ if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
+ int saved_errno = errno;
+ fprintf(stderr, "Shutting down interface %s failed: %s\n",
+ slave_ifname, strerror(saved_errno));
+ }
+ }
+
+ strncpy(if_hwaddr.ifr_name, slave_ifname, IFNAMSIZ);
+ if (ioctl(skfd, SIOCSIFHWADDR, &if_hwaddr) < 0) {
+ int saved_errno = errno;
+ fprintf(stderr, "SIOCSIFHWADDR on %s failed: %s\n", if_hwaddr.ifr_name,
+ strerror(saved_errno));
+ if (saved_errno == EBUSY)
+ fprintf(stderr, " The slave device %s is busy: it must be"
+ " idle before running this command.\n", slave_ifname);
+ else if (saved_errno == EOPNOTSUPP)
+ fprintf(stderr, " The slave device you specified does not support"
+ " setting the MAC address.\n Your kernel likely does not"
+ " support slave devices.\n");
+ else if (saved_errno == EINVAL)
+ fprintf(stderr, " The slave device's address type does not match"
+ " the master's address type.\n");
+ } else {
+ if (verbose) {
+ unsigned char *hwaddr = if_hwaddr.ifr_hwaddr.sa_data;
+ printf("Slave's (%s) hardware address set to "
+ "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", slave_ifname,
+ hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
+ }
+ }
+ }
+
+ if (*spp && !strcmp(*spp, "metric")) {
+ if (*++spp == NULL) {
+ fprintf(stderr, usage_msg);
+ exit(2);
+ }
+ if_metric.ifr_metric = atoi(*spp);
+ strncpy(if_metric.ifr_name, slave_ifname, IFNAMSIZ);
+ if (ioctl(skfd, SIOCSIFMETRIC, &if_metric) < 0) {
+ fprintf(stderr, "SIOCSIFMETRIC on %s: %s\n", slave_ifname,
+ strerror(errno));
+ goterr = 1;
+ }
+ spp++;
+ }
+
+ if (strncpy(if_ipaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0
+ || ioctl(skfd, SIOCSIFADDR, &if_ipaddr) < 0) {
+ fprintf(stderr,
+ "Something broke setting the slave's address: %s.\n",
+ strerror(errno));
+ } else {
+ if (verbose) {
+ unsigned char *ipaddr = if_ipaddr.ifr_addr.sa_data;
+ printf("Set the slave's (%s) IP address to %d.%d.%d.%d.\n",
+ slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
+ }
+ }
+
+ if (strncpy(if_mtu.ifr_name, slave_ifname, IFNAMSIZ) <= 0
+ || ioctl(skfd, SIOCSIFMTU, &if_mtu) < 0) {
+ fprintf(stderr, "Something broke setting the slave MTU: %s.\n",
+ strerror(errno));
+ } else {
+ if (verbose)
+ printf("Set the slave's (%s) MTU to %d.\n", slave_ifname, if_mtu.ifr_mtu);
+ }
+
+ if (strncpy(if_dstaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0
+ || ioctl(skfd, SIOCSIFDSTADDR, &if_dstaddr) < 0) {
+ fprintf(stderr, "Error setting the slave (%s) with SIOCSIFDSTADDR: %s.\n",
+ slave_ifname, strerror(errno));
+ } else {
+ if (verbose) {
+ unsigned char *ipaddr = if_dstaddr.ifr_dstaddr.sa_data;
+ printf("Set the slave's (%s) destination address to %d.%d.%d.%d.\n",
+ slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
+ }
+ }
+
+ if (strncpy(if_brdaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0
+ || ioctl(skfd, SIOCSIFBRDADDR, &if_brdaddr) < 0) {
+ fprintf(stderr,
+ "Something broke setting the slave (%s) broadcast address: %s.\n",
+ slave_ifname, strerror(errno));
+ } else {
+ if (verbose) {
+ unsigned char *ipaddr = if_brdaddr.ifr_broadaddr.sa_data;
+ printf("Set the slave's (%s) broadcast address to %d.%d.%d.%d.\n",
+ slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
+ }
+ }
+
+ if (strncpy(if_netmask.ifr_name, slave_ifname, IFNAMSIZ) <= 0
+ || ioctl(skfd, SIOCSIFNETMASK, &if_netmask) < 0) {
+ fprintf(stderr,
+ "Something broke setting the slave (%s) netmask: %s.\n",
+ slave_ifname, strerror(errno));
+ } else {
+ if (verbose) {
+ unsigned char *ipaddr = if_netmask.ifr_netmask.sa_data;
+ printf("Set the slave's (%s) netmask to %d.%d.%d.%d.\n",
+ slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
+ }
+ }
+
+ ifr2.ifr_flags |= IFF_UP; /* the interface will need to be up to be bonded */
+ if ((ifr2.ifr_flags &= ~(IFF_SLAVE | IFF_MASTER)) == 0
+ || strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ) <= 0
+ || ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
+ fprintf(stderr,
+ "Something broke setting the slave (%s) flags: %s.\n",
+ slave_ifname, strerror(errno));
+ } else {
+ if (verbose)
+ printf("Set the slave's (%s) flags %4.4x.\n", slave_ifname, if_flags.ifr_flags);
+ }
+
+ /* Do the real thing */
+ if ( ! opt_r) {
+ strncpy(if_flags.ifr_name, master_ifname, IFNAMSIZ);
+ strncpy(if_flags.ifr_slave, slave_ifname, IFNAMSIZ);
+ if (!opt_c) {
+ if ((ioctl(skfd, SIOCBONDENSLAVE, &if_flags) < 0) &&
+ (ioctl(skfd, BOND_ENSLAVE_OLD, &if_flags) < 0)) {
+ fprintf(stderr, "SIOCBONDENSLAVE: %s.\n", strerror(errno));
+ }
+ }
+ else {
+ if ((ioctl(skfd, SIOCBONDCHANGEACTIVE, &if_flags) < 0) &&
+ (ioctl(skfd, BOND_CHANGE_ACTIVE_OLD, &if_flags) < 0)) {
+ fprintf(stderr, "SIOCBONDCHANGEACTIVE: %s.\n", strerror(errno));
+ }
+ }
+ }
+ }
+ } while ( (slave_ifname = *spp++) != NULL);
+
+ /* Close the socket. */
+ (void) close(skfd);
+
+ return(goterr);
+}
+
+static short mif_flags;
+
+/* Get the inteface configuration from the kernel. */
+static int if_getconfig(char *ifname)
+{
+ struct ifreq ifr;
+ int metric, mtu; /* Parameters of the master interface. */
+ struct sockaddr dstaddr, broadaddr, netmask;
+
+ strcpy(ifr.ifr_name, ifname);
+ if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
+ return -1;
+ mif_flags = ifr.ifr_flags;
+ printf("The result of SIOCGIFFLAGS on %s is %x.\n",
+ ifname, ifr.ifr_flags);
+
+ strcpy(ifr.ifr_name, ifname);
+ if (ioctl(skfd, SIOCGIFADDR, &ifr) < 0)
+ return -1;
+ printf("The result of SIOCGIFADDR is %2.2x.%2.2x.%2.2x.%2.2x.\n",
+ ifr.ifr_addr.sa_data[0], ifr.ifr_addr.sa_data[1],
+ ifr.ifr_addr.sa_data[2], ifr.ifr_addr.sa_data[3]);
+
+ strcpy(ifr.ifr_name, ifname);
+ if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
+ return -1;
+
+ {
+ /* Gotta convert from 'char' to unsigned for printf(). */
+ unsigned char *hwaddr = (unsigned char *)ifr.ifr_hwaddr.sa_data;
+ printf("The result of SIOCGIFHWADDR is type %d "
+ "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
+ ifr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
+ hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
+ }
+
+ strcpy(ifr.ifr_name, ifname);
+ if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0) {
+ metric = 0;
+ } else
+ metric = ifr.ifr_metric;
+
+ strcpy(ifr.ifr_name, ifname);
+ if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
+ mtu = 0;
+ else
+ mtu = ifr.ifr_mtu;
+
+ strcpy(ifr.ifr_name, ifname);
+ if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) < 0) {
+ memset(&dstaddr, 0, sizeof(struct sockaddr));
+ } else
+ dstaddr = ifr.ifr_dstaddr;
+
+ strcpy(ifr.ifr_name, ifname);
+ if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) < 0) {
+ memset(&broadaddr, 0, sizeof(struct sockaddr));
+ } else
+ broadaddr = ifr.ifr_broadaddr;
+
+ strcpy(ifr.ifr_name, ifname);
+ if (ioctl(skfd, SIOCGIFNETMASK, &ifr) < 0) {
+ memset(&netmask, 0, sizeof(struct sockaddr));
+ } else
+ netmask = ifr.ifr_netmask;
+
+ return(0);
+}
+
+static void if_print(char *ifname)
+{
+ char buff[1024];
+ struct ifconf ifc;
+ struct ifreq *ifr;
+ int i;
+
+ if (ifname == (char *)NULL) {
+ ifc.ifc_len = sizeof(buff);
+ ifc.ifc_buf = buff;
+ if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
+ fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
+ return;
+ }
+
+ ifr = ifc.ifc_req;
+ for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
+ if (if_getconfig(ifr->ifr_name) < 0) {
+ fprintf(stderr, "%s: unknown interface.\n",
+ ifr->ifr_name);
+ continue;
+ }
+
+ if (((mif_flags & IFF_UP) == 0) && !opt_a) continue;
+ /*ife_print(&ife);*/
+ }
+ } else {
+ if (if_getconfig(ifname) < 0)
+ fprintf(stderr, "%s: unknown interface.\n", ifname);
+ }
+}
+
+
+/*
+ * Local variables:
+ * version-control: t
+ * kept-new-versions: 5
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 4
+ * compile-command: "gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave"
+ * End:
+ */
diff -u --recursive --new-file v2.4.14/linux/Documentation/networking/multicast.txt linux/Documentation/networking/multicast.txt
--- v2.4.14/linux/Documentation/networking/multicast.txt Wed Jul 25 17:10:17 2001
+++ linux/Documentation/networking/multicast.txt Wed Nov 7 14:46:01 2001
@@ -31,6 +31,7 @@
X de600 NO NO NO N/A
X de620 PROMISC PROMISC YES Software
X depca YES PROMISC YES Hardware
+dmfe YES YES YES Software(*)
X e2100 YES YES YES Hardware
X eepro YES PROMISC YES Hardware
X eexpress NO NO NO N/A
@@ -52,9 +53,12 @@
X tulip YES YES YES Hardware
X wavelan YES PROMISC YES Hardware
X wd YES YES YES Hardware
+xirc2ps_cs YES YES YES Hardware
X znet YES YES YES Software
X
X
X PROMISC = This multicast mode is in fact promiscuous mode. Avoid using
X cards who go PROMISC on any multicast in a multicast kernel.
+
X (#) = Hardware multicast support is not used yet.
+(*) = Hardware support for Davicom 9132 chipset only.
diff -u --recursive --new-file v2.4.14/linux/Documentation/parport.txt linux/Documentation/parport.txt
--- v2.4.14/linux/Documentation/parport.txt Sat May 19 17:54:14 2001
+++ linux/Documentation/parport.txt Fri Nov 9 14:30:55 2001
@@ -162,6 +162,10 @@
X is available and will be used.
X DMA DMA is available and will be used.
X
+ Note that the current implementation will only take
+ advantage of COMPAT and ECP modes if it has an IRQ
+ line to use.
+
X autoprobe Any IEEE-1284 device ID information that has been
X acquired from the (non-IEEE 1284.3) device.
X
diff -u --recursive --new-file v2.4.14/linux/Documentation/s390/Debugging390.txt linux/Documentation/s390/Debugging390.txt
--- v2.4.14/linux/Documentation/s390/Debugging390.txt Sun Aug 12 13:27:58 2001
+++ linux/Documentation/s390/Debugging390.txt Wed Nov 7 14:46:01 2001
@@ -1287,10 +1287,14 @@
X circumstances as the process may change when doing a
X TR I R <address range>.
X Thankfully after reading VM's online help I figured out how to debug
-I particular process.
+particular processes in 31 bit mode, however, according to the current
+VM online help documentation the method described below uses
+TR STO or STD which don't currently work on z/Series while in
+64-bit mode.
X
X Your first problem is to find the STD ( segment table designation )
X of the program you wish to debug.
+
X There are several ways you can do this here are a few
X 1) objdump --syms <program to be debugged> | grep main
X To get the address of main in the program.
diff -u --recursive --new-file v2.4.14/linux/Documentation/s390/chandev.8 linux/Documentation/s390/chandev.8
--- v2.4.14/linux/Documentation/s390/chandev.8 Tue Oct 23 22:48:49 2001
+++ linux/Documentation/s390/chandev.8 Wed Nov 7 14:46:01 2001
@@ -56,7 +56,7 @@
X .El
X .Bl -item
X .It
-Multiple options can be passed separated by semicolons but no spaces are allowed between parameters. To be consistent with other hotpluggable architectures the script pointed to /proc/sys/kernel/hotplug (normally /sbin/hotplug) will be called automatically on startup or a machine check of a device as follows.
+Multiple options can be passed separated by semicolons, no spaces or newlines are allowed between parameters on the kernel parameter line as it complicates parsing, spaces are allowed in /proc/chandev & chandev.conf, newlines are allowed in chandev.conf only. To be consistent with other hotpluggable architectures the script pointed to /proc/sys/kernel/hotplug (normally /sbin/hotplug) will be called automatically on startup or a machine check of a device as follows.
X /sbin/hotplug chandev <start starting_devnames> <machine_check (devname last/pre_recovery_status) (current/post_recovery_status)>.
X The chandev layer doesn't open stdin stdout or stderr so it is advisable that you add the following lines to the start of your script, here is a sample script which starts devices as they become available.
X .It
@@ -132,7 +132,7 @@
X .It
X Tells the channel layer to force ctc0 if detected to use cuu's 7c00 & 7c01 port,port_no is the relative adapter no on lcs, on ctc/escon this field is the ctc/escon protocol number ( default 0 ), don't do checksumming on received ip packets & as ctc doesn't have hardware stats so it ignores this parameter. This can be used for instance to force a device if it presents bad sense data to the IO layer & thus autodetection fails.
X .It
-lcs,0x7c00,0x7d00,-1,4096
+lcs,0x7c00,0x7d00,4096,-1
X All devices between 0x7c00 & 7d00 should be detected as lcs, let the driver use 4096k for each instance, don't care what port relative adapter number is chosen, don't checksum received ip packets & use hw stats .
X .It
X qeth1,0x7c00,0x7c01,0x7c02
diff -u --recursive --new-file v2.4.14/linux/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt
--- v2.4.14/linux/Documentation/usb/usb-serial.txt Tue Jul 3 17:08:18 2001
+++ linux/Documentation/usb/usb-serial.txt Mon Nov 12 09:50:39 2001
@@ -44,28 +44,33 @@
X device, including providing a unit to test with. This driver will end up
X being fully supported.
X
-Current status:
- The device's firmware is downloaded on connection, the new firmware
- runs properly and all four ports are successfully recognized and connected.
- Data can be sent and received through the device on all ports.
- Hardware flow control needs to be implemented.
+ Current status:
+ The device's firmware is downloaded on connection, the new firmware
+ runs properly and all four ports are successfully recognized and connected.
+ Data can be sent and received through the device on all ports.
+ Hardware flow control needs to be implemented.
X
+ For any questions or problems with this driver, please contact Greg
+ Kroah-Hartman at gr...@kroah.com
X
-HandSpring Visor USB docking station
-
-Current status:
- Only when the Visor tries to connect to the host, does the docking
- station show up as a valid USB device. When this happens, the device is
+
+HandSpring Visor, Palm USB, and Clié USB driver
+
+ This driver works with all HandSpring USB, Palm USB, and Sony Clié USB
+ devices.
+
+ Only when the device tries to connect to the host, will the device show
+ up to the host as a valid USB device. When this happens, the device is
X properly enumerated, assigned a port, and then communication _should_ be
X possible. The driver cleans up properly when the device is removed, or
- the connection is canceled on the Visor.
+ the connection is canceled on the device.
X
X NOTE:
- This means that in order to talk to the Visor, the sync button must be
- pressed BEFORE trying to get any program to communicate to the Visor.
+ This means that in order to talk to the device, the sync button must be
+ pressed BEFORE trying to get any program to communicate to the device.
X This goes against the current documentation for pilot-xfer and other
X packages, but is the only way that it will work due to the hardware
- in the Visor.
+ in the device.
X
X When the device is connected, try talking to it on the second port
X (this is usually /dev/ttyUSB1 if you do not have any other usb-serial
@@ -73,37 +78,49 @@
X the port to use for the HotSync transfer. The "Generic" port can be used
X for other device communication, such as a PPP link.
X
+ For some Sony Clié devices, /dev/ttyUSB0 must be used to talk to the
+ device. This is true for all OS version 3.5 devices, and most devices
+ that have had a flash upgrade to a newer version of the OS. See the
+ kernel system log for information on which is the correct port to use.
+
X If after pressing the sync button, nothing shows up in the system log,
- try resetting the Visor, first a hot reset, and then a cold reset if
- necessary. Some Visors need this before they can talk to the USB port
+ try resetting the device, first a hot reset, and then a cold reset if
+ necessary. Some devices need this before they can talk to the USB port
X properly.
X
- There is a webpage and mailing lists for this portion of the driver at:
+ There is a webpage and mailing lists for this portion of the driver at:
X http://usbvisor.sourceforge.net/
X
+ For any questions or problems with this driver, please contact Greg
+ Kroah-Hartman at gr...@kroah.com
+
X
X Keyspan PDA Serial Adapter
X
X Single port DB-9 serial adapter, pushed as a PDA adapter for iMacs (mostly
X sold in Macintosh catalogs, comes in a translucent white/green dongle).
X Fairly simple device. Firmware is homebrew.
+ This driver also works for the Xircom/Entrgra single port serial adapter.
X
-Current status:
- Things that work:
- basic input/output (tested with 'cu')
- blocking write when serial line can't keep up
- changing baud rates (up to 115200)
- getting/setting modem control pins (TIOCM{GET,SET,BIS,BIC})
- sending break (although duration looks suspect)
- Things that don't:
- device strings (as logged by kernel) have trailing binary garbage
- device ID isn't right, might collide with other Keyspan products
- changing baud rates ought to flush tx/rx to avoid mangled half characters
- Big Things on the todo list:
- parity, 7 vs 8 bits per char, 1 or 2 stop bits
- HW flow control
- not all of the standard USB descriptors are handled: Get_Status, Set_Feature
- O_NONBLOCK, select()
+ Current status:
+ Things that work:
+ basic input/output (tested with 'cu')
+ blocking write when serial line can't keep up
+ changing baud rates (up to 115200)
+ getting/setting modem control pins (TIOCM{GET,SET,BIS,BIC})
+ sending break (although duration looks suspect)
+ Things that don't:
+ device strings (as logged by kernel) have trailing binary garbage
+ device ID isn't right, might collide with other Keyspan products
+ changing baud rates ought to flush tx/rx to avoid mangled half characters
+ Big Things on the todo list:
+ parity, 7 vs 8 bits per char, 1 or 2 stop bits
+ HW flow control
+ not all of the standard USB descriptors are handled: Get_Status, Set_Feature
+ O_NONBLOCK, select()
+
+ For any questions or problems with this driver, please contact Brian
+ Warner at war...@lothar.com
X
X
X Keyspan USA-series Serial Adapters
@@ -111,19 +128,22 @@
X Single, Dual and Quad port adapters - driver uses Keyspan supplied
X firmware and is being developed with their support.
X
-Current status:
- The USA-18X, USA-28X, USA-19, USA-19W and USA-49W are supported and
- have been pretty throughly tested at various baud rates with 8-N-1
- character settings. Other character lengths and parity setups are
- presently untested.
-
- The USA-28 isn't yet supported though doing so should be pretty
- straightforward. Contact the maintainer if you require this
- functionality.
+ Current status:
+ The USA-18X, USA-28X, USA-19, USA-19W and USA-49W are supported and
+ have been pretty throughly tested at various baud rates with 8-N-1
+ character settings. Other character lengths and parity setups are
+ presently untested.
+
+ The USA-28 isn't yet supported though doing so should be pretty
+ straightforward. Contact the maintainer if you require this
+ functionality.
X
X More information is available at:
- http://www.linuxcare.com.au/hugh/keyspan.html
+ http://misc.nu/hugh/keyspan.html
X
+ For any questions or problems with this driver, please contact Hugh
+ Blemings at hu...@misc.nu
+
X
X FTDI Single Port Serial Driver
X
@@ -131,6 +151,9 @@
X device and the Linux driver can be found at:
X http://reality.sgi.com/bryder_wellington/ftdi_sio/
X
+ For any questions or problems with this driver, please contact Bill Ryder
+ at bry...@sgi.com
+
X
X ZyXEL omni.net lcd plus ISDN TA
X
@@ -162,65 +185,71 @@
X Belkin USB Serial Adapter F5U103
X
X Single port DB-9/PS-2 serial adapter from Belkin with firmware by eTEK Labs.
- The Peracom single port serial adapter also works with this driver.
+ The Peracom single port serial adapter also works with this driver, as
+ well as the GoHubs adapter.
+
+ Current status:
+ The following have been tested and work:
+ Baud rate 300-230400
+ Data bits 5-8
+ Stop bits 1-2
+ Parity N,E,O,M,S
+ Handshake None, Software (XON/XOFF), Hardware (CTSRTS,CTSDTR)*
+ Break Set and clear
+ Line contrl Input/Output query and control **
+
+ * Hardware input flow control is only enabled for firmware
+ levels above 2.06. Read source code comments describing Belkin
+ firmware errata. Hardware output flow control is working for all
+ firmware versions.
+ ** Queries of inputs (CTS,DSR,CD,RI) show the last
+ reported state. Queries of outputs (DTR,RTS) show the last
+ requested state and may not reflect current state as set by
+ automatic hardware flow control.
+
+ TO DO List:
+ -- Add true modem contol line query capability. Currently tracks the
+ states reported by the interrupt and the states requested.
+ -- Add error reporting back to application for UART error conditions.
+ -- Add support for flush ioctls.
+ -- Add everything else that is missing :)
X
-Current status:
- The following have been tested and work:
- Baud rate 300-230400
- Data bits 5-8
- Stop bits 1-2
- Parity N,E,O,M,S
- Handshake None, Software (XON/XOFF), Hardware (CTSRTS,CTSDTR)*
- Break Set and clear
- Line contrl Input/Output query and control **
-
- * Hardware input flow control is only enabled for firmware
- levels above 2.06. Read source code comments describing Belkin
- firmware errata. Hardware output flow control is working for all
- firmware versions.
- ** Queries of inputs (CTS,DSR,CD,RI) show the last
- reported state. Queries of outputs (DTR,RTS) show the last
- requested state and may not reflect current state as set by
- automatic hardware flow control.
-
-TO DO List:
- -- Add true modem contol line query capability. Currently tracks the
- states reported by the interrupt and the states requested.
- -- Add error reporting back to application for UART error conditions.
- -- Add support for flush ioctls.
- -- Add everything else that is missing :)
+ For any questions or problems with this driver, please contact William
+ Greathouse at wgrea...@smva.com
X
X
-Empeg empeg-car Mark I/II Driver (empeg.c)
+Empeg empeg-car Mark I/II Driver
X
X This is an experimental driver to provide connectivity support for the
X client synchronization tools for an Empeg empeg-car mp3 player.
X
X Tips:
-
X * Don't forget to create the device nodes for ttyUSB{0,1,2,...}
X * modprobe empeg (modprobe is your friend)
X * emptool --usb /dev/ttyUSB0 (or whatever you named your device node)
X
- The driver is still pretty new, so some testing 'in the wild' would be
- helpful. :)
+ For any questions or problems with this driver, please contact Gary
+ Brubaker at xav...@ix.netcom.com
X
X
X MCT USB Single Port Serial Adapter U232
X
- This driver is for the MCT USB-RS232 Converter (25 pin, Model No.
- U232-P25) from Magic Control Technology Corp. (there is also a 9 pin
- Model No. U232-P9). More information about this device can be found
- at the manufacture's web-site: http://www.mct.com.tw.
-
- The driver is generally working, though it still needs some more
- testing. It is derived from the Belkin USB Serial Adapter F5U103
- driver and its TODO list is valid for this driver as well.
-
- This driver has also been found to work for other products, which have
- the same Vendor ID but different Product IDs. Sitecom's U232-P25
- serial converter uses Product ID 0x230 and Vendor ID 0x711 and works with
- this driver. Also, D-Link's DU-H3SP USB BAY also works with this driver.
+ This driver is for the MCT USB-RS232 Converter (25 pin, Model No.
+ U232-P25) from Magic Control Technology Corp. (there is also a 9 pin
+ Model No. U232-P9). More information about this device can be found at
+ the manufacture's web-site: http://www.mct.com.tw.
+
+ The driver is generally working, though it still needs some more testing.
+ It is derived from the Belkin USB Serial Adapter F5U103 driver and its
+ TODO list is valid for this driver as well.
+
+ This driver has also been found to work for other products, which have
+ the same Vendor ID but different Product IDs. Sitecom's U232-P25 serial
+ converter uses Product ID 0x230 and Vendor ID 0x711 and works with this
+ driver. Also, D-Link's DU-H3SP USB BAY also works with this driver.
+
+ For any questions or problems with this driver, please contact Wolfgang
+ Grandegger at wolf...@ces.ch
X
X
X Inside Out Networks Edgeport Driver
@@ -244,17 +273,34 @@
X Edgeport/4 DIN
X Edgeport/16 Dual
X
+ For any questions or problems with this driver, please contact Greg
+ Kroah-Hartman at gr...@kroah.com
+
X
X REINER SCT cyberJack pinpad/e-com USB chipcard reader
X
X Interface to ISO 7816 compatible contactbased chipcards, e.g. GSM SIMs.
X
-Current status:
- This is the kernel part of the driver for this USB card reader.
- There is also a user part for a CT-API driver available. A site
- for downloading is TBA. For now, you can request it from the
- maintainer (linu...@sii.li).
+ Current status:
+ This is the kernel part of the driver for this USB card reader.
+ There is also a user part for a CT-API driver available. A site
+ for downloading is TBA. For now, you can request it from the
+ maintainer (linu...@sii.li).
+
+ For any questions or problems with this driver, please contact
+ linu...@sii.li
+
X
+Prolific PL2303 Driver
+
+ This driver support any device that has the PL2303 chip from Prolific
+ in it. This includes a number of single port USB to serial
+ converters and USB GPS devices. Devices from Aten (the UC-232) and
+ IO-Data work with this driver.
+
+ For any questions or problems with this driver, please contact Greg
+ Kroah-Hartman at gr...@kroah.com
+
X
X Generic Serial driver
X
@@ -275,13 +321,17 @@
X development board, providing a way to develop USB firmware without
X having to write a custom driver.
X
+ For any questions or problems with this driver, please contact Greg
+ Kroah-Hartman at gr...@kroah.com
+
X
X CONTACT:
X
- If anyone has any problems using this driver, with any of the above
- specified products, please contact me, or join the Linux-USB mailing
- list (information on joining the mailing list, as well as a link to its
- searchable archive is at http://www.linux-usb.org/ )
+ If anyone has any problems using these drivers, with any of the above
+ specified products, please contact the specific driver's author listed
+ above, or join the Linux-USB mailing list (information on joining the
+ mailing list, as well as a link to its searchable archive is at
+ http://www.linux-usb.org/ )
X
X
X Greg Kroah-Hartman
diff -u --recursive --new-file v2.4.14/linux/MAINTAINERS linux/MAINTAINERS
--- v2.4.14/linux/MAINTAINERS Mon Nov 5 15:55:25 2001
+++ linux/MAINTAINERS Fri Nov 16 10:03:24 2001
@@ -201,6 +201,12 @@
X M: li...@treblig.org
X S: Maintained
X
+ARM/SHARK MACHINE SUPPORT
+P: Alexander Schulz
+M: al...@shark-linux.de
+W: http://www.shark-linux.de/shark.html
+S: Maintained
+
X ARM/STRONGARM110 PORT
X P: Russell King
X M: r...@arm.linux.org.uk
@@ -529,6 +535,12 @@
X L: linux-...@vger.kernel.org
X S: Maintained
X
+EXT3 FILE SYSTEM
+P: Remy Card, Stephen Tweedie
+M: s...@redhat.com, ak...@zip.com.au, adi...@turbolinux.com
+L: ext3-...@redhat.com
+S: Maintained
+
X FARSYNC SYNCHRONOUS DRIVER
X P: Bob Dunlop
X M: r...@xyzzy.clara.co.uk
@@ -758,6 +770,13 @@
X M: tig...@veritas.com
X S: Maintained
X
+INTERMEZZO FILE SYSTEM
+P: Peter J. Braam
+M: br...@clusterfs.com
+W: http://www.inter-mezzo.org/
+L: intermezz...@lists.sourceforge.net
+S: Maintained
+
X IP MASQUERADING:
X P: Juanjo Ciarlante
X M: jjci...@raiz.uncu.edu.ar
@@ -1025,7 +1044,7 @@
X
X NETWORK DEVICE DRIVERS
X P: Andrew Morton
-M: and...@uow.edu.au
+M: ak...@zip.com.au
X P: Jeff Garzik
X M: jga...@mandrakesoft.com
X L: linu...@vger.kernel.org
@@ -1155,6 +1174,17 @@
X L: linux-...@vger.kernel.org
X S: Odd Fixes
X
+PCI HOTPLUG CORE
+P: Greg Kroah-Hartman
+M: gr...@kroah.com
+M: gre...@us.ibm.com
+S: Supported
+
+PCI HOTPLUG COMPAQ DRIVER
+P: Greg Kroah-Hartman
+M: gr...@kroah.com
+S: Maintained
+
X PCMCIA SUBSYSTEM
X P: David Hinds
X M: dhi...@zen.stanford.edu
@@ -1182,6 +1212,11 @@
X L: linu...@vger.kernel.org
X S: Maintained
X
+PPP OVER ATM (RFC 2364)
+P: Mitchell Blank Jr
+M: mi...@sfgoth.com
+S: Maintained
+
X PPP OVER ETHERNET
X P: Michal Ostrowski
X M: most...@styx.uwaterloo.ca
@@ -1406,8 +1441,8 @@
X S: Maintained
X
X SYSV FILESYSTEM
-P: Krzysztof G. Baranowski
-M: k...@manjak.knm.org.pl
+P: Christoph Hellwig
+M: h...@caldera.de
X S: Maintained
X
X TLAN NETWORK DRIVER
diff -u --recursive --new-file v2.4.14/linux/Makefile linux/Makefile
--- v2.4.14/linux/Makefile Mon Nov 5 15:55:25 2001
+++ linux/Makefile Thu Nov 22 11:22:58 2001
@@ -1,7 +1,7 @@
X VERSION = 2
X PATCHLEVEL = 4
-SUBLEVEL = 14
-EXTRAVERSION =
+SUBLEVEL = 15
+EXTRAVERSION =-greased-turkey
X
X KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
X
@@ -183,6 +183,7 @@
X DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.o
X DRIVERS-$(CONFIG_MD) += drivers/md/mddev.o
X DRIVERS-$(CONFIG_BLUEZ) += drivers/bluetooth/bluetooth.o
+DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o
X
X DRIVERS := $(DRIVERS-y)
X
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.4.14/linux/arch/alpha/config.in Mon Nov 5 15:55:25 2001
+++ linux/arch/alpha/config.in Tue Nov 20 15:49:31 2001
@@ -296,6 +296,10 @@
X fi
X endmenu
X
+if [ "$CONFIG_PCI" = "y" ]; then
+ source drivers/message/fusion/Config.in
+fi
+
X if [ "$CONFIG_NET" = "y" ]; then
X mainmenu_option next_comment
X comment 'Network device support'
@@ -374,14 +378,18 @@
X mainmenu_option next_comment
X comment 'Kernel hacking'
X
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- tristate 'Kernel FP software completion' CONFIG_MATHEMU
+bool 'Legacy kernel start address' CONFIG_ALPHA_LEGACY_START_ADDRESS
+
+bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
+if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
+ tristate ' Kernel FP software completion' CONFIG_MATHEMU
+ bool ' Debug memory allocations' CONFIG_DEBUG_SLAB
+ bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ
+ bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+ bool ' Read-write spinlock debugging' CONFIG_DEBUG_RWLOCK
+ bool ' Semaphore debugging' CONFIG_DEBUG_SEMAPHORE
X else
- define_tristate CONFIG_MATHEMU y
+ define_tristate CONFIG_MATHEMU y
X fi
-
-bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
-
-bool 'Legacy kernel start address' CONFIG_ALPHA_LEGACY_START_ADDRESS
X
X endmenu
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v2.4.14/linux/arch/alpha/defconfig Mon Aug 27 12:41:37 2001
+++ linux/arch/alpha/defconfig Mon Nov 19 15:19:42 2001
@@ -1,7 +1,10 @@
X #
X # Automatically generated make config: don't edit
X #
+CONFIG_ALPHA=y
X # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
X
X #
X # Code maturity level options
@@ -49,10 +52,13 @@
X # CONFIG_ALPHA_TITAN is not set
X # CONFIG_ALPHA_WILDFIRE is not set
X CONFIG_ISA=y
+CONFIG_EISA=y
X # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
X CONFIG_PCI=y
X CONFIG_ALPHA_BROKEN_IRQ_MASK=y
X # CONFIG_SMP is not set
+# CONFIG_DISCONTIGMEM is not set
X # CONFIG_ALPHA_LARGE_VMALLOC is not set
X CONFIG_PCI_NAMES=y
X # CONFIG_HOTPLUG is not set
@@ -107,8 +113,8 @@
X # CONFIG_MD_RAID0 is not set
X # CONFIG_MD_RAID1 is not set
X # CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
X # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
X
X #
X # Networking options
@@ -135,12 +141,16 @@
X #
X CONFIG_IP_NF_CONNTRACK=m
X CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
X CONFIG_IP_NF_IPTABLES=m
X # CONFIG_IP_NF_MATCH_LIMIT is not set
X # CONFIG_IP_NF_MATCH_MAC is not set
X # CONFIG_IP_NF_MATCH_MARK is not set
X # CONFIG_IP_NF_MATCH_MULTIPORT is not set
X # CONFIG_IP_NF_MATCH_TOS is not set
+# CONFIG_IP_NF_MATCH_LENGTH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_TCPMSS is not set
X # CONFIG_IP_NF_MATCH_STATE is not set
X # CONFIG_IP_NF_MATCH_UNCLEAN is not set
X # CONFIG_IP_NF_MATCH_OWNER is not set
@@ -151,13 +161,18 @@
X CONFIG_IP_NF_NAT_NEEDED=y
X CONFIG_IP_NF_TARGET_MASQUERADE=m
X # CONFIG_IP_NF_TARGET_REDIRECT is not set
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
X # CONFIG_IP_NF_MANGLE is not set
X # CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_TCPMSS is not set
X CONFIG_IP_NF_COMPAT_IPCHAINS=y
X CONFIG_IP_NF_NAT_NEEDED=y
X # CONFIG_IPV6 is not set
X # CONFIG_KHTTPD is not set
X # CONFIG_ATM is not set
+CONFIG_VLAN_8021Q=m


X
X #
X #

@@ -222,6 +237,7 @@
X CONFIG_BLK_DEV_IDEPCI=y
X # CONFIG_IDEPCI_SHARE_IRQ is not set
X CONFIG_BLK_DEV_IDEDMA_PCI=y
+CONFIG_BLK_DEV_ADMA=y
X # CONFIG_BLK_DEV_OFFBOARD is not set
X CONFIG_IDEDMA_PCI_AUTO=y
X CONFIG_BLK_DEV_IDEDMA=y
@@ -231,8 +247,8 @@
X # CONFIG_AEC62XX_TUNING is not set
X CONFIG_BLK_DEV_ALI15X3=y
X # CONFIG_WDC_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD7409 is not set
-# CONFIG_AMD7409_OVERRIDE is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_AMD74XX_OVERRIDE is not set
X CONFIG_BLK_DEV_CMD64X=y
X CONFIG_BLK_DEV_CY82C693=y
X # CONFIG_BLK_DEV_CS5530 is not set
@@ -243,7 +259,10 @@
X # CONFIG_BLK_DEV_OPTI621 is not set
X # CONFIG_BLK_DEV_PDC202XX is not set
X # CONFIG_PDC202XX_BURST is not set
+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_SVWKS is not set
X # CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
X # CONFIG_BLK_DEV_TRM290 is not set
X # CONFIG_BLK_DEV_VIA82CXXX is not set
X # CONFIG_IDE_CHIPSETS is not set
@@ -251,6 +270,9 @@
X # CONFIG_IDEDMA_IVB is not set
X # CONFIG_DMA_NONPCI is not set
X CONFIG_BLK_DEV_IDE_MODES=y
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
X
X #
X # SCSI support
@@ -263,6 +285,7 @@
X CONFIG_BLK_DEV_SD=y
X CONFIG_SD_EXTRA_DEVS=40
X # CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
X CONFIG_BLK_DEV_SR=y
X CONFIG_BLK_DEV_SR_VENDOR=y
X CONFIG_SR_EXTRA_DEVS=2
@@ -288,6 +311,8 @@
X CONFIG_SCSI_AIC7XXX=y
X CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
X CONFIG_AIC7XXX_RESET_DELAY_MS=5000
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+# CONFIG_SCSI_DPT_I2O is not set
X # CONFIG_SCSI_ADVANSYS is not set
X # CONFIG_SCSI_IN2000 is not set
X # CONFIG_SCSI_AM53C974 is not set
@@ -349,6 +374,12 @@
X # Ethernet (10 or 100Mbit)
X #
X CONFIG_NET_ETHERNET=y
+# CONFIG_SUNLANCE is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNGEM is not set
X CONFIG_NET_VENDOR_3COM=y
X # CONFIG_EL1 is not set
X # CONFIG_EL2 is not set
@@ -356,12 +387,15 @@
X # CONFIG_EL16 is not set
X # CONFIG_EL3 is not set
X # CONFIG_3C515 is not set
+# CONFIG_ELMC is not set
+# CONFIG_ELMC_II is not set
X CONFIG_VORTEX=y
X # CONFIG_LANCE is not set
X # CONFIG_NET_VENDOR_SMC is not set
X # CONFIG_NET_VENDOR_RACAL is not set
X # CONFIG_AT1700 is not set
X # CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
X # CONFIG_NET_ISA is not set
X CONFIG_NET_PCI=y
X # CONFIG_PCNET32 is not set
@@ -393,11 +427,15 @@
X # Ethernet (1000 Mbit)
X #
X # CONFIG_ACENIC is not set
+CONFIG_DL2K=m
+# CONFIG_MYRI_SBUS is not set
+CONFIG_NS83820=m
X # CONFIG_HAMACHI is not set
X CONFIG_YELLOWFIN=y
X # CONFIG_SK98LIN is not set
X # CONFIG_FDDI is not set
X # CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
X # CONFIG_PPP is not set
X # CONFIG_SLIP is not set
X
@@ -463,7 +501,11 @@
X #
X # Joysticks
X #
-# CONFIG_JOYSTICK is not set
+# CONFIG_INPUT_GAMEPORT is not set
+
+#
+# Input core support is needed for gameports
+#
X
X #
X # Input core support is needed for joysticks
@@ -499,6 +541,8 @@
X # CONFIG_QUOTA is not set
X CONFIG_AUTOFS_FS=m
X # CONFIG_AUTOFS4_FS is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
X # CONFIG_ADFS_FS is not set
X # CONFIG_ADFS_FS_RW is not set
X # CONFIG_AFFS_FS is not set
@@ -510,11 +554,15 @@
X CONFIG_VFAT_FS=y
X # CONFIG_EFS_FS is not set
X # CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
X # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
X # CONFIG_RAMFS is not set
X CONFIG_ISO9660_FS=y
X # CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
X # CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
X # CONFIG_NTFS_FS is not set
X # CONFIG_NTFS_RW is not set
X # CONFIG_HPFS_FS is not set
@@ -528,7 +576,6 @@
X # CONFIG_ROMFS_FS is not set
X CONFIG_EXT2_FS=y
X # CONFIG_SYSV_FS is not set
-# CONFIG_SYSV_FS_WRITE is not set
X # CONFIG_UDF_FS is not set
X # CONFIG_UDF_RW is not set
X # CONFIG_UFS_FS is not set
@@ -554,10 +601,10 @@
X # CONFIG_NCPFS_NFS_NS is not set
X # CONFIG_NCPFS_OS2_NS is not set
X # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
X # CONFIG_NCPFS_NLS is not set
X # CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
X
X #
X # Partition Types
@@ -565,6 +612,7 @@
X # CONFIG_PARTITION_ADVANCED is not set
X CONFIG_OSF_PARTITION=y
X CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
X CONFIG_NLS=y
X
X #
@@ -586,11 +634,13 @@
X # CONFIG_NLS_CODEPAGE_865 is not set
X # CONFIG_NLS_CODEPAGE_866 is not set
X # CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
X # CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
X # CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
X # CONFIG_NLS_ISO8859_1 is not set
X # CONFIG_NLS_ISO8859_2 is not set
X # CONFIG_NLS_ISO8859_3 is not set
@@ -598,11 +648,12 @@
X # CONFIG_NLS_ISO8859_5 is not set
X # CONFIG_NLS_ISO8859_6 is not set
X # CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
X # CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
X # CONFIG_NLS_ISO8859_14 is not set
X # CONFIG_NLS_ISO8859_15 is not set
X # CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
X # CONFIG_NLS_UTF8 is not set
X
X #
@@ -626,13 +677,121 @@
X # CONFIG_USB is not set
X
X #
+# USB Controllers
+#
+# CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
+# CONFIG_USB_OHCI is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+
+#
+# Input core support is needed for USB HID
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_CDCETHER is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set


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

echo 'End of part 020'
echo 'File patch-2.4.15 is continued in part 021'
echo "021" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:57 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part021

#!/bin/sh -x
# this is part 021 of a 115 - part archive


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

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

+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_RIO500 is not set
+
+#


X # Input core support

X #
X # CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
X
X #
X # Kernel hacking
X #
+CONFIG_ALPHA_LEGACY_START_ADDRESS=y
+CONFIG_DEBUG_KERNEL=y
X CONFIG_MATHEMU=y
+# CONFIG_DEBUG_SLAB is not set
X CONFIG_MAGIC_SYSRQ=y
-CONFIG_ALPHA_LEGACY_START_ADDRESS=y
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.4.14/linux/arch/alpha/kernel/alpha_ksyms.c Mon Nov 5 15:55:25 2001
+++ linux/arch/alpha/kernel/alpha_ksyms.c Tue Nov 20 15:49:31 2001
@@ -222,12 +222,12 @@
X EXPORT_SYMBOL(__global_save_flags);
X EXPORT_SYMBOL(__global_restore_flags);
X EXPORT_SYMBOL(atomic_dec_and_lock);
-#if DEBUG_SPINLOCK
+#ifdef CONFIG_DEBUG_SPINLOCK
X EXPORT_SYMBOL(spin_unlock);
X EXPORT_SYMBOL(debug_spin_lock);
X EXPORT_SYMBOL(debug_spin_trylock);
X #endif
-#if DEBUG_RWLOCK
+#ifdef CONFIG_DEBUG_RWLOCK
X EXPORT_SYMBOL(write_lock);
X EXPORT_SYMBOL(read_lock);
X #endif
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v2.4.14/linux/arch/alpha/kernel/entry.S Sun Aug 12 13:27:58 2001
+++ linux/arch/alpha/kernel/entry.S Fri Nov 9 13:45:35 2001
@@ -1145,3 +1145,6 @@
X .quad sys_mincore /* 375 */
X .quad sys_pciconfig_iobase
X .quad sys_getdents64
+ .quad sys_gettid
+ .quad sys_readahead
+ .quad sys_ni_syscall /* 380, sys_security */
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/kernel/irq_smp.c linux/arch/alpha/kernel/irq_smp.c
--- v2.4.14/linux/arch/alpha/kernel/irq_smp.c Fri Aug 4 16:15:38 2000
+++ linux/arch/alpha/kernel/irq_smp.c Tue Nov 20 15:49:31 2001
@@ -124,7 +124,7 @@
X /*
X * Finally.
X */
-#if DEBUG_SPINLOCK
+#ifdef CONFIG_DEBUG_SPINLOCK
X global_irq_lock.task = current;
X global_irq_lock.previous = where;
X #endif
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/kernel/proto.h linux/arch/alpha/kernel/proto.h
--- v2.4.14/linux/arch/alpha/kernel/proto.h Fri Mar 2 11:12:07 2001
+++ linux/arch/alpha/kernel/proto.h Wed Nov 14 08:18:06 2001
@@ -91,7 +91,6 @@
X
X /* smp.c */
X extern void setup_smp(void);
-extern int smp_info(char *buffer);
X extern void handle_ipi(struct pt_regs *);
X extern void smp_percpu_timer_interrupt(struct pt_regs *);
X
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/kernel/semaphore.c linux/arch/alpha/kernel/semaphore.c
--- v2.4.14/linux/arch/alpha/kernel/semaphore.c Tue Apr 17 17:19:24 2001
+++ linux/arch/alpha/kernel/semaphore.c Tue Nov 20 15:49:31 2001
@@ -57,7 +57,7 @@
X {
X DECLARE_WAITQUEUE(wait, current);
X
-#if DEBUG_SEMAPHORE
+#ifdef CONFIG_DEBUG_SEMAPHORE
X printk("%s(%d): down failed(%p)\n",
X current->comm, current->pid, sem);
X #endif
@@ -97,7 +97,7 @@
X remove_wait_queue(&sem->wait, &wait);
X current->state = TASK_RUNNING;
X
-#if DEBUG_SEMAPHORE
+#ifdef CONFIG_DEBUG_SEMAPHORE
X printk("%s(%d): down acquired(%p)\n",
X current->comm, current->pid, sem);
X #endif
@@ -109,7 +109,7 @@
X DECLARE_WAITQUEUE(wait, current);
X long ret;
X
-#if DEBUG_SEMAPHORE
+#ifdef CONFIG_DEBUG_SEMAPHORE
X printk("%s(%d): down failed(%p)\n",
X current->comm, current->pid, sem);
X #endif
@@ -185,7 +185,7 @@
X current->state = TASK_RUNNING;
X wake_up(&sem->wait);
X
-#if DEBUG_SEMAPHORE
+#ifdef CONFIG_DEBUG_SEMAPHORE
X printk("%s(%d): down %s(%p)\n",
X current->comm, current->pid,
X (ret < 0 ? "interrupted" : "acquired"), sem);
@@ -207,7 +207,7 @@
X #if WAITQUEUE_DEBUG
X CHECK_MAGIC(sem->__magic);
X #endif
-#if DEBUG_SEMAPHORE
+#ifdef CONFIG_DEBUG_SEMAPHORE
X printk("%s(%d): down(%p) <count=%d> from %p\n",
X current->comm, current->pid, sem,
X atomic_read(&sem->count), __builtin_return_address(0));
@@ -221,7 +221,7 @@
X #if WAITQUEUE_DEBUG
X CHECK_MAGIC(sem->__magic);
X #endif
-#if DEBUG_SEMAPHORE
+#ifdef CONFIG_DEBUG_SEMAPHORE
X printk("%s(%d): down(%p) <count=%d> from %p\n",
X current->comm, current->pid, sem,
X atomic_read(&sem->count), __builtin_return_address(0));
@@ -240,7 +240,7 @@
X
X ret = __down_trylock(sem);
X
-#if DEBUG_SEMAPHORE
+#ifdef CONFIG_DEBUG_SEMAPHORE
X printk("%s(%d): down_trylock %s from %p\n",
X current->comm, current->pid,
X ret ? "failed" : "acquired",
@@ -256,7 +256,7 @@
X #if WAITQUEUE_DEBUG
X CHECK_MAGIC(sem->__magic);
X #endif
-#if DEBUG_SEMAPHORE
+#ifdef CONFIG_DEBUG_SEMAPHORE
X printk("%s(%d): up(%p) <count=%d> from %p\n",
X current->comm, current->pid, sem,
X atomic_read(&sem->count), __builtin_return_address(0));
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v2.4.14/linux/arch/alpha/kernel/setup.c Mon Nov 5 15:55:25 2001
+++ linux/arch/alpha/kernel/setup.c Fri Nov 16 18:38:39 2001
@@ -30,6 +30,7 @@
X #include <linux/ioport.h>
X #include <linux/bootmem.h>
X #include <linux/pci.h>
+#include <linux/seq_file.h>
X
X #ifdef CONFIG_BLK_DEV_INITRD
X #include <linux/blk.h>
@@ -1043,10 +1044,8 @@
X }
X
X
-/*
- * BUFFER is PAGE_SIZE bytes long.
- */
-int get_cpuinfo(char *buffer)
+static int
+show_cpuinfo(struct seq_file *f, void *slot)
X {
X extern struct unaligned_stat {
X unsigned long count, va, pc;
@@ -1058,14 +1057,13 @@
X "EV68CX", "EV7", "EV79", "EV69"
X };
X
- struct percpu_struct *cpu;
+ struct percpu_struct *cpu = slot;
X unsigned int cpu_index;
X char *cpu_name;
X char *systype_name;
X char *sysvariation_name;
- int len, nr_processors;
+ int nr_processors;
X
- cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
X cpu_index = (unsigned) (cpu->type - 1);
X cpu_name = "Unknown";
X if (cpu_index < N(cpu_names))
@@ -1076,8 +1074,7 @@
X
X nr_processors = get_nr_processors(cpu, hwrpb->nr_processors);
X
- len = sprintf(buffer,
- "cpu\t\t\t: Alpha\n"
+ seq_printf(f, "cpu\t\t\t: Alpha\n"
X "cpu model\t\t: %s\n"
X "cpu variation\t\t: %ld\n"
X "cpu revision\t\t: %ld\n"
@@ -1114,11 +1111,41 @@
X platform_string(), nr_processors);
X
X #ifdef CONFIG_SMP
- len += smp_info(buffer+len);
+ seq_printf(f, "cpus active\t\t: %d\n"
+ "cpu active mask\t\t: %016lx\n",
+ smp_num_cpus, cpu_present_mask);
X #endif
X
- return len;


+ return 0;
+}
+

+/*
+ * We show only CPU #0 info.
+ */
+static void *
+c_start(struct seq_file *f, loff_t *pos)
+{
+ return *pos ? NULL : (char *)hwrpb + hwrpb->processor_offset;
+}
+
+static void *
+c_next(struct seq_file *f, void *v, loff_t *pos)
+{
+ return NULL;
X }
+
+static void
+c_stop(struct seq_file *f, void *v)
+{
+}
+
+struct seq_operations cpuinfo_op = {
+ start: c_start,
+ next: c_next,
+ stop: c_stop,
+ show: show_cpuinfo,
+};
+
X
X static int alpha_panic_event(struct notifier_block *this,
X unsigned long event,
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/kernel/signal.c linux/arch/alpha/kernel/signal.c
--- v2.4.14/linux/arch/alpha/kernel/signal.c Wed Jan 24 15:16:23 2001
+++ linux/arch/alpha/kernel/signal.c Fri Nov 9 13:45:35 2001
@@ -17,6 +17,7 @@
X #include <linux/smp.h>
X #include <linux/smp_lock.h>
X #include <linux/stddef.h>
+#include <linux/tty.h>
X
X #include <asm/bitops.h>
X #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c
--- v2.4.14/linux/arch/alpha/kernel/smp.c Tue Oct 9 17:06:51 2001
+++ linux/arch/alpha/kernel/smp.c Wed Nov 21 10:31:09 2001
@@ -491,9 +491,9 @@
X panic("idle process is init_task for CPU %d", cpuid);
X
X idle->processor = cpuid;
+ idle->cpus_runnable = 1 << cpuid; /* we schedule the first task manually */
X __cpu_logical_map[cpunum] = cpuid;
X __cpu_number_map[cpuid] = cpunum;
- idle->has_cpu = 1; /* we schedule the first task manually */
X
X del_from_runqueue(idle);
X unhash_process(idle);
@@ -1091,16 +1091,7 @@
X }
X }
X
-int
-smp_info(char *buffer)
-{
- return sprintf(buffer,
- "cpus active\t\t: %d\n"
- "cpu active mask\t\t: %016lx\n",
- smp_num_cpus, cpu_present_mask);
-}
-
-#if DEBUG_SPINLOCK
+#ifdef CONFIG_DEBUG_SPINLOCK
X void
X spin_unlock(spinlock_t * lock)
X {
@@ -1190,9 +1181,9 @@
X }
X return ret;
X }
-#endif /* DEBUG_SPINLOCK */
+#endif /* CONFIG_DEBUG_SPINLOCK */
X
-#if DEBUG_RWLOCK
+#ifdef CONFIG_DEBUG_RWLOCK
X void write_lock(rwlock_t * lock)
X {
X long regx, regy;
@@ -1270,4 +1261,4 @@
X goto try_again;
X }
X }
-#endif /* DEBUG_RWLOCK */
+#endif /* CONFIG_DEBUG_RWLOCK */
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/kernel/sys_miata.c linux/arch/alpha/kernel/sys_miata.c
--- v2.4.14/linux/arch/alpha/kernel/sys_miata.c Tue Oct 23 22:48:49 2001
+++ linux/arch/alpha/kernel/sys_miata.c Fri Nov 9 13:58:02 2001
@@ -176,6 +176,19 @@
X { -1, -1, -1, -1, -1}, /* IdSel 31, PCI-PCI */
X };
X const long min_idsel = 3, max_idsel = 20, irqs_per_slot = 5;
+
+ /* the USB function of the 82c693 has it's interrupt connected to
+ the 2nd 8259 controller. So we have to check for it first. */
+
+ if((slot == 7) && (PCI_FUNC(dev->devfn) == 3)) {
+ u8 irq=0;
+
+ if(pci_read_config_byte(pci_find_slot(dev->bus->number, dev->devfn & ~(7)), 0x40,&irq)!=PCIBIOS_SUCCESSFUL)
+ return -1;
+ else
+ return irq;
+ }
+
X return COMMON_TABLE_LOOKUP;
X }
X
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c
--- v2.4.14/linux/arch/alpha/kernel/time.c Mon Nov 5 15:55:25 2001
+++ linux/arch/alpha/kernel/time.c Sat Nov 17 11:47:44 2001
@@ -186,8 +186,8 @@
X [EV4_CPU] = { 150000000, 300000000 },
X [LCA4_CPU] = { 150000000, 300000000 }, /* guess */
X [EV45_CPU] = { 200000000, 300000000 },
- [EV5_CPU] = { 266000000, 333333333 },
- [EV56_CPU] = { 366000000, 667000000 },
+ [EV5_CPU] = { 250000000, 433000000 },
+ [EV56_CPU] = { 333000000, 667000000 },
X [PCA56_CPU] = { 400000000, 600000000 }, /* guess */
X [PCA57_CPU] = { 500000000, 600000000 }, /* guess */
X [EV6_CPU] = { 466000000, 600000000 },
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v2.4.14/linux/arch/alpha/kernel/traps.c Mon Nov 5 15:55:25 2001
+++ linux/arch/alpha/kernel/traps.c Tue Nov 20 15:49:31 2001
@@ -20,6 +20,7 @@
X #include <asm/unaligned.h>
X #include <asm/sysinfo.h>
X #include <asm/hwrpb.h>
+#include <asm/mmu_context.h>
X
X #include "proto.h"
X
@@ -311,8 +312,22 @@
X if (alpha_fp_emul(regs.pc-4))
X return;
X }
- /* fallthrough as illegal instruction .. */
+ break;
+
X case 3: /* FEN fault */
+ /* Irritating users can call PAL_clrfen to disable the
+ FPU for the process. The kernel will then trap in
+ do_switch_stack and undo_switch_stack when we try
+ to save and restore the FP registers.
+
+ Given that GCC by default generates code that uses the
+ FP registers, PAL_clrfen is not useful except for DoS
+ attacks. So turn the bleeding FPU back on and be done
+ with it. */
+ current->thread.pal_flags |= 1;
+ __reload_thread(&current->thread);
+ return;
+
X case 5: /* illoc */
X default: /* unexpected instruction-fault type */
X ;
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/lib/dec_and_lock.c linux/arch/alpha/lib/dec_and_lock.c
--- v2.4.14/linux/arch/alpha/lib/dec_and_lock.c Mon Nov 5 15:55:25 2001
+++ linux/arch/alpha/lib/dec_and_lock.c Fri Nov 9 13:39:57 2001
@@ -18,15 +18,16 @@
X subl $1, 1, $1 \n\
X beq $1, 2f \n\
X stl_c $1, 0($16) \n\
- beq $1, 3f \n\
+ beq $1, 4f \n\
X mb \n\
X clr $0 \n\
X ret \n\
-3: br 1b \n\
-2: lda $27, atomic_dec_and_lock_1 \n\
+2: br $29, 3f \n\
+3: ldgp $29, 0($29) \n\
+ br $atomic_dec_and_lock_1..ng \n\
+ .subsection 2 \n\
+4: br 1b \n\
X .end atomic_dec_and_lock");
-
- /* FALLTHRU */
X
X static int __attribute__((unused))
X atomic_dec_and_lock_1(atomic_t *atomic, spinlock_t *lock)
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/lib/io.c linux/arch/alpha/lib/io.c
--- v2.4.14/linux/arch/alpha/lib/io.c Sat Nov 27 15:27:48 1999
+++ linux/arch/alpha/lib/io.c Fri Nov 9 13:45:35 2001
@@ -9,124 +9,124 @@
X
X #include <asm/io.h>
X
-unsigned int _inb(unsigned long addr)
+u8 _inb(unsigned long addr)
X {
X return __inb(addr);
X }
X
-unsigned int _inw(unsigned long addr)
+u16 _inw(unsigned long addr)
X {
X return __inw(addr);
X }
X
-unsigned int _inl(unsigned long addr)
+u32 _inl(unsigned long addr)
X {
X return __inl(addr);
X }
X
X
-void _outb(unsigned char b, unsigned long addr)
+void _outb(u8 b, unsigned long addr)
X {
X __outb(b, addr);
X }
X
-void _outw(unsigned short b, unsigned long addr)
+void _outw(u16 b, unsigned long addr)
X {
X __outw(b, addr);
X }
X
-void _outl(unsigned int b, unsigned long addr)
+void _outl(u32 b, unsigned long addr)
X {
X __outl(b, addr);
X }
X
-unsigned long ___raw_readb(unsigned long addr)
+u8 ___raw_readb(unsigned long addr)
X {
X return __readb(addr);
X }
X
-unsigned long ___raw_readw(unsigned long addr)
+u16 ___raw_readw(unsigned long addr)
X {
X return __readw(addr);
X }
X
-unsigned long ___raw_readl(unsigned long addr)
+u32 ___raw_readl(unsigned long addr)
X {
X return __readl(addr);
X }
X
-unsigned long ___raw_readq(unsigned long addr)
+u64 ___raw_readq(unsigned long addr)
X {
X return __readq(addr);
X }
X
-unsigned long _readb(unsigned long addr)
+u8 _readb(unsigned long addr)
X {
X unsigned long r = __readb(addr);
X mb();
X return r;
X }
X
-unsigned long _readw(unsigned long addr)
+u16 _readw(unsigned long addr)
X {
X unsigned long r = __readw(addr);
X mb();
X return r;
X }
X
-unsigned long _readl(unsigned long addr)
+u32 _readl(unsigned long addr)
X {
X unsigned long r = __readl(addr);
X mb();
X return r;
X }
X
-unsigned long _readq(unsigned long addr)
+u64 _readq(unsigned long addr)
X {
X unsigned long r = __readq(addr);
X mb();
X return r;
X }
X
-void ___raw_writeb(unsigned char b, unsigned long addr)
+void ___raw_writeb(u8 b, unsigned long addr)
X {
X __writeb(b, addr);
X }
X
-void ___raw_writew(unsigned short b, unsigned long addr)
+void ___raw_writew(u16 b, unsigned long addr)
X {
X __writew(b, addr);
X }
X
-void ___raw_writel(unsigned int b, unsigned long addr)
+void ___raw_writel(u32 b, unsigned long addr)
X {
X __writel(b, addr);
X }
X
-void ___raw_writeq(unsigned long b, unsigned long addr)
+void ___raw_writeq(u64 b, unsigned long addr)
X {
X __writeq(b, addr);
X }
X
-void _writeb(unsigned char b, unsigned long addr)
+void _writeb(u8 b, unsigned long addr)
X {
X __writeb(b, addr);
X mb();
X }
X
-void _writew(unsigned short b, unsigned long addr)
+void _writew(u16 b, unsigned long addr)
X {
X __writew(b, addr);
X mb();
X }
X
-void _writel(unsigned int b, unsigned long addr)
+void _writel(u32 b, unsigned long addr)
X {
X __writel(b, addr);
X mb();
X }
X
-void _writeq(unsigned long b, unsigned long addr)
+void _writeq(u64 b, unsigned long addr)
X {
X __writeq(b, addr);
X mb();
diff -u --recursive --new-file v2.4.14/linux/arch/alpha/vmlinux.lds.in linux/arch/alpha/vmlinux.lds.in
--- v2.4.14/linux/arch/alpha/vmlinux.lds.in Tue Jul 3 17:08:18 2001
+++ linux/arch/alpha/vmlinux.lds.in Thu Nov 22 10:54:10 2001
@@ -92,5 +92,5 @@
X .debug_typenames 0 : { *(.debug_typenames) }
X .debug_varnames 0 : { *(.debug_varnames) }
X
- /DISCARD/ : { *(.text.exit) *(.data.exit) }
+ /DISCARD/ : { *(.text.exit) *(.data.exit) *(.exitcall.exit) }
X }
diff -u --recursive --new-file v2.4.14/linux/arch/arm/Makefile linux/arch/arm/Makefile
--- v2.4.14/linux/arch/arm/Makefile Tue Oct 23 22:48:49 2001
+++ linux/arch/arm/Makefile Fri Nov 9 13:58:02 2001
@@ -39,11 +39,12 @@
X tune-$(CONFIG_CPU_ARM710) :=-mtune=arm710
X tune-$(CONFIG_CPU_ARM720T) :=-mtune=arm7tdmi
X tune-$(CONFIG_CPU_ARM920T) :=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi
X tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
X tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
X
X CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float
-AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu
+AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float
X
X ifeq ($(CONFIG_CPU_26),y)
X PROCESSOR = armo
@@ -120,6 +121,10 @@
X MACHINE = integrator
X endif
X
+ifeq ($(CONFIG_ARCH_CAMELOT),y)
+MACHINE = epxa10db
+endif
+
X ifeq ($(CONFIG_ARCH_CLPS711X),y)
X TEXTADDR = 0xc0028000
X MACHINE = clps711x
@@ -150,17 +155,22 @@
X
X HEAD := arch/arm/kernel/head-$(PROCESSOR).o \
X arch/arm/kernel/init_task.o
-SUBDIRS += arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpe \
- arch/arm/fastfpe
+SUBDIRS += arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpe
X CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)
X LIBS := arch/arm/lib/lib.a $(LIBS)
X
X ifeq ($(CONFIG_FPE_NWFPE),y)
X LIBS := arch/arm/nwfpe/math-emu.o $(LIBS)
X endif
+
+# Only include fastfpe if it is part of the kernel tree.
+FASTFPE := arch/arm/fastfpe
+ifeq ($(FASTFPE),$(wildcard $(FASTFPE)))
+SUBDIRS += $(FASTFPE)
X ifeq ($(CONFIG_FPE_FASTFPE),y)
X LIBS := arch/arm/fastfpe/fast-math-emu.o $(LIBS)
X endif
+endif
X
X ifeq ($(findstring y,$(CONFIG_ARCH_CLPS7500) $(CONFIG_ARCH_L7200)),y)
X SUBDIRS += drivers/acorn/char
@@ -213,7 +223,8 @@
X @$(MAKETOOLS) dep
X @$(MAKEBOOT) dep
X
-maketools: checkbin
+# we need version.h
+maketools: checkbin include/linux/version.h
X @$(MAKETOOLS) all
X
X # Ensure this is ld "2.9.4" or later
diff -u --recursive --new-file v2.4.14/linux/arch/arm/config.in linux/arch/arm/config.in
--- v2.4.14/linux/arch/arm/config.in Mon Nov 5 15:55:25 2001
+++ linux/arch/arm/config.in Fri Nov 9 13:58:02 2001
@@ -12,7 +12,7 @@
X define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
X define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
X define_bool CONFIG_GENERIC_BUST_SPINLOCK n
-
+define_bool CONFIG_GENERIC_ISA_DMA n
X
X mainmenu_option next_comment
X comment 'Code maturity level options'
@@ -261,19 +261,42 @@
X fi
X fi
X
+# ARM926T
+if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
+ bool 'Support ARM926T processor' CONFIG_CPU_ARM926T
+else
+ define_bool CONFIG_CPU_ARM926T n
+fi
+if [ "$CONFIG_CPU_ARM926T" = "y" ]; then
+ bool ' ARM926T CPU idle' CONFIG_CPU_ARM926_CPU_IDLE
+ bool ' ARM926T I-Cache on' CONFIG_CPU_ARM926_I_CACHE_ON
+ bool ' ARM926T D-Cache on' CONFIG_CPU_ARM926_D_CACHE_ON
+ if [ "$CONFIG_CPU_ARM926_D_CACHE_ON" = "y" ] ; then
+ bool ' Force write through caches on ARM926T' CONFIG_CPU_ARM926_WRITETHROUGH
+ fi
+ if [ "$CONFIG_CPU_ARM926_I_CACHE_ON" = "y" -o \
+ "$CONFIG_CPU_ARM926_D_CACHE_ON" = "y" ]; then
+ bool ' Round robin I and D cache replacement algorithm' CONFIG_CPU_ARM926_ROUND_ROBIN
+ fi
+fi
+
X # ARM1020
-#if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
-# bool 'Support ARM1020 processor' CONFIG_CPU_ARM1020
-#else
+if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
+ bool 'Support ARM1020 processor' CONFIG_CPU_ARM1020
+else
X define_bool CONFIG_CPU_ARM1020 n
-#fi
-#if [ "$CONFIG_CPU_ARM1020" = "y" ]; then
-# bool ' ARM10 I-Cache on' CONFIG_CPU_ARM10_I_CACHE_ON
-# bool ' ARM10 D-Cache on' CONFIG_CPU_ARM10_D_CACHE_ON
-# if [ "$CONFIG_CPU_ARM10_D_CACHE_ON" = "y" ] ; then
-# bool ' Force write through caches on ARM10' CONFIG_CPU_ARM10_FORCE_WRITE_THROUGH
-# fi
-#fi
+fi
+if [ "$CONFIG_CPU_ARM1020" = "y" ]; then
+ bool ' ARM1020 I-Cache on' CONFIG_CPU_ARM1020_I_CACHE_ON
+ bool ' ARM10 D-Cache on' CONFIG_CPU_ARM1020_D_CACHE_ON
+ if [ "$CONFIG_CPU_ARM1020_D_CACHE_ON" = "y" ] ; then
+ bool ' Force write through caches on ARM1020' CONFIG_CPU_ARM1020_FORCE_WRITE_THROUGH
+ fi
+ if [ "$CONFIG_CPU_ARM1020_I_CACHE_ON" = "y" -o \
+ "$CONFIG_CPU_ARM1020_D_CACHE_ON" = "y" ]; then
+ bool ' Round robin I and D cache replacement algorithm' CONFIG_CPU_ARM1020_ROUND_ROBIN
+ fi
+fi
X
X # SA110
X if [ "$CONFIG_ARCH_EBSA110" = "y" -o "$CONFIG_FOOTBRIDGE" = "y" -o \
diff -u --recursive --new-file v2.4.14/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c
--- v2.4.14/linux/arch/arm/kernel/setup.c Tue Oct 23 22:48:49 2001
+++ linux/arch/arm/kernel/setup.c Fri Nov 16 10:07:47 2001
@@ -1,7 +1,7 @@
X /*
X * linux/arch/arm/kernel/setup.c
X *
- * Copyright (C) 1995-2000 Russell King
+ * Copyright (C) 1995-2001 Russell King
X *
X * This program is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License version 2 as
@@ -16,6 +16,7 @@
X #include <linux/blk.h>
X #include <linux/console.h>
X #include <linux/bootmem.h>
+#include <linux/seq_file.h>
X #include <linux/init.h>
X
X #include <asm/elf.h>
@@ -532,58 +533,53 @@
X NULL
X };
X
-/*
- * get_cpuinfo - Get information on one CPU for use by the procfs.
- *
- * Prints info on the next CPU into buffer. Beware, doesn't check for
- * buffer overflow. Current implementation of procfs assumes that the
- * resulting data is <= 1K.
- *
- * Args:
- * buffer -- you guessed it, the data buffer
- * cpu_np -- Input: next cpu to get (start at 0). Output: Updated.
- *
- * Returns number of bytes written to buffer.
- */
-
-int get_cpuinfo(char *buffer, unsigned *cpu_np)
+static int c_show(struct seq_file *m, void *v)
X {
- char *p = buffer;
- unsigned n;
X int i;
X
- /* No SMP at the moment, so just toggle 0/1 */
- n = *cpu_np;
- *cpu_np = 1;
- if (n != 0) {
- return (0);
- }
-
- p += sprintf(p, "Processor\t: %s %s rev %d (%s)\n",
- proc_info.manufacturer, proc_info.cpu_name,
- (int)processor_id & 15, elf_platform);
-
- p += sprintf(p, "BogoMIPS\t: %lu.%02lu\n",
- loops_per_jiffy / (500000/HZ),
- (loops_per_jiffy / (5000/HZ)) % 100);
+ seq_printf(m, "Processor\t: %s %s rev %d (%s)\n",
+ proc_info.manufacturer, proc_info.cpu_name,
+ (int)processor_id & 15, elf_platform);
+
+ seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
+ loops_per_jiffy / (500000/HZ),
+ (loops_per_jiffy / (5000/HZ)) % 100);
X
X /* dump out the processor features */
- p += sprintf(p, "Features\t: ");
+ seq_puts(m, "Features\t: ");
X
X for (i = 0; hwcap_str[i]; i++)
X if (elf_hwcap & (1 << i))
- p += sprintf(p, "%s ", hwcap_str[i]);
+ seq_printf(m, "%s ", hwcap_str[i]);
+
+ seq_puts(m, "\n\n");
X
- p += sprintf(p, "\n\n");
+ seq_printf(m, "Hardware\t: %s\n", machine_name);
+ seq_printf(m, "Revision\t: %04x\n", system_rev);
+ seq_printf(m, "Serial\t\t: %08x%08x\n",
+ system_serial_high, system_serial_low);
X
- p += sprintf(p, "Hardware\t: %s\n", machine_name);
+ return 0;
+}
X
- p += sprintf(p, "Revision\t: %04x\n",
- system_rev);
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ return *pos < 1 ? (void *)1 : NULL;
+}
X
- p += sprintf(p, "Serial\t\t: %08x%08x\n",
- system_serial_high,
- system_serial_low);
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return NULL;
+}
X
- return p - buffer;
+static void c_stop(struct seq_file *m, void *v)
+{
X }
+
+struct seq_operations cpuinfo_op = {
+ start: c_start,
+ next: c_next,
+ stop: c_stop,
+ show: c_show
+};
diff -u --recursive --new-file v2.4.14/linux/arch/arm/lib/gcclib.h linux/arch/arm/lib/gcclib.h
--- v2.4.14/linux/arch/arm/lib/gcclib.h Tue Oct 23 22:48:49 2001
+++ linux/arch/arm/lib/gcclib.h Fri Nov 9 13:58:02 2001
@@ -11,7 +11,7 @@
X typedef int word_type __attribute__ ((mode (__word__)));
X typedef unsigned int UDItype __attribute__ ((mode (DI)));
X
-#if 0 /* FIXME: endian test here!!! */
+#ifdef __ARMEB__
X struct DIstruct {SItype high, low;};
X #else
X struct DIstruct {SItype low, high;};
diff -u --recursive --new-file v2.4.14/linux/arch/arm/mach-epxa10db/dma.c linux/arch/arm/mach-epxa10db/dma.c
--- v2.4.14/linux/arch/arm/mach-epxa10db/dma.c Mon Nov 5 15:55:25 2001
+++ linux/arch/arm/mach-epxa10db/dma.c Thu Nov 22 10:41:14 2001
@@ -19,7 +19,7 @@
X * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
X */
X #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
X #include <linux/mman.h>
X #include <linux/init.h>
X
diff -u --recursive --new-file v2.4.14/linux/arch/arm/mm/Makefile linux/arch/arm/mm/Makefile
--- v2.4.14/linux/arch/arm/mm/Makefile Mon Aug 27 12:41:38 2001
+++ linux/arch/arm/mm/Makefile Fri Nov 9 13:58:02 2001
@@ -34,6 +34,7 @@
X p-$(CONFIG_CPU_ARM710) += proc-arm6,7.o
X p-$(CONFIG_CPU_ARM720T) += proc-arm720.o
X p-$(CONFIG_CPU_ARM920T) += proc-arm920.o
+p-$(CONFIG_CPU_ARM926T) += proc-arm926.o
X p-$(CONFIG_CPU_ARM1020) += proc-arm1020.o
X p-$(CONFIG_CPU_SA110) += proc-sa110.o
X p-$(CONFIG_CPU_SA1100) += proc-sa110.o
diff -u --recursive --new-file v2.4.14/linux/arch/arm/mm/proc-arm1020.S linux/arch/arm/mm/proc-arm1020.S
--- v2.4.14/linux/arch/arm/mm/proc-arm1020.S Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mm/proc-arm1020.S Fri Nov 9 13:58:02 2001
@@ -0,0 +1,762 @@
+/*
+ * linux/arch/arm/mm/arm1020.S: MMU functions for ARM1020
+ *
+ * Copyright (C) 2000 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions 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 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
+ *
+ *
+ * These are the low level assembler for performing cache and TLB
+ * functions on the arm1020.
+ */
+#include <linux/linkage.h>
+#include <linux/config.h>
+#include <asm/assembler.h>
+#include <asm/constants.h>
+#include <asm/procinfo.h>
+#include <asm/hardware.h>
+
+/*
+ * This is the maximum size of an area which will be invalidated
+ * using the single invalidate entry instructions. Anything larger
+ * than this, and we go for the whole cache.
+ *
+ * This value should be chosen such that we choose the cheapest
+ * alternative.
+ */
+#define MAX_AREA_SIZE 32768
+
+/*
+ * the cache line size of the I and D cache
+ */
+#define DCACHELINESIZE 32
+#define ICACHELINESIZE 32
+
+/*
+ * and the page size
+ */
+#define PAGESIZE 4096
+
+ .text
+
+/*
+ * cpu_arm1020_data_abort()
+ *
+ * obtain information about current aborted instruction
+ *
+ * r0 = address of aborted instruction
+ *
+ * Returns:
+ * r0 = address of abort
+ * r1 != 0 if writing
+ * r3 = FSR
+ */
+ .align 5
+ENTRY(cpu_arm1020_data_abort)
+ ldr r1, [r0] @ read aborted instruction
+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
+ tst r1, r1, lsr #21 @ C = bit 20
+ mrc p15, 0, r3, c5, c0, 0 @ get FSR
+ sbc r1, r1, r1 @ r1 = C - 1
+ and r3, r3, #255
+ mov pc, lr
+
+/*
+ * cpu_arm1020_check_bugs()
+ */
+ENTRY(cpu_arm1020_check_bugs)
+ mrs ip, cpsr
+ bic ip, ip, #F_BIT
+ msr cpsr, ip
+ mov pc, lr
+
+/*
+ * cpu_arm1020_proc_init()
+ */
+ENTRY(cpu_arm1020_proc_init)
+ mov pc, lr
+
+/*
+ * cpu_arm1020_proc_fin()
+ */
+ENTRY(cpu_arm1020_proc_fin)
+ stmfd sp!, {lr}
+ mov ip, #F_BIT | I_BIT | SVC_MODE
+ msr cpsr_c, ip
+ bl cpu_arm1020_cache_clean_invalidate_all
+ mrc p15, 0, r0, c1, c0, 0 @ ctrl register
+ bic r0, r0, #0x1000 @ ...i............
+ bic r0, r0, #0x000e @ ............wca.
+ mcr p15, 0, r0, c1, c0, 0 @ disable caches
+ ldmfd sp!, {pc}
+
+/*
+ * cpu_arm1020_reset(loc)
+ *
+ * Perform a soft reset of the system. Put the CPU into the
+ * same state as it would be if it had been reset, and branch
+ * to what would be the reset vector.
+ *
+ * loc: location to jump to for soft reset
+ */
+ .align 5
+ENTRY(cpu_arm1020_reset)
+ mov ip, #0
+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ mrc p15, 0, ip, c1, c0, 0 @ ctrl register
+ bic ip, ip, #0x000f @ ............wcam
+ bic ip, ip, #0x1100 @ ...i...s........
+ mcr p15, 0, ip, c1, c0, 0 @ ctrl register
+ mov pc, r0
+
+/*
+ * cpu_arm1020_do_idle()
+ */
+ .align 5
+ENTRY(cpu_arm1020_do_idle)
+ mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+ mov r0, r0
+#endif
+ mov pc, lr
+
+/* ================================= CACHE ================================ */
+
+
+/*
+ * cpu_arm1020_cache_clean_invalidate_all()
+ *
+ * clean and invalidate all cache lines
+ *
+ * Note:
+ * 1. we should preserve r0 at all times
+ */
+ .align 5
+ENTRY(cpu_arm1020_cache_clean_invalidate_all)
+ mov r2, #1
+cpu_arm1020_cache_clean_invalidate_all_r2:
+#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+ mcr p15, 0, ip, c7, c10, 4
+
+ mov r1, #0xf @ 16 segments
+1: mov r3, #0x3F @ 64 entries
+2: mov ip, r3, LSL #26 @ shift up entry
+ orr ip, ip, r1, LSL #5 @ shift in/up index
+ mcr p15, 0, ip, c7, c14, 2 @ Clean & Inval DCache entry
+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov ip, ip
+#endif
+ subs r3, r3, #1
+ cmp r3, #0
+ bge 2b @ entries 3F to 0
+ subs r1, r1, #1
+ cmp r1, #0
+ bge 1b @ segments 7 to 0
+#endif
+
+#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON
+ teq r2, #0
+ mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
+#endif
+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov ip, ip
+ mov ip, ip
+#endif
+ mov pc, lr
+
+/*
+ * cpu_arm1020_cache_clean_invalidate_range(start, end, flags)
+ *
+ * clean and invalidate all cache lines associated with this area of memory
+ *
+ * start: Area start address
+ * end: Area end address
+ * flags: nonzero for I cache as well
+ */
+ .align 5
+ENTRY(cpu_arm1020_cache_clean_invalidate_range)
+ bic r0, r0, #DCACHELINESIZE - 1
+ sub r3, r1, r0
+ cmp r3, #MAX_AREA_SIZE
+ bgt cpu_arm1020_cache_clean_invalidate_all_r2
+ mcr p15, 0, r3, c7, c10, 4
+#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+#endif
+ add r0, r0, #DCACHELINESIZE
+ cmp r0, r1
+ blt 1b
+#endif
+
+#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON
+ teq r2, #0
+ movne r0, #0
+ mcrne p15, 0, r0, c7, c5, 0 @ invalidate I cache
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+ mov r0, r0
+#endif
+#endif
+ mov pc, lr
+
+/*
+ * cpu_arm1020_flush_ram_page(page)
+ *
+ * clean and invalidate all cache lines associated with this area of memory
+ *
+ * page: page to clean and invalidate
+ */
+ .align 5
+ENTRY(cpu_arm1020_flush_ram_page)
+ mcr p15, 0, r1, c7, c10, 4
+#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+ mov r1, #PAGESIZE
+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+ mov r0, r0
+#endif
+ subs r1, r1, #2 * DCACHELINESIZE
+ bne 1b
+ mov r0, #0
+
+#endif
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+ mov r0, r0
+#endif
+ mov pc, lr
+
+/* ================================ D-CACHE =============================== */
+
+/*
+ * cpu_arm1020_dcache_invalidate_range(start, end)
+ *
+ * throw away all D-cached data in specified region without an obligation
+ * to write them back. Note however that we must clean the D-cached entries
+ * around the boundaries if the start and/or end address are not cache
+ * aligned.
+ *
+ * start: virtual start address
+ * end: virtual end address
+ */
+ .align 5
+ENTRY(cpu_arm1020_dcache_invalidate_range)
+#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+ /* D cache are on */
+ tst r0, #DCACHELINESIZE - 1
+ bic r0, r0, #DCACHELINESIZE - 1
+ mcrne p15, 0, r0, c7, c10, 4
+ mcrne p15, 0, r0, c7, c10, 1 @ clean D entry at start
+ mcrne p15, 0, r0, c7, c10, 4 @ drain WB
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+ mov r0, r0
+#endif
+ tst r1, #DCACHELINESIZE - 1
+ mcrne p15, 0, r1, c7, c10, 4
+ mcrne p15, 0, r1, c7, c10, 1 @ clean D entry at end
+ mcrne p15, 0, r1, c7, c10, 4 @ drain WB
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r1, r1
+ mov r1, r1
+ mov r1, r1
+#endif
+
+1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+#endif
+ add r0, r0, #DCACHELINESIZE
+ cmp r0, r1
+ blt 1b
+#else
+ /* D cache off, but still drain the write buffer */
+ mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+ mov r0, r0
+#endif
+#endif
+ mov pc, lr
+
+/*
+ * cpu_arm1020_dcache_clean_range(start, end)
+ *
+ * For the specified virtual address range, ensure that all caches contain
+ * clean data, such that peripheral accesses to the physical RAM fetch
+ * correct data.
+ *
+ * start: virtual start address
+ * end: virtual end address
+ */
+ .align 5
+ENTRY(cpu_arm1020_dcache_clean_range)
+ bic r0, r0, #DCACHELINESIZE - 1
+ sub r3, r1, r0
+ cmp r3, #MAX_AREA_SIZE
+ bgt cpu_arm1020_cache_clean_invalidate_all_r2
+ mcr p15, 0, r3, c7, c10, 4
+#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+#endif
+ add r0, r0, #DCACHELINESIZE
+ cmp r0, r1
+ blt 1b
+#endif
+
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+ mov r0, r0
+#endif
+ mov pc, lr
+
+/*
+ * cpu_arm1020_dcache_clean_page(page)
+ *
+ * Cleans a single page of dcache so that if we have any future aliased
+ * mappings, they will be consistent at the time that they are created.
+ *
+ * page: virtual address of page to clean from dcache
+ *
+ * Note:
+ * 1. we don't need to flush the write buffer in this case.
+ * 2. we don't invalidate the entries since when we write the page
+ * out to disk, the entries may get reloaded into the cache.
+ */
+ .align 5
+ENTRY(cpu_arm1020_dcache_clean_page)
+ mov r1, #PAGESIZE
+ mcr p15, 0, r0, c7, c10, 4
+#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns)
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+#endif
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+#endif
+ add r0, r0, #DCACHELINESIZE
+ subs r1, r1, #2 * DCACHELINESIZE
+ bhi 1b
+#endif
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+ mov r0, r0
+#endif
+ mov pc, lr
+
+/*
+ * cpu_arm1020_dcache_clean_entry(addr)
+ *
+ * Clean the specified entry of any caches such that the MMU
+ * translation fetches will obtain correct data.
+ *
+ * addr: cache-unaligned virtual address
+ */
+ .align 5
+ENTRY(cpu_arm1020_dcache_clean_entry)
+ mov r1, #0
+ mcr p15, 0, r1, c7, c10, 4
+#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+ mcr p15, 0, r0, c7, c10, 1 @ clean single D entry
+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
+#endif
+#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON
+ mcr p15, 0, r1, c7, c5, 1 @ invalidate I entry
+#endif
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r1, r1
+ mov r1, r1
+#endif
+ mov pc, lr
+
+/* ================================ I-CACHE =============================== */
+
+/*
+ * cpu_arm1020_icache_invalidate_range(start, end)
+ *
+ * invalidate a range of virtual addresses from the Icache
+ *
+ * start: virtual start address
+ * end: virtual end address
+ */
+ .align 5
+ENTRY(cpu_arm1020_icache_invalidate_range)
+1: mcr p15, 0, r0, c7, c10, 4
+#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+ mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+#endif
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+#endif
+ add r0, r0, #DCACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ENTRY(cpu_arm1020_icache_invalidate_page)
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+ mov r0, r0
+#endif
+ mov pc, lr
+
+/* ================================== TLB ================================= */
+
+/*
+ * cpu_arm1020_tlb_invalidate_all()
+ *
+ * Invalidate all TLB entries
+ */
+ .align 5
+ENTRY(cpu_arm1020_tlb_invalidate_all)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D tlbs
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+ mov r0, r0
+#endif
+ mov pc, lr
+
+/*
+ * cpu_arm1020_tlb_invalidate_range(start, end)
+ *
+ * invalidate TLB entries covering the specified range
+ *
+ * start: range start address
+ * end: range end address
+ */
+ .align 5
+ENTRY(cpu_arm1020_tlb_invalidate_range)
+ mov r3, #0
+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
+1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
+ mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
+ add r0, r0, #PAGESIZE
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+#endif
+ cmp r0, r1
+ blt 1b
+ mov pc, lr
+
+/*
+ * cpu_arm1020_tlb_invalidate_page(page, flags)
+ *
+ * invalidate the TLB entries for the specified page.
+ *
+ * page: page to invalidate
+ * flags: non-zero if we include the I TLB
+ */
+ .align 5
+ENTRY(cpu_arm1020_tlb_invalidate_page)
+ mov r3, #0
+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+ mov r0, r0
+#endif
+ teq r1, #0
+ mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
+ mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+ mov r0, r0
+#endif
+ mov pc, lr
+
+/* =============================== PageTable ============================== */
+
+/*
+ * cpu_arm1020_set_pgd(pgd)
+ *
+ * Set the translation base pointer to be as described by pgd.
+ *
+ * pgd: new page tables
+ */
+ .align 5
+ENTRY(cpu_arm1020_set_pgd)
+#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+ mcr p15, 0, r3, c7, c10, 4
+ mov r1, #0xF @ 16 segments
+1: mov r3, #0x3F @ 64 entries
+2: mov ip, r3, LSL #26 @ shift up entry
+ orr ip, ip, r1, LSL #5 @ shift in/up index
+ mcr p15, 0, ip, c7, c14, 2 @ Clean & Inval DCache entry
+ mov ip, #0
+ mcr p15, 0, ip, c7, c10, 4
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov ip, ip
+#endif
+ subs r3, r3, #1
+ cmp r3, #0
+ bge 2b @ entries 3F to 0
+ subs r1, r1, #1
+ cmp r1, #0
+ bge 1b @ segments 15 to 0
+
+#endif
+ mov r1, #0
+#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON
+ mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache
+#endif
+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
+ mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov ip, ip
+ mov ip, ip
+#endif
+ mov pc, lr
+
+/*
+ * cpu_arm1020_set_pmd(pmdp, pmd)
+ *
+ * Set a level 1 translation table entry, and clean it out of
+ * any caches such that the MMUs can load it correctly.
+ *
+ * pmdp: pointer to PMD entry
+ * pmd: PMD value to store
+ */
+ .align 5
+ENTRY(cpu_arm1020_set_pmd)
+#ifdef CONFIG_CPU_ARM1020_FORCE_WRITE_THROUGH
+ eor r2, r1, #0x0a @ C & Section
+ tst r2, #0x0b
+ biceq r1, r1, #4 @ clear bufferable bit
+#endif
+ str r1, [r0]
+#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+ mcr p15, 0, r0, c7, c10, 4
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns)
+#endif
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+ mov r0, r0
+#endif
+ mov pc, lr
+
+/*
+ * cpu_arm1020_set_pte(ptep, pte)
+ *
+ * Set a PTE and flush it out
+ */
+ .align 5
+ENTRY(cpu_arm1020_set_pte)
+ str r1, [r0], #-1024 @ linux version
+
+ eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
+
+ bic r2, r1, #0xff0
+ bic r2, r2, #3
+ orr r2, r2, #HPTE_TYPE_SMALL
+
+ tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
+ orrne r2, r2, #HPTE_AP_READ
+
+ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
+ orreq r2, r2, #HPTE_AP_WRITE
+
+ tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
+ movne r2, #0
+
+#ifdef CONFIG_CPU_ARM1020_FORCE_WRITE_THROUGH
+ eor r3, r1, #0x0a @ C & small page?
+ tst r3, #0x0b
+ biceq r2, r2, #4
+#endif
+ str r2, [r0] @ hardware version
+ mov r0, r0
+#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+ mcr p15, 0, r0, c7, c10, 4
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+#endif
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ mov r0, r0
+ mov r0, r0
+#endif
+ mov pc, lr
+
+
+cpu_manu_name:
+ .asciz "ARM/VLSI"
+ENTRY(cpu_arm1020_name)
+ .ascii "Arm1020"
+#if defined(CONFIG_CPU_ARM1020_CPU_IDLE)
+ .ascii "s"
+#endif
+#if defined(CONFIG_CPU_ARM1020_I_CACHE_ON)
+ .ascii "i"
+#endif
+#if defined(CONFIG_CPU_ARM1020_D_CACHE_ON)
+ .ascii "d"
+#if defined(CONFIG_CPU_ARM1020_FORCE_WRITE_THROUGH)
+ .ascii "(wt)"
+#else
+ .ascii "(wb)"
+#endif
+#endif
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ .ascii "B"
+#endif
+#ifdef CONFIG_CPU_ARM1020_ROUND_ROBIN
+ .ascii "RR"
+#endif
+ .ascii "\0"
+ .align
+
+ .section ".text.init", #alloc, #execinstr
+
+__arm1020_setup:
+ mov r0, #0
+ mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4
+ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
+ mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4
+ mcr p15, 0, r4, c2, c0 @ load page table pointer
+ mov r0, #0x1f @ Domains 0, 1 = client
+ mcr p15, 0, r0, c3, c0 @ load domain access register
+ mrc p15, 0, r0, c1, c0 @ get control register v4
+/*
+ * Clear out 'unwanted' bits (then put them in if we need them)
+ */
+ bic r0, r0, #0x0e00 @ ....??r.........
+ bic r0, r0, #0x0002 @ ..............a.
+ bic r0, r0, #0x000c @ W,D
+ bic r0, r0, #0x1000 @ I
+/*
+ * Turn on what we want
+ */
+ orr r0, r0, #0x0031 @ ..........DP...M
+ orr r0, r0, #0x0100 @ .......S........
+
+#ifdef CONFIG_CPU_ARM1020_ROUND_ROBIN
+ orr r0, r0, #0x4000 @ .R..............
+#endif
+#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+ orr r0, r0, #0x0800 @ ....Z...........
+#endif
+#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+ orr r0, r0, #0x0004 @ Enable D cache
+#endif
+#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON
+ orr r0, r0, #0x1000 @ I Cache on
+#endif
+ mov pc, lr
+
+ .text
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ * come through these
+ */
+ .type arm1020_processor_functions, #object
+arm1020_processor_functions:
+ .word cpu_arm1020_data_abort
+ .word cpu_arm1020_check_bugs
+ .word cpu_arm1020_proc_init
+ .word cpu_arm1020_proc_fin
+ .word cpu_arm1020_reset
+ .word cpu_arm1020_do_idle
+
+ /* cache */
+ .word cpu_arm1020_cache_clean_invalidate_all
+ .word cpu_arm1020_cache_clean_invalidate_range
+ .word cpu_arm1020_flush_ram_page
+
+ /* dcache */
+ .word cpu_arm1020_dcache_invalidate_range
+ .word cpu_arm1020_dcache_clean_range
+ .word cpu_arm1020_dcache_clean_page
+ .word cpu_arm1020_dcache_clean_entry
+
+ /* icache */
+ .word cpu_arm1020_icache_invalidate_range
+ .word cpu_arm1020_icache_invalidate_page
+
+ /* tlb */
+ .word cpu_arm1020_tlb_invalidate_all
+ .word cpu_arm1020_tlb_invalidate_range
+ .word cpu_arm1020_tlb_invalidate_page
+
+ /* pgtable */
+ .word cpu_arm1020_set_pgd
+ .word cpu_arm1020_set_pmd
+ .word cpu_arm1020_set_pte
+ .size arm1020_processor_functions, . - arm1020_processor_functions
+
+ .type cpu_arm1020_info, #object
+cpu_arm1020_info:
+ .long cpu_manu_name
+ .long cpu_arm1020_name
+ .size cpu_arm1020_info, . - cpu_arm1020_info
+
+ .type cpu_arch_name, #object
+cpu_arch_name:
+ .asciz "armv4"
+ .size cpu_arch_name, . - cpu_arch_name
+
+ .type cpu_elf_name, #object
+cpu_elf_name:
+ .asciz "v4"
+ .size cpu_elf_name, . - cpu_elf_name
+ .align
+
+ .section ".proc.info", #alloc, #execinstr
+
+ .type __arm1020_proc_info,#object
+__arm1020_proc_info:
+ .long 0x4100a200
+ .long 0xff00fff0
+ .long 0x00000c02 @ mmuflags
+ b __arm1020_setup
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
+ .long cpu_arm1020_info
+ .long arm1020_processor_functions
+ .size __arm1020_proc_info, . - __arm1020_proc_info
diff -u --recursive --new-file v2.4.14/linux/arch/arm/mm/proc-arm926.S linux/arch/arm/mm/proc-arm926.S
--- v2.4.14/linux/arch/arm/mm/proc-arm926.S Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mm/proc-arm926.S Fri Nov 9 13:58:02 2001
@@ -0,0 +1,667 @@
+/*
+ * linux/arch/arm/mm/arm926.S: MMU functions for ARM926EJ-S
+ *
+ * Copyright (C) 1999-2001 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions 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 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
+ *
+ *
+ * These are the low level assembler for performing cache and TLB
+ * functions on the arm926.
+ */
+#include <linux/linkage.h>
+#include <linux/config.h>
+#include <asm/assembler.h>
+#include <asm/constants.h>
+#include <asm/procinfo.h>
+#include <asm/hardware.h>
+
+/*
+ * This is the maximum size of an area which will be invalidated
+ * using the single invalidate entry instructions. Anything larger
+ * than this, and we go for the whole cache.
+ *
+ * This value should be chosen such that we choose the cheapest
+ * alternative.
+ */
+#define MAX_AREA_SIZE 16384
+
+/*
+ * the cache line size of the I and D cache
+ */
+#define DCACHELINESIZE 32
+#define ICACHELINESIZE 32
+
+/*
+ * and the page size
+ */
+#define PAGESIZE 4096
+
+ .text
+
+/*
+ * cpu_arm926_data_abort()
+ *
+ * obtain information about current aborted instruction
+ *
+ * Inputs:
+ * r0 = address of abort
+ * r1 = cpsr of abort
+ *
+ * Returns:
+ * r0 = address of abort
+ * r1 != 0 if writing
+ * r3 = FSR
+ */
+ .align 5
+ENTRY(cpu_arm926_data_abort)
+ tst r1, #1<<24 @ Check for Jbit (NE -> found)
+ movne r1, #-1 @ Mark as writing
+ bne 2f
+
+ tst r1, #1<<5 @ Check for Thumb-bit (NE -> found)
+ ldrneh r1, [r0] @ Read aborted Thumb instruction
+ tstne r1, r1, lsr #12 @ C = bit 11
+
+ ldreq r1, [r0] @ Read aborted ARM instruction
+ tsteq r1, r1, lsr #21 @ C = bit 20
+
+ sbc r1, r1, r1 @ r1 = C - 1
+2:
+ mrc p15, 0, r3, c5, c0, 0 @ get FSR
+ and r3, r3, #255
+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
+
+ mov pc, lr
+
+/*
+ * cpu_arm926_check_bugs()
+ */
+ENTRY(cpu_arm926_check_bugs)
+ mrs ip, cpsr
+ bic ip, ip, #F_BIT
+ msr cpsr, ip
+ mov pc, lr
+
+/*
+ * cpu_arm926_proc_init()
+ */
+ENTRY(cpu_arm926_proc_init)
+ mov pc, lr
+
+/*
+ * cpu_arm926_proc_fin()
+ */
+ENTRY(cpu_arm926_proc_fin)
+ stmfd sp!, {lr}
+ mov ip, #F_BIT | I_BIT | SVC_MODE
+ msr cpsr_c, ip
+ bl cpu_arm926_cache_clean_invalidate_all
+ mrc p15, 0, r0, c1, c0, 0 @ ctrl register
+ bic r0, r0, #0x1000 @ ...i............
+ bic r0, r0, #0x000e @ ............wca.
+ mcr p15, 0, r0, c1, c0, 0 @ disable caches
+ ldmfd sp!, {pc}
+
+/*
+ * cpu_arm926_reset(loc)
+ *
+ * Perform a soft reset of the system. Put the CPU into the
+ * same state as it would be if it had been reset, and branch
+ * to what would be the reset vector.
+ *
+ * loc: location to jump to for soft reset
+ */
+ .align 5
+ENTRY(cpu_arm926_reset)
+ mov ip, #0
+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ mrc p15, 0, ip, c1, c0, 0 @ ctrl register
+ bic ip, ip, #0x000f @ ............wcam
+ bic ip, ip, #0x1100 @ ...i...s........
+ mcr p15, 0, ip, c1, c0, 0 @ ctrl register
+ mov pc, r0
+
+/*
+ * cpu_arm926_do_idle()
+ */
+ .align 5
+ENTRY(cpu_arm926_do_idle)
+#if defined(CONFIG_CPU_ARM926_CPU_IDLE)
+ mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
+#endif
+ mov pc, lr
+
+/* ================================= CACHE ================================ */
+
+
+/*
+ * cpu_arm926_cache_clean_invalidate_all()
+ *
+ * clean and invalidate all cache lines
+ *
+ * Note:
+ * 1. we should preserve r0 at all times
+ */
+ .align 5
+ENTRY(cpu_arm926_cache_clean_invalidate_all)
+ mov r2, #1
+cpu_arm926_cache_clean_invalidate_all_r2:
+ mov ip, #0
+#ifdef CONFIG_CPU_ARM926_WRITETHROUGH
+ mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
+#else
+1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate
+ bne 1b
+#endif
+ teq r2, #0
+ mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+/*
+ * cpu_arm926_cache_clean_invalidate_range(start, end, flags)
+ *
+ * clean and invalidate all cache lines associated with this area of memory
+ *
+ * This is a little misleading, it is not intended to clean out
+ * the i-cache but to make sure that any data written to the
+ * range is made consistant. This means that when we execute code
+ * in that region, everything works as we expect.
+ *
+ * This generally means writing back data in the Dcache and
+ * write buffer and flushing the Icache over that region
+ * start: Area start address
+ * end: Area end address
+ * flags: nonzero for I cache as well
+ */
+ .align 5
+ENTRY(cpu_arm926_cache_clean_invalidate_range)
+ bic r0, r0, #DCACHELINESIZE - 1 @ && added by PGM
+ bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM
+ sub r3, r1, r0
+ cmp r3, #MAX_AREA_SIZE
+ bgt cpu_arm926_cache_clean_invalidate_all_r2
+
+1: teq r2, #0
+#ifdef CONFIG_CPU_ARM926_WRITETHROUGH
+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
+ add r0, r0, #DCACHELINESIZE
+#else
+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
+ add r0, r0, #DCACHELINESIZE
+#endif
+
+ cmp r0, r1
+ blt 1b
+
+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
+
+ mov pc, lr
+
+/*
+ * cpu_arm926_flush_ram_page(page)
+ *
+ * clean and invalidate all cache lines associated with this area of memory
+ *
+ * page: page to clean and invalidate
+ */
+ .align 5
+ENTRY(cpu_arm926_flush_ram_page)
+ mov r1, #PAGESIZE
+#ifdef CONFIG_CPU_ARM926_WRITETHROUGH
+1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
+ add r0, r0, #DCACHELINESIZE
+#else
+1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
+ add r0, r0, #DCACHELINESIZE
+#endif
+ subs r1, r1, #2 * DCACHELINESIZE
+ bne 1b
+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+/* ================================ D-CACHE =============================== */
+
+/*
+ * cpu_arm926_dcache_invalidate_range(start, end)
+ *
+ * throw away all D-cached data in specified region without an obligation
+ * to write them back. Note however that we must clean the D-cached entries
+ * around the boundaries if the start and/or end address are not cache
+ * aligned.
+ *
+ * start: virtual start address
+ * end: virtual end address
+ */
+ .align 5
+ENTRY(cpu_arm926_dcache_invalidate_range)
+#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
+ tst r0, #DCACHELINESIZE - 1
+ mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
+ tst r1, #DCACHELINESIZE - 1
+ mcrne p15, 0, r1, c7, c10, 1
+#endif @ clean D entry
+ bic r0, r0, #DCACHELINESIZE - 1
+ bic r1, r1, #DCACHELINESIZE - 1
+1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
+ add r0, r0, #DCACHELINESIZE
+ cmp r0, r1
+ blt 1b
+ mov pc, lr
+
+/*
+ * cpu_arm926_dcache_clean_range(start, end)
+ *
+ * For the specified virtual address range, ensure that all caches contain
+ * clean data, such that peripheral accesses to the physical RAM fetch
+ * correct data.
+ *
+ * start: virtual start address
+ * end: virtual end address
+ */
+ .align 5
+ENTRY(cpu_arm926_dcache_clean_range)
+#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
+ bic r0, r0, #DCACHELINESIZE - 1
+ sub r1, r1, r0
+ cmp r1, #MAX_AREA_SIZE
+ mov r2, #0
+ bgt cpu_arm926_cache_clean_invalidate_all_r2
+
+ bic r1, r1, #DCACHELINESIZE -1
+ add r1, r1, #DCACHELINESIZE
+
+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #DCACHELINESIZE
+ subs r1, r1, #DCACHELINESIZE
+ bpl 1b
+#endif
+ mcr p15, 0, r2, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+/*
+ * cpu_arm926_dcache_clean_page(page)
+ *
+ * Cleans a single page of dcache so that if we have any future aliased
+ * mappings, they will be consistent at the time that they are created.
+ *
+ * page: virtual address of page to clean from dcache
+ *
+ * Note:
+ * 1. we don't need to flush the write buffer in this case.
+ * 2. we don't invalidate the entries since when we write the page
+ * out to disk, the entries may get reloaded into the cache.
+ */
+ .align 5
+ENTRY(cpu_arm926_dcache_clean_page)
+#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
+ mov r1, #PAGESIZE
+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #DCACHELINESIZE
+ subs r1, r1, #2 * DCACHELINESIZE
+ bne 1b
+#endif
+ mov pc, lr
+
+/*
+ * cpu_arm926_dcache_clean_entry(addr)
+ *
+ * Clean the specified entry of any caches such that the MMU
+ * translation fetches will obtain correct data.
+ *
+ * addr: cache-unaligned virtual address
+ */
+ .align 5
+ENTRY(cpu_arm926_dcache_clean_entry)
+#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+#endif
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+/* ================================ I-CACHE =============================== */
+
+/*
+ * cpu_arm926_icache_invalidate_range(start, end)
+ *
+ * invalidate a range of virtual addresses from the Icache
+ *
+ * start: virtual start address
+ * end: virtual end address
+ */
+ .align 5
+ENTRY(cpu_arm926_icache_invalidate_range)
+ bic r0, r0, #DCACHELINESIZE - 1 @ Safety check
+ sub r1, r1, r0
+ cmp r1, #MAX_AREA_SIZE
+ bgt cpu_arm926_cache_clean_invalidate_all_r2
+
+ bic r1, r1, #DCACHELINESIZE - 1
+ add r1, r1, #DCACHELINESIZE
+
+1: mcr p15, 0, r0, c7, c5, 1 @ clean I entries
+ add r0, r0, #DCACHELINESIZE
+ subs r1, r1, #DCACHELINESIZE
+ bne 1b
+
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+ENTRY(cpu_arm926_icache_invalidate_page)
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
+ mov pc, lr
+
+
+/* ================================== TLB ================================= */
+
+/*
+ * cpu_arm926_tlb_invalidate_all()
+ *
+ * Invalidate all TLB entries
+ */
+ .align 5
+ENTRY(cpu_arm926_tlb_invalidate_all)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D TLBs
+ mov pc, lr
+
+/*
+ * cpu_arm926_tlb_invalidate_range(start, end)
+ *
+ * invalidate TLB entries covering the specified range
+ *
+ * start: range start address
+ * end: range end address
+ */
+ .align 5
+ENTRY(cpu_arm926_tlb_invalidate_range)
+ mov r3, #0
+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
+
+ mov r3, #PAGESIZE
+ sub r3, r3, #1
+ bic r0, r0, r3
+ bic r1, r1, r3
+
+1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
+ mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
+ add r0, r0, #PAGESIZE
+ cmp r0, r1
+ blt 1b
+ mov pc, lr
+
+/*
+ * cpu_arm926_tlb_invalidate_page(page, flags)
+ *
+ * invalidate the TLB entries for the specified page.
+ *
+ * page: page to invalidate
+ * flags: non-zero if we include the I TLB
+ */
+ .align 5
+ENTRY(cpu_arm926_tlb_invalidate_page)
+ mov r3, #0
+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
+ teq r1, #0
+ mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
+ mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
+ mov pc, lr
+
+/* =============================== PageTable ============================== */
+
+/*
+ * cpu_arm926_set_pgd(pgd)
+ *
+ * Set the translation base pointer to be as described by pgd.
+ *
+ * pgd: new page tables
+ */
+ .align 5
+ENTRY(cpu_arm926_set_pgd)
+ mov ip, #0
+#ifdef CONFIG_CPU_ARM926_WRITETHROUGH


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

echo 'End of part 021'
echo 'File patch-2.4.15 is continued in part 022'
echo "022" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:40 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part004

#!/bin/sh -x
# this is part 004 of a 115 - part archive


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

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

- a module, say M here and read Documentation/modules.txt.
+ a module, say M here and read <file:Documentation/modules.txt>.
X

X You can pass several parameters to the driver at boot time or at

X module load time. The parameters look like "video=matrox:XXX", where


X the meaning of XXX can be found at the end of the main source file

- (drivers/video/matroxfb.c). Please see the file
- Documentation/fb/matroxfb.txt.
+ (<file:drivers/video/matroxfb.c>). Please see
+ <file:Documentation/fb/matroxfb.txt>.
X
-Matrox Millennium support
+Matrox Millennium I/II support
X CONFIG_FB_MATROX_MILLENIUM
X Say Y here if you have a Matrox Millennium or Matrox Millennium II
X video card. If you select "Advanced lowlevel driver options" below,
@@ -3638,9 +4330,9 @@
X Matrox G100/G200/G400/G450 support
X CONFIG_FB_MATROX_G100
X Say Y here if you have a Matrox G100, G200, G400 or G450 based
- video card. If you select "Advanced lowlevel driver options", you
- should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed
- pixel and 32 bpp packed pixel. You can also use font widths
+ video card. If you select "Advanced lowlevel driver options", you
+ should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed
+ pixel and 32 bpp packed pixel. You can also use font widths
X different from 8.
X
X If you need support for G400 secondary head, you must first say Y to
@@ -3654,14 +4346,14 @@
X DDC (I2C) bus present on all Matroxes, an I2C bus which
X interconnects Matrox optional devices, like MGA-TVO on G200 and
X G400, and the secondary head DDC bus, present on G400 only.
-
- You can say Y or M here if you want to experiment with monitor
+
+ You can say Y or M here if you want to experiment with monitor
X detection code. You must say Y or M here if you want to use either
X second head of G400 or MGA-TVO on G200 or G400.
-
+
X If you compile it as module, it will create a module named
X i2c-matroxfb.o.
-
+
X Matrox G400 second head support
X CONFIG_FB_MATROX_MAVEN
X WARNING !!! This support does not work with G450 !!!
@@ -3672,26 +4364,24 @@
X secondary head output is blanked while you are in X. With XFree
X 3.9.17 preview you can use both heads if you use SVGA over fbdev or
X the fbdev driver on first head and the fbdev driver on second head.
-
+
X If you compile it as module, two modules are created,
X matroxfb_crtc2.o and matroxfb_maven.o. Matroxfb_maven is needed for
X both G200 and G400, matroxfb_crtc2 is needed only by G400. You must
X also load i2c-matroxfb to get it to run.
-
+
X The driver starts in monitor mode and you must use the matroxset
- tool (available at ftp://platan.vc.cvut.cz/pub/linux/matrox-latest)
- to switch it to PAL or NTSC or to swap primary and secondary head
- outputs. Secondary head driver also always start in 640x480
- resolution, you must use fbset to change it.
-
+ tool (available at
+ <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest>) to switch it to
+ PAL or NTSC or to swap primary and secondary head outputs.
+ Secondary head driver also always start in 640x480 resolution, you
+ must use fbset to change it.
+
X Also do not forget that second head supports only 16 and 32 bpp
X packed pixels, so it is a good idea to compile them into the kernel
- too. You can use only some font widths, as the driver uses generic
+ too. You can use only some font widths, as the driver uses generic
X painting procedures (the secondary head does not use acceleration
X engine).
-
- There is no need for enabling 'Matrox multihead support' if you have
- only one Matrox card in the box.
X
X Matrox G450 second head support
X CONFIG_FB_MATROX_G450
@@ -3703,10 +4393,10 @@
X want two independent display devices.
X
X The driver starts in monitor mode and currently does not support
- output in TV modes. You must use the matroxset tool (available
- at ftp://platan.vc.cvut.cz/pub/linux/matrox-latest) to swap primary
- and secondary head outputs. Secondary head driver always start in
- 640x480 resolution and you must use fbset to change it.
+ output in TV modes. You must use the matroxset tool (available
+ at <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest>) to swap
+ primary and secondary head outputs. Secondary head driver always
+ start in 640x480 resolution and you must use fbset to change it.
X
X Also do not forget that second head supports only 16 and 32 bpp
X packed pixels, so it is a good idea to compile them into the kernel
@@ -3714,9 +4404,6 @@
X painting procedures (the secondary head does not use acceleration
X engine).
X
- There is no need for enabling 'Matrox multihead support' if you have
- only one Matrox card in the box.
-
X Matrox unified driver multihead support
X CONFIG_FB_MATROX_MULTIHEAD
X Say Y here if you have more than one (supported) Matrox device in
@@ -3732,6 +4419,24 @@
X for the different Matrox devices. This method is slightly faster but
X uses 40 KB of kernel memory per Matrox card.
X
+ There is no need for enabling 'Matrox multihead support' if you have
+ only one Matrox card in the box.
+
+3Dfx Voodoo Graphics / Voodoo2 frame buffer support
+CONFIG_FB_VOODOO1
+ Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or
+ Voodoo2 (cvg) based graphics card.
+
+ This driver is also available as a module ( = code which can be
+ inserted and removed from the running kernel whenever you want).
+ The module will be called sstfb.o. If you want to compile it as
+ a module, say M here and read Documentation/modules.txt.
+
+ WARNING: Do not use any application that uses the 3D engine
+ (namely glide) while using this driver.
+ Please read the file Documentation/fb/README-sstfb.txt for supported
+ options and other important info support.
+
X MDA text console (dual-headed)
X CONFIG_MDA_CONSOLE
X Say Y here if you have an old MDA or monochrome Hercules graphics
@@ -3739,15 +4444,15 @@
X will then be able to use two monitors with your Linux system. Do not
X say Y here if your MDA card is the primary card in your system; the
X normal VGA driver will handle it.
-
+


X This driver is also available as a module ( = code which can be
X inserted and removed from the running kernel whenever you want).

X The module will be called mdacon.o. If you want to compile it as


- a module, say M here and read Documentation/modules.txt.

-

+ a module, say M here and read <file:Documentation/modules.txt>.
+

X If unsure, say N.
X

-SBUS and UPA frame buffers
+SBUS and UPA framebuffers
X CONFIG_FB_SBUS
X Say Y if you want support for SBUS or UPA based frame buffer device.
X
@@ -3769,11 +4474,59 @@
X CONFIG_FB_CGTHREE
X This is the frame buffer device driver for the CGthree frame buffer.
X
+CGfourteen (SX) support
+CONFIG_FB_CGFOURTEEN
+ This is the frame buffer device driver for the CGfourteen frame
+ buffer on Desktop SPARCsystems with the SX graphics option.
+
+P9100 (Sparcbook 3 only) support
+CONFIG_FB_P9100
+ This is the frame buffer device driver for the P9100 card
+ supported on Sparcbook 3 machines.
+
+Leo (ZX) support
+CONFIG_FB_LEO
+ This is the frame buffer device driver for the SBUS-based Sun ZX
+ (leo) frame buffer cards.
+
+IGA 168x display support
+CONFIG_FB_IGA
+ This is the framebuffer device for the INTERGRAPHICS 1680 and
+ successor frame buffer cards.
+
X TCX (SS4/SS5 only) support
X CONFIG_FB_TCX
X This is the frame buffer device driver for the TCX 24/8bit frame
X buffer.
X
+HD64461 Frame Buffer support
+CONFIG_FB_HIT
+ This is the frame buffer device driver for the Hitachi HD64461 LCD
+ frame buffer card.
+
+SIS 630/540 display support
+CONFIG_FB_SIS
+ This is the frame buffer device driver for the SiS 630 and 640 Super
+ Socket 7 UMA cards. Specs available at <http://www.sis.com.tw/>.


+
+# AC tree only

+SIS 630/540/730 support
+CONFIG_FB_SIS_300
+ This is the frame buffer device driver for the SiS 630 and related
+ Super Socket 7 UMA cards. Specs available at
+ <http://www.sis.com.tw/>.


+
+# AC tree only

+SIS 315H/315 support
+CONFIG_FB_SIS_315
+ This is the frame buffer device driver for the SiS 315 graphics
+ card. Specs available at <http://www.sis.com.tw/>.
+
+IMS Twin Turbo display support
+CONFIG_FB_IMSTT
+ The IMS Twin Turbo is a PCI-based frame buffer card bundled with
+ many Macintosh and compatible computers.
+
X Virtual Frame Buffer support (ONLY FOR TESTING!)
X CONFIG_FB_VIRTUAL
X This is a `virtual' frame buffer device. It operates on a chunk of
@@ -3788,13 +4541,48 @@


X This driver is also available as a module ( = code which can be

X inserted and removed from the running kernel whenever you want). The
X module will be called vfb.o. If you want to compile it as a module,


- say M here and read Documentation/modules.txt.

-

+ say M here and read <file:Documentation/modules.txt>.

+


X If unsure, say N.
X

+Mach64 CT/VT/GT/LT (incl. 3D RAGE) support
+CONFIG_FB_ATY_CT
+ Say Y here to support use of ATI's 64-bit Rage boards (or other
+ boards based on the Mach64 CT, VT, GT, and LT chipsets) as a
+ framebuffer device. The ATI product support page for these boards
+ is at <http://support.ati.com/products/pc/mach64/>.
+
+Sony Vaio Picturebook laptop LCD panel support
+CONFIG_FB_ATY_CT_VAIO_LCD
+ Say Y here if you want to use the full width of the Sony Vaio
+ Picturebook laptops LCD panels (you will get a 128x30 console).
+
+ Note that you need to activate this mode using the 'vga=0x301'
+ option from your boot loader (lilo or loadlin). See the
+ documentation of your boot loader about how to pass options to the
+ kernel.
+
+Mach64 GX support
+CONFIG_FB_ATY_GX
+ Say Y here to support use of the ATI Mach64 Graphics Expression
+ board (or other boards based on the Mach64 GX chipset) as a
+ framebuffer device. The ATI product support page for these boards
+ is at
+ <http://support.ati.com/products/pc/mach64/graphics_xpression.html>.


+
+# AC tree only

+ATI Radeon display support
+CONFIG_FB_RADEON
+ Choose this option if you want to use an ATI Radeon graphics card as
+ a framebuffer device. There are both PCI and AGP versions. You
+ don't need to choose this to run the Radeon in plain VGA mode.
+ There is a product page at
+ <http://www.ati.com/na/pages/products/pc/radeon32/index.html>.
+
+SA-1100 LCD support
X CONFIG_FB_SA1100
X This is a framebuffer device for the SA-1100 LCD Controller.
- See http://www.linux-fbdev.org/ for information on framebuffer
+ See <http://www.linux-fbdev.org/> for information on framebuffer
X devices.
X
X If you plan to use the LCD display with your SA-1100 system, say
@@ -3819,8 +4607,8 @@
X Low level frame buffer console drivers can be modules ( = code which
X can be inserted and removed from the running kernel whenever you
X want). The modules will be called fbcon-*.o. If you want to compile
- (some of) them as modules, read Documentation/modules.txt.
-
+ (some of) them as modules, read <file:Documentation/modules.txt>.
+


X If unsure, say N.
X

X Monochrome support
@@ -3890,10 +4678,10 @@
X This is the low level frame buffer console driver for 1/2/4/8/16/32
X bits per pixel packed pixels on Mac. It supports variable font
X widths for low resolution screens.
-
-HGA monochrome support (EXPERIMENTAL)
+
+HGA monochrome support
X CONFIG_FBCON_HGA
- This is the low level frame buffer console driver for Hercules mono
+ This is the low level frame buffer console driver for Hercules mono
X graphics cards.
X
X VGA characters/attributes support
@@ -3909,21 +4697,21 @@
X drive, PLIP link (Parallel Line Internet Protocol is mainly used to
X create a mini network by connecting the parallel ports of two local
X machines) etc., then you need to say Y here; please read
- Documentation/parport.txt and drivers/parport/BUGS-parport.
+ <file:Documentation/parport.txt> and drivers/parport/BUGS-parport.
X
X For extensive information about drivers for many devices attaching
- to the parallel port see http://www.torque.net/linux-pp.html on the
- WWW.
+ to the parallel port see <http://www.torque.net/linux-pp.html> on
+ the WWW.
X
X It is possible to share a single parallel port among several devices
X and it is safe to compile all the corresponding drivers into the
- kernel. If you want to compile parallel port support as a module ( =
- code which can be inserted in and removed from the running kernel
- whenever you want), say M here and read Documentation/modules.txt.
- The module will be called parport.o. If you have more than one
- parallel port and want to specify which port and IRQ to be used by
- this driver at module load time, take a look at
- Documentation/parport.txt.
+ kernel. If you want to compile parallel port support as a module
+ ( = code which can be inserted in and removed from the running
+ kernel whenever you want), say M here and read


+ <file:Documentation/modules.txt>. The module will be called

+ parport.o. If you have more than one parallel port and want to
+ specify which port and IRQ to be used by this driver at module load
+ time, take a look at <file:Documentation/parport.txt>.


X
X If unsure, say Y.
X

@@ -3931,20 +4719,21 @@
X CONFIG_PARPORT_PC
X You should say Y here if you have a PC-style parallel port. All IBM
X PC compatible computers and some Alphas have PC-style parallel
- ports.
+ ports.
X
- This code is also available as a module. If you want to compile it
+ This code is also available as a module. If you want to compile it


X as a module ( = code which can be inserted in and removed from the
X running kernel whenever you want), say M here and read

- Documentation/modules.txt. The module will be called parport_pc.o.
-

+ <file:Documentation/modules.txt>. The module will be called

+ parport_pc.o.
+


X If unsure, say Y.
X

X Parallel+serial PCI card support
X CONFIG_PARPORT_SERIAL
- This adds support for multi-IO PCI cards that have parallel and serial
- ports. You should say Y or M here. If you say M, the module will be
- called parport_serial.o.
+ This adds support for multi-IO PCI cards that have parallel and
+ serial ports. You should say Y or M here. If you say M, the module
+ will be called parport_serial.o.
X
X Use FIFO/DMA if available
X CONFIG_PARPORT_PC_FIFO
@@ -3952,12 +4741,12 @@
X printing. Say Y here if you want to take advantage of that.
X
X As well as actually having a FIFO, or DMA capability, the kernel
- will need to know which IRQ the parallel port has. By default,
+ will need to know which IRQ the parallel port has. By default,
X parallel port interrupts will not be used, and so neither will the
- FIFO. See Documentation/parport.txt to find out how to specify
- which IRQ/DMA to use.
+ FIFO. See <file:Documentation/parport.txt> to find out how to
+ specify which IRQ/DMA to use.
X
-SuperIO chipset support (EXPERIMENTAL)
+SuperIO chipset support
X CONFIG_PARPORT_PC_SUPERIO
X Saying Y here enables some probes for Super-IO chipsets in order to
X find out things like base addresses, IRQ lines and DMA channels. It
@@ -3974,12 +4763,6 @@
X other non-standard types of parallel ports. This causes a
X performance loss, so most people say N.
X
-Sun Ultra/AX-style hardware
-CONFIG_PARPORT_AX
- Say Y here if you need support for the parallel port hardware on Sun
- Ultra/AX machines. This code is also available as a module (say M),
- called parport_ax.o. If in doubt, saying N is the safe plan.
-
X Amiga built-in parallel port support
X CONFIG_PARPORT_AMIGA
X Say Y here if you need support for the parallel port hardware on
@@ -3992,51 +4775,51 @@
X Atari machines. This code is also available as a module (say M),
X called parport_atari.o. If in doubt, saying N is the safe plan.
X
-Multiface 3 parallel port card support
+Multiface III parallel port support
X CONFIG_PARPORT_MFC3
X Say Y here if you need parallel port support for the MFC3 card.
X This code is also available as a module (say M), called
X parport_mfc3.o. If in doubt, saying N is the safe plan.
X
-Support IEEE1284 status readback
+Support IEEE 1284 status readback
X CONFIG_PRINTER_READBACK
X If you have a device on your parallel port that support this
X protocol, this option will allow the device to report its status. It
X is safe to say Y.
X
-IEEE1284 transfer modes
+IEEE 1284 transfer modes
X CONFIG_PARPORT_1284
X If you have a printer that supports status readback or device ID, or
X want to use a device that uses enhanced parallel port transfer modes
X such as EPP and ECP, say Y here to enable advanced IEEE 1284
X transfer modes. Also say Y if you want device ID information to
X appear in /proc/sys/dev/parport/*/autoprobe*. It is safe to say N.
-
+
X Enable loadable module support
X CONFIG_MODULES
X Kernel modules are small pieces of compiled code which can be
X inserted in or removed from the running kernel, using the programs
X insmod and rmmod. This is described in the file
- Documentation/modules.txt, including the fact that you have to say
- "make modules" in order to compile the modules that you chose during
- kernel configuration. Modules can be device drivers, file systems,
- binary executable formats, and so on. If you think that you may want
- to make use of modules with this kernel in the future, then say Y
- here. If unsure, say Y.
+ <file:Documentation/modules.txt>, including the fact that you have
+ to say "make modules" in order to compile the modules that you chose
+ during kernel configuration. Modules can be device drivers, file
+ systems, binary executable formats, and so on. If you think that you
+ may want to make use of modules with this kernel in the future, then
+ say Y here. If unsure, say Y.
X
X Set version information on all symbols for modules
X CONFIG_MODVERSIONS
X Usually, modules have to be recompiled whenever you switch to a new
- kernel. Saying Y here makes it possible, and safe, to use the
+ kernel. Saying Y here makes it possible, and safe, to use the
X same modules even after compiling a new kernel; this requires the
X program modprobe. All the software needed for module support is in
- the modutils package (check the file Documentation/Changes for
- location and latest version). NOTE: if you say Y here but don't
+ the modutils package (check the file <file:Documentation/Changes>
+ for location and latest version). NOTE: if you say Y here but don't
X have the program genksyms (which is also contained in the above
X mentioned modutils package), then the building of your kernel will
- fail. If you are going to use modules that are generated from
- non-kernel sources, you would benefit from this option. Otherwise
- it's not that important. So, N ought to be a safe bet.
+ fail. If you are going to use modules that are generated from
+ non-kernel sources, you would benefit from this option. Otherwise
+ it's not that important. So, N ought to be a safe bet.
X
X Kernel module loader support
X CONFIG_KMOD
@@ -4048,11 +4831,11 @@
X kernel needs a module, it runs modprobe with the appropriate
X arguments, thereby loading the module if it is available. (This is a
X replacement for kerneld.) Say Y here and read about configuring it
- in Documentation/kmod.txt.
+ in <file:Documentation/kmod.txt>.
X
-ARP daemon support (EXPERIMENTAL)
+ARP daemon support
X CONFIG_ARPD
- Normally, the kernel maintains an internal cache which maps IP
+ Normally, the kernel maintains an internal cache which maps IP
X addresses to hardware addresses on the local network, so that
X Ethernet/Token Ring/ etc. frames are sent to the proper address on
X the physical networking layer. For small networks having a few
@@ -4060,7 +4843,7 @@
X resolution (ARP) cache inside the kernel works well. However,
X maintaining an internal ARP cache does not work well for very large
X switched networks, and will use a lot of kernel memory if TCP/IP
- connections are made to many machines on the network.
+ connections are made to many machines on the network.
X
X If you say Y here, the kernel's internal ARP cache will never grow
X to more than 256 entries (the oldest entries are expired in a LIFO
@@ -4084,35 +4867,35 @@
X
X For an excellent introduction to Linux networking, please read the
X NET-3-HOWTO, available from

X This option is also necessary if you want to use the full power of
X term (term is a program which gives you almost full Internet
X connectivity if you have a regular dial up shell account on some
X Internet connected Unix computer; for more information, read
- http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html ).
-
+ <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>).
+
X If you say Y here and also to "/proc file system support" and
X "Sysctl support" below, you can change various aspects of the
X behavior of the TCP/IP code by writing to the (virtual) files in
X /proc/sys/net/ipv4/*; the options are explained in the file
- Documentation/networking/ip-sysctl.txt.
+ <file:Documentation/networking/ip-sysctl.txt>.
X
X Short answer: say Y.
X
-IP: multicasting
+IP multicasting
X CONFIG_IP_MULTICAST
X This is code for addressing several networked computers at once,
X enlarging your kernel by about 2 KB. You need multicasting if you
X intend to participate in the MBONE, a high bandwidth network on top
X of the Internet which carries audio and video broadcasts. More
X information about the MBONE is on the WWW at
- http://www-itg.lbl.gov/mbone/ . Information about the multicast
+ <http://www-itg.lbl.gov/mbone/>. Information about the multicast
X capabilities of the various network cards is contained in
- Documentation/networking/multicast.txt. For most people, it's safe
- to say N.
+ <file:Documentation/networking/multicast.txt>. For most people, it's
+ safe to say N.
X
-IP: advanced router
+Advanced router
X CONFIG_IP_ADVANCED_ROUTER
X If you intend to run your Linux box mostly as a router, i.e. as a
X computer that forwards and redistributes network packets, say Y; you
@@ -4120,7 +4903,7 @@
X control about the routing process.
X
X The answer to this question won't directly affect the kernel:
- answering N will just cause this configure script to skip all the
+ answering N will just cause the configurator to skip all the
X questions about advanced routing.
X
X Note that your box can only act as a router if you enable IP
@@ -4130,7 +4913,7 @@
X
X echo "1" > /proc/sys/net/ipv4/ip_forward
X
- at boot time after the /proc file system has been mounted.
+ at boot time after the /proc file system has been mounted.
X
X If you turn on IP forwarding, you will also get the rp_filter, which
X automatically rejects incoming packets if the routing table entry
@@ -4148,26 +4931,27 @@
X
X If unsure, say N here.
X
-IP: policy routing
+Policy routing
X CONFIG_IP_MULTIPLE_TABLES
X Normally, a router decides what to do with a received packet based
X solely on the packet's final destination address. If you say Y here,
X the Linux router will also be able to take the packet's source
- address into account. Furthermore, if you also say Y to "IP: use TOS
+ address into account. Furthermore, if you also say Y to "Use TOS
X value as routing key" below, the TOS (Type-Of-Service) field of the
X packet can be used for routing decisions as well. In addition, if
- you say Y here and to "IP: fast network address translation" below,
+ you say Y here and to "Fast network address translation" below,
X the router will also be able to modify source and destination
X addresses of forwarded packets.
X
X If you are interested in this, please see the preliminary
- documentation at http://www.compendium.com.ar/policy-routing.txt and
- ftp://post.tepkom.ru/pub/vol2/Linux/docs/advanced-routing.tex . You
- will need supporting software from ftp://ftp.inr.ac.ru/ip-routing/
-
+ documentation at <http://www.compendium.com.ar/policy-routing.txt>
+ and <ftp://post.tepkom.ru/pub/vol2/Linux/docs/advanced-routing.tex>.
+ You will need supporting software from
+ <ftp://ftp.inr.ac.ru/ip-routing/>.
+


X If unsure, say N.

-
-IP: equal cost multipath
+
+Equal cost multipath
X CONFIG_IP_ROUTE_MULTIPATH
X Normally, the routing tables specify a single action to be taken in
X a deterministic manner for a given packet. If you say Y here
@@ -4177,20 +4961,20 @@
X equal "cost" and chooses one of them in a non-deterministic fashion
X if a matching packet arrives.
X
-IP: use TOS value as routing key
+Use TOS value as routing key
X CONFIG_IP_ROUTE_TOS
X The header of every IP packet carries a TOS (Type Of Service) value
- with which the packet requests a certain treatment, e.g. low latency
- (for interactive traffic), high throughput, or high reliability. If
- you say Y here, you will be able to specify different routes for
- packets with different TOS values.
+ with which the packet requests a certain treatment, e.g. low
+ latency (for interactive traffic), high throughput, or high
+ reliability. If you say Y here, you will be able to specify
+ different routes for packets with different TOS values.
X
-IP: use netfilter MARK value as routing key
+Use netfilter MARK value as routing key
X CONFIG_IP_ROUTE_FWMARK
X If you say Y here, you will be able to specify different routes for
X packets with different mark values (see iptables(8), MARK target).
X
-IP: verbose route monitoring
+Verbose route monitoring
X CONFIG_IP_ROUTE_VERBOSE
X If you say Y here, which is recommended, then the kernel will print
X verbose messages regarding the routing, for example warnings about
@@ -4199,20 +4983,20 @@
X handled by the klogd daemon which is responsible for kernel messages
X ("man klogd").
X
-IP: large routing tables
+Large routing tables
X CONFIG_IP_ROUTE_LARGE_TABLES
X If you have routing zones that grow to more than about 64 entries,
X you may want to say Y here to speed up the routing process.
X
-IP: fast network address translation
+Fast network address translation
X CONFIG_IP_ROUTE_NAT
X If you say Y here, your router will be able to modify source and
X destination addresses of packets that pass through it, in a manner
- you specify. General information about Network Address Translation
+ you specify. General information about Network Address Translation
X can be gotten from the document
- http://www.csn.tu-chemnitz.de/~mha/linux-ip-nat/diplom/nat.html
+ <http://www.csn.tu-chemnitz.de/~mha/linux-ip-nat/diplom/nat.html>.
X
-IP: kernel level autoconfiguration
+Kernel level IP autoconfiguration
X CONFIG_IP_PNP
X This enables automatic configuration of IP addresses of devices and
X of the routing table during kernel boot, based on either information
@@ -4233,7 +5017,22 @@
X does BOOTP itself, providing all necessary information on the kernel
X command line, you can say N here. If unsure, say Y. Note that if you
X want to use BOOTP, a BOOTP server must be operating on your network.
- Read Documentation/nfsroot.txt for details.
+ Read <file:Documentation/nfsroot.txt> for details.
+
+DHCP support
+CONFIG_IP_PNP_DHCP
+ If you want your Linux box to mount its whole root file system (the
+ one containing the directory /) from some other computer over the
+ net via NFS and you want the IP address of your computer to be
+ discovered automatically at boot time using the DHCP protocol (a
+ special protocol designed for doing this job), say Y here. In case
+ the boot ROM of your network card was designed for booting Linux and
+ does DHCP itself, providing all necessary information on the kernel
+ command line, you can say N here.
+
+ If unsure, say Y. Note that if you want to use DHCP, a DHCP server
+ must be operating on your network. Read
+ <file:Documentation/nfsroot.txt> for details.
X
X RARP support
X CONFIG_IP_PNP_RARP
@@ -4243,10 +5042,10 @@
X discovered automatically at boot time using the RARP protocol (an
X older protocol which is being obsoleted by BOOTP and DHCP), say Y
X here. Note that if you want to use RARP, a RARP server must be
- operating on your network. Read Documentation/nfsroot.txt for
+ operating on your network. Read <file:Documentation/nfsroot.txt> for
X details.
X
-IP: tunneling
+IP tunneling
X CONFIG_NET_IPIP
X Tunneling means encapsulating data of one protocol type within
X another protocol and sending it over a channel that understands the
@@ -4256,13 +5055,13 @@
X appear on a different network than it physically is, or to use
X mobile-IP facilities (allowing laptops to seamlessly move between
X networks without changing their IP addresses; check out
- http://anchor.cs.binghamton.edu/~mobileip/LJ/index.html ).
+ <http://anchor.cs.binghamton.edu/~mobileip/LJ/index.html>).
X
X Saying Y to this option will produce two modules ( = code which can
X be inserted in and removed from the running kernel whenever you
X want). Most people won't need this and can say N.
X
-IP: GRE tunnels over IP
+GRE tunnels over IP
X CONFIG_NET_IPGRE
X Tunneling means encapsulating data of one protocol type within
X another protocol and sending it over a channel that understands the
@@ -4270,18 +5069,18 @@
X GRE (Generic Routing Encapsulation) and at this time allows
X encapsulating of IPv4 or IPv6 over existing IPv4 infrastructure.
X This driver is useful if the other endpoint is a Cisco router: Cisco
- likes GRE much better than the other Linux tunneling driver ("IP:
+ likes GRE much better than the other Linux tunneling driver ("IP
X tunneling" above). In addition, GRE allows multicast redistribution
X through the tunnel.
X
-IP: broadcast GRE over IP
+Broadcast GRE over IP
X CONFIG_NET_IPGRE_BROADCAST
X One application of GRE/IP is to construct a broadcast WAN (Wide Area
X Network), which looks like a normal Ethernet LAN (Local Area
X Network), but can be distributed all over the Internet. If you want
- to do that, say Y here and to "IP: multicast routing" below.
+ to do that, say Y here and to "IP multicast routing" below.
X
-IP: multicast routing
+IP multicast routing
X CONFIG_IP_MROUTE
X This is used if you want your machine to act as a router for IP
X packets that have several destination addresses. It is needed on the
@@ -4289,118 +5088,69 @@
X audio and video broadcasts. In order to do that, you would most
X likely run the program mrouted. Information about the multicast
X capabilities of the various network cards is contained in
- Documentation/networking/multicast.txt. If you haven't heard about
- it, you don't need it.
+ <file:Documentation/networking/multicast.txt>. If you haven't heard
+ about it, you don't need it.
X
-IP: PIM-SM version 1 support
+PIM-SM version 1 support
X CONFIG_IP_PIMSM_V1
X Kernel side support for Sparse Mode PIM (Protocol Independent
X Multicast) version 1. This multicast routing protocol is used widely
X because Cisco supports it. You need special software to use it
- (pimd-v1). Please see http://netweb.usc.edu/pim/ for more
+ (pimd-v1). Please see <http://netweb.usc.edu/pim/> for more
X information about PIM.
X
X Say Y if you want to use PIM-SM v1. Note that you can say N here if
X you just want to use Dense Mode PIM.
X
-IP: PIM-SM version 2 support
+PIM-SM version 2 support
X CONFIG_IP_PIMSM_V2
X Kernel side support for Sparse Mode PIM version 2. In order to use
X this, you need an experimental routing daemon supporting it (pimd or
X gated-5). This routing protocol is not used widely, so say N unless
X you want to play with it.
X
-PC/TCP compatibility mode
-CONFIG_INET_PCTCP
- If you have been having difficulties telnetting to your Linux
- machine from a DOS system that uses (broken) PC/TCP networking
- software (all versions up to OnNet 2.0) over your local Ethernet try
- saying Y here. Everyone else says N.
-
- People having problems with NCSA telnet should see the file
- Documentation/networking/ncsa-telnet.
-
-Path MTU Discovery (normally enabled)
-CONFIG_PATH_MTU_DISCOVERY
- MTU (maximal transfer unit) is the size of the chunks we send out
- over the net. "Path MTU Discovery" means that, instead of always
- sending very small chunks, we start out sending big ones and if we
- then discover that some host along the way likes its chunks smaller,
- we adjust to a smaller size. This is good, so most people say Y
- here.
-
- However, some DOS software (versions of DOS NCSA telnet and Trumpet
- Winsock in PPP mode) is broken and won't be able to connect to your
- Linux machine correctly in all cases (especially through a terminal
- server) unless you say N here. See
- Documentation/networking/ncsa-telnet for the location of fixed NCSA
- telnet clients. If in doubt, say Y.
-
-Disable NAGLE algorithm (normally enabled)
-CONFIG_TCP_NAGLE_OFF
- The NAGLE algorithm works by requiring an acknowledgment before
- sending small IP frames (packets). This keeps tiny telnet and
- rlogin packets from congesting Wide Area Networks. Most people
- strongly recommend to say N here, thereby leaving NAGLE
- enabled. Those programs that would benefit from disabling this
- facility can do it on a per connection basis themselves.
-
-IP: Allow large windows (not recommended if <16 MB of memory)
-CONFIG_SKB_LARGE
- On high speed, long distance networks the performance limit on
- networking becomes the amount of data the sending machine can buffer
- until the other end confirms its reception. (At 45 Mbit/second there
- are a lot of bits between New York and London ...). If you say Y
- here, bigger buffers can be used which allows larger amounts of data
- to be "in flight" at any given time. It also means a user process
- can require a lot more memory for network buffers and thus this
- option is best used only on machines with 16 MB of memory or higher.
- Unless you are using long links with end to end speeds of over 2
- Mbit a second or satellite links this option will make no difference
- to performance.
-
X Unix domain sockets
X CONFIG_UNIX
X If you say Y here, you will include support for Unix domain sockets;
X sockets are the standard Unix mechanism for establishing and
- accessing network connections. Many commonly used programs such as
+ accessing network connections. Many commonly used programs such as
X the X Window system and syslog use these sockets even if your
- machine is not connected to any network. Unless you are working on
+ machine is not connected to any network. Unless you are working on
X an embedded system or something similar, you therefore definitely


X want to say Y here.
X

X However, the socket support is also available as a module ( = code


X 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. The module will be called
- unix.o. If you try building this as a module and you have said Y to
- "Kernel module loader support" above, be sure to add 'alias net-pf-1
- unix' to your /etc/modules.conf file. Note that several important
- services won't work correctly if you say M here and then neglect to
- load the module.
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>. The module will be
+ called unix.o. If you try building this as a module and you have
+ said Y to "Kernel module loader support" above, be sure to add
+ 'alias net-pf-1 unix' to your /etc/modules.conf file. Note that
+ several important services won't work correctly if you say M here
+ and then neglect to load the module.
X
X Say Y unless you know what you are doing.
X
-The IPv6 protocol (EXPERIMENTAL)
+The IPv6 protocol
X CONFIG_IPV6
X This is experimental support for the next version of the Internet
X Protocol: IP version 6 (also called IPng "IP next generation").
X Features of this new protocol include: expanded address space,
X authentication and privacy, and seamless interoperability with the
X current version of IP (IP version 4). For general information about
- IPv6, see http://playground.sun.com/pub/ipng/html/ipng-main.html ;
+ IPv6, see <http://playground.sun.com/pub/ipng/html/ipng-main.html>;
X for specific information about IPv6 under Linux read the HOWTO at
- http://www.bieringer.de/linux/IPv6/ and the file net/ipv6/README in
- the kernel source.
+ <http://www.bieringer.de/linux/IPv6/> and the file net/ipv6/README
+ in the kernel source.
X
X If you want to use IPv6, please upgrade to the newest net-tools as
- given in Documentation/Changes. You will still be able to do regular
- IPv4 networking as well.
+ given in <file:Documentation/Changes>. You will still be able to do
+ regular IPv4 networking as well.
X
X This protocol support is also available as a module ( = code which
X can be inserted in and removed from the running kernel whenever you
X want). The module will be called ipv6.o. If you want to compile it
- as a module, say M here and read Documentation/modules.txt.


+ as a module, say M here and read <file:Documentation/modules.txt>.

X
X It is safe to say N here for now.
X
@@ -4410,8 +5160,8 @@
X through the old netlink interface. However, a better option is to
X say Y to "Kernel/User network link driver" and to "Routing
X messages" instead.
-
-Kernel httpd acceleration (EXPERIMENTAL)
+
+Kernel httpd acceleration
X CONFIG_KHTTPD
X The kernel httpd acceleration daemon (kHTTPd) is a (limited) web
X server built into the kernel. It is limited since it can only serve
@@ -4430,17 +5180,17 @@
X The kHTTPd is experimental. Be careful when using it on a production
X machine. Also note that kHTTPd doesn't support virtual servers yet.
X
-IPX networking
+The IPX protocol
X CONFIG_IPX
X This is support for the Novell networking protocol, IPX, commonly
- used for local networks of Windows machines. You need it if you want
- to access Novell NetWare file or print servers using the Linux
+ used for local networks of Windows machines. You need it if you
+ want to access Novell NetWare file or print servers using the Linux
X Novell client ncpfs (available from
- ftp://metalab.unc.edu/pub/Linux/system/filesystems/ ) or from within
- the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto ). In order to do the
- former, you'll also have to say Y to "NCP file system support",
- below.
+ <ftp://metalab.unc.edu/pub/Linux/system/filesystems/>) or from
+ within the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO,
+ available from <http://www.linuxdoc.org/docs.html#howto>). In order
+ to do the former, you'll also have to say Y to "NCP file system
+ support", below.
X
X IPX is similar in scope to IP, while SPX, which runs on top of IPX,
X is similar to TCP. There is also experimental support for SPX in
@@ -4448,22 +5198,22 @@
X
X To turn your Linux box into a fully featured NetWare file server and
X IPX router, say Y here and fetch either lwared from
- ftp://metalab.unc.edu/pub/Linux/system/network/daemons/ or mars_nwe
- from ftp://ftp.gwdg.de/pub/linux/misc/ncpfs . For more information,
- read the IPX-HOWTO available from
- http://www.linuxdoc.org/docs.html#howto .
+ <ftp://metalab.unc.edu/pub/Linux/system/network/daemons/> or
+ mars_nwe from <ftp://ftp.gwdg.de/pub/linux/misc/ncpfs>. For more
+ information, read the IPX-HOWTO available from

X General information about how to connect Linux, Windows machines and
- Macs is on the WWW at http://www.eats.com/linux_mac_win.html .
+ Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
X
X The IPX driver would enlarge your kernel by about 16 KB. This driver
X is also available as a module ( = code which can be inserted in and
- removed from the running kernel whenever you want). The module will
- be called ipx.o. If you want to compile it as a module, say M here
- and read Documentation/modules.txt. Unless you want to integrate
- your Linux box with a local Novell network, say N.
+ removed from the running kernel whenever you want). The module will
+ be called ipx.o. If you want to compile it as a module, say M here
+ and read <file:Documentation/modules.txt>. Unless you want to
+ integrate your Linux box with a local Novell network, say N.
X
-IPX: Full internal IPX network
+Full internal IPX network
X CONFIG_IPX_INTERN
X Every IPX network has an address that identifies it. Sometimes it is
X useful to give an IPX "network" address to your Linux box as well
@@ -4472,7 +5222,7 @@
X same address). The way this is done is to create a virtual internal
X "network" inside your box and to assign an IPX address to this
X network. Say Y here if you want to do this; read the IPX-HOWTO at
- http://www.linuxdoc.org/docs.html#howto for details.
+ <http://www.linuxdoc.org/docs.html#howto> for details.
X
X The full internal IPX network enables you to allocate sockets on
X different virtual nodes of the internal network. This is done by
@@ -4485,12 +5235,17 @@
X 'special' sockets to sockets listening on the primary network is
X disabled. This might break existing applications, especially RIP/SAP
X daemons. A RIP/SAP daemon that works well with the full internal net
- can be found on ftp://ftp.gwdg.de/pub/linux/misc/ncpfs .
+ can be found on <ftp://ftp.gwdg.de/pub/linux/misc/ncpfs>.
X
X If you don't know what you are doing, say N.
X
-IPX: SPX networking (EXPERIMENTAL)
+#(We're told this will come back someday)
+
+SPX networking
X CONFIG_SPX
+ * Orphaned entry retained 20 April 2001 by Petr Vandrovec *
+ * If you read this note from the configurator, please contact *
+ * the Configure.help maintainers. *
X The Sequenced Packet eXchange protocol is a transport layer protocol
X built on top of IPX. It is used in Novell NetWare systems for
X client-server applications and is similar to TCP (which runs on top
@@ -4502,26 +5257,26 @@
X space programs lwared or mars_nwe for the server side).
X
X Say Y here if you have use for SPX; read the IPX-HOWTO at
- http://www.linuxdoc.org/docs.html#howto for details.
+ <http://www.linuxdoc.org/docs.html#howto> for details.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called af_spx.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X

-DECnet networking (EXPERIMENTAL)
+DECnet networking
X CONFIG_DECNET
X The DECnet networking protocol was used in many products made by
- Digital (now Compaq). It provides reliable stream and sequenced
+ Digital (now Compaq). It provides reliable stream and sequenced
X packet communications over which run a variety of services similar
X to those which run over TCP/IP.
X
X To find some tools to use with the kernel layer support, please
- look at Patrick Caulfield's web site:
- http://linux.dreamtime.org/decnet/
+ look at Patrick Caulfield's web site:
+ <http://linux.dreamtime.org/decnet/>.
X
- More detailed documentation is available in the
- Documentation/networking/decnet.txt file.
+ More detailed documentation is available in
+ <file:Documentation/networking/decnet.txt>.
X
X Be sure to say Y to "/proc file system support" and "Sysctl support"
X below when using DECnet, since you will need sysctl support to aid
@@ -4533,27 +5288,27 @@
X
X DECnet SIOCFIGCONF support
X CONFIG_DECNET_SIOCGIFCONF
- This option should only be turned on if you are really sure that
- you know what you are doing. It can break other applications which
- use this system call and the proper way to get the information
- provided by this call is to use rtnetlink.
-
- If unsure, say N.
+ This option should only be turned on if you are really sure that
+ you know what you are doing. It can break other applications which
+ use this system call and the proper way to get the information
+ provided by this call is to use rtnetlink.


+
+ If unsure, say N.

X
-DECnet Router Support (EXPERIMENTAL)
+DECnet router support
X CONFIG_DECNET_ROUTER
- Add support for turning your DECnet Endnode into a level 1 or 2
- router. This is an unfinished option for developers only. If you do
- say Y here, then make sure that you also say Y to "Kernel/User
- network link driver", "Routing messages" and "Network packet
- filtering". The first two are required to allow configuration via
- rtnetlink (currently you need Alexey Kuznetsov's iproute2 package
- from ftp://ftp.inr.ac.ru). The "Network packet filtering" option
- will be required for the forthcoming routing daemon to work.
+ Add support for turning your DECnet Endnode into a level 1 or 2
+ router. This is an unfinished option for developers only. If you
+ do say Y here, then make sure that you also say Y to "Kernel/User
+ network link driver", "Routing messages" and "Network packet
+ filtering". The first two are required to allow configuration via
+ rtnetlink (currently you need Alexey Kuznetsov's iproute2 package
+ from <ftp://ftp.inr.ac.ru>). The "Network packet filtering" option
+ will be required for the forthcoming routing daemon to work.
X
- See Documentation/networking/decnet.txt for more information.
+ See <file:Documentation/networking/decnet.txt> for more information.
X
-DECnet: use FWMARK value as routing key
+Use FWMARK value as DECnet routing key
X CONFIG_DECNET_ROUTE_FWMARK
X If you say Y here, you will be able to specify different routes for
X packets with different FWMARK ("firewalling mark") values
@@ -4568,28 +5323,29 @@
X AppleTalk protocol support
X CONFIG_ATALK
X AppleTalk is the way Apple computers speak to each other on a
- network. If your Linux box is connected to such a network and you
- want to join the conversation, say Y. You will need to use the
+ network. If your Linux box is connected to such a network and you
+ want to join the conversation, say Y. You will need to use the
X netatalk package so that your Linux box can act as a print and file
- server for Macs as well as access AppleTalk printers. Check out
- http://www.zettabyte.net/netatalk/ on the WWW for details. EtherTalk
- is the name used for AppleTalk over Ethernet and the cheaper and
- slower LocalTalk is AppleTalk over a proprietary Apple network using
- serial links. EtherTalk and LocalTalk are fully supported by Linux.
+ server for Macs as well as access AppleTalk printers. Check out
+ <http://www.zettabyte.net/netatalk/> on the WWW for details.
+ EtherTalk is the name used for AppleTalk over Ethernet and the
+ cheaper and slower LocalTalk is AppleTalk over a proprietary Apple
+ network using serial links. EtherTalk and LocalTalk are fully
+ supported by Linux.
X
X General information about how to connect Linux, Windows machines and
- Macs is on the WWW at http://www.eats.com/linux_mac_win.html . The
+ Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>. The
X NET-3-HOWTO, available from

X information as well.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module is called appletalk.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt. You almost
- certainly want to compile it as a module so you can restart your
- AppleTalk stack without rebooting your machine. I hear that the
- GNU boycott of Apple is over, so even politically correct people
+ The module is called appletalk.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. You
+ almost certainly want to compile it as a module so you can restart
+ your AppleTalk stack without rebooting your machine. I hear that
+ the GNU boycott of Apple is over, so even politically correct people
X are allowed to say Y here.
X
X AppleTalk-IP driver support
@@ -4600,7 +5356,7 @@
X box is stuck on an AppleTalk only network) or decapsulate (e.g. if
X you want your Linux box to act as an Internet gateway for a zoo of
X AppleTalk connected Macs). Please see the file
- Documentation/networking/ipddp.txt for more information.
+ <file:Documentation/networking/ipddp.txt> for more information.
X
X If you say Y here, the AppleTalk-IP support will be compiled into
X the kernel. In this case, you can either use encapsulation or
@@ -4609,11 +5365,11 @@
X
X If you say M here, the AppleTalk-IP support will be compiled as a
X module ( = code which can be inserted in and removed from the
- running kernel whenever you want, read Documentation/modules.txt).
- The module is called ipddp.o. In this case, you will be able to use
- both encapsulation and decapsulation simultaneously, by loading two
- copies of the module and specifying different values for the module
- option ipddp_mode.
+ running kernel whenever you want, read
+ <file:Documentation/modules.txt>). The module is called ipddp.o.
+ In this case, you will be able to use both encapsulation and
+ decapsulation simultaneously, by loading two copies of the module
+ and specifying different values for the module option ipddp_mode.
X
X IP to AppleTalk-IP Encapsulation support
X CONFIG_IPDDP_ENCAP
@@ -4621,20 +5377,20 @@
X IP packets inside AppleTalk frames; this is useful if your Linux box
X is stuck on an AppleTalk network (which hopefully contains a
X decapsulator somewhere). Please see
- Documentation/networking/ipddp.txt for more information. If you said
- Y to "AppleTalk-IP driver support" above and you say Y here, then
- you cannot say Y to "AppleTalk-IP to IP Decapsulation support",
- below.
+ <file:Documentation/networking/ipddp.txt> for more information. If
+ you said Y to "AppleTalk-IP driver support" above and you say Y
+ here, then you cannot say Y to "AppleTalk-IP to IP Decapsulation
+ support", below.
X
X AppleTalk-IP to IP Decapsulation support
X CONFIG_IPDDP_DECAP
X If you say Y here, the AppleTalk-IP code will be able to decapsulate
X AppleTalk-IP frames to IP packets; this is useful if you want your
X Linux box to act as an Internet gateway for an AppleTalk network.
- Please see Documentation/networking/ipddp.txt for more information.
- If you said Y to "AppleTalk-IP driver support" above and you say Y
- here, then you cannot say Y to "IP to AppleTalk-IP Encapsulation
- support", above.
+ Please see <file:Documentation/networking/ipddp.txt> for more
+ information. If you said Y to "AppleTalk-IP driver support" above
+ and you say Y here, then you cannot say Y to "IP to AppleTalk-IP
+ Encapsulation support", above.
X
X Apple/Farallon LocalTalk PC card support
X CONFIG_LTPC
@@ -4643,7 +5399,7 @@
X If you are in doubt, this card is the one with the 65C02 chip on it.
X You also need version 1.3.3 or later of the netatalk package.
X This driver is experimental, which means that it may not work.
- See the file Documentation/networking/ltpc.txt.
+ See the file <file:Documentation/networking/ltpc.txt>.
X
X COPS LocalTalk PC card support
X CONFIG_COPS
@@ -4652,7 +5408,7 @@
X package. This driver is experimental, which means that it may not
X work. This driver will only work if you choose "AppleTalk DDP"
X networking support, above.
- Please read the file Documentation/networking/cops.txt.
+ Please read the file <file:Documentation/networking/cops.txt>.
X
X Dayna firmware support
X CONFIG_COPS_DAYNA
@@ -4668,15 +5424,15 @@
X Amateur Radio support
X CONFIG_HAMRADIO
X If you want to connect your Linux box to an amateur radio, answer Y
- here. You want to read http://www.tapr.org/tapr/html/pkthome.html
+ here. You want to read <http://www.tapr.org/tapr/html/pkthome.html>
X and the HAM-HOWTO and the AX25-HOWTO, both available from

X Note that the answer to this question won't directly affect the
- kernel: saying N will just cause this configure script to skip all
+ kernel: saying N will just cause the configurator to skip all

X the questions about amateur radio.
X
-Amateur Radio AX.25 Level 2
+Amateur Radio AX.25 Level 2 protocol
X CONFIG_AX25
X This is the protocol used for computer communication over amateur
X radio. It is either used by itself for point-to-point links, or to
@@ -4694,15 +5450,16 @@
X Information about where to get supporting software for Linux amateur
X radio as well as information about how to configure an AX.25 port is
X contained in the AX25-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . You might also want to
- check out the file Documentation/networking/ax25.txt in the kernel
- source. More information about digital amateur radio in general is
- on the WWW at http://www.tapr.org/tapr/html/pkthome.html .
+ <http://www.linuxdoc.org/docs.html#howto>. You might also want to
+ check out the file <file:Documentation/networking/ax25.txt> in the
+ kernel source. More information about digital amateur radio in
+ general is on the WWW at
+ <http://www.tapr.org/tapr/html/pkthome.html>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called ax25.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X

X AX.25 DAMA Slave support
X CONFIG_AX25_DAMA_SLAVE
@@ -4722,7 +5479,7 @@
X slaves. If you say Y here, your Linux box will act as a DAMA server.


X If unsure, say N.
X

-Amateur Radio NET/ROM
+Amateur Radio NET/ROM support
X CONFIG_NETROM
X NET/ROM is a network layer protocol on top of AX.25 useful for
X routing.
@@ -4730,15 +5487,15 @@
X A comprehensive listing of all the software for Linux amateur radio
X users as well as information about how to configure an AX.25 port is
X contained in the AX25-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . You also might want to
- check out the file Documentation/networking/ax25.txt. More
+ <http://www.linuxdoc.org/docs.html#howto>. You also might want to
+ check out the file <file:Documentation/networking/ax25.txt>. More
X information about digital amateur radio in general is on the WWW at
- http://www.tapr.org/tapr/html/pkthome.html .
+ <http://www.tapr.org/tapr/html/pkthome.html>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called netrom.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X

X Amateur Radio X.25 PLP (Rose)
X CONFIG_ROSE
@@ -4749,15 +5506,15 @@
X A comprehensive listing of all the software for Linux amateur radio
X users as well as information about how to configure an AX.25 port is
X contained in the AX25-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . You also might want to
- check out the file Documentation/networking/ax25.txt. More
+ <http://www.linuxdoc.org/docs.html#howto>. You also might want to
+ check out the file <file:Documentation/networking/ax25.txt>. More
X information about digital amateur radio in general is on the WWW at
- http://www.tapr.org/tapr/html/pkthome.html .
+ <http://www.tapr.org/tapr/html/pkthome.html>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called rose.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X

X Serial port KISS driver for AX.25
X CONFIG_MKISS
@@ -4773,8 +5530,8 @@
X
X If you want to compile this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called mkiss.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called mkiss.o.
X
X Serial port 6PACK driver for AX.25
X CONFIG_6PACK
@@ -4787,12 +5544,12 @@
X
X Note that this driver is still experimental and might cause
X problems. For details about the features and the usage of the
- driver, read Documentation/networking/6pack.txt.
+ driver, read <file:Documentation/networking/6pack.txt>.
X
X If you want to compile this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called 6pack.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called 6pack.o.
X
X BPQ Ethernet driver
X CONFIG_BPQETHER
@@ -4813,7 +5570,7 @@
X Currently, this driver supports Ottawa PI/PI2, Paccomm/Gracilis
X PackeTwin, and S5SCC/DMA boards. They are detected automatically.
X If you have one of these cards, say Y here and read the AX25-HOWTO,
- available from http://www.linuxdoc.org/docs.html#howto .
+ available from <http://www.linuxdoc.org/docs.html#howto>.
X
X This driver can operate multiple boards simultaneously. If you
X compile it as a module (by saying M instead of Y), it will be called


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

echo 'End of part 004'
echo 'File patch-2.4.15 is continued in part 005'
echo "005" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:41 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part005

#!/bin/sh -x
# this is part 005 of a 115 - part archive


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

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

@@ -4829,7 +5586,7 @@
X certain parameters, such as channel access timing, clock mode, and
X DMA channel. This is accomplished with a small utility program,
X dmascc_cfg, available at
- http://www.nt.tuwien.ac.at/~kkudielk/Linux/ . Please be sure to get
+ <http://www.nt.tuwien.ac.at/~kkudielk/Linux/>. Please be sure to get
X at least version 1.27 of dmascc_cfg, as older versions will not
X work with the current driver.
X
@@ -4837,27 +5594,28 @@
X CONFIG_SCC
X These cards are used to connect your Linux box to an amateur radio
X in order to communicate with other computers. If you want to use
- this, read Documentation/networking/z8530drv.txt and the AX25-HOWTO,
- available from http://www.linuxdoc.org/docs.html#howto . Also
- make sure to say Y to "Amateur Radio AX.25 Level 2" support.
+ this, read <file:Documentation/networking/z8530drv.txt> and the
+ AX25-HOWTO, available from
+ <http://www.linuxdoc.org/docs.html#howto>. Also make sure to say Y
+ to "Amateur Radio AX.25 Level 2" support.
X
X If you want to compile this as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called scc.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called scc.o.
+
+Support for TRX that feedback the tx signal to rx
+CONFIG_SCC_TRXECHO
+ Some transmitters feed the transmitted signal back to the receive
+ line. Say Y here to foil this by explicitly disabling the receiver
+ during data transmission. If in doubt, say Y.
X
-additional delay for PA0HZP OptoSCC compatible boards
+Additional delay for PA0HZP OptoSCC compatible boards
X CONFIG_SCC_DELAY
X Say Y here if you experience problems with the SCC driver not
- working properly; please read Documentation/networking/z8530drv.txt
- for details. If unsure, say N.
-
-#support for TRX that feedback the tx signal to rx
-#CONFIG_SCC_TRXECHO
-###
-### Don't know what's going on here.
-###
-#
+ working properly; please read
+ <file:Documentation/networking/z8530drv.txt> for details. If unsure,
+ say N.
X
X YAM driver for AX.25
X CONFIG_YAM
@@ -4867,7 +5625,7 @@
X
X If you want to compile this as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt.

+ say M here and read <file:Documentation/modules.txt>.

X
X BAYCOM picpar and par96 driver for AX.25
X CONFIG_BAYCOM_PAR
@@ -4875,13 +5633,13 @@
X connect to a parallel interface. The driver supports the picpar and
X par96 designs. To configure the driver, use the sethdlc utility
X available in the standard ax25 utilities package. For information on
- the modems, see http://www.baycom.de and the file
- Documentation/networking/baycom.txt.
+ the modems, see <http://www.baycom.de> and the file
+ <file:Documentation/networking/baycom.txt>.


X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt. This is recommended.
- The module will be called baycom_par.o.
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called baycom_par.o.
X
X BAYCOM EPP driver for AX.25
X CONFIG_BAYCOM_EPP
@@ -4889,48 +5647,49 @@
X connect to a parallel interface. The driver supports the EPP
X designs. To configure the driver, use the sethdlc utility available
X in the standard ax25 utilities package. For information on the
- modems, see http://www.baycom.de and the file
- Documentation/networking/baycom.txt.
+ modems, see <http://www.baycom.de> and the file
+ <file:Documentation/networking/baycom.txt>.


X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt. This is recommended.
- The module will be called baycom_par.o.
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called baycom_par.o.
X
-BAYCOM ser12 full duplex driver for AX.25
+BAYCOM ser12 full-duplex driver for AX.25
X CONFIG_BAYCOM_SER_FDX
X This is one of two drivers for Baycom style simple amateur radio
X modems that connect to a serial interface. The driver supports the
- ser12 design in full duplex mode. In addition, it allows the
+ ser12 design in full-duplex mode. In addition, it allows the
X baudrate to be set between 300 and 4800 baud (however not all modems
X support all baudrates). This is the preferred driver. The next
- driver, "BAYCOM ser12 half duplex driver for AX.25" is the old
+ driver, "BAYCOM ser12 half-duplex driver for AX.25" is the old
X driver and still provided in case this driver does not work with
X your serial interface chip. To configure the driver, use the sethdlc
X utility available in the standard ax25 utilities package. For
- information on the modems, see http://www.baycom.de and
- Documentation/networking/baycom.txt.
+ information on the modems, see <http://www.baycom.de> and
+ <file:Documentation/networking/baycom.txt>.


X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt. This is recommended.
- The module will be called baycom_ser_fdx.o.
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called baycom_ser_fdx.o.
X
-BAYCOM ser12 half duplex driver for AX.25
+BAYCOM ser12 half-duplex driver for AX.25
X CONFIG_BAYCOM_SER_HDX
X This is one of two drivers for Baycom style simple amateur radio
X modems that connect to a serial interface. The driver supports the
- ser12 design in full duplex mode. This is the old driver. It is
+ ser12 design in full-duplex mode. This is the old driver. It is
X still provided in case your serial interface chip does not work with
- the full duplex driver. This driver is depreciated. To configure the
- driver, use the sethdlc utility available in the standard ax25
+ the full-duplex driver. This driver is depreciated. To configure
+ the driver, use the sethdlc utility available in the standard ax25
X utilities package. For information on the modems, see
- http://www.baycom.de and Documentation/networking/baycom.txt.
+ <http://www.baycom.de> and
+ <file:Documentation/networking/baycom.txt>.


X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt. This is recommended.
- The module will be called baycom_ser_hdx.o.
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called baycom_ser_hdx.o.
X
X Sound card modem driver for AX.25
X CONFIG_SOUNDMODEM
@@ -4942,13 +5701,13 @@
X To configure the driver, use the sethdlc, smdiag and smmixer
X utilities available in the standard ax25 utilities package. For
X information on how to key the transmitter, see
- http://www.ife.ee.ethz.ch/~sailer/pcf/ptt_circ/ptt.html and
- Documentation/networking/soundmodem.txt.
+ <http://www.ife.ee.ethz.ch/~sailer/pcf/ptt_circ/ptt.html> and
+ <file:Documentation/networking/soundmodem.txt>.


X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt. This is recommended.
- The module will be called soundmodem.o.
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called soundmodem.o.
X
X Sound card modem support for Sound Blaster and compatible cards
X CONFIG_SOUNDMODEM_SBC
@@ -4957,7 +5716,7 @@
X with a Sound Blaster emulation) you should say N here and Y to
X "Sound card modem support for WSS and Crystal cards", below, because
X this usually results in better performance. This option also
- supports SB16/32/64 in full duplex mode.
+ supports SB16/32/64 in full-duplex mode.
X
X Sound card modem support for WSS and Crystal cards
X CONFIG_SOUNDMODEM_WSS
@@ -4965,8 +5724,8 @@
X compatible cards. These cards feature a codec chip from either
X Analog Devices (such as AD1848, AD1845, AD1812) or Crystal
X Semiconductors (such as CS4248, CS423x). This option also supports
- the WSS full duplex operation which currently works with Crystal
- CS423x chips. If you don't need full duplex operation, do not enable
+ the WSS full-duplex operation which currently works with Crystal
+ CS423x chips. If you don't need full-duplex operation, do not enable
X it to save performance.
X
X Sound card modem support for 1200 baud AFSK modulation
@@ -5026,7 +5785,7 @@
X can only use one protocol at a time, depending on what the other end
X can understand).
X
-CCITT X.25 Packet Layer (EXPERIMENTAL)
+CCITT X.25 Packet Layer
X CONFIG_X25
X X.25 is a set of standardized network protocols, similar in scope to
X frame relay; the one physical line from your box to the X.25 network
@@ -5037,13 +5796,13 @@
X countries have public X.25 networks. X.25 consists of two
X protocols: the higher level Packet Layer Protocol (PLP) (say Y here
X if you want that) and the lower level data link layer protocol LAPB
- (say Y to "LAPB Data Link Driver" below if you want that).
+ (say Y to "LAPB Data Link Driver" below if you want that).
X
- You can read more about X.25 at http://www.sangoma.com/x25.htm and
- http://www.cisco.com/univercd/data/doc/software/11_0/rpcg/cx25.htm .
+ You can read more about X.25 at <http://www.sangoma.com/x25.htm> and
+ <http://www.cisco.com/univercd/data/doc/software/11_0/rpcg/cx25.htm>.
X Information about X.25 for Linux is contained in the files
- Documentation/networking/x25.txt and
- Documentation/networking/x25-iface.txt.
+ <file:Documentation/networking/x25.txt> and
+ <file:Documentation/networking/x25-iface.txt>.
X
X One connects to an X.25 network either with a dedicated network card
X using the X.21 protocol (not yet supported by Linux) or one can do
@@ -5051,14 +5810,14 @@
X to "X.25 async driver" below) or over Ethernet using an ordinary
X Ethernet card and either the 802.2 LLC protocol (say Y to "802.2
X LLC" below) or LAPB over Ethernet (say Y to "LAPB Data Link Driver"
- and "LAPB over Ethernet driver" below).
+ and "LAPB over Ethernet driver" below).


X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called x25.o. If unsure, say N.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called x25.o. If unsure, say N.
X
-LAPB Data Link Driver (EXPERIMENTAL)
+LAPB Data Link Driver
X CONFIG_LAPB
X Link Access Procedure, Balanced (LAPB) is the data link layer (i.e.
X the lower) part of the X.25 protocol. It offers a reliable
@@ -5069,41 +5828,42 @@
X currently supports LAPB only over Ethernet connections. If you want
X to use LAPB connections over Ethernet, say Y here and to "LAPB over
X Ethernet driver" below. Read
- Documentation/networking/lapb-module.txt for technical details.
+ <file:Documentation/networking/lapb-module.txt> for technical
+ details.
X
X If you want to compile this driver as a module though ( = code which


X can be inserted in and removed from the running kernel whenever you

- want), say M here and read Documentation/modules.txt. The module
- will be called lapb.o. If unsure, say N.
+ want), say M here and read <file:Documentation/modules.txt>. The
+ module will be called lapb.o. If unsure, say N.
X
-802.2 LLC (EXPERIMENTAL)
+802.2 LLC
X CONFIG_LLC
X This is a Logical Link Layer protocol used for X.25 connections over
- Ethernet, using ordinary Ethernet cards.
+ Ethernet, using ordinary Ethernet cards.
X
-
-Frame Diverter (EXPERIMENTAL)
+Frame Diverter
X CONFIG_NET_DIVERT
X The Frame Diverter allows you to divert packets from the
- network, that are not aimed at the interface receiving it (in
- promisc. mode). Typically, a Linux box setup as an ethernet bridge
- with the Frames Diverter on, can do some *really* transparent www
+ network, that are not aimed at the interface receiving it (in
+ promisc. mode). Typically, a Linux box setup as an Ethernet bridge
+ with the Frames Diverter on, can do some *really* transparent www
X caching using a Squid proxy for example.
X
X This is very useful when you don't want to change your router's
X config (or if you simply don't have access to it).
X
- The other possible usages of diverting Ethernet Frames are numberous:
+ The other possible usages of diverting Ethernet Frames are
+ numberous:
X - reroute smtp traffic to another interface
X - traffic-shape certain network streams
X - transparently proxy smtp connections
X - etc...
X
X For more informations, please refer to:
- http://www.freshmeat.net/projects/etherdivert
- http://perso.wanadoo.fr/magpie/EtherDivert.html
+ <http://www.freshmeat.net/projects/etherdivert>
+ <http://perso.wanadoo.fr/magpie/EtherDivert.html>
X
- If unsure, say N


+ If unsure, say N.
X

X 802.1d Ethernet Bridging
X CONFIG_BRIDGE
@@ -5113,21 +5873,22 @@
X Several such bridges can work together to create even larger
X networks of Ethernets using the IEEE 802.1 spanning tree algorithm.
X As this is a standard, Linux bridges will cooperate properly with
- other third party bridge products.
+ other third party bridge products.
+
+ In order to use the Ethernet bridge, you'll need the bridge
+ configuration tools; see <file:Documentation/networking/bridge.txt>
+ for location. Please read the Bridge mini-HOWTO for more
+ information.
X
- In order to use the ethernet bridge, you'll need the bridge
- configuration tools; see Documentation/networking/bridge.txt for
- location. Please read the Bridge mini-HOWTO for more information.
-
X Note that if your box acts as a bridge, it probably contains several
X Ethernet devices, but the kernel is not able to recognize more than
X one at boot time without help; for details read the Ethernet-HOWTO,
- available from in http://www.linuxdoc.org/docs.html#howto .
+ available from in <http://www.linuxdoc.org/docs.html#howto>.
X
X If you want to compile this code as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called bridge.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called bridge.o.
X
X If unsure, say N.
X
@@ -5135,15 +5896,15 @@
X CONFIG_PACKET
X The Packet protocol is used by applications which communicate
X directly with network devices without an intermediate network
- protocol implemented in the kernel, e.g. tcpdump. If you want them
- to work, choose Y.
+ protocol implemented in the kernel, e.g. tcpdump. If you want them
+ to work, choose Y.
X
X This driver is also available as a module called af_packet.o ( =
X 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; if you use modprobe or
- kmod, you may also want to add "alias net-pf-17 af_packet" to
- /etc/modules.conf.

+ whenever you want). If you want to compile it as a module, say M

+ here and read <file:Documentation/modules.txt>; if you use modprobe
+ or kmod, you may also want to add "alias net-pf-17 af_packet" to
+ /etc/modules.conf.


X
X If unsure, say Y.
X

@@ -5157,17 +5918,17 @@
X Kernel/User network link driver
X CONFIG_NETLINK
X This driver allows for two-way communication between the kernel and
- user processes. It does so by creating a new socket family, PF_NETLINK.
- Over this socket, the kernel can send and receive datagrams carrying
- information. It is documented on many systems in netlink(7), a HOWTO is
- provided as well, for example on
- http://snafu.freedom.org/linux2.2/docs/netlink-HOWTO.html
+ user processes. It does so by creating a new socket family,
+ PF_NETLINK. Over this socket, the kernel can send and receive
+ datagrams carrying information. It is documented on many systems in
+ netlink(7), a HOWTO is provided as well, for example on
+ <http://snafu.freedom.org/linux2.2/docs/netlink-HOWTO.html>.
X
X So far, the kernel uses this feature to publish some network related
X information if you say Y to "Routing messages", below. You also need
X to say Y here if you want to use arpd, a daemon that helps keep the
X internal ARP cache (a mapping between IP addresses and hardware
- addresses on the local network) small. The ethertap device, which
+ addresses on the local network) small. The ethertap device, which
X lets user space programs read and write raw Ethernet frames, also
X needs the network link driver.
X
@@ -5177,7 +5938,7 @@
X CONFIG_RTNETLINK
X If you say Y here, user space programs can receive some network
X related routing information over the netlink. 'rtmon', supplied
- with the iproute2 package (ftp://ftp.inr.ac.ru), can read and
+ with the iproute2 package (<ftp://ftp.inr.ac.ru>), can read and
X interpret this data. Information sent to the kernel over this link
X is ignored.
X
@@ -5192,17 +5953,17 @@
X Asynchronous Transfer Mode (ATM)
X CONFIG_ATM
X ATM is a high-speed networking technology for Local Area Networks
- and Wide Area Networks. It uses a fixed packet size and is
+ and Wide Area Networks. It uses a fixed packet size and is
X connection oriented, allowing for the negotiation of minimum
X bandwidth requirements.
-
+
X In order to participate in an ATM network, your Linux box needs an
X ATM networking card. If you have that, say Y here and to the driver
X of your ATM card below.
X
X Note that you need a set of user-space programs to actually make use
- of ATM. See the file Documentation/networking/atm.txt for further
- details.
+ of ATM. See the file <file:Documentation/networking/atm.txt> for
+ further details.
X
X Classical IP over ATM
X CONFIG_ATM_CLIP
@@ -5247,9 +6008,9 @@
X The driver works with MMF (-MF or ...F) and UTP-5 (-U5 or ...D)
X adapters.
X
- This driver is also available as a module. If you want to compile
- it as a module, say M here and read Documentation/modules.txt. The
- module will be called eni.o.
+ This driver is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called eni.o.
X
X Enable extended debugging
X CONFIG_ATM_ENI_DEBUG
@@ -5296,7 +6057,7 @@
X Burst four words at once in the send direction. You may want to try
X this if you have disabled 8W bursts. Enabling 4W if 8W is also set
X may or may not improve throughput.
-
+
X Enable 2W TX bursts (optional)
X CONFIG_ATM_ENI_BURST_TX_2W
X Burst two words at once in the send direction. You may want to try
@@ -5331,9 +6092,9 @@
X Driver for the ZeitNet ZN1221 (MMF) and ZN1225 (UTP-5) 155 Mbps ATM
X adapters.
X
- This driver is also available as a module. If you want to compile
- it as a module, say M here and read Documentation/modules.txt. The
- module will be called zatm.o.
+ This driver is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called zatm.o.
X
X Enable extended debugging
X CONFIG_ATM_ZATM_DEBUG
@@ -5345,12 +6106,13 @@
X
X Fujitsu FireStream (FS50/FS155)
X CONFIG_ATM_FIRESTREAM
- Driver for the Fujitsu FireStream 155 (MB86697) and
+ Driver for the Fujitsu FireStream 155 (MB86697) and
X FireStream 50 (MB86695) ATM PCI chips.
X
- This driver is also available as a module. If you want to compile
- it as a module, say M here and read Documentation/modules.txt. The
- module will be called firestream.o.
+ This driver is also available as a module. If you want to compile
+ it as a module, say M here and read


+ <file:Documentation/modules.txt>. The module will be called

+ firestream.o.
X
X Enable usec resolution timestamps
X CONFIG_ATM_ZATM_EXACT_TS
@@ -5368,21 +6130,22 @@
X 25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE
X series. Say Y if you have one of those.
X
- This driver is also available as a module. If you want to compile
- it as a module, say M here and read Documentation/modules.txt. The
- module will be called nicstar.o.
+ This driver is also available as a module. If you want to compile
+ it as a module, say M here and read


+ <file:Documentation/modules.txt>. The module will be called

+ nicstar.o.
X
-ForeRunner LE155 PHYsical layer
+Use suni PHY driver (155Mbps)
X CONFIG_ATM_NICSTAR_USE_SUNI
X Support for the S-UNI and compatible PHYsical layer chips. These are
X found in most 155Mbps NICStAR based ATM cards, namely in the
- ForeRunner LE155 cards. This driver provides detection of cable
+ ForeRunner LE155 cards. This driver provides detection of cable~
X removal and reinsertion and provides some statistics. This driver
X doesn't have removal capability when compiled as a module, so if you
X need that capability don't include S-UNI support (it's not needed to
X make the card work).
X
-ForeRunner LE25 PHYsical layer
+Use IDT77015 PHY driver (25Mbps)
X CONFIG_ATM_NICSTAR_USE_IDT77105
X Support for the PHYsical layer chip in ForeRunner LE25 cards. In
X addition to cable removal/reinsertion detection, this driver allows
@@ -5390,6 +6153,31 @@
X This driver is required for proper handling of temporary carrier
X loss, so if you have a 25Mbps NICStAR based ATM card you must say Y.
X
+IDT 77252 (NICStAR II)
+CONFIG_ATM_IDT77252
+ Driver for the IDT 77252 ATM PCI chips.
+
+ This driver is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called idt77252.o
+
+Enable debugging messages
+CONFIG_ATM_IDT77252_DEBUG
+ Somewhat useful debugging messages are available. The choice of
+ messages is controlled by a bitmap. This may be specified as a
+ module argument. See the file <file:drivers/atm/idt77252.h> for
+ the meanings of the bits in the mask.
+
+ When active, these messages can have a significant impact on the
+ speed of the driver, and the size of your syslog files! When
+ inactive, they will have only a modest impact on performance.
+
+Receive ALL cells in raw queue
+CONFIG_ATM_IDT77252_RCV_ALL
+ Enable receiving of all cells on the ATM link, that do not match
+ an open connection in the raw cell queue of the driver. Useful
+ for debugging or special applications only, so the safe answer is N.
+
X Madge Ambassador (Collage PCI 155 Server)
X CONFIG_ATM_AMBASSADOR
X This is a driver for ATMizer based ATM card produced by Madge
@@ -5399,11 +6187,12 @@
X Enable debugging messages
X CONFIG_ATM_AMBASSADOR_DEBUG
X Somewhat useful debugging messages are available. The choice of
- messages is controlled by a bitmap. This may be specified as a
+ messages is controlled by a bitmap. This may be specified as a
X module argument (kernel command line argument as well?), changed
X dynamically using an ioctl (not yet) or changed by sending the
- string "Dxxxx" to VCI 1023 (where x is a hex digit). See the file
- drivers/atm/ambassador.h for the meanings of the bits in the mask.
+ string "Dxxxx" to VCI 1023 (where x is a hex digit). See the file
+ <file:drivers/atm/ambassador.h> for the meanings of the bits in the
+ mask.
X
X When active, these messages can have a significant impact on the
X speed of the driver, and the size of your syslog files! When
@@ -5418,28 +6207,29 @@
X Enable debugging messages
X CONFIG_ATM_HORIZON_DEBUG
X Somewhat useful debugging messages are available. The choice of
- messages is controlled by a bitmap. This may be specified as a
+ messages is controlled by a bitmap. This may be specified as a
X module argument (kernel command line argument as well?), changed
X dynamically using an ioctl (not yet) or changed by sending the
- string "Dxxxx" to VCI 1023 (where x is a hex digit). See the file
- drivers/atm/horizon.h for the meanings of the bits in the mask.
+ string "Dxxxx" to VCI 1023 (where x is a hex digit). See the file
+ <file:drivers/atm/horizon.h> for the meanings of the bits in the
+ mask.
X
X When active, these messages can have a significant impact on the
X speed of the driver, and the size of your syslog files! When
X inactive, they will have only a modest impact on performance.
X
-Interphase ATM PCI x575/x525/x531
+Interphase ATM PCI x575/x525/x531
X CONFIG_ATM_IA
X This is a driver for the Interphase (i)ChipSAR adapter cards
- which include a variety of variants in term of the size of the
- control memory (128K-1KVC, 512K-4KVC), the size of the packet
- memory (128K, 512K, 1M), and the PHY type (Single/Multi mode OC3,
+ which include a variety of variants in term of the size of the
+ control memory (128K-1KVC, 512K-4KVC), the size of the packet
+ memory (128K, 512K, 1M), and the PHY type (Single/Multi mode OC3,
X UTP155, UTP25, DS3 and E3). Go to:
X www.iphase.com/products/ClassSheet.cfm?ClassID=ATM
- for more info about the cards. Say Y (or M to compile as a module
+ for more info about the cards. Say Y (or M to compile as a module
X named iphase.o) here if you have one of these cards.
X
- See the file Documentation/networking/iphase.txt for further
+ See the file <file:Documentation/networking/iphase.txt> for further
X details.
X
X Enable debugging messages
@@ -5447,9 +6237,11 @@
X Somewhat useful debugging messages are available. The choice of
X messages is controlled by a bitmap. This may be specified as a
X module argument (kernel command line argument as well?), changed
- dynamically using an ioctl (Get the debug utility, iadbg, from
- ftp.iphase.com/pub/atm/pci). See the file drivers/atm/iphase.h
- for the meanings of the bits in the mask.
+ dynamically using an ioctl (Get the debug utility, iadbg, from
+ <ftp://ftp.iphase.com/pub/atm/pci>).
+
+ See the file <file:drivers/atm/iphase.h> for the meanings of the
+ bits in the mask.
X
X When active, these messages can have a significant impact on the
X speed of the driver, and the size of your syslog files! When
@@ -5458,36 +6250,37 @@
X Linux telephony support
X CONFIG_PHONE
X Say Y here if you have a telephony card, which for example allows
- you to use a regular phone for voice-over-IP applications.
+ you to use a regular phone for voice-over-IP applications.
X
- Note: this has nothing to do with modems. You do not need to say Y
+ Note: this has nothing to do with modems. You do not need to say Y
X here in order to be able to use a modem under Linux.
X
- This support is also available as a module. If you want to compile
- it as a module, say M here and read Documentation/modules.txt. The
- module will be called phonedev.o.
+ This support is also available as a module. If you want to compile
+ it as a module, say M here and read


+ <file:Documentation/modules.txt>. The module will be called

+ phonedev.o.
X
X Compaq Smart Array support
X CONFIG_BLK_CPQ_CISS_DA
- This is the driver for Compaq Smart Array 5xxx controllers.


- Everyone using these boards should say Y here.

- See Documentation/cciss.txt for the current list of


- boards supported by this driver, and for further information
- on the use of this driver.

+ This is the driver for Compaq Smart Array 5xxx controllers.
+ Everyone using these boards should say Y here.
+ See <file:Documentation/cciss.txt> for the current list of
+ boards supported by this driver, and for further information
+ on the use of this driver.
X
X QuickNet Internet LineJack/PhoneJack support
X CONFIG_PHONE_IXJ
X Say M if you have a telephony card manufactured by Quicknet
X Technologies, Inc. These include the Internet PhoneJACK and
X Internet LineJACK Telephony Cards. You will get a module called
- ixj.o.
+ ixj.o.
X
X For the ISA versions of these products, you can configure the
X cards using the isapnp tools (pnpdump/isapnp) or you can use the
- isapnp support. Please read Documentation/telephony/ixj.txt.
+ isapnp support. Please read <file:Documentation/telephony/ixj.txt>.
X
X For more information on these cards, see Quicknet's web site at:
- http://www.quicknet.net/ .
+ <http://www.quicknet.net/>.
X
X If you do not have any Quicknet telephony cards, you can safely
X say N here.
@@ -5498,66 +6291,66 @@
X cards. It simultaneously supports PCA-200E and SBA-200E models
X on PCI and SBUS hosts. Say Y (or M to compile as a module
X named fore_200e.o) here if you have one of these ATM adapters.
-
+
X Note that the driver will actually be compiled only if you
X additionally enable the support for PCA-200E and/or SBA-200E
X cards.
X
- See the file Documentation/networking/fore200e.txt for further
- details.
-
+ See the file <file:Documentation/networking/fore200e.txt> for
+ further details.
+
X Enable PCA-200E card support on PCI-based hosts
X CONFIG_ATM_FORE200E_PCA
X Say Y here if you want your PCA-200E cards to be probed.
-
+
X Use default PCA-200E firmware
X CONFIG_ATM_FORE200E_PCA_DEFAULT_FW
X Use the default PCA-200E firmware data shipped with the driver.
-
+
X Normal users do not have to deal with the firmware stuff, so
X they should say Y here.
-
+
X Pathname of user-supplied binary firmware
X CONFIG_ATM_FORE200E_PCA_FW
X This defines the pathname of an alternative PCA-200E binary
X firmware image supplied by the user. This pathname may be
X absolute or relative to the drivers/atm directory.
-
+
X The driver comes with an adequate firmware image, so normal users do
X not have to supply an alternative one. They just say Y to "Use
X default PCA-200E firmware" instead.
-
+
X Enable SBA-200E card support on SBUS-based hosts
X CONFIG_ATM_FORE200E_SBA
X Say Y here if you want your SBA-200E cards to be probed.
-
+
X Use default SBA-200E firmware
X CONFIG_ATM_FORE200E_SBA_DEFAULT_FW
X Use the default SBA-200E firmware data shipped with the driver.
-
+
X Normal users do not have to deal with the firmware stuff, so
X they should say Y here.
-
+
X Pathname of user-supplied binary firmware
X CONFIG_ATM_FORE200E_SBA_FW
X This defines the pathname of an alternative SBA-200E binary
X firmware image supplied by the user. This pathname may be
X absolute or relative to the drivers/atm directory.
-
+
X The driver comes with an adequate firmware image, so normal users do
X not have to supply an alternative one. They just say Y to "Use
X default SBA-200E firmware", above.
-
+
X Maximum number of tx retries
X CONFIG_ATM_FORE200E_TX_RETRY
X Specifies the number of times the driver attempts to transmit
X a message before giving up, if the transmit queue of the ATM card
X is transiently saturated.
-
+
X Saturation of the transmit queue may occur only under extreme
X conditions, e.g. when a fast host continuously submits very small
X frames (<64 bytes) or raw AAL0 cells (48 bytes) to the ATM adapter.
-
+
X Note that under common conditions, it is unlikely that you encounter
X a saturation of the transmit queue, so the retry mechanism never
X comes into play.
@@ -5567,54 +6360,168 @@
X Specifies the level of debugging messages issued by the driver.
X The verbosity of the driver increases with the value of this
X parameter.
-
+
X When active, these messages can have a significant impact on
X the performances of the driver, and the size of your syslog files!
X Keep the debugging level to 0 during normal operations.
X
-SCSI support?
+Fusion MPT device support
+CONFIG_FUSION
+ LSI Logic Fusion(TM) Message Passing Technology (MPT) device support
+ provides high performance SCSI host initiator, and LAN [1] interface
+ services to a host system. The Fusion architecture is capable of
+ duplexing these protocols on high-speed Fibre Channel
+ (up to 2 GHz x 2 ports = 4 GHz) and parallel SCSI (up to Ultra-320)
+ physical medium.
+
+ [1] LAN is not supported on parallel SCSI medium.
+
+ These drivers require a Fusion MPT compatible PCI adapter installed
+ in the host system. MPT adapters contain specialized I/O processors
+ to handle I/O workload, and more importantly to offload this work
+ from the host CPU(s).
+
+ If you have Fusion MPT hardware and want to use it, you can say
+ Y or M here to add MPT (base + ScsiHost) drivers.
+ <Y> = build lib (fusion.o), and link [static] into the kernel [2]
+ proper
+ <M> = compiled as [dynamic] modules [3] named: (mptbase.o,
+ mptscsih.o)
+
+ [2] In order enable capability to boot the linux kernel
+ natively from a Fusion MPT target device, you MUST
+ answer Y here! (currently requires CONFIG_BLK_DEV_SD)
+ [3] This support is also available as a module ( = code
+ which can be inserted in and removed from the running
+ kernel whenever you want). If you want to compile as
+ modules, say M here and read
+ <file:Documentation/modules.txt>.


+
+ If unsure, say N.

+
+ If you say Y or M here you will get a choice of these
+ additional protocol and support module options: Module Name:
+ <M> Enhanced SCSI error reporting (isense.o)
+ <M> Fusion MPT misc device (ioctl) driver (mptctl.o)
+ <M> Fusion MPT LAN driver (mptlan.o)
+
+ ---
+ Fusion MPT is trademark of LSI Logic Corporation, and its
+ architecture is based on LSI Logic's Message Passing Interface (MPI)
+ specification.
+
+Fusion MPT enhanced SCSI error reporting [optional] module
+CONFIG_FUSION_ISENSE
+ The isense module (roughly stands for Interpret SENSE data) is
+ completely optional. It simply provides extra English readable
+ strings in SCSI Error Report(s) that might be generated from the
+ Fusion MPT SCSI Host driver, for example when a target device
+ returns a SCSI check condition on a I/O. Without this module
+ loaded you might see:
+
+ SCSI Error Report =-=-= (ioc0,scsi5:0)
+ SCSI_Status=02h (CHECK_CONDITION)
+ Original_CDB[]: 2A 00 00 00 00 41 00 00 02 00
+ SenseData[12h]: 70 00 02 00 00 00 00 0A 00 00 00 00 04 02 02 00 00 00
+ SenseKey=2h (NOT READY); FRU=02h
+ ASC/ASCQ=29h/00h
+
+ Where otherwise, if this module had been loaded, you would see:
+
+ SCSI Error Report =-=-= (ioc0,scsi5:0)
+ SCSI_Status=02h (CHECK_CONDITION)
+ Original_CDB[]: 2A 00 00 00 00 41 00 00 02 00 - "WRITE(10)"
+ SenseData[12h]: 70 00 02 00 00 00 00 0A 00 00 00 00 04 02 02 00 00 00
+ SenseKey=2h (NOT READY); FRU=02h
+ ASC/ASCQ=29h/00h "LOGICAL UNIT NOT READY, INITIALIZING CMD. REQUIRED"
+
+ Say M for "Enhanced SCSI error reporting" to compile this optional module,
+ creating a driver named: isense.o.
+
+ NOTE: Support for building this feature into the kernel is not
+ available, due to kernel size considerations.
+
+Fusion MPT misc device (ioctl) driver [optional] module
+CONFIG_FUSION_CTL
+ The Fusion MPT misc device driver provides specialized control
+ of MPT adapters via system ioctl calls. Use of ioctl calls to
+ the MPT driver requires that you create and use a misc device
+ node ala:
+ mknod /dev/mptctl c 10 240
+
+ One use of this ioctl interface is to perform an upgrade (reflash)
+ of the MPT adapter firmware. Refer to readme file(s) distributed
+ with the Fusion MPT linux driver for additional details.
+
+ If enabled by saying M to this, a driver named: mptctl.o
+ will be compiled.
+
+ If unsure whether you really want or need this, say N.
+
+Fusion MPT LAN driver [optional]
+CONFIG_FUSION_LAN
+ This module supports LAN IP traffic over Fibre Channel port(s)
+ on Fusion MPT compatible hardware (LSIFC9xx chips).
+ The physical interface used is defined in RFC 2625.
+ Please refer to that document for details.
+
+ Installing this driver requires the knowledge to configure and
+ activate a new network interface, "fc0", using standard Linux tools.
+
+ If enabled by saying M to this, a driver named: mptlan.o
+ will be compiled.
+
+ If unsure whether you really want or need this, say N.
+
+ NOTES: This feature is NOT available nor supported for linux-2.2.x
+ kernels. You must be building a linux-2.3.x or linux-2.4.x kernel
+ in order to configure this option.
+ Support for building this feature into the linux kernel is not
+ yet available.
+
+SCSI support
X CONFIG_SCSI
- If you want to use a SCSI hard disk, SCSI tape drive, SCSI CDROM or
+ If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or
X any other SCSI device under Linux, say Y and make sure that you know
X the name of your SCSI host adapter (the card inside your computer
X that "speaks" the SCSI protocol, also called SCSI controller),
- because you will be asked for it.
+ because you will be asked for it.
X
X You also need to say Y here if you want support for the parallel
X port version of the 100 MB IOMEGA ZIP drive.
X
X Please read the SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . The
+ <http://www.linuxdoc.org/docs.html#howto>. The
X SCSI-Programming-HOWTO contains information about how to add or
X remove an SCSI device from a running Linux machine without
X rebooting.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called scsi_mod.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt and
- Documentation/scsi.txt. However, do not compile this as a module if
- your root file system (the one containing the directory /) is
- located on a SCSI device.
+ The module will be called scsi_mod.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt> and
+ <file:Documentation/scsi.txt>. However, do not compile this as a
+ module if your root file system (the one containing the directory /)
+ is located on a SCSI device.
X
X SCSI disk support
X CONFIG_BLK_DEV_SD
X If you want to use a SCSI hard disk or the SCSI or parallel port
X version of the IOMEGA ZIP drive under Linux, say Y and read the
X SCSI-HOWTO, the Disk-HOWTO and the Multi-Disk-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . This is NOT for SCSI
- CDROMs.
+ <http://www.linuxdoc.org/docs.html#howto>. This is NOT for SCSI
+ CD-ROMs.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called sd_mod.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt and
- Documentation/scsi.txt. Do not compile this driver as a module if
- your root file system (the one containing the directory /) is
- located on a SCSI disk. In this case, do not compile the driver for
- your SCSI host adapter (below) as a module either.
+ The module will be called sd_mod.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> and
+ <file:Documentation/scsi.txt>. Do not compile this driver as a
+ module if your root file system (the one containing the directory /)
+ is located on a SCSI disk. In this case, do not compile the driver
+ for your SCSI host adapter (below) as a module either.
X
-Extra SCSI Disks
+Maximum number of SCSI disks that can be loaded as modules
X CONFIG_SD_EXTRA_DEVS
X This controls the amount of additional space allocated in tables for
X drivers that are loaded as modules after the kernel is booted. In
@@ -5628,63 +6535,76 @@
X
X If you don't understand what's going on, go with the default.
X
+Maximum number of SCSI tapes that can be loaded as modules
+CONFIG_ST_EXTRA_DEVS
+ This controls the amount of additional space allocated in tables for
+ drivers that are loaded as modules after the kernel is booted. In
+ the event that the SCSI core itself was loaded as a module, this
+ value is the number of additional tapes that can be loaded after the
+ first host driver is loaded.
+
+ Admittedly this isn't pretty, but there are tons of race conditions
+ involved with resizing the internal arrays on the fly. Someday this
+ flag will go away, and everything will work automatically.
+
+ If you don't understand what's going on, go with the default.
+
X SCSI tape support
X CONFIG_CHR_DEV_ST
X If you want to use a SCSI tape drive under Linux, say Y and read the
X SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto , and
- drivers/scsi/README.st in the kernel source. This is NOT for SCSI
- CDROMs.
+ <http://www.linuxdoc.org/docs.html#howto>, and
+ <file:drivers/scsi/README.st> in the kernel source. This is NOT for
+ SCSI CD-ROMs.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called st.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt and
- Documentation/scsi.txt .
+ module, say M here and read <file:Documentation/modules.txt> and
+ <file:Documentation/scsi.txt>.
X
X OnStream SC-x0 SCSI tape support
X CONFIG_CHR_DEV_OSST
- The OnStream SC-x0 SCSI tape drives can not be driven by the
- standard st driver, but instead need this special osst driver and
- use the /dev/osstX char device nodes (major 206).
- Via usb-storage and ide-scsi, you may be able to drive the USB-x0
- and DI-x0 drives as well. Note that there is also a second generation
- of OnStream tape drives (ADR-x0) that supports the standard SCSI-2
- commands for tapes (QIC-157) and can be driven by the standard
- driver st.
+ The OnStream SC-x0 SCSI tape drives can not be driven by the
+ standard st driver, but instead need this special osst driver and
+ use the /dev/osstX char device nodes (major 206). Via usb-storage
+ and ide-scsi, you may be able to drive the USB-x0 and DI-x0 drives
+ as well. Note that there is also a second generation of OnStream
+ tape drives (ADR-x0) that supports the standard SCSI-2 commands for
+ tapes (QIC-157) and can be driven by the standard driver st.
X For more information, you may have a look at the SCSI-HOWTO
- ftp://metalab.unc.edu/pub/Linux/docs/HOWTO and
- drivers/scsi/README.osst in the kernel source.
- More info on the OnStream driver may be found on
- http://linux1.onstream.nl/test/
+ <ftp://metalab.unc.edu/pub/Linux/docs/HOWTO> and
+ <file:drivers/scsi/README.osst> in the kernel source.
+ More info on the OnStream driver may be found on
+ <http://linux1.onstream.nl/test/>
X Please also have a look at the standard st docu, as most of it
X applies to osst as well.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called osst.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt and
- Documentation/scsi.txt .
+ module, say M here and read <file:Documentation/modules.txt> and
+ <file:Documentation/scsi.txt>.
X
-SCSI CDROM support
+SCSI CD-ROM support
X CONFIG_BLK_DEV_SR
- If you want to use a SCSI CDROM under Linux, say Y and read the
- SCSI-HOWTO and the CDROM-HOWTO at
- http://www.linuxdoc.org/docs.html#howto . Also make sure to say Y
- or M to "ISO 9660 CDROM file system support" later.
+ If you want to use a SCSI CD-ROM under Linux, say Y and read the
+ SCSI-HOWTO and the CD-ROM-HOWTO at
+ <http://www.linuxdoc.org/docs.html#howto>. Also make sure to say Y
+ or M to "ISO 9660 CD-ROM file system support" later.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called sr_mod.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt and
- Documentation/scsi.txt .
+ module, say M here and read <file:Documentation/modules.txt> and
+ <file:Documentation/scsi.txt>.
X
-Extra SCSI CDROMs
+Maximum number of CD-ROM devices that can be loaded as modules
X CONFIG_SR_EXTRA_DEVS
X This controls the amount of additional space allocated in tables for
X drivers that are loaded as modules after the kernel is booted. In
X the event that the SCSI core itself was loaded as a module, this
- value is the number of additional CDROMs that can be loaded after
+ value is the number of additional CD-ROMs that can be loaded after
X the first host driver is loaded.
X
X Admittedly this isn't pretty, but there are tons of race conditions
@@ -5693,7 +6613,7 @@
X
X If you don't understand what's going on, go with the default.
X
-Enable vendor-specific extensions (for SCSI CDROM)
+Enable vendor-specific extensions (for SCSI CD-ROM)
X CONFIG_BLK_DEV_SR_VENDOR
X This enables the usage of vendor specific SCSI commands. This is
X required to support multisession CDs with old NEC/TOSHIBA cdrom
@@ -5704,27 +6624,27 @@
X CONFIG_CHR_DEV_SG
X If you want to use SCSI scanners, synthesizers or CD-writers or just
X about anything having "SCSI" in its name other than hard disks,
- CDROMs or tapes, say Y here. These won't be supported by the kernel
+ CD-ROMs or tapes, say Y here. These won't be supported by the kernel
X directly, so you need some additional software which knows how to
X talk to these devices using the SCSI protocol:
X
- For scanners, look at SANE (http://www.mostang.com/sane). For CD
+ For scanners, look at SANE (<http://www.mostang.com/sane>). For CD
X writer software look at cdrecord
- (http://www.fokus.gmd.de/research/cc/glone/employees/joerg.schilling/private/cdrecord.html)
+ (<http://www.fokus.gmd.de/research/cc/glone/employees/joerg.schilling/private/cdrecord.html>)
X and for burning a "disk at once": cdrdao
- (http://www.ping.de/sites/daneb/cdrdao.html). Cdparanoia is a high
- quality digital reader of audio CDs (http://www.xiph.org/paranoia).
+ (<http://www.ping.de/sites/daneb/cdrdao.html>). Cdparanoia is a high
+ quality digital reader of audio CDs (<http://www.xiph.org/paranoia>).
X For other devices, it's possible that you'll have to write the
X driver software yourself. Please read the file
- Documentation/scsi-generic.txt for more information.
+ <file:Documentation/scsi-generic.txt> for more information.
X
X If you want to compile this as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt and
- Documentation/scsi.txt. The module will be called sg.o. If unsure,
+ say M here and read <file:Documentation/modules.txt> and
+ <file:Documentation/scsi.txt>. The module will be called sg.o. If unsure,
X say N.
X
-Debug new queueing code for SCSI
+Enable extra checks in SCSI queueing code
X CONFIG_SCSI_DEBUG_QUEUES
X This option turns on a lot of additional consistency checking for
X the new queueing code. This will adversely affect performance, but
@@ -5732,14 +6652,14 @@
X This will typically cause the kernel to panic if an error is
X detected, but it would have probably crashed if the panic weren't
X there. Comments/questions/problems to linux-scsi mailing list
- please. See http://www.andante.org/scsi_queue.html for more
+ please. See <http://www.andante.org/scsi_queue.html> for more
X up-to-date information.
X
X Probe all LUNs on each SCSI device
X CONFIG_SCSI_MULTI_LUN
X If you have a SCSI device that supports more than one LUN (Logical
X Unit Number), e.g. a CD jukebox, and only one LUN is detected, you
- can say Y here to force the SCSI driver to probe for multiple LUNs.
+ can say Y here to force the SCSI driver to probe for multiple LUNs.
X A SCSI device with multiple LUNs acts logically like multiple SCSI
X devices. The vast majority of SCSI devices have only one LUN, and
X so most people can say N here and should in fact do so, because it
@@ -5754,7 +6674,7 @@
X SCSI logging facility
X CONFIG_SCSI_LOGGING
X This turns on a logging facility that can be used to debug a number
- of SCSI related problems.
+ of SCSI related problems.
X
X If you say Y here, no logging output will appear by default, but you
X can enable logging by saying Y to "/proc file system support" and
@@ -5765,25 +6685,37 @@
X at boot time after the /proc file system has been mounted.
X
X There are a number of things that can be used for 'token' (you can
- find them in the source: drivers/scsi/scsi.c), and this allows you
- to select the types of information you want, and the level allows
- you to select the level of verbosity.
+ find them in the source: <file:drivers/scsi/scsi.c>), and this
+ allows you to select the types of information you want, and the
+ level allows you to select the level of verbosity.
X
X If you say N here, it may be harder to track down some types of SCSI
X problems. If you say Y here your kernel will be somewhat larger, but
X there should be no noticeable performance impact as long as you have
X logging turned off.
X
+SGI WD93C93 SCSI Driver
+CONFIG_SCSI_SGIWD93
+ Say Y here to support the on-board WD93C93 SCSI controller found (a)
+ on the Indigo2 and other MIPS-based SGI machines, and (b) on ARCS
+ ARM-based machines.
+
+DEC NCR53C94 SCSI Driver
+CONFIG_SCSI_DECNCR
+ Say Y here to support the NCR53C94 SCSI controller chips on IOASIC
+ based TURBOchannel DECstations and TURBOchannel PMAZ-A cards.
+
X AdvanSys SCSI support
X CONFIG_SCSI_ADVANSYS
X This is a driver for all SCSI host adapters manufactured by
X AdvanSys. It is documented in the kernel source in
- drivers/scsi/advansys.c.
+ <file:drivers/scsi/advansys.c>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. The module will be called advansys.o.


+ <file:Documentation/modules.txt>. The module will be called

+ advansys.o.
X
X Adaptec AHA152X/2825 support
X CONFIG_SCSI_AHA152X
@@ -5792,49 +6724,61 @@
X must be manually specified in this case.
X
X It is explained in section 3.3 of the SCSI-HOWTO, available from


- http://www.linuxdoc.org/docs.html#howto . You might also want to

- read the file drivers/scsi/README.aha152x.


+ <http://www.linuxdoc.org/docs.html#howto>. You might also want to

+ read the file <file:drivers/scsi/README.aha152x>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called aha152x.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X

X Adaptec AHA1542 support
X CONFIG_SCSI_AHA1542
- This is support for a SCSI host adapter. It is explained in section
+ This is support for a SCSI host adapter. It is explained in section
X 3.4 of the SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . Note that Trantor was
+ <http://www.linuxdoc.org/docs.html#howto>. Note that Trantor was
X purchased by Adaptec, and some former Trantor products are being
- sold under the Adaptec name. If it doesn't work out of the box, you
- may have to change some settings in drivers/scsi/aha1542.h.
-
+ sold under the Adaptec name. If it doesn't work out of the box, you
+ may have to change some settings in <file:drivers/scsi/aha1542.h>.
+
X If you want to compile this as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called aha1542.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called aha1542.o.
X
X Adaptec AHA1740 support
X CONFIG_SCSI_AHA1740
- This is support for a SCSI host adapter. It is explained in section
+ This is support for a SCSI host adapter. It is explained in section
X 3.5 of the SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . If it doesn't work out
+ <http://www.linuxdoc.org/docs.html#howto>. If it doesn't work out
X of the box, you may have to change some settings in
- drivers/scsi/aha1740.h.
+ <file:drivers/scsi/aha1740.h>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called aha1740.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.

+ The module will be called aha1740.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.

X
-Adaptec AIC7xxx chipset SCSI controller support
+Adaptec AIC7xxx support
X CONFIG_SCSI_AIC7XXX
- This driver supports all of Adaptec's PCI based SCSI controllers (not
- the hardware RAID controllers though) as well as the aic7770 based
- EISA and VLB SCSI controllers (the 274x and 284x series). This is
- an Adaptec sponsored driver written by Justin Gibbs. It is intended
- to replace the previous aic7xxx driver maintained by Doug Ledford since
- Doug is no longer maintaining that driver.
+ This driver supports all of Adaptec's PCI based SCSI controllers
+ (not the hardware RAID controllers though) as well as the aic7770
+ based EISA and VLB SCSI controllers (the 274x and 284x series).
+ This is an Adaptec sponsored driver written by Justin Gibbs. It is
+ intended to replace the previous aic7xxx driver maintained by Doug
+ Ledford since Doug is no longer maintaining that driver.
+
+Adaptec I2O RAID controllers
+CONFIG_SCSI_DPT_I2O
+ This driver supports all of Adaptec's I2O based RAID controllers as
+ well as the DPT SmartRaid V cards. This is an Adaptec maintained
+ driver by Deanna Bonds. See <file:drivers/scsi/README.dpti>.


+
+ This driver is also available 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


+ <file:Documentation/modules.txt>. The module will be called

+ dpt_i2o.o.
X
X Default number of TCQ commands per device
X CONFIG_AIC7XXX_CMDS_PER_DEVICE
@@ -5852,21 +6796,31 @@
X
X Default: 253
X
-Initial Bus Reset Settle Delay
+Delay in seconds after SCSI bus reset
X CONFIG_AIC7XXX_RESET_DELAY_MS
X The number of milliseconds to delay after an initial bus reset.
X The bus settle delay following all error recovery actions is
X dictated by the SCSI layer and is not affected by this value.
X
- Default: 5000 (5 seconds)
+ Default: 15000 (15 seconds)
X
-Old Adaptec AIC7xxx chipset SCSI controller support
+Build Adapter Firmware with Kernel Build
+CONFIG_AIC7XXX_BUILD_FIRMWARE
+ This option should only be enabled if you are modifying the firmware
+ source to the aic7xxx driver and wish to have the generated firmware
+ include files updated during a normal kernel build. The assembler
+ for the firmware requires lex and yacc or their equivalents, as well
+ as the db v1 library. You may have to install additional packages
+ or modify the assembler make file or the files it includes if your
+ build environment is different than that of the author.
+
+Old Adaptec AIC7xxx support
X CONFIG_SCSI_AIC7XXX_OLD
- WARNING This driver is an older aic7xxx driver and is no longer under
- active development. Adaptec, Inc. is writing a new driver to take the
- place of this one, and it is recommended that whenever possible, people
- should use the new Adaptec written driver instead of this one. This
- driver will eventually be phased out entirely.
+ WARNING This driver is an older aic7xxx driver and is no longer
+ under active development. Adaptec, Inc. is writing a new driver to
+ take the place of this one, and it is recommended that whenever
+ possible, people should use the new Adaptec written driver instead
+ of this one. This driver will eventually be phased out entirely.
X
X This is support for the various aic7xxx based Adaptec SCSI
X controllers. These include the 274x EISA cards; 284x VLB cards;
@@ -5889,47 +6843,47 @@
X
X Information on the configuration options for this controller can be
X found by checking the help file for each of the available
- configuration options. You should read drivers/scsi/aic7xxx_old/README.aic7xxx
- at a minimum before contacting the maintainer with any questions.
- The SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto , can also be of great
- help.
+ configuration options. You should read
+ <file:drivers/scsi/aic7xxx_old/README.aic7xxx> at a minimum before
+ contacting the maintainer with any questions. The SCSI-HOWTO,
+ available from <http://www.linuxdoc.org/docs.html#howto>, can also
+ be of great help.


X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called aic7xxx_old.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called aic7xxx_old.o.
X
-Enable or Disable Tagged Command Queueing by default


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

echo 'End of part 005'
echo 'File patch-2.4.15 is continued in part 006'
echo "006" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:43 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part007

#!/bin/sh -x
# this is part 007 of a 115 - part archive


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

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

-
-OnSpec 90c26 adapter
-CONFIG_PPSCSI_ONSCSI
- This option enables support for the OnSpec 90c26 in its SCSI adapter
- mode. If you build this as a module it will be called onscsi.o.
-
-Shining SparSCI adapter
-CONFIG_PPSCSI_SPARCSI
- This option enables support for the WBS-11A parallel port SCSI
- adapter. This adapter has been marketed by LinkSys as the
- "ParaSCSI+" and by Shining Technologies as the "SparCSI". If you
- build this as a module it will be called sparcsi.o.
-
-Shuttle EPSA-2 adapter
-CONFIG_PPSCSI_EPSA2
- This option enables support for the Shuttle Technologies EPSA2
- parallel port SCSI adapter. EPAS2 is a predecessor to the EPST. If
- you build this as a module it will be called epsa2.o.
-
-Shuttle EPST adapter
-CONFIG_PPSCSI_EPST
- This option enables support for the Shuttle Technologies EPST
- parallel port SCSI adapter. If you build this as a module is will
- be called epst.o.
-
-SCSI Debug host simulator. (EXPERIMENTAL)
+SCSI debugging host simulator
X CONFIG_SCSI_DEBUG
X This is a host adapter simulator that can be programmed to simulate
X a large number of conditions that could occur on a real bus. The
@@ -6950,7 +7934,7 @@
X important data. This is primarily of use to people trying to debug
X the middle and upper layers of the SCSI subsystem. If unsure, say N.
X
-Fibre Channel support and FC4 SCSI support
+Fibre Channel and FC4 SCSI support
X CONFIG_FC4
X Fibre Channel is a high speed serial protocol mainly used to
X connect large storage devices to the computer; it is compatible with
@@ -6966,7 +7950,7 @@


X
X If unsure, say N.
X

-Sun SOC
+Sun SOC/Sbus
X CONFIG_FC4_SOC
X Serial Optical Channel is an interface card with one or two Fibre
X Optic ports, each of which can be connected to a disk array. Note
@@ -6976,7 +7960,7 @@
X This support is also available as a module called soc.o ( = code
X which can be inserted in and removed from the running kernel
X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X
X Sun SOC+ (aka SOCAL)
X CONFIG_FC4_SOCAL
@@ -6989,16 +7973,16 @@
X This support is also available as a module called socal.o ( = code
X which can be inserted in and removed from the running kernel
X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X
X SparcSTORAGE Array 100 and 200 series
X CONFIG_SCSI_PLUTO
- If you never bought a disk array made by Sun, go with N.
+ If you never bought a disk array made by Sun, go with N.
X
X This support is also available as a module called pluto.o ( = code
X which can be inserted in and removed from the running kernel
X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X
X Sun Enterprise Network Array (A5000 and EX500)
X CONFIG_SCSI_FCAL
@@ -7010,14 +7994,14 @@
X This support is also available as a module called fcal.o ( = code
X which can be inserted in and removed from the running kernel
X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt. If unsure, say N.
+ here and read <file:Documentation/modules.txt>. If unsure, say N.
X
-AcornSCSI support
+Acorn SCSI card (aka30) support
X CONFIG_SCSI_ACORNSCSI_3
X This enables support for the Acorn SCSI card (aka30). If you have an
X Acorn system with one of these, say Y. If unsure, say N.
X
-Acorn SCSI tagged queue support
+Support SCSI 2 Tagged queueing
X CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
X Say Y here to enable tagged queuing support on the Acorn SCSI card.
X
@@ -7026,7 +8010,7 @@
X previous commands haven't finished yet. Some SCSI devices don't
X implement this properly, so the safe answer is N.
X
-Acorn SCSI Synchronous transfers support
+Support SCSI 2 Synchronous Transfers
X CONFIG_SCSI_ACORNSCSI_SYNC
X Say Y here to enable synchronous transfer negotiation with all
X targets on the Acorn SCSI card.
@@ -7034,6 +8018,16 @@
X In general, this improves performance; however some SCSI devices
X don't implement it properly, so the safe answer is N.
X
+ARXE SCSI support
+CONFIG_SCSI_ARXESCSI
+ Around 1991, Arxe Systems Limited released a high density floppy
+ disc interface for the Acorn Archimedes range, to allow the use of
+ HD discs from the then new A5000 on earlier models. This interface
+ was either sold on its own or with an integral SCSI controller.
+ Technical details on this NCR53c94-based device are available at
+ <http://www.cryton.demon.co.uk/acornbits/scsi_arxe.html>
+ Say Y here to compile in support for the SCSI controller.
+
X Oak SCSI support
X CONFIG_SCSI_OAK1
X This enables support for the Oak SCSI card. If you have an Acorn
@@ -7044,7 +8038,7 @@
X This enables support for the Cumana SCSI I card. If you have an
X Acorn system with one of these, say Y. If unsure, say N.
X
-Cumana SCSI II support (EXPERIMENTAL)
+Cumana SCSI II support
X CONFIG_SCSI_CUMANA_2
X This enables support for the Cumana SCSI II card. If you have an
X Acorn system with one of these, say Y. If unsure, say N.
@@ -7055,17 +8049,17 @@
X in the Econet socket. If you have an Acorn system with one of these,
X say Y. If unsure, say N.
X
-EESOX SCSI support (EXPERIMENTAL)
+EESOX SCSI support
X CONFIG_SCSI_EESOXSCSI
X This enables support for the EESOX SCSI card. If you have an Acorn
X system with one of these, say Y, otherwise say N.
X
-Powertec SCSI support (EXPERIMENTAL)
+PowerTec SCSI support
X CONFIG_SCSI_POWERTECSCSI
X This enables support for the Powertec SCSI card on Acorn systems. If
X you have one of these, say Y. If unsure, say N.
X
-IEEE 1394 (aka FireWire) support
+IEEE 1394 (FireWire) support
X CONFIG_IEEE1394
X IEEE 1394 describes a high performance serial bus, which is also
X known as FireWire(tm) or i.Link(tm) and is used for connecting all
@@ -7078,10 +8072,10 @@


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt. The module will be

- called ieee1394.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called ieee1394.o.
X
-TI PCILynx IEEE 1394 support
+Texas Instruments PCILynx support
X CONFIG_IEEE1394_PCILYNX
X Say Y here if you have an IEEE-1394 controller with the Texas
X Instruments PCILynx chip. Note: this driver is written for revision
@@ -7089,8 +8083,8 @@


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt. The module will be

- called pcilynx.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called pcilynx.o.
X
X Use local RAM on PCILynx board
X CONFIG_IEEE1394_PCILYNX_LOCALRAM
@@ -7100,7 +8094,7 @@
X computer's motherboard. Local RAM may speed up command processing
X because no PCI transfers are necessary during use of the Packet
X Control Lists.
-
+
X Note that there are no known PCILynx systems providing local RAM
X except for the evaluation boards by Texas Instruments and that the
X PCILynx does not reliably report missing RAM. This means that it is
@@ -7114,32 +8108,43 @@
X This option enables driver code to access the RAM, ROM and AUX ports
X of the PCILynx through character devices in /dev. If you don't know
X what this is about then you won't need it.
-
+


X If unsure, say N.
X

+#Adaptec AIC-5800 IEEE 1394 support
+#CONFIG_IEEE1394_AIC5800
+# Say Y here if you have a IEEE 1394 controller using the Adaptec
+# AIC-5800 chip. All Adaptec host adapters (89xx series) use this
+# chip, as well as miro's DV boards.
+#
+# If you want to compile this as a module ( = code which can be
+# inserted in and removed from the running kernel whenever you want),
+# say M here and read <file:Documentation/modules.txt>. The module
+# will be called aic5800.o.
+#
X OHCI-1394 support
X CONFIG_IEEE1394_OHCI1394
X Enable this driver if you have an IEEE 1394 controller based on the
X OHCI-1394 specification. The current driver is only tested with OHCI
X chipsets made by Texas Instruments and NEC. Most third-party vendors
- use one of these chipsets. It should work with any OHCI-1394 compliant
- card, however.
+ use one of these chipsets. It should work with any OHCI-1394
+ compliant card, however.


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called ohci1394.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called ohci1394.o.
X
X OHCI-1394 Video support
X CONFIG_IEEE1394_VIDEO1394
- This option enables video device usage for OHCI-1394 cards. Enable this
- option only if you have an IEEE 1394 video device connected to an
- OHCI-1394 card.
+ This option enables video device usage for OHCI-1394 cards. Enable
+ this option only if you have an IEEE 1394 video device connected to
+ an OHCI-1394 card.
X
X SBP-2 support (Harddisks etc.)
X CONFIG_IEEE1394_SBP2
- This option enables you to use SBP-2 devices connected to your IEEE 1394
- bus. SBP-2 devices include harddrives and DVD devices.
+ This option enables you to use SBP-2 devices connected to your IEEE
+ 1394 bus. SBP-2 devices include harddrives and DVD devices.
X
X Raw IEEE 1394 I/O support
X CONFIG_IEEE1394_RAWIO
@@ -7150,8 +8155,8 @@


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt. The module will be

- called raw1394.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called raw1394.o.
X
X Excessive debugging output
X CONFIG_IEEE1394_VERBOSEDEBUG
@@ -7164,18 +8169,18 @@
X Say Y if you really want or need the debugging output, everyone else
X says N.
X
-Network device support?
+Network device support
X CONFIG_NETDEVICES
X You can say N here if you don't intend to connect your Linux box to
X any other computer at all or if all your connections will be over a
X telephone line with a modem either via UUCP (UUCP is a protocol to
X forward mail and news between unix hosts over telephone lines; read
X the UUCP-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto ) or dialing up a shell
+ <http://www.linuxdoc.org/docs.html#howto>) or dialing up a shell
X account or a BBS, even using term (term is a program which gives you
X almost full Internet connectivity if you have a regular dial up
X shell account on some Internet connected Unix computer. Read
- http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html ).
+ <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>).
X
X You'll have to say Y if your computer contains a network card that
X you want to use under Linux (make sure you know its name because you
@@ -7191,7 +8196,7 @@
X
X Make sure to read the NET-3-HOWTO. Eventually, you will have to read
X Olaf Kirch's excellent and free book "Network Administrator's
- Guide", to be found in http://www.linuxdoc.org/docs.html#guide . If
+ Guide", to be found in <http://www.linuxdoc.org/docs.html#guide>. If
X unsure, say Y.
X
X Dummy net driver support
@@ -7204,14 +8209,15 @@
X thing often comes in handy, the default is Y. It won't enlarge your
X kernel either. What a deal. Read about it in the Network
X Administrator's Guide, available from
- http://www.linuxdoc.org/docs.html#guide .
+ <http://www.linuxdoc.org/docs.html#guide>.
X

X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called dummy.o. If you want to use more than one dummy device at a
- time, you need to compile this driver as a module. Instead of
- 'dummy', the devices will then be called 'dummy0', 'dummy1' etc.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called dummy.o. If you want to use more than one dummy
+ device at a time, you need to compile this driver as a module.
+ Instead of 'dummy', the devices will then be called 'dummy0',
+ 'dummy1' etc.
X
X Bonding driver support
X CONFIG_BONDING
@@ -7219,7 +8225,7 @@
X Channels together. This is called 'Etherchannel' by Cisco,
X 'Trunking' by Sun, and 'Bonding' in Linux.
X
- If you have two ethernet connections to some other computer, you can
+ If you have two Ethernet connections to some other computer, you can
X make them behave like one double speed connection using this driver.
X Naturally, this has to be supported at the other end as well, either
X with a similar Bonding Linux driver, a Cisco 5500 switch or a
@@ -7230,8 +8236,8 @@


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt. The module will be

- called bonding.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called bonding.o.
X
X SLIP (serial line) support
X CONFIG_SLIP
@@ -7247,23 +8253,23 @@
X Normally, your access provider has to support SLIP in order for you
X to be able to use it, but there is now a SLIP emulator called SLiRP
X around (available via FTP (user: anonymous) from
- ftp://metalab.unc.edu/pub/Linux/system/network/serial/ ) which
+ <ftp://metalab.unc.edu/pub/Linux/system/network/serial/>) which
X allows you to use SLIP over a regular dial up shell connection. If
X you plan to use SLiRP, make sure to say Y to CSLIP, below. The
X NET-3-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto , explains how to
+ <http://www.linuxdoc.org/docs.html#howto>, explains how to
X configure SLIP. Note that you don't need this option if you just
X want to run term (term is a program which gives you almost full
X Internet connectivity if you have a regular dial up shell account on
X some Internet connected Unix computer. Read
- http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html ). SLIP
+ <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>). SLIP
X support will enlarge your kernel by about 4 KB. If unsure, say N.
X

X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt as well as
- Documentation/networking/net-modules.txt. The module will be called
- slip.o.
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called slip.o.
X
X CSLIP compressed headers
X CONFIG_SLIP_COMPRESSED
@@ -7272,10 +8278,10 @@
X on both ends. Ask your access provider if you are not sure and
X answer Y, just in case. You will still be able to use plain SLIP. If
X you plan to use SLiRP, the SLIP emulator (available from
- ftp://metalab.unc.edu/pub/Linux/system/network/serial/ ) which
+ <ftp://metalab.unc.edu/pub/Linux/system/network/serial/>) which
X allows you to use SLIP over a regular dial up shell connection, you
X definitely want to say Y here. The NET-3-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto , explains how to configure
+ <http://www.linuxdoc.org/docs.html#howto>, explains how to configure
X CSLIP. This won't enlarge your kernel.
X
X Keepalive and linefill
@@ -7296,24 +8302,24 @@
X
X PPP (point-to-point protocol) support
X CONFIG_PPP
- PPP (Point to Point Protocol) is a newer and better SLIP. It serves
+ PPP (Point to Point Protocol) is a newer and better SLIP. It serves
X the same purpose: sending Internet traffic over telephone (and other
- serial) lines. Ask your access provider if they support it, because
- otherwise you can't use it; most internet access providers these
+ serial) lines. Ask your access provider if they support it, because
+ otherwise you can't use it; most Internet access providers these
X days support PPP rather than SLIP.
X
X To use PPP, you need an additional program called pppd as described
- in Documentation/networking/ppp.txt and in the PPP-HOWTO, available
- at http://www.linuxdoc.org/docs.html#howto . If you upgrade
- from an older kernel, you might need to upgrade pppd as well. The
- PPP option enlarges your kernel by about 16 KB.
+ in the PPP-HOWTO, available at
+ <http://www.linuxdoc.org/docs.html#howto>. Make sure that you have
+ the version of pppd recommended in <file:Documentation/Changes>.
+ The PPP option enlarges your kernel by about 16 KB.
X
X There are actually two versions of PPP: the traditional PPP for
X asynchronous lines, such as regular analog phone lines, and
X synchronous PPP which can be used over digital ISDN lines for
- example. If you want to use PPP over phone lines or other
+ example. If you want to use PPP over phone lines or other
X asynchronous serial lines, you need to say Y (or M) here and also to
- the next option, "PPP support for async serial ports". For PPP over
+ the next option, "PPP support for async serial ports". For PPP over
X synchronous lines, you should say Y (or M) here and to "Support
X synchronous PPP", below.
X
@@ -7321,12 +8327,12 @@


X inserted in and removed from the running kernel whenever you want).

X If you said Y to "Version information on all symbols" above, then
X you cannot compile the PPP driver into the kernel; you can then only
- compile it as a module. The module will be called ppp_generic.o. 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.
+ compile it as a module. The module will be called ppp_generic.o.


+ If you want to compile it as a module, say M here and read

+ <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>.
X
-PPP multilink support (EXPERIMENTAL)
+PPP multilink support
X CONFIG_PPP_MULTILINK
X PPP multilink is a protocol (defined in RFC 1990) which allows you
X to combine several (logical or physical) lines into one logical PPP
@@ -7337,7 +8343,7 @@


X
X If unsure, say N.
X

-PPP filtering (EXPERIMENTAL)
+PPP filtering
X CONFIG_PPP_FILTER
X Say Y here if you want to be able to filter the packets passing over
X PPP interfaces. This allows you to control which packets count as
@@ -7357,7 +8363,7 @@
X
X This code is also available as a module (code which can be inserted
X into and removed from the running kernel). If you want to compile


- it as a module, say M here and read Documentation/modules.txt.

+ it as a module, say M here and read <file:Documentation/modules.txt>.
X

X If unsure, say Y.
X

@@ -7369,20 +8375,22 @@
X
X This code is also available as a module (code which can be inserted
X into and removed from the running kernel). If you want to compile


- it as a module, say M here and read Documentation/modules.txt.

+ it as a module, say M here and read
+ <file:Documentation/modules.txt>.

X
X PPP Deflate compression
X CONFIG_PPP_DEFLATE
X Support for the Deflate compression method for PPP, which uses the
X Deflate algorithm (the same algorithm that gzip uses) to compress
- each PPP packet before it is sent over the wire. The machine at the
+ each PPP packet before it is sent over the wire. The machine at the
X other end of the PPP link (usually your ISP) has to support the
- Deflate compression method as well for this to be useful. Even if
+ Deflate compression method as well for this to be useful. Even if
X they don't support it, it is safe to say Y here.
X
X This code is also available as a module (code which can be inserted
X into and removed from the running kernel). If you want to compile


- it as a module, say M here and read Documentation/modules.txt.

+ it as a module, say M here and read
+ <file:Documentation/modules.txt>.

X
X PPP BSD-Compress compression
X CONFIG_PPP_BSDCOMP
@@ -7401,14 +8409,14 @@
X module; it is called bsd_comp.o and will show up in the directory
X modules once you have said "make modules". If unsure, say N.
X
-PPP over Ethernet (EXPERIMENTAL)
+PPP over Ethernet
X CONFIG_PPPOE
X Support for PPP over Ethernet.
X
X This driver requires a specially patched pppd daemon. The patch to
X pppd, along with binaries of a patched pppd package can be found at:
- http://www.shoshin.uwaterloo.ca/~mostrows
-
+ <http://www.shoshin.uwaterloo.ca/~mostrows>.
+
X Wireless LAN (non-hamradio)
X CONFIG_NET_RADIO
X Support for wireless LANs and everything having to do with radio,
@@ -7425,18 +8433,18 @@
X driver (or Linux). If you wish to use Wireless Extensions with
X wireless PCMCIA (PC-) cards, you need to say Y here; you can fetch
X the tools from
- http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html .
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
X
X Some user-level drivers for scarab devices which don't require
X special kernel support are available from
- ftp://shadow.cabi.net/pub/Linux .
+ <ftp://shadow.cabi.net/pub/Linux>.
X
X STRIP (Metricom Starmode radio IP)
X CONFIG_STRIP
X Say Y if you have a Metricom radio and intend to use Starmode Radio
X IP. STRIP is a radio protocol developed for the MosquitoNet project
- (on the WWW at http://mosquitonet.stanford.edu/ ) to send Internet
- traffic using Metricom radios. Metricom radios are small, battery
+ (on the WWW at <http://mosquitonet.stanford.edu/>) to send Internet
+ traffic using Metricom radios. Metricom radios are small, battery
X powered, 100kbit/sec packet radio transceivers, about the size and
X weight of a cellular telephone. (You may also have heard them called
X "Metricom modems" but we avoid the term "modem" because it misleads
@@ -7447,50 +8455,51 @@
X it is obviously most useful for people with laptop computers. If you
X think you might get a Metricom radio in the future, there is no harm
X in saying Y to STRIP now, except that it makes the kernel a bit
- bigger.
+ bigger.
X
X You can also compile this as a module ( = code which can be inserted
X in and removed from the running kernel whenever you want), say M
- here and read Documentation/modules.txt. The module will be called
- strip.o.
+ here and read <file:Documentation/modules.txt>. The module will be
+ called strip.o.
X
X AT&T WaveLAN & DEC RoamAbout DS support
X CONFIG_WAVELAN
X The Lucent WaveLAN (formerly NCR and AT&T; or DEC RoamAbout DS) is
X a Radio LAN (wireless Ethernet-like Local Area Network) using the
X radio frequencies 900 MHz and 2.4 GHz.
-
- This driver support the ISA version of the WaveLAN card. A separate
+
+ This driver support the ISA version of the WaveLAN card. A separate
X driver for the PCMCIA (PC-card) hardware is available in David
- Hinds' pcmcia-cs package (see the file Documentation/Changes for
- location).
+ Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
+ for location).
X
X If you want to use an ISA WaveLAN card under Linux, say Y and read
X the Ethernet-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . Some more specific
- information is contained in Documentation/networking/wavelan.txt and
- in the source code drivers/net/wavelan.p.h.
+ <http://www.linuxdoc.org/docs.html#howto>. Some more specific


+ information is contained in

+ <file:Documentation/networking/wavelan.txt> and in the source code
+ <file:drivers/net/wavelan.p.h>.
X
X You will also need the wireless tools package available from
- http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html .
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
X Please read the man pages contained therein.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called wavelan.o. 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.
+ The module will be called wavelan.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
X
X Aironet Arlan 655 & IC2200 DS support
X CONFIG_ARLAN
X Aironet makes Arlan, a class of wireless LAN adapters. These use the
X www.Telxon.com chip, which is also used on several similar cards.
X This driver is tested on the 655 and IC2200 series cards. Look at
- http://www.ylenurme.ee/~elmer/655/ for the latest information.
-
+ <http://www.ylenurme.ee/~elmer/655/> for the latest information.
+
X The driver is built as two modules, arlan and arlan-proc. The latter
X is the /proc interface and is not needed most of time.
-
+
X On some computers the card ends up in non-valid state after some
X time. Use a ping-reset script to clear it.
X
@@ -7499,27 +8508,27 @@
X www.aironet.com (recently bought by Cisco) makes these 802.11 DS
X adapters. Driver by Elmer Joandi (el...@ylenurme.ee).
X
- Say Y here if you have such an adapter, and then say Y below to
- the option that applies to your particular type of card (PCI, ISA,
+ Say Y here if you have such an adapter, and then say Y below to
+ the option that applies to your particular type of card (PCI, ISA,
X or PCMCIA).


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called aironet4500_core.o. 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.
+ The module will be called aironet4500_core.o. If you want to
+ compile it as a module, say M here and read
+ <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>.
X
- quick config parameters:
+ quick config parameters:
X SSID=tsunami - "The Password"
X adhoc=1 there are no Access Points around
- master=1 Adhoc master (the one who creates network
+ master=1 Adhoc master (the one who creates network
X sync)
- slave=1 Adhoc slave (btw, it is still forming own net
+ slave=1 Adhoc slave (btw, it is still forming own net
X sometimes, and has problems with firmware...
X change IbssJoinNetTimeout from /proc...)
X channel=1..? meaningful in adhoc mode
-
+
X If you have problems with screwing up card, both_bap_lock=1 is a
X conservative value (performance hit 15%).
X
@@ -7527,107 +8536,107 @@
X
X Aironet 4500/4800 ISA/PCI/PNP/365 support
X CONFIG_AIRONET4500_NONCS
- If you have an ISA, PCI or PCMCIA Aironet 4500/4800 wireless LAN
- card, say Y here, and then also to the options below that apply
+ If you have an ISA, PCI or PCMCIA Aironet 4500/4800 wireless LAN
+ card, say Y here, and then also to the options below that apply
X to you.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called aironet4500_card.o. If you want to
- compile it as a module, say M here and read
- Documentation/modules.txt
+ The module will be called aironet4500_card.o. If you want to
+ compile it as a module, say M here and read
+ <file:Documentation/modules.txt>.
X
X Aironet 4500/4800 PNP support
X CONFIG_AIRONET4500_PNP
- If you have an ISA Aironet 4500/4800 card which you want to use in
- PNP (Plug and Play) mode, say Y here. This is the recommended mode
- for ISA cards. Remember however to enable the PNP jumper on the
+ If you have an ISA Aironet 4500/4800 card which you want to use in
+ PnP (Plug and Play) mode, say Y here. This is the recommended mode
+ for ISA cards. Remember however to enable the PnP jumper on the
X board if you say Y here.
X
X Aironet 4500/4800 PCI support
X CONFIG_AIRONET4500_PCI
X If you have an PCI Aironet 4500/4800 card, say Y here.
X
-Aironet 4500/4800 ISA broken support (EXPERIMENTAL)
+Aironet 4500/4800 ISA broken support
X CONFIG_AIRONET4500_ISA
X If you have an ISA Aironet 4500/4800 card which you want to run in
- non-PNP mode, say Y here. This is not recommended and does not work
+ non-PnP mode, say Y here. This is not recommended and does not work
X correctly at this point. Say N.
X
-Aironet 4500/4800 I365 broken support (EXPERIMENTAL)
+Aironet 4500/4800 I365 broken support
X CONFIG_AIRONET4500_I365
- If you have a PCMCIA Aironet 4500/4800 card which you want to use
- without the standard PCMCIA cardservices provided by the pcmcia-cs
+ If you have a PCMCIA Aironet 4500/4800 card which you want to use
+ without the standard PCMCIA cardservices provided by the pcmcia-cs
X package, say Y here. This is not recommended, so say N.
X
X Aironet 4500/4800 PCMCIA support
X CONFIG_AIRONET4500_CS
- Say Y here if you have a PCMCIA Aironet 4500/4800 card which you
+ Say Y here if you have a PCMCIA Aironet 4500/4800 card which you
X want to use with the standard PCMCIA cardservices provided by the
X pcmcia-cs package.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called aironet4500_cs.o. If you want to
- compile it as a module, say M here and read
- Documentation/modules.txt.
-
+ The module will be called aironet4500_cs.o. If you want to
+ compile it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+
X Aironet 4500/4800 PROC interface
X CONFIG_AIRONET4500_PROC
- If you say Y here (and to the "/proc file system" below), you will
- be able to configure your Aironet card via the
+ If you say Y here (and to the "/proc file system" below), you will
+ be able to configure your Aironet card via the
X /proc/sys/aironet4500 interface.
X
- Additional info: look in drivers/net/aironet4500_rids.c.
+ Additional info: look in <file:drivers/net/aironet4500_rid.c>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called aironet4500_proc.o. If you want to
- compile it as a module, say M here and read
- Documentation/modules.txt.
+ The module will be called aironet4500_proc.o. If you want to
+ compile it as a module, say M here and read
+ <file:Documentation/modules.txt>.
X
X NOTE: the proc interface uses a lot of memory, so it is recommended
- to compile it as a module and remove the module after
+ to compile it as a module and remove the module after
X configuration.
X
X LAPB over Ethernet driver
X CONFIG_LAPBETHER
X This is a driver for a pseudo device (typically called /dev/lapb0)
X which allows you to open an LAPB point-to-point connection to some
- other computer on your Ethernet network. In order to do this, you
+ other computer on your Ethernet network. In order to do this, you
X need to say Y or M to the driver for your Ethernet card as well as
- to "LAPB Data Link Driver".
+ to "LAPB Data Link Driver".


X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt. The module will be

- called lapbether.o. If unsure, say N.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called lapbether.o. If unsure, say N.
X
X X.25 async driver
X CONFIG_X25_ASY
X This is a driver for sending and receiving X.25 frames over regular
X asynchronous serial lines such as telephone lines equipped with
- ordinary modems. Experts should note that this driver doesn't
+ ordinary modems. Experts should note that this driver doesn't
X currently comply with the asynchronous HDLS framing protocols in
- CCITT recommendation X.25.
+ CCITT recommendation X.25.


X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called x25_asy.o. If unsure, say N.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called x25_asy.o. If unsure, say N.
X
X PCMCIA network device support
X CONFIG_NET_PCMCIA
X Say Y if you would like to include support for any PCMCIA or CardBus
X network adapters, then say Y to the driver for your particular card
- below. PCMCIA- or PC-cards are credit-card size devices often used
+ below. PCMCIA- or PC-cards are credit-card size devices often used
X with laptops computers; CardBus is the newer and faster version of
- PCMCIA.
+ PCMCIA.
X
X To use your PC-cards, you will need supporting software from David
- Hinds' pcmcia-cs package (see the file Documentation/Changes for
- location). You also want to check out the PCMCIA-HOWTO, available
- from http://www.linuxdoc.org/docs.html#howto .
+ Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
+ for location). You also want to check out the PCMCIA-HOWTO,
+ available from <http://www.linuxdoc.org/docs.html#howto>.


X
X If unsure, say N.
X

@@ -7638,9 +8647,9 @@


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called 3c589_cs.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt. If unsure,
- say N.
+ The module will be called 3c589_cs.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
X
X 3Com 3c574 PCMCIA support
X CONFIG_PCMCIA_3C574
@@ -7649,9 +8658,9 @@


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called 3c574_cs.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt. If unsure,
- say N.
+ The module will be called 3c574_cs.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
X
X Fujitsu FMV-J18x PCMCIA support
X CONFIG_PCMCIA_FMVJ18X
@@ -7660,9 +8669,9 @@


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called fmvj18x_cs.o. If you want to compile it as


- a module, say M here and read Documentation/modules.txt. If unsure,
- say N.

+ The module will be called fmvj18x_cs.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.


+ If unsure, say N.
X

X NE2000 compatible PCMCIA support
X CONFIG_PCMCIA_PCNET
@@ -7671,9 +8680,9 @@


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called pcnet_cs.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt. If unsure,
- say N.
+ The module will be called pcnet_cs.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
X
X New Media PCMCIA support
X CONFIG_PCMCIA_NMCLAN
@@ -7682,9 +8691,9 @@


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called nmclan_cs.o. If you want to compile it as


- a module, say M here and read Documentation/modules.txt. If unsure,
- say N.

+ The module will be called nmclan_cs.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
X
X SMC 91Cxx PCMCIA support
X CONFIG_PCMCIA_SMC91C92
@@ -7693,20 +8702,20 @@


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called smc91c92_cs.o. If you want to compile it
- as a module, say M here and read Documentation/modules.txt. If
- unsure, say N.
+ The module will be called smc91c92_cs.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.


+ If unsure, say N.
X

X Xircom 16-bit PCMCIA support
X CONFIG_PCMCIA_XIRC2PS
- Say Y here if you intend to attach a Xircom 16-bit PCMCIA
- (PC-card) Ethernet or Fast Ethernet card to your computer.
+ Say Y here if you intend to attach a Xircom 16-bit PCMCIA (PC-card)
+ Ethernet or Fast Ethernet card to your computer.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called xirc2ps_cs.o. If you want to compile it as


- a module, say M here and read Documentation/modules.txt. If unsure,
- say N.

+ The module will be called xirc2ps_cs.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.


+ If unsure, say N.
X

X COM20020 ARCnet PCMCIA support
X CONFIG_ARCNET_COM20020_CS
@@ -7715,20 +8724,20 @@


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called com20020_cs.o. If you want to compile it
- as a module, say M here and read Documentation/modules.txt. If
- unsure, say N.
+ The module will be called com20020_cs.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.


+ If unsure, say N.
X

X IBM PCMCIA Token Ring adapter support
X CONFIG_PCMCIA_IBMTR
X Say Y here if you intend to attach this type of Token Ring PCMCIA
X card to your computer. You then also need to say Y to "Token Ring
- driver support".
+ driver support".


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called ibmtr_cs.o. If you want to compile it
- as a module, say M here and read Documentation/modules.txt.
+ The module will be called ibmtr_cs.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
X
X Xircom Tulip-like CardBus support
X CONFIG_PCMCIA_XIRTULIP
@@ -7739,20 +8748,20 @@


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called xircom_tulip_cb.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt. If
- unsure, say N.
+ The module will be called xircom_tulip_cb.o. If you want to compile


+ it as a module, say M here and read

+ <file:Documentation/modules.txt>. If unsure, say N.
X
-Pcmcia Wireless LAN
+PCMCIA Wireless LAN
X CONFIG_NET_PCMCIA_RADIO
X Say Y here if you would like to use a PCMCIA (PC-card) device to
X connect to a wireless local area network. Then say Y to the driver
X for your particular card below.
X
X To use your PC-cards, you will need supporting software from David
- Hinds' pcmcia-cs package (see the file Documentation/Changes for
- location). You also want to check out the PCMCIA-HOWTO, available
- from http://www.linuxdoc.org/docs.html#howto .
+ Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
+ for location). You also want to check out the PCMCIA-HOWTO,
+ available from <http://www.linuxdoc.org/docs.html#howto>.
X
X Hermes chipset 802.11b support (Orinoco/Prism2/Symbol cards)
X CONFIG_HERMES
@@ -7772,7 +8781,7 @@
X
X You will also very likely also need the Wireless Tools in order to
X configure your card and that /etc/pcmcia/wireless.opts works :
- http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>
X
X Apple Airport support (built-in)
X CONFIG_APPLE_AIRPORT
@@ -7796,24 +8805,24 @@
X CONFIG_PCMCIA_HERMES
X A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
X as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
- EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and others).
- It should also be usable on various Prism II based cards such as the
- Linksys, D-Link and Farallon Skyline. It should also work on Symbol
- cards such as the 3Com AirConnect and Ericsson WLAN.
+ EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and
+ others). It should also be usable on various Prism II based cards
+ such as the Linksys, D-Link and Farallon Skyline. It should also
+ work on Symbol cards such as the 3Com AirConnect and Ericsson WLAN.
X
X To use your PC-cards, you will need supporting software from David
- Hinds' pcmcia-cs package (see the file Documentation/Changes for
- location). You also want to check out the PCMCIA-HOWTO, available
- from http://www.linuxdoc.org/docs.html#howto .
+ Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
+ for location). You also want to check out the PCMCIA-HOWTO,
+ available from <http://www.linuxdoc.org/docs.html#howto>.
X
X You will also very likely also need the Wireless Tools in order to
- configure your card and that /etc/pcmcia/wireless.opts works :
- http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html
+ configure your card and that /etc/pcmcia/wireless.opts works:
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
X
X Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards
X CONFIG_AIRO
- This is the standard Linux driver to support Cisco/Aironet ISA
- and PCI 802.11 wireless cards.
+ This is the standard Linux driver to support Cisco/Aironet ISA and
+ PCI 802.11 wireless cards.
X It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
X - with or without encryption) as well as card before the Cisco
X aquisition (Aironet 4500, Aironet 4800, Aironet 4800B).
@@ -7827,7 +8836,7 @@
X Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards
X CONFIG_AIRO_CS
X This is the standard Linux driver to support Cisco/Aironet PCMCIA
- 802.11 wireless cards. This driver is the same as the Aironet
+ 802.11 wireless cards. This driver is the same as the Aironet
X driver part of the Linux Pcmcia package.
X It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
X - with or without encryption) as well as card before the Cisco
@@ -7840,22 +8849,28 @@
X Cisco Linux utilities can be used to configure the card.
X
X To use your PC-cards, you will need supporting software from David
- Hinds' pcmcia-cs package (see the file Documentation/Changes for
- location). You also want to check out the PCMCIA-HOWTO, available
- from http://www.linuxdoc.org/docs.html#howto .
+ Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
+ for location). You also want to check out the PCMCIA-HOWTO,
+ available from <http://www.linuxdoc.org/docs.html#howto>.
X
X Aviator/Raytheon 2.4MHz wireless support
X CONFIG_PCMCIA_RAYCS
X Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
X (PC-card) wireless Ethernet networking card to your computer.
- Please read the file Documentation/networking/ray_cs.txt for
+ Please read the file <file:Documentation/networking/ray_cs.txt> for
X details.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called ray_cs.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt. If unsure,
- say N.
+ The module will be called ray_cs.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. If


+ unsure, say N.
+

+Apple Airport support (built-in)
+CONFIG_APPLE_AIRPORT
+ Say Y here to support the Airport 802.11b wireless Ethernet hardware
+ built into the Macintosh iBook and other recent PowerPC-based
+ Macintosh machines.
X
X Xircom Netwave AirSurfer wireless support
X CONFIG_PCMCIA_NETWAVE
@@ -7864,9 +8879,9 @@


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called netwave_cs.o. If you want to compile it as


- a module, say M here and read Documentation/modules.txt. If unsure,
- say N.

+ The module will be called netwave_cs.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.


+ If unsure, say N.
X

X AT&T/Lucent Wavelan wireless support
X CONFIG_PCMCIA_WAVELAN
@@ -7876,44 +8891,45 @@


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called wavelan_cs.o. If you want to compile it as


- a module, say M here and read Documentation/modules.txt. If unsure,
- say N.

+ The module will be called wavelan_cs.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.


+ If unsure, say N.
X

X PLIP (parallel port) support
X CONFIG_PLIP
X PLIP (Parallel Line Internet Protocol) is used to create a
X reasonably fast mini network consisting of two (or, rarely, more)
- local machines. A PLIP link from a Linux box is a popular means to
- install a Linux distribution on a machine which doesn't have a CDROM
- drive (a minimal system has to be transferred with floppies first).
- The kernels on both machines need to have this PLIP option enabled
- for this to work.
-
- The PLIP driver has two modes, mode 0 and mode 1. The parallel ports
- (the connectors at the computers with 25 holes) are connected with
- "null printer" or "Turbo Laplink" cables which can transmit 4 bits
- at a time (mode 0) or with special PLIP cables, to be used on
+ local machines. A PLIP link from a Linux box is a popular means to
+ install a Linux distribution on a machine which doesn't have a
+ CD-ROM drive (a minimal system has to be transferred with floppies
+ first). The kernels on both machines need to have this PLIP option
+ enabled for this to work.
+
+ The PLIP driver has two modes, mode 0 and mode 1. The parallel
+ ports (the connectors at the computers with 25 holes) are connected
+ with "null printer" or "Turbo Laplink" cables which can transmit 4
+ bits at a time (mode 0) or with special PLIP cables, to be used on
X bidirectional parallel ports only, which can transmit 8 bits at a
X time (mode 1); you can find the wiring of these cables in
- Documentation/networking/PLIP.txt. The cables can be up to 15m long.
- Mode 0 works also if one of the machines runs DOS/Windows and has
- some PLIP software installed, e.g. the Crynwr PLIP packet driver
- (http://oak.oakland.edu/simtel.net/msdos/pktdrvr-pre.html ) and
- winsock or NCSA's telnet.
+ <file:Documentation/networking/PLIP.txt>. The cables can be up to
+ 15m long. Mode 0 works also if one of the machines runs DOS/Windows
+ and has some PLIP software installed, e.g. the Crynwr PLIP packet
+ driver (<http://oak.oakland.edu/simtel.net/msdos/pktdrvr-pre.html>)
+ and winsock or NCSA's telnet.
X
X If you want to use PLIP, say Y and read the PLIP mini-HOWTO as well
X as the NET-3-HOWTO, both available from
- http://www.linuxdoc.org/docs.html#howto . Note that the PLIP
+ <http://www.linuxdoc.org/docs.html#howto>. Note that the PLIP
X protocol has been changed and this PLIP driver won't work together
- with the PLIP support in Linux versions 1.0.x. This option enlarges
+ with the PLIP support in Linux versions 1.0.x. This option enlarges
X your kernel by about 8 KB.


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M here and read Documentation/modules.txt as well as
- Documentation/networking/net-modules.txt. The module will be called
- plip.o. If unsure, say Y or M, in case you buy a laptop later.
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called plip.o. If unsure, say Y or M, in case you buy a laptop
+ later.
X
X EQL (serial line load balancing) support
X CONFIG_EQUALIZER
@@ -7921,39 +8937,41 @@
X usually requires two modems and two telephone lines) and you use
X SLIP (the protocol for sending Internet traffic over telephone
X lines) or PPP (a better SLIP) on them, you can make them behave like
- one double speed connection using this driver. Naturally, this has
+ one double speed connection using this driver. Naturally, this has
X to be supported at the other end as well, either with a similar EQL
- Linux driver or with a Livingston Portmaster 2e.
+ Linux driver or with a Livingston Portmaster 2e.
X
- Say Y if you want this and read Documentation/networking/eql.txt.
- You may also want to read section 6.2 of the NET-3-HOWTO, available
- from http://www.linuxdoc.org/docs.html#howto .
+ Say Y if you want this and read
+ <file:Documentation/networking/eql.txt>. You may also want to read
+ section 6.2 of the NET-3-HOWTO, available from
+ <http://www.linuxdoc.org/docs.html#howto>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called eql.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt. If unsure,
- say N.
+ The module will be called eql.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
X
-Universal TUN/TAP device driver.
+Universal TUN/TAP device driver support
X CONFIG_TUN
- TUN/TAP provides packet reception and transmission for user space programs.
- It can be viewed as a simple Point-to-Point or Ethernet device, which
- instead of receiving packets from a physical media, receives them from
- user space program and instead of sending packets via physical media
- writes them to the user space program.
+ TUN/TAP provides packet reception and transmission for user space
+ programs. It can be viewed as a simple Point-to-Point or Ethernet
+ device, which instead of receiving packets from a physical media,
+ receives them from user space program and instead of sending packets
+ via physical media writes them to the user space program.
+
+ When a program opens /dev/net/tun, driver creates and registers
+ corresponding net device tunX or tapX. After a program closed above
+ devices, driver will automatically delete tunXX or tapXX device and
+ all routes corresponding to it.
X
- When a program opens /dev/net/tun, driver creates and registers
- corresponding net device tunX or tapX. After a program closed above
- devices, driver will automatically delete tunXX or tapXX device and all
- routes corresponding to it.
-
- Please read Documentation/networking/tuntap.txt for more information.
+ Please read <file:Documentation/networking/tuntap.txt> for more
+ information.
X

X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called tun.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.

+ The module will be called tun.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X If you don't know what to use this for, you don't need it.
X
@@ -7963,7 +8981,7 @@
X driver", above) and create a character special file /dev/tap0 with
X major number 36 and minor number 16 using mknod ("man mknod"), you
X will be able to have a user space program read and write raw
- Ethernet frames from/to that special file. tap0 can be configured
+ Ethernet frames from/to that special file. tap0 can be configured
X with ifconfig and route like any other Ethernet device but it is not
X connected to any physical LAN; everything written by the user to
X /dev/tap0 is treated by the kernel as if it had come in from a LAN
@@ -7971,19 +8989,19 @@
X device tap0 can instead be read by the user from /dev/tap0: the user
X mode program replaces the LAN that would be attached to an ordinary
X Ethernet device. Please read the file
- Documentation/networking/ethertap.txt for more information.
+ <file:Documentation/networking/ethertap.txt> for more information.
X

X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called ethertap.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X

X If you don't know what to use this for, you don't need it.
X
X Sealevel Systems 4021 support
X CONFIG_SEALEVEL_4021
X This is a driver for the Sealevel Systems ACB 56 serial I/O adapter.
-
+
X This driver can only be compiled as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want).

X If you want to do that, say M here. The module will be called
@@ -7997,6 +9015,21 @@
X of the Cisco HDLC/PPP driver (syncppp.c).
X The SyncLink WAN driver (in character devices) must also be enabled.
X
+FarSync T-Series support
+CONFIG_FARSYNC
+ This driver supports the FarSync T-Series X.21 (and V.35/V.24) cards
+ from FarSite Communications Ltd.
+ Synchronous communication is supported on all ports at speeds up to
+ 8Mb/s (128K on V.24) using synchronous PPP or Cisco HDLC.
+
+ If you want to compile this driver as a module ( = code which can be


+ inserted in and removed from the running kernel whenever you want)

+ say M here and read <file:Documentation/modules.txt>.

+ The module will be called farsync.o and if you want the module to be
+ automatically loaded when the interface is referenced then you
+ should add "alias syncX farsync" to /etc/modules.conf for each
+ interface, where X is 0, 1, 2, ...
+
X Frame Relay (DLCI) support
X CONFIG_DLCI
X This is support for the frame relay protocol; frame relay is a fast
@@ -8006,15 +9039,15 @@
X network, usually at the phone company) can carry several logical
X point-to-point connections to other computers connected to the frame
X relay network. For a general explanation of the protocol, check out
- http://www.frforum.com/ on the WWW. To use frame relay, you need
+ <http://www.frforum.com/> on the WWW. To use frame relay, you need
X supporting hardware (called FRAD) and certain programs from the
X net-tools package as explained in
- Documentation/networking/framerelay.txt.
+ <file:Documentation/networking/framerelay.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called dlci.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X

X Max open DLCI
X CONFIG_DLCI_COUNT
@@ -8029,19 +9062,19 @@
X handled by each of your hardware frame relay access devices. Go with
X the default.
X
-Sangoma S502A FRAD support
+SDLA (Sangoma S502/S508) support
X CONFIG_SDLA
X Say Y here if you need a driver for the Sangoma S502A, S502E, and
X S508 Frame Relay Access Devices. These are multi-protocol cards, but
X only frame relay is supported by the driver at this time. Please
- read Documentation/framerelay.txt.
+ read <file:Documentation/framerelay.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called sdla.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X

-Acorn Econet/AUN protocols (EXPERIMENTAL)
+Acorn Econet/AUN protocols
X CONFIG_ECONET
X Econet is a fairly old and slow networking protocol mainly used by
X Acorn computers to access file and print servers. It uses native
@@ -8057,7 +9090,7 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called econet.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X

X AUN over UDP
X CONFIG_ECONET_AUNUDP
@@ -8070,7 +9103,7 @@
X Say Y here if you have a native Econet network card installed in
X your computer.
X
-WAN Router
+WAN router
X CONFIG_WAN_ROUTER
X Wide Area Networks (WANs), such as X.25, frame relay and leased
X lines, are used to interconnect Local Area Networks (LANs) over vast
@@ -8082,16 +9115,17 @@
X As an alternative, WAN routing can be built into the Linux kernel.
X With relatively inexpensive WAN interface cards available on the
X market, a perfectly usable router can be built for less than half
- the price of an external router. If you have one of those cards and
+ the price of an external router. If you have one of those cards and
X wish to use your Linux box as a WAN router, say Y here and also to


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

echo 'End of part 007'
echo 'File patch-2.4.15 is continued in part 008'
echo "008" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:42 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part006

#!/bin/sh -x
# this is part 006 of a 115 - part archive


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

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

+Enable tagged command queueing (TCQ) by default
X CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT
X This option causes the aic7xxx driver to attempt to use Tagged
- Command Queueing (TCQ) on all devices that claim to support it.
+ Command Queueing (TCQ) on all devices that claim to support it.
X
X TCQ is a feature of SCSI-2 which improves performance: the host
X adapter can send several SCSI commands to a device's queue even if
- previous commands haven't finished yet. Because the device is
+ previous commands haven't finished yet. Because the device is
X intelligent, it can optimize its operations (like head positioning)
- based on its own request queue. Not all devices implement this
- correctly.
+ based on its own request queue. Not all devices implement this
+ correctly.
X
X If you say Y here, you can still turn off TCQ on troublesome devices
- with the use of the tag_info boot parameter. See the file
- 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
+ with the use of the tag_info boot parameter. See the file
+ <file: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
X parameter.
X
X If you are unsure about your devices then it is safest to say N
X here.
-
+
X However, TCQ can increase performance on some hard drives by as much
X as 50% or more, so it is recommended that if you say N here, you
- should 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.
+ should at least read the <file:drivers/scsi/README.aic7xxx> file so
+ you will know how to enable this option manually should your drives
+ prove to be safe in regards to TCQ.
X
X Conversely, certain drives are known to lock up or cause bus resets
- when TCQ is enabled on them. If you have a Western Digital
+ when TCQ is enabled on them. If you have a Western Digital
X Enterprise SCSI drive for instance, then don't even bother to enable
X TCQ on it as the drive will become unreliable, and it will actually
X reduce performance.
@@ -5947,7 +6901,7 @@
X eventually have their command depth reduced, but is a waste of
X memory if all of your devices end up reducing this number down to a
X more reasonable figure.
-
+
X NOTE: Certain very broken drives are known to lock up when given
X more commands than they like to deal with. Quantum Fireball drives
X are the most common in this category. For the Quantum Fireball
@@ -5964,14 +6918,14 @@
X small amount of overhead to each and every SCSI command the aic7xxx
X driver handles, so if you aren't really interested in this
X information, it is best to leave it disabled. This will only work if
- you also say Y to "/proc file system support", below.
+ you also say Y to "/proc file system support", below.


X
X If unsure, say N.
X

-IBM ServeRAID Support
+IBM ServeRAID support
X CONFIG_SCSI_IPS
X This is support for the IBM ServeRAID hardware RAID controllers.
- See http://www.developer.ibm.com/welcome/netfinity/serveraid.html
+ See <http://www.developer.ibm.com/welcome/netfinity/serveraid.html>
X for more information. If this driver does not work correctly
X without modification please contact the author by email at
X ipsl...@us.ibm.com.
@@ -5979,14 +6933,14 @@
X You can build this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),

X but only a single instance may be loaded. If you want to compile it
- as a module, say M here and read Documentation/modules.txt. The
- module will be called ips.o.
+ as a module, say M here and read <file:Documentation/modules.txt>.
+ The module will be called ips.o.
X
X BusLogic SCSI support
X CONFIG_SCSI_BUSLOGIC
X This is support for BusLogic MultiMaster and FlashPoint SCSI Host
X Adapters. Consult the SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto , and the files
+ <http://www.linuxdoc.org/docs.html#howto>, and the files
X README.BusLogic and README.FlashPoint in drivers/scsi for more
X information. If this driver does not work correctly without
X modification, please contact the author, Leonard N. Zubkoff, by
@@ -5995,8 +6949,8 @@
X You can also build this driver as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),

X but only a single instance may be loaded. If you want to compile it
- as a module, say M here and read Documentation/modules.txt. The
- module will be called BusLogic.o.
+ as a module, say M here and read <file:Documentation/modules.txt>.
+ The module will be called BusLogic.o.
X
X Omit BusLogic SCSI FlashPoint support
X CONFIG_SCSI_OMIT_FLASHPOINT
@@ -6005,81 +6959,86 @@
X substantial, so users of MultiMaster Host Adapters may wish to omit
X it.
X
+Compaq Fibre Channel 64-bit/66Mhz HBA support
+CONFIG_SCSI_CPQFCTS
+ Say Y here to compile in support for the Compaq StorageWorks Fibre
+ Channel 64-bit/66Mhz Host Bus Adapter.
+
X DMX3191D SCSI support
X CONFIG_SCSI_DMX3191D
X This is support for Domex DMX3191D SCSI Host Adapters.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called dmx3191d.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.

+ The module will be called dmx3191d.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
X
X DTC3180/3280 SCSI support
X CONFIG_SCSI_DTC3280
- This is support for DTC 3180/3280 SCSI Host Adapters. Please read
+ This is support for DTC 3180/3280 SCSI Host Adapters. Please read
X the SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto , and the file
- drivers/scsi/README.dtc3x80.
+ <http://www.linuxdoc.org/docs.html#howto>, and the file
+ <file:drivers/scsi/README.dtc3x80>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called dtc.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.

+ The module will be called dtc.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X EATA-DMA [Obsolete] (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support
X CONFIG_SCSI_EATA_DMA
X This is support for the EATA-DMA protocol compliant SCSI Host
X Adapters like the SmartCache III/IV, SmartRAID controller families
- and the DPT PM2011B and PM2012B controllers.
+ and the DPT PM2011B and PM2012B controllers.
X
- Note that this driver is obsolete; if you have one of the above SCSI
- Host Adapters, you should normally say N here and Y to "EATA
- ISA/EISA/PCI support", below. Please read the SCSI-HOWTO, available

+ Note that this driver is obsolete; if you have one of the above
+ SCSI Host Adapters, you should normally say N here and Y to "EATA
+ ISA/EISA/PCI support", below. Please read the SCSI-HOWTO, available
+ from <http://www.linuxdoc.org/docs.html#howto>.
X

X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called eata_dma.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.

+ The module will be called eata_dma.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
X
X EATA-PIO (old DPT PM2001, PM2012A) support
X CONFIG_SCSI_EATA_PIO
X This driver supports all EATA-PIO protocol compliant SCSI Host
- Adapters like the DPT PM2001 and the PM2012A. EATA-DMA compliant
+ Adapters like the DPT PM2001 and the PM2012A. EATA-DMA compliant
X host adapters could also use this driver but are discouraged from
X doing so, since this driver only supports hard disks and lacks
- numerous features. You might want to have a look at the SCSI-HOWTO,

+ numerous features. You might want to have a look at the SCSI-HOWTO,
+ available from <http://www.linuxdoc.org/docs.html#howto>.
X

X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called eata_pio.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called eata_pio.o.
X
X UltraStor 14F/34F support
X CONFIG_SCSI_U14_34F
X This is support for the UltraStor 14F and 34F SCSI-2 host adapters.
- The source at drivers/scsi/u14-34f.c contains some information about
- this hardware. If the driver doesn't work out of the box, you may
- have to change some settings in drivers/scsi/u14-34f.c. Read the
- SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . Note that there is also
+ The source at <file:drivers/scsi/u14-34f.c> contains some
+ information about this hardware. If the driver doesn't work out of
+ the box, you may have to change some settings in
+ <file: drivers/scsi/u14-34f.c>. Read the SCSI-HOWTO, available from
+ <http://www.linuxdoc.org/docs.html#howto>. Note that there is also
X another driver for the same hardware: "UltraStor SCSI support",
- below. You should say Y to both only if you want 24F support as
+ below. You should say Y to both only if you want 24F support as
X well.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called u14-34f.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.

+ The module will be called u14-34f.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X enable elevator sorting
X CONFIG_SCSI_U14_34F_LINKED_COMMANDS
- This option enables elevator sorting for all probed SCSI disks and
- CDROMs. It definitely reduces the average seek distance when doing
+ This option enables elevator sorting for all probed SCSI disks and
+ CD-ROMs. It definitely reduces the average seek distance when doing
X random seeks, but this does not necessarily result in a noticeable
X performance improvement: your mileage may vary...
-
+
X The safe answer is N.
X
X maximum number of queued commands
@@ -6098,7 +7057,7 @@
X other adapters based on the Future Domain chipsets (Quantum
X ISA-200S, ISA-250MG; Adaptec AHA-2920A; and at least one IBM board).
X It is explained in section 3.7 of the SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto .
+ <http://www.linuxdoc.org/docs.html#howto>.
X
X NOTE: Newer Adaptec AHA-2920C boards use the Adaptec AIC-7850 chip
X and should use the aic7xxx driver ("Adaptec AIC7xxx chipset SCSI
@@ -6108,7 +7067,7 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called fdomain.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X

X Future Domain MCS-600/700 SCSI support
X CONFIG_SCSI_FD_MCS
@@ -6121,71 +7080,90 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called fd_mcs.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X

X Generic NCR5380/53c400 SCSI support
X CONFIG_SCSI_GENERIC_NCR5380
X This is the generic NCR family of SCSI controllers, not to be
- confused with the NCR 53c7 or 8xx controllers. It is explained in
+ confused with the NCR 53c7 or 8xx controllers. It is explained in
X section 3.8 of the SCSI-HOWTO, available from


- http://www.linuxdoc.org/docs.html#howto . If it doesn't work out
+ <http://www.linuxdoc.org/docs.html#howto>. If it doesn't work out
X of the box, you may have to change some settings in

- drivers/scsi/g_NCR5380.h.
+ <file:drivers/scsi/g_NCR5380.h>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called g_NCR5380.o. If you want to compile it as
- a module, say M here and read Documentation/modules.txt.
+ The module will be called g_NCR5380.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
X
X Enable NCR53c400 extensions
X CONFIG_SCSI_GENERIC_NCR53C400
- This enables certain optimizations for the NCR53c400 SCSI cards. You
- might as well try it out. Note that this driver will only probe for
- the Trantor T130B in its default configuration; you might have to
- pass a command line option to the kernel at boot time if it doesn't
- detect your card. See the file drivers/scsi/README.g_NCR5380 for
- details.
+ This enables certain optimizations for the NCR53c400 SCSI cards.
+ You might as well try it out. Note that this driver will only probe
+ for the Trantor T130B in its default configuration; you might have
+ to pass a command line option to the kernel at boot time if it does
+ not detect your card. See the file
+ <file:drivers/scsi/README.g_NCR5380> for details.
X
+# Choice: ncr5380
X NCR5380/53c400 mapping method (use Port for T130B)
X CONFIG_SCSI_G_NCR5380_PORT
X The NCR5380 and NCR53c400 SCSI controllers come in two varieties:
X port or memory mapped. You should know what you have. The most
X common card, Trantor T130B, uses port mapped mode.
X
+NCR Dual 700 MCA SCSI support
+CONFIG_SCSI_NCR_D700
+ This is a driver for the MicroChannel Dual 700 card produced by
+ NCR and commonly used in 345x/35xx/4100 class machines. It always
+ tries to negotiate sync and uses tag command queueing.
+
+ Unless you have an NCR manufactured machine, the chances are that
+ you do not have this SCSI card, so say N.
+
+HP LASI SCSI support for 53c700
+CONFIG_SCSI_LASI700
+ This is a driver for the lasi baseboard in some parisc machines
+ which is based on the 53c700 chip. Will also support LASI subsystems
+ based on the 710 chip using 700 emulation mode.
+
+ Unless you know you have a 53c700 or 53c710 based lasi, say N here
+
X NCR53c7,8xx SCSI support
X CONFIG_SCSI_NCR53C7xx
X This is a driver for the 53c7 and 8xx NCR family of SCSI
- controllers, not to be confused with the NCR 5380 controllers. It is
- explained in section 3.8 of the SCSI-HOWTO, available from


- http://www.linuxdoc.org/docs.html#howto . If it doesn't work out

+ controllers, not to be confused with the NCR 5380 controllers. It
+ is explained in section 3.8 of the SCSI-HOWTO, available from


+ <http://www.linuxdoc.org/docs.html#howto>. If it doesn't work out
X of the box, you may have to change some settings in

- drivers/scsi/53c7,8xx.h. Please read drivers/scsi/README.ncr53c7xx
- for the available boot time command line options.
+ <file:drivers/scsi/53c7,8xx.h>. Please read
+ <file:drivers/scsi/README.ncr53c7xx> for the available boot time
+ command line options.
X
X Note: there is another driver for the 53c8xx family of controllers
- ("NCR53C8XX SCSI support" below). If you want to use them both, you
+ ("NCR53C8XX SCSI support" below). If you want to use them both, you
X need to say M to both and build them as modules, but only one may be
X active at a time. If you have a 53c8xx board, it's better to use the
X other driver.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called 53c7,8xx.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.

+ The module will be called 53c7,8xx.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
X
-always negotiate synchronous transfers
+Always negotiate synchronous transfers
X CONFIG_SCSI_NCR53C7xx_sync
X In general, this is good; however, it is a bit dangerous since there
X are some broken SCSI devices out there. Take your chances. Safe bet
X is N.
X
-allow FAST-SCSI [10MHz]
+Allow FAST-SCSI [10MHz]
X CONFIG_SCSI_NCR53C7xx_FAST
X This will enable 10MHz FAST-SCSI transfers with your host
X adapter. Some systems have problems with that speed, so it's safest
X to say N here.
X
-allow DISCONNECT
+Allow DISCONNECT
X CONFIG_SCSI_NCR53C7xx_DISCONNECT
X This enables the disconnect/reconnect feature of the NCR SCSI
X controller. When you say Y here, a slow SCSI device will not lock
@@ -6197,10 +7175,67 @@
X to hang, which might cause a system crash. The safe answer
X therefore is to say N.
X
+SYM53C8XX Version 2 SCSI support
+CONFIG_SCSI_SYM53C8XX_2
+ This driver supports the whole NCR53C8XX/SYM53C8XX family of
+ PCI-SCSI controllers. It also supports the subset of LSI53C10XX
+ Ultra-160 controllers that are based on the SYM53C8XX SCRIPTS
+ language. It does not support LSI53C10XX Ultra-320 PCI-X SCSI
+ controllers.
+
+ If your system has problems using this new major version of the
+ SYM53C8XX driver, you may switch back to driver version 1.
+
+ Please read drivers/scsi/sym53c8xx_2/Documentation.txt for more
+ information.
+
+PCI DMA addressing mode
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE
+ This option only applies to PCI-SCSI chip that are PCI DAC capable
+ (875A, 895A, 896, 1010-33, 1010-66, 1000).
+
+ When set to 0, only PCI 32 bit DMA addressing (SAC) will be performed.
+ When set to 1, 40 bit DMA addressing (with upper 24 bits of address
+ set to zero) is supported. The addressable range is here 1 TB.
+ When set to 2, full 64 bits of address for DMA are supported, but only
+ 16 segments of 4 GB can be addressed. The addressable range is so
+ limited to 64 GB.
+
+ The safest value is 0 (32 bit DMA addressing) that is guessed to still
+ fit most of real machines.
+
+ The preferred value 1 (40 bit DMA addressing) should make happy
+ properly engineered PCI DAC capable host bridges. You may configure
+ this option for Intel platforms with more than 4 GB of memory.
+
+ The still experimental value 2 (64 bit DMA addressing with 16 x 4GB
+ segments limitation) can be used on systems that require PCI address
+ bits past bit 39 to be set for the addressing of memory using PCI
+ DAC cycles.
+
+use normal IO
+CONFIG_SCSI_SYM53C8XX_IOMAPPED
+ If you say Y here, the driver will preferently use normal IO rather than
+ memory mapped IO.
+
+maximum number of queued commands
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS
+ This option allows you to specify the maximum number of commands
+ that can be queued to any device, when tagged command queuing is
+ possible. The driver supports up to 256 queued commands per device.
+ This value is used as a compiled-in hard limit.
+
+default tagged command queue depth
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS
+ This is the default value of the command queue depth the driver will
+ announce to the generic SCSI layer for devices that support tagged
+ command queueing. This value can be changed from the boot command line.
+ This is a soft limit that cannot exceed CONFIG_SCSI_SYM53C8XX_MAX_TAGS.
+
X NCR53C8XX SCSI support
X CONFIG_SCSI_NCR53C8XX
X This is the BSD ncr driver adapted to Linux for the NCR53C8XX family
- of PCI-SCSI controllers. This driver supports parity checking,
+ of PCI-SCSI controllers. This driver supports parity checking,
X tagged command queuing and fast synchronous data transfers up to 80
X MB/s with wide FAST-40 LVD devices and controllers.
X
@@ -6208,21 +7243,22 @@
X option "SYM53C8XX SCSI support", below.
X
X Note: there is yet another driver for the 53c8xx family of
- controllers ("NCR53c7,8xx SCSI support" above). If you want to use
+ controllers ("NCR53c7,8xx SCSI support" above). If you want to use
X them both, you need to say M to both and build them as modules, but
- only one may be active at a time. If you have a 53c8xx board, you
+ only one may be active at a time. If you have a 53c8xx board, you
X probably do not want to use the "NCR53c7,8xx SCSI support".
X
- Please read drivers/scsi/README.ncr53c8xx for more information.
+ Please read <file:drivers/scsi/README.ncr53c8xx> for more
+ information.
X
-SYM53C8XX SCSI support
+SYM53C8XX Version 1 SCSI support
X CONFIG_SCSI_SYM53C8XX
X This driver supports all the features of recent 53C8XX chips (used
X in PCI SCSI controllers), notably the hardware phase mismatch
X feature of the SYM53C896.
X
X Older versions of the 53C8XX chips are not supported by this
- driver. If your system uses either a 810 rev. < 16, a 815, or a 825
+ driver. If your system uses either a 810 rev. < 16, a 815, or a 825
X rev. < 16 PCI SCSI processor, you must use the generic NCR53C8XX
X driver ("NCR53C8XX SCSI support" above) or configure both the
X NCR53C8XX and this SYM53C8XX drivers either as module or linked to
@@ -6231,32 +7267,33 @@
X When both drivers are linked into the kernel, the SYM53C8XX driver
X is called first at initialization and you can use the 'excl=ioaddr'
X driver boot option to exclude attachment of adapters by the
- SYM53C8XX driver. For example, entering
+ SYM53C8XX driver. For example, entering
X 'sym53c8xx=excl:0xb400,excl=0xc000' at the lilo prompt prevents
X adapters at io address 0xb400 and 0xc000 from being attached by the
X SYM53C8XX driver, thus allowing the NCR53C8XX driver to attach them.
X The 'excl' option is also supported by the NCR53C8XX driver.
-
- Please read drivers/scsi/README.ncr53c8xx for more information.
X
-synchronous data transfers frequency
+ Please read <file:drivers/scsi/README.ncr53c8xx> for more
+ information.
+
+Synchronous transfer frequency in MHz
X CONFIG_SCSI_NCR53C8XX_SYNC
X The SCSI Parallel Interface-2 Standard defines 5 classes of transfer
- rates: FAST-5, FAST-10, FAST-20, FAST-40 and FAST-80. The numbers are
- respectively the maximum data transfer rates in mega-transfers per
- second for each class. For example, a FAST-20 Wide 16 device is able
- to transfer data at 20 million 16 bit packets per second for a total
- rate of 40 MB/s.
+ rates: FAST-5, FAST-10, FAST-20, FAST-40 and FAST-80. The numbers
+ are respectively the maximum data transfer rates in mega-transfers
+ per second for each class. For example, a FAST-20 Wide 16 device is
+ able to transfer data at 20 million 16 bit packets per second for a
+ total rate of 40 MB/s.
X
X You may specify 0 if you want to only use asynchronous data
X transfers. This is the safest and slowest option. Otherwise, specify
X a value between 5 and 80, depending on the capability of your SCSI
- controller. The higher the number, the faster the data transfer.
+ controller. The higher the number, the faster the data transfer.
X Note that 80 should normally be ok since the driver decreases the
X value automatically according to the controller's capabilities.
X
X Your answer to this question is ignored for controllers with NVRAM,
- since the driver will get this information from the user set-up. It
+ since the driver will get this information from the user set-up. It
X also can be overridden using a boot setup option, as follows
X (example): 'ncr53c8xx=sync:12' will allow the driver to negotiate
X for FAST-20 synchronous data transfer (20 mega-transfers per
@@ -6270,18 +7307,18 @@
X There is no safe option other than using good cabling, right
X terminations and SCSI conformant devices.
X
-use normal IO
+Use normal IO
X CONFIG_SCSI_NCR53C8XX_IOMAPPED
X If you say Y here, the driver will use normal IO, as opposed to
X memory mapped IO. Memory mapped IO has less latency than normal IO
X and works for most Intel-based hardware. Under Linux/Alpha only
X normal IO is currently supported by the driver and so, this option
- has no effect on those systems.
+ has no effect on those systems.
X
X The normal answer therefore is N; try Y only if you encounter SCSI
X related problems.
X
-not allow targets to disconnect
+Not allow targets to disconnect
X CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
X This option is only provided for safety if you suspect some SCSI
X device of yours to not support properly the target-disconnect
@@ -6289,7 +7326,7 @@
X not allow targets to disconnect is not reasonable if there is more
X than 1 device on a SCSI bus. The normal answer therefore is N.
X
-default tagged command queue depth
+Default tagged command queue depth
X CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
X "Tagged command queuing" is a feature of SCSI-2 which improves
X performance: the host adapter can send several SCSI commands to a
@@ -6300,33 +7337,33 @@
X feature, enter 0 or 1 here (it doesn't matter which).
X
X The default value is 8 and should be supported by most hard disks.
- This value can be overridden from the boot command line using the
+ This value can be overridden from the boot command line using the
X 'tags' option as follows (example):
X 'ncr53c8xx=tags:4/t2t3q16/t0u2q10' will set default queue depth to
X 4, set queue depth to 16 for target 2 and target 3 on controller 0
X and set queue depth to 10 for target 0 / lun 2 on controller 1.
X
- The normal answer therefore is to go with the default 8 and to use
- a boot command line option for devices that need to use a different
+ The normal answer therefore is to go with the default 8 and to use
+ a boot command line option for devices that need to use a different
X command queue depth.
X
X There is no safe option other than using good SCSI devices.
X
-maximum number of queued commands
+Maximum number of queued commands
X CONFIG_SCSI_NCR53C8XX_MAX_TAGS
X This option allows you to specify the maximum number of commands
X that can be queued to any device, when tagged command queuing is
X possible. The default value is 32. Minimum is 2, maximum is 64.
- Modern hard disks are able to support 64 tags and even more, but
+ Modern hard disks are able to support 64 tags and even more, but
X do not seem to be faster when more than 32 tags are being used.
-
+
X So, the normal answer here is to go with the default value 32 unless
X you are using very large hard disks with large cache (>= 1 MB) that
X are able to take advantage of more than 32 tagged commands.
X
X There is no safe option and the default answer is recommended.
X
-assume boards are SYMBIOS compatible (EXPERIMENTAL)
+Assume boards are SYMBIOS compatible
X CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT
X This option allows you to enable some features depending on GPIO
X wiring. These General Purpose Input/Output pins can be used for
@@ -6335,7 +7372,7 @@
X controller LED and GPIO3 bit as a flag indicating
X singled-ended/differential interface. The Tekram DC-390U/F boards
X uses a different GPIO wiring.
-
+
X Your answer to this question is ignored if all your controllers have
X NVRAM, since the driver is able to detect the board type from the
X NVRAM format.
@@ -6344,16 +7381,16 @@
X use BIOS and drivers from SYMBIOS, you would want to say Y here,
X otherwise N. N is the safe answer.
X
-enable profiling statistics gathering
+Enable traffic profiling
X CONFIG_SCSI_NCR53C8XX_PROFILE
X This option allows you to enable profiling information gathering.
- These statistics are not very accurate due to the low frequency
- of the kernel clock (100 Hz on i386) and have performance impact
+ These statistics are not very accurate due to the low frequency
+ of the kernel clock (100 Hz on i386) and have performance impact
X on systems that use very fast devices.
X
X The normal answer therefore is N.
X
-include support for the NCR PQS/PDS SCSI card
+Include support for the NCR PQS/PDS SCSI card
X CONFIG_SCSI_NCR53C8XX_PQS_PDS
X Say Y here if you have a special SCSI adapter produced by NCR
X corporation called a PCI Quad SCSI or PCI Dual SCSI. You do not need
@@ -6366,23 +7403,24 @@
X IBMMCA SCSI support
X CONFIG_SCSI_IBMMCA
X This is support for the IBM SCSI adapter found in many of the PS/2
- series computers. These machines have an MCA bus, so you need to
- answer Y to "MCA support" as well and read Documentation/mca.txt.
+ series computers. These machines have an MCA bus, so you need to
+ answer Y to "MCA support" as well and read
+ <file:Documentation/mca.txt>.
X
X If the adapter isn't found during boot (a common problem for models
X 56, 57, 76, and 77) you'll need to use the 'ibmmcascsi=<pun>' kernel
X option, where <pun> is the id of the SCSI subsystem (usually 7, but
- if that doesn't work check your reference diskette). Owners of model
- 95 with a LED-matrix-display can in addition activate some activity
- info like under OS/2, but more informative, by setting
- 'ibmmcascsi=display' as an additional kernel parameter. Try "man
+ if that doesn't work check your reference diskette). Owners of
+ model 95 with a LED-matrix-display can in addition activate some
+ activity info like under OS/2, but more informative, by setting
+ 'ibmmcascsi=display' as an additional kernel parameter. Try "man
X bootparam" or see the documentation of your boot loader about how to
X pass options to the kernel.


X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called ibmmca.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called ibmmca.o.
X
X Standard SCSI-order
X CONFIG_IBMMCA_SCSI_ORDER_STANDARD
@@ -6399,7 +7437,7 @@
X highest priority. This must therefore be the disk with the highest
X SCSI-id (e.g. 6) and not the one with the lowest! IBM-BIOS kept the
X original definition of the SCSI-standard as also industrial- and
- process-control-machines, like VME-CPUs running under realtime-OSs
+ process-control-machines, like VME-CPUs running under realtime-OSes
X (e.g. LynxOS, OS9) do.
X
X If you like to run Linux on your MCA-machine with the same
@@ -6428,96 +7466,96 @@
X you know that one of your older devices needs it; N is the safe
X answer.
X
-NCR 53C9x MCA support
+NCR MCA 53C9x SCSI support
X CONFIG_SCSI_MCA_53C9X
- Some Microchannel machines, notably the NCR 35xx line, use a SCSI
+ Some MicroChannel machines, notably the NCR 35xx line, use a SCSI
X controller based on the NCR 53C94. This driver will allow use of
- the controller on the 3550, and very possibly others.
+ the controller on the 3550, and very possibly others.
X
X If you want to compile this as a module (= code which can be
X inserted and removed from the running kernel whenever you want), say
- M here and read Documentation/modules.txt. The module will be called
- mca_53c9x.o.
-
+ M here and read <file:Documentation/modules.txt>. The module will
+ be called mca_53c9x.o.
+
X Always IN2000 SCSI support
X CONFIG_SCSI_IN2000
- This is support for an ISA bus SCSI host adapter. You'll find more
- information in drivers/scsi/in2000.readme. If it doesn't work out of
- the box, you may have to change the jumpers for IRQ or address
- selection.
+ This is support for an ISA bus SCSI host adapter. You'll find more
+ information in <file:drivers/scsi/README.in2000>. If it doesn't work
+ out of the box, you may have to change the jumpers for IRQ or
+ address selection.


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called in2000.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called in2000.o.
X
X Initio 91XXU(W) SCSI support
X CONFIG_SCSI_INITIO
- This is support for the Initio 91XXU(W) SCSI host adapter. Please
+ This is support for the Initio 91XXU(W) SCSI host adapter. Please
X read the SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto .
+ <http://www.linuxdoc.org/docs.html#howto>.
X

X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called initio.o


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called initio.o.
X
X PAS16 SCSI support
X CONFIG_SCSI_PAS16


- This is support for a SCSI host adapter. It is explained in section
+ This is support for a SCSI host adapter. It is explained in section

X 3.10 of the SCSI-HOWTO, available from


- http://www.linuxdoc.org/docs.html#howto . If it doesn't work out
+ <http://www.linuxdoc.org/docs.html#howto>. If it doesn't work out
X of the box, you may have to change some settings in

- drivers/scsi/pas16.h.
-
+ <file:drivers/scsi/pas16.h>.
+


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called pas16.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.

+ The module will be called pas16.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X Initio INI-A100U2W SCSI support
X CONFIG_SCSI_INIA100
- This is support for the Initio INI-A100U2W SCSI host adapter. Please
- read the SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto .
+ This is support for the Initio INI-A100U2W SCSI host adapter.
+ Please read the SCSI-HOWTO, available from

- If you want to compile this as a module ( = code which can be
+ If you want to compile this as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called a100u2w.o


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called a100u2w.o.
X
X PCI2000 support
X CONFIG_SCSI_PCI2000
X This is support for the PCI2000I EIDE interface card which acts as a
- SCSI host adapter. Please read the SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto .
+ SCSI host adapter. Please read the SCSI-HOWTO, available from
+ <http://www.linuxdoc.org/docs.html#howto>.
X
X This driver is also available as a module called pci2000.o ( = code
X 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.


+ whenever you want). If you want to compile it as a module, say M

+ here and read <file:Documentation/modules.txt>.
X
X PCI2220i support
X CONFIG_SCSI_PCI2220I
X This is support for the PCI2220i EIDE interface card which acts as a
- SCSI host adapter. Please read the SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto .
+ SCSI host adapter. Please read the SCSI-HOWTO, available from
+ <http://www.linuxdoc.org/docs.html#howto>.
X
X This driver is also available as a module called pci2220i.o ( = code
X 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.


+ whenever you want). If you want to compile it as a module, say M

+ here and read <file:Documentation/modules.txt>.
X
X PSI240i support
X CONFIG_SCSI_PSI240I
X This is support for the PSI240i EIDE interface card which acts as a
- SCSI host adapter. Please read the SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto .
+ SCSI host adapter. Please read the SCSI-HOWTO, available from
+ <http://www.linuxdoc.org/docs.html#howto>.
X
X This driver is also available as a module called psi240i.o ( = code
X 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.


+ whenever you want). If you want to compile it as a module, say M

+ here and read <file:Documentation/modules.txt>.
X
X Qlogic FAS SCSI support
X CONFIG_SCSI_QLOGIC_FAS
@@ -6530,31 +7568,32 @@
X SCSI support"), below.
X
X Information about this driver is contained in
- drivers/scsi/README.qlogicfas. You should also read the SCSI-HOWTO,

+ <file:drivers/scsi/README.qlogicfas>. You should also read the
+ SCSI-HOWTO, available from
+ <http://www.linuxdoc.org/docs.html#howto>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called qlogicfas.o. If you want to compile it as
- a module, say M here and read Documentation/modules.txt.
+ a module, say M here and read <file:Documentation/modules.txt>.
X
-Qlogic ISP SCSI support (EXPERIMENTAL)
+Qlogic ISP SCSI support
X CONFIG_SCSI_QLOGIC_ISP
X This driver works for all QLogic PCI SCSI host adapters (IQ-PCI,
- IQ-PCI-10, IQ_PCI-D) except for the PCI-basic card. (This latter
- card is supported by the "AM53/79C974 PCI SCSI" driver).
+ IQ-PCI-10, IQ_PCI-D) except for the PCI-basic card. (This latter
+ card is supported by the "AM53/79C974 PCI SCSI" driver.)
X
X If you say Y here, make sure to choose "BIOS" at the question "PCI
X access mode".
X
- Please read the file drivers/scsi/README.qlogicisp. You should also
- read the SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto .
+ Please read the file <file:drivers/scsi/README.qlogicisp>. You
+ should also read the SCSI-HOWTO, available from
+ <http://www.linuxdoc.org/docs.html#howto>.
X

X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called qlogicisp.o. If you want to compile it as
- a module, say M here and read Documentation/modules.txt.
+ The module will be called qlogicisp.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
X
X Qlogic ISP FC SCSI support
X CONFIG_SCSI_QLOGIC_FC
@@ -6562,8 +7601,8 @@


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called qlogicfc.o. If you want to compile it as
- a module, say M here and read Documentation/modules.txt.
+ The module will be called qlogicfc.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
X
X Qlogic QLA 1280 SCSI support
X CONFIG_SCSI_QLOGIC_1280
@@ -6572,61 +7611,63 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called qla1280.o. If you want to compile it as
- a module, say M here and read Documentation/modules.txt.
+ a module, say M here and read <file:Documentation/modules.txt>.
X
X Seagate ST-02 and Future Domain TMC-8xx SCSI support
X CONFIG_SCSI_SEAGATE
X These are 8-bit SCSI controllers; the ST-01 is also supported by
- this driver. It is explained in section 3.9 of the SCSI-HOWTO,
- available from http://www.linuxdoc.org/docs.html#howto . If it
+ this driver. It is explained in section 3.9 of the SCSI-HOWTO,
+ available from <http://www.linuxdoc.org/docs.html#howto>. If it
X doesn't work out of the box, you may have to change some settings in
- drivers/scsi/seagate.h.
+ <file:drivers/scsi/seagate.h>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called seagate.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.

+ The module will be called seagate.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X Trantor T128/T128F/T228 SCSI support
X CONFIG_SCSI_T128
X This is support for a SCSI host adapter. It is explained in section
X 3.11 of the SCSI-HOWTO, available from


- http://www.linuxdoc.org/docs.html#howto . If it doesn't work out
+ <http://www.linuxdoc.org/docs.html#howto>. If it doesn't work out
X of the box, you may have to change some settings in

- drivers/scsi/t128.h. Note that Trantor was purchased by Adaptec, and
- some former Trantor products are being sold under the Adaptec name.
+ <file:drivers/scsi/t128.h>. Note that Trantor was purchased by
+ Adaptec, and some former Trantor products are being sold under the
+ Adaptec name.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called t128.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.

+ The module will be called t128.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X UltraStor SCSI support
X CONFIG_SCSI_ULTRASTOR
X This is support for the UltraStor 14F, 24F and 34F SCSI-2 host
- adapter family. This driver is explained in section 3.12 of the
+ adapter family. This driver is explained in section 3.12 of the
X SCSI-HOWTO, available from


- http://www.linuxdoc.org/docs.html#howto . If it doesn't work out
+ <http://www.linuxdoc.org/docs.html#howto>. If it doesn't work out
X of the box, you may have to change some settings in

- drivers/scsi/ultrastor.h.
-
+ <file:drivers/scsi/ultrastor.h>.
+
X Note that there is also another driver for the same hardware:
X "UltraStor 14F/34F support", above.


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called ultrastor.o.

+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called ultrastor.o.
X
X 7000FASST SCSI support
X CONFIG_SCSI_7000FASST
X This driver supports the Western Digital 7000 SCSI host adapter
- family. Some information is in the source: drivers/scsi/wd7000.c.
+ family. Some information is in the source:
+ <file:drivers/scsi/wd7000.c>.


X
X This driver is also available as a module ( = code which can be

- inserted in and removed from the running kernel whenever you
- want). The module will be called wd7000.o. If you want to compile it
- as a module, say M here and read Documentation/modules.txt.


+ inserted in and removed from the running kernel whenever you want).

+ The module will be called wd7000.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X ACARD SCSI support
X CONFIG_SCSI_ACARD
@@ -6635,40 +7676,41 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called atp870u.o. If you want to compile it as a


- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X

X EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support
X CONFIG_SCSI_EATA
- This driver supports all EATA/DMA-compliant SCSI host adapters. DPT
- ISA and all EISA i/o addresses are probed looking for the "EATA"
- signature. If you chose "BIOS" at the question "PCI access mode",
+ This driver supports all EATA/DMA-compliant SCSI host adapters. DPT
+ ISA and all EISA I/O addresses are probed looking for the "EATA"
+ signature. If you chose "BIOS" at the question "PCI access mode",
X the addresses of all the PCI SCSI controllers reported by the PCI
X subsystem are probed as well.
X
- You want to read the start of drivers/scsi/eata.c and the
+ You want to read the start of <file:drivers/scsi/eata.c> and the
X SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto .
+ <http://www.linuxdoc.org/docs.html#howto>.
X
X Note that there is also another driver for the same hardware
- available: "EATA-DMA support". You should say Y to only one of them.
+ available: "EATA-DMA [Obsolete] (DPT, NEC, AT&T, SNI, AST, Olivetti,
+ Alphatronix) support". You should say Y to only one of them.


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called eata.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called eata.o.
X
-enable tagged command queuing
+enable tagged command queueing
X CONFIG_SCSI_EATA_TAGGED_QUEUE
X This is a feature of SCSI-2 which improves performance: the host
X adapter can send several SCSI commands to a device's queue even if
X previous commands haven't finished yet. Most EATA adapters negotiate
X this feature automatically with the device, even if your answer is
X N. The safe answer is N.
-
+
X enable elevator sorting
X CONFIG_SCSI_EATA_LINKED_COMMANDS
- This option enables elevator sorting for all probed SCSI disks and
- CDROMs. It definitely reduces the average seek distance when doing
+ This option enables elevator sorting for all probed SCSI disks and
+ CD-ROMs. It definitely reduces the average seek distance when doing
X random seeks, but this does not necessarily result in a noticeable
X performance improvement: your mileage may vary...
X The safe answer is N.
@@ -6684,21 +7726,21 @@
X
X NCR53c406a SCSI support
X CONFIG_SCSI_NCR53C406A
- This is support for the NCR53c406a SCSI host adapter. For user
- configurable parameters, check out drivers/scsi/NCR53c406.c in the
- kernel source. Also read the SCSI-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto .
+ This is support for the NCR53c406a SCSI host adapter. For user
+ configurable parameters, check out <file:drivers/scsi/NCR53c406.c>
+ in the kernel source. Also read the SCSI-HOWTO, available from
+ <http://www.linuxdoc.org/docs.html#howto>.
X

X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called NCR53c406.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called NCR53c406.o.
X
-Symbios Logic sym53c416 support
+Symbios 53c416 SCSI support
X CONFIG_SCSI_SYM53C416
X This is support for the sym53c416 SCSI host adapter, the SCSI
X adapter that comes with some HP scanners. This driver requires that
- the sym53c416 is configured first using some sort of pnp
+ the sym53c416 is configured first using some sort of PnP
X configuration program (e.g. isapnp) or by a PnP aware BIOS. If you
X are using isapnp then you need to compile this driver as a module
X and then load it using insmod after isapnp has run. The parameters
@@ -6710,8 +7752,8 @@
X There is support for up to four adapters. If you want to compile
X this driver as a module ( = code which can be inserted in and
X removed from the running kernel whenever you want), say M here and
- read Documentation/modules.txt. The module will be called
- sym53c416.o.
+ read <file:Documentation/modules.txt>. The module will be called
+ sym53c416.o.
X
X Simple 53c710 SCSI support (Compaq, NCR machines)
X CONFIG_SCSI_SIM710
@@ -6720,46 +7762,46 @@
X More complex drivers for this chip are available ("NCR53c7,8xx SCSI
X support", above), but they require that the scsi chip be able to do
X DMA block moves between memory and on-chip registers, which can
- cause problems under certain conditions. This driver is designed to
+ cause problems under certain conditions. This driver is designed to
X avoid these problems and is intended to work with any Intel machines
X using 53c710 chips, including various Compaq and NCR machines.
X
X Please read the comments at the top of the file
- drivers/scsi/sim710.c for more information.
+ <file:drivers/scsi/sim710.c> for more information.
X

X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called sim710.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called sim710.o.
X
-Tekram DC390(T) and Am53/79C974 (PCscsi) SCSI support
+Tekram DC390(T) and Am53/79C974 SCSI support
X CONFIG_SCSI_DC390T
X This driver supports PCI SCSI host adapters based on the Am53C974A
X chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
X PCscsi/PCnet (Am53/79C974) solutions.
X
- Documentation can be found in drivers/scsi/README.tmscsim.
-
+ Documentation can be found in <file:drivers/scsi/README.tmscsim>.
+
X Note that this driver does NOT support Tekram DC390W/U/F, which are
X based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
X Also note that there is another generic Am53C974 driver,
- "AM53/79C974 PCI SCSI support" below. You can pick either one.
+ "AM53/79C974 PCI SCSI support" below. You can pick either one.


X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called tmscsim.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called tmscsim.o.
X
X Omit support for other Am53/79C974 based SCSI adapters
X CONFIG_SCSI_DC390T_NOGENSUPP
X If you say N here, the DC390(T) SCSI driver relies on the DC390
X EEPROM to get initial values for its settings, such as speed,
- termination, etc. If it can't find this EEPROM, it will use defaults
- or the user supplied boot/module parameters. For details on driver
- configuration see drivers/scsi/README.tmscsim.
+ termination, etc. If it can't find this EEPROM, it will use
+ defaults or the user supplied boot/module parameters. For details
+ on driver configuration see <file:drivers/scsi/README.tmscsim>.
X
X If you say Y here and if no EEPROM is found, the driver gives up and
- thus only supports Tekram DC390(T) adapters. This can be useful if
+ thus only supports Tekram DC390(T) adapters. This can be useful if
X you have a DC390(T) and another Am53C974 based adapter, which, for
X some reason, you want to drive with the other AM53C974 driver.
X
@@ -6767,40 +7809,42 @@
X
X AM53/79C974 PCI SCSI support
X CONFIG_SCSI_AM53C974
- This is support for the AM53/79C974 SCSI host adapters. Please read
- drivers/scsi/README.AM53C974 for details. Also, the SCSI-HOWTO,
- available from http://www.linuxdoc.org/docs.html#howto , is for
- you.
+ This is support for the AM53/79C974 SCSI host adapters. Please read
+ <file:drivers/scsi/README.AM53C974> for details. Also, the
+ SCSI-HOWTO, available from
+ <http://www.linuxdoc.org/docs.html#howto>, is for you.
X
X Note that there is another driver for AM53C974 based adapters:
- "Tekram DC390(T) and Am53/79C974 (PCscsi) SCSI support", above. You
+ "Tekram DC390(T) and Am53/79C974 (PCscsi) SCSI support", above. You
X can pick either one.


X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called AM53C974.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called AM53C974.o.
X
X AMI MegaRAID support
X CONFIG_SCSI_MEGARAID
X This driver supports the AMI MegaRAID 418, 428, 438, 466, 762, 490
- and 467 SCSI host adapters.
+ and 467 SCSI host adapters.


X
X If you want to compile this driver as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called megaraid.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called megaraid.o.
X
-GDT SCSI Disk Array Controller support
+Intel/ICP (former GDT SCSI Disk Array) RAID Controller Support
X CONFIG_SCSI_GDTH
- This is a driver for all SCSI Disk Array Controllers (EISA/ISA/PCI)
- manufactured by ICP vortex. It is documented in the kernel source in
- drivers/scsi/gdth.c and drivers/scsi/gdth.h.
+ Formerly called GDT SCSI Disk Array Controller Support.
+
+ This is a driver for RAID/SCSI Disk Array Controllers (EISA/ISA/PCI)
+ manufactured by Intel/ICP vortex (an Intel Company). It is documented
+ in the kernel source in drivers/scsi/gdth.c and drivers/scsi/gdth.h.

X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt.

+ <file:Documentation/modules.txt>.
X
X IOMEGA parallel port (ppa - older drives)
X CONFIG_SCSI_PPA
@@ -6817,17 +7861,17 @@
X newer drives)", below.
X
X For more information about this driver and how to use it you should
- read the file drivers/scsi/README.ppa. You should also read the
- SCSI-HOWTO, which is available from
- http://www.linuxdoc.org/docs.html#howto . If you use this driver,
+ read the file <file:drivers/scsi/README.ppa>. You should also read
+ the SCSI-HOWTO, which is available from
+ <http://www.linuxdoc.org/docs.html#howto>. If you use this driver,
X you will still be able to use the parallel port for other tasks,
X such as a printer; it is safe to compile both drivers into the
X kernel.
X
X This driver is also available as a module which can be inserted in
- and removed from the running kernel whenever you want. To compile
+ and removed from the running kernel whenever you want. To compile
X this driver as a module, say M here and read
- Documentation/modules.txt. The module will be called ppa.o.
+ <file:Documentation/modules.txt>. The module will be called ppa.o.
X
X IOMEGA parallel port (imm - newer drives)
X CONFIG_SCSI_IMM
@@ -6844,17 +7888,17 @@
X here and Y to "IOMEGA Parallel Port (ppa - older drives)", above.
X
X For more information about this driver and how to use it you should
- read the file drivers/scsi/README.ppa. You should also read the
- SCSI-HOWTO, which is available from
- http://www.linuxdoc.org/docs.html#howto . If you use this driver,
+ read the file <file:drivers/scsi/README.ppa>. You should also read
+ the SCSI-HOWTO, which is available from
+ <http://www.linuxdoc.org/docs.html#howto>. If you use this driver,
X you will still be able to use the parallel port for other tasks,
X such as a printer; it is safe to compile both drivers into the
X kernel.
X
X This driver is also available as a module which can be inserted in
- and removed from the running kernel whenever you want. To compile
+ and removed from the running kernel whenever you want. To compile
X this driver as a module, say M here and read
- Documentation/modules.txt. The module will be called imm.o.
+ <file:Documentation/modules.txt>. The module will be called imm.o.
X
X Force the Iomega ZIP drivers to use EPP-16
X CONFIG_SCSI_IZIP_EPP16
@@ -6866,7 +7910,7 @@
X so we have to control the state of the chipset's FIFO queue every
X now and then to avoid data loss. This will be done if you say Y
X here.
-
+
X Generally, saying Y is the safe option and slows things down a bit.
X
X Assume slow parallel port control register
@@ -6881,67 +7925,7 @@
X
X Generally, saying N is fine.
X
-Parallel port SCSI device support
-CONFIG_PPSCSI
- There are many external CD-ROM and disk devices that connect through
- your computer's parallel port. Lots of them are actually SCSI
- devices using a parallel port SCSI adapter. This option enables the
- ppSCSI subsystem which contains drivers for many of these external
- drives. You may also want to look at CONFIG_PARIDE (Parallel port
- IDE device support).
-
- If you built ppSCSI support into your kernel, you may still build
- the individual protocol modules and high-level drivers as loadable
- modules. If you build this support as a module, it will be called
- ppscsi.o.
-
- To use the ppSCSI support, you must say Y or M here and also to at
- least one protocol driver (e.g. "Shuttle EPST adapter", "Iomega VPI0
- adapter", "Shining ScarSCI adapter" etc.).
-
-Adaptec APA-348 adapter
-CONFIG_PPSCSI_T348
- This option enables support for the APA-348 adapter from Adaptec
- (also known as Trantor T348). If you build this as a module it will
- be called t348.o.
-
-Adaptec APA-358 adapter
-CONFIG_PPSCSI_T358
- This option enables support for the APA-358 adapter from Adaptec
- (also known as Trantor T358). If you build this as a module it will
- be called t358.o.
-
-Iomega VPI0 adapter
-CONFIG_PPSCSI_VPI0
- This option enables support for the Iomega VPI0 adapter found in the
- original ZIP-100 drives and the Jaz Traveller. If you build this as
- a module it will be called vpi0.o.


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

echo 'End of part 006'
echo 'File patch-2.4.15 is continued in part 007'
echo "007" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:58 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part022

#!/bin/sh -x
# this is part 022 of a 115 - part archive


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

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

+ /* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */


+ mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
+#else

+@ && 'Clean & Invalidate whole DCache'


+1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate
+ bne 1b
+#endif

+ mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache


+ mcr p15, 0, ip, c7, c10, 4 @ drain WB

+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer

+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs

+ mov pc, lr
+
+/*

+ * cpu_arm926_set_pmd(pmdp, pmd)


+ *
+ * Set a level 1 translation table entry, and clean it out of
+ * any caches such that the MMUs can load it correctly.
+ *
+ * pmdp: pointer to PMD entry
+ * pmd: PMD value to store
+ */
+ .align 5

+ENTRY(cpu_arm926_set_pmd)
+#ifdef CONFIG_CPU_ARM926_WRITETHROUGH


+ eor r2, r1, #0x0a @ C & Section
+ tst r2, #0x0b
+ biceq r1, r1, #4 @ clear bufferable bit
+#endif
+ str r1, [r0]

+#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+#endif
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+/*

+ * cpu_arm926_set_pte(ptep, pte)


+ *
+ * Set a PTE and flush it out
+ */
+ .align 5

+ENTRY(cpu_arm926_set_pte)


+ str r1, [r0], #-1024 @ linux version
+
+ eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
+
+ bic r2, r1, #0xff0
+ bic r2, r2, #3
+ orr r2, r2, #HPTE_TYPE_SMALL
+
+ tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
+ orrne r2, r2, #HPTE_AP_READ
+
+ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
+ orreq r2, r2, #HPTE_AP_WRITE
+
+ tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
+ movne r2, #0
+

+#ifdef CONFIG_CPU_ARM926_WRITETHROUGH
+ eor r3, r2, #0x0a @ C & small page?


+ tst r3, #0x0b
+ biceq r2, r2, #4
+#endif
+ str r2, [r0] @ hardware version
+ mov r0, r0

+#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+#endif
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+

+cpu_manu_name:
+ .asciz "ARM"
+ENTRY(cpu_arm926_name)
+ .ascii "ARM926EJ-S"
+#if defined(CONFIG_CPU_ARM926_CPU_IDLE)
+ .ascii "s"
+#endif
+#if defined(CONFIG_CPU_ARM926_I_CACHE_ON)
+ .ascii "i"
+#endif
+#if defined(CONFIG_CPU_ARM926_D_CACHE_ON)
+ .ascii "d"
+#if defined(CONFIG_CPU_ARM926_WRITETHROUGH)


+ .ascii "(wt)"
+#else
+ .ascii "(wb)"
+#endif

+#ifdef CONFIG_CPU_ARM926_ROUND_ROBIN
+ .ascii "RR"
+#endif


+#endif
+ .ascii "\0"
+ .align
+
+ .section ".text.init", #alloc, #execinstr
+

+__arm926_setup:


+ mov r0, #0
+ mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4
+ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
+ mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4
+ mcr p15, 0, r4, c2, c0 @ load page table pointer
+

+
+#if defined(CONFIG_CPU_ARM926_WRITETHROUGH)
+ mov r0, #4 @ disable write-back on caches explicitly
+ mcr p15, 7, r0, c15, c0, 0
+#endif
+


+ mov r0, #0x1f @ Domains 0, 1 = client
+ mcr p15, 0, r0, c3, c0 @ load domain access register
+ mrc p15, 0, r0, c1, c0 @ get control register v4
+/*
+ * Clear out 'unwanted' bits (then put them in if we need them)
+ */

+ @ VI ZFRS BLDP WCAM


+ bic r0, r0, #0x0e00

+ bic r0, r0, #0x0002

+ bic r0, r0, #0x000c

+ bic r0, r0, #0x1000 @ ...0 000. .... 000.


+/*
+ * Turn on what we want
+ */
+ orr r0, r0, #0x0031

+ orr r0, r0, #0x2100 @ ..1. ...1 ..11 ...1
+
+#ifdef CONFIG_CPU_ARM926_ROUND_ROBIN
+ orr r0, r0, #0x4000 @ .1.. .... .... ....
+#endif
+#ifdef CONFIG_CPU_ARM926_D_CACHE_ON
+ orr r0, r0, #0x0004 @ .... .... .... .1..
+#endif
+#ifdef CONFIG_CPU_ARM926_I_CACHE_ON
+ orr r0, r0, #0x1000 @ ...1 .... .... ....


+#endif
+ mov pc, lr
+
+ .text
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ * come through these
+ */

+ .type arm926_processor_functions, #object
+arm926_processor_functions:
+ .word cpu_arm926_data_abort
+ .word cpu_arm926_check_bugs
+ .word cpu_arm926_proc_init
+ .word cpu_arm926_proc_fin
+ .word cpu_arm926_reset
+ .word cpu_arm926_do_idle


+
+ /* cache */

+ .word cpu_arm926_cache_clean_invalidate_all
+ .word cpu_arm926_cache_clean_invalidate_range
+ .word cpu_arm926_flush_ram_page


+
+ /* dcache */

+ .word cpu_arm926_dcache_invalidate_range
+ .word cpu_arm926_dcache_clean_range
+ .word cpu_arm926_dcache_clean_page
+ .word cpu_arm926_dcache_clean_entry


+
+ /* icache */

+ .word cpu_arm926_icache_invalidate_range
+ .word cpu_arm926_icache_invalidate_page


+
+ /* tlb */

+ .word cpu_arm926_tlb_invalidate_all
+ .word cpu_arm926_tlb_invalidate_range
+ .word cpu_arm926_tlb_invalidate_page


+
+ /* pgtable */

+ .word cpu_arm926_set_pgd
+ .word cpu_arm926_set_pmd
+ .word cpu_arm926_set_pte
+ .size arm926_processor_functions, . - arm926_processor_functions
+
+ .type cpu_arm926_info, #object
+cpu_arm926_info:
+ .long cpu_manu_name
+ .long cpu_arm926_name
+ .size cpu_arm926_info, . - cpu_arm926_info


+
+ .type cpu_arch_name, #object
+cpu_arch_name:

+ .asciz "armv5EJ"


+ .size cpu_arch_name, . - cpu_arch_name
+
+ .type cpu_elf_name, #object
+cpu_elf_name:

+ .asciz "v5EJ"


+ .size cpu_elf_name, . - cpu_elf_name
+ .align
+
+ .section ".proc.info", #alloc, #execinstr
+

+ .type __arm926_proc_info,#object
+__arm926_proc_info:
+ .long 0x41009260
+ .long 0xff00fff0
+ .long 0x00000c1e @ mmuflags
+ b __arm926_setup


+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT

+ .long cpu_arm926_info
+ .long arm926_processor_functions
+ .size __arm926_proc_info, . - __arm926_proc_info
diff -u --recursive --new-file v2.4.14/linux/arch/arm/tools/mach-types linux/arch/arm/tools/mach-types
--- v2.4.14/linux/arch/arm/tools/mach-types Mon Nov 5 15:55:26 2001
+++ linux/arch/arm/tools/mach-types Fri Nov 9 13:58:02 2001
@@ -6,7 +6,7 @@
X # To add an entry into this database, please see Documentation/arm/README,
X # or contact r...@arm.linux.org.uk
X #
-# Last update: Mon Oct 22 09:49:06 2001
+# Last update: Fri Oct 26 17:37:13 2001
X #
X # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
X #
@@ -134,3 +134,6 @@
X epsilon1 SA1100_EPSILON1 EPSILON1 123
X balloon SA1100_BALLOON BALLOON 124
X puppy ARCH_PUPPY PUPPY 125
+elroy SA1100_ELROY ELROY 126
+gms720 ARCH_GMS720 GMS720 127
+s24x ARCH_S24X S24X 128
diff -u --recursive --new-file v2.4.14/linux/arch/cris/defconfig linux/arch/cris/defconfig
--- v2.4.14/linux/arch/cris/defconfig Tue Oct 9 17:06:51 2001
+++ linux/arch/cris/defconfig Fri Nov 9 13:58:02 2001
@@ -82,8 +82,9 @@
X CONFIG_NET_ETHERNET=y
X # CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK is not set
X CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY=y
-C# CONFIG_ETRAX_ETHERNET_LPSLAVE is not set
-ONFIG_ETRAX_SERIAL=y
+# CONFIG_ETRAX_ETHERNET_LPSLAVE is not set
+CONFIG_ETRAX_SERIAL=y
+CONFIG_ETRAX_SERIAL_PORT0=y
X # CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB is not set
X CONFIG_ETRAX_SERIAL_PORT1=y
X # CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_PB is not set
diff -u --recursive --new-file v2.4.14/linux/arch/cris/drivers/Config.in linux/arch/cris/drivers/Config.in
--- v2.4.14/linux/arch/cris/drivers/Config.in Tue Oct 9 17:06:51 2001
+++ linux/arch/cris/drivers/Config.in Fri Nov 9 13:58:02 2001
@@ -23,6 +23,14 @@
X
X bool 'Serial-port support' CONFIG_ETRAX_SERIAL
X if [ "$CONFIG_ETRAX_SERIAL" = "y" ]; then
+# bool ' Use fast timers for DMA flush and RS-485 timing' CONFIG_ETRAX_SERIAL_FAST_TIMER n
+ define_bool CONFIG_ETRAX_SERIAL_FAST_TIMER n
+ if [ "$CONFIG_ETRAX_SERIAL_FAST_TIMER" = "n" ]; then
+ bool ' Fast serial port DMA flush' CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
+ if [ "$CONFIG_ETRAX100_SERIAL_FLUSH_DMA_FAST" = "n" ]; then
+ int ' Receive flush timeout (ticks) ' CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS 5
+ fi
+ fi
X bool ' Serial port 0 enabled' CONFIG_ETRAX_SERIAL_PORT0
X if [ "$CONFIG_ETRAX_SERIAL_PORT0" = "y" ]; then
X bool ' Ser0 DTR, RI, DSR, CD on PB' CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB
diff -u --recursive --new-file v2.4.14/linux/arch/cris/drivers/axisflashmap.c linux/arch/cris/drivers/axisflashmap.c
--- v2.4.14/linux/arch/cris/drivers/axisflashmap.c Tue Oct 9 17:06:51 2001
+++ linux/arch/cris/drivers/axisflashmap.c Fri Nov 9 13:58:02 2001
@@ -11,6 +11,9 @@
X * partition split defined below.
X *
X * $Log: axisflashmap.c,v $
+ * Revision 1.15 2001/10/19 12:41:04 jonashg
+ * Name of probe has changed in MTD.
+ *
X * Revision 1.14 2001/09/21 07:14:10 jonashg
X * Made root filesystem (cramfs) use mtdblock driver when booting from flash.
X *
@@ -237,7 +240,9 @@
X printk(KERN_NOTICE "Axis flash mapping: %x at %x\n",
X WINDOW_SIZE, FLASH_CACHED_ADDR);
X
- mymtd = (struct mtd_info *)do_map_probe("cfi", &axis_map);
+#ifdef CONFIG_MTD_CFI
+ mymtd = (struct mtd_info *)do_map_probe("cfi_probe", &axis_map);
+#endif
X
X #ifdef CONFIG_MTD_AMDSTD
X if (!mymtd) {
diff -u --recursive --new-file v2.4.14/linux/arch/cris/drivers/gpio.c linux/arch/cris/drivers/gpio.c
--- v2.4.14/linux/arch/cris/drivers/gpio.c Wed Jul 25 17:10:17 2001
+++ linux/arch/cris/drivers/gpio.c Fri Nov 9 13:58:02 2001
@@ -1,4 +1,4 @@
-/* $Id: gpio.c,v 1.9 2001/05/04 14:16:07 matsfg Exp $
+/* $Id: gpio.c,v 1.11 2001/10/30 14:39:12 johana Exp $
X *
X * Etrax general port I/O device
X *
@@ -6,9 +6,18 @@
X *
X * Authors: Bjorn Wesen (initial version)
X * Ola Knutsson (LED handling)
- * Johan Adolfsson (read/set directions)
+ * Johan Adolfsson (read/set directions, write)
X *
X * $Log: gpio.c,v $
+ * Revision 1.11 2001/10/30 14:39:12 johana
+ * Added D() around gpio_write printk.
+ *
+ * Revision 1.10 2001/10/25 10:24:42 johana
+ * Added IO_CFG_WRITE_MODE ioctl and write method that can do fast
+ * bittoggling in the kernel. (This speeds up programming an FPGA with 450kB
+ * from ~60 seconds to 4 seconds).
+ * Added save_flags/cli/restore_flags in ioctl.
+ *
X * Revision 1.9 2001/05/04 14:16:07 matsfg
X * Corrected spelling error
X *
@@ -69,6 +78,8 @@
X
X static int gpio_ioctl(struct inode *inode, struct file *file,
X unsigned int cmd, unsigned long arg);
+static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
+ loff_t *off);
X static int gpio_open(struct inode *inode, struct file *filp);
X static int gpio_release(struct inode *inode, struct file *filp);
X static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait);
@@ -82,6 +93,9 @@
X unsigned char changeable_dir;
X unsigned char changeable_bits;
X unsigned char highalarm, lowalarm;
+ unsigned char clk_mask;
+ unsigned char data_mask;
+ unsigned char write_msb;
X wait_queue_head_t alarm_wq;
X int minor;
X };
@@ -139,6 +153,59 @@
X return 1;
X }
X
+static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
+ loff_t *off)
+{
+ struct gpio_private *priv = (struct gpio_private *)file->private_data;
+ unsigned char data, clk_mask, data_mask, write_msb;
+ unsigned long flags;
+ ssize_t retval = count;
+ if (verify_area(VERIFY_READ, buf, count))
+ {
+ return -EFAULT;
+ }
+ clk_mask = priv->clk_mask;
+ data_mask = priv->data_mask;
+ /* It must have been configured using the IO_CFG_WRITE_MODE */
+ /* Perhaps a better error code? */
+ if (clk_mask == 0 || data_mask == 0)
+ {
+ return -EPERM;
+ }
+ write_msb = priv->write_msb;
+ D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb));
+ while (count--) {
+ int i;
+ data = *buf++;
+ if (priv->write_msb) {
+ for (i = 7; i>=0;i--) {
+ save_flags(flags); cli();
+ *priv->port = *priv->shadow &= ~clk_mask;
+ if (data & 1<<i)
+ *priv->port = *priv->shadow |= data_mask;
+ else
+ *priv->port = *priv->shadow &= ~data_mask;
+ /* For FPGA: min 5.0ns (DCC) before CCLK high */
+ *priv->port = *priv->shadow |= clk_mask;
+ restore_flags(flags);
+ }
+ } else {
+ for (i = 0; i<=7;i++) {
+ save_flags(flags); cli();
+ *priv->port = *priv->shadow &= ~clk_mask;
+ if (data & 1<<i)
+ *priv->port = *priv->shadow |= data_mask;
+ else
+ *priv->port = *priv->shadow &= ~data_mask;
+ /* For FPGA: min 5.0ns (DCC) before CCLK high */
+ *priv->port = *priv->shadow |= clk_mask;
+ restore_flags(flags);
+ }
+ }
+ }
+ return retval;
+}
+
X static int
X gpio_open(struct inode *inode, struct file *filp)
X {
@@ -170,6 +237,8 @@
X
X priv->highalarm = 0;
X priv->lowalarm = 0;
+ priv->clk_mask = 0;
+ priv->data_mask = 0;
X init_waitqueue_head(&priv->alarm_wq);
X
X filp->private_data = (void *)priv;
@@ -209,8 +278,8 @@
X gpio_ioctl(struct inode *inode, struct file *file,
X unsigned int cmd, unsigned long arg)
X {
+ unsigned long flags;
X struct gpio_private *priv = (struct gpio_private *)file->private_data;
-
X if(_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
X return -EINVAL;
X }
@@ -220,14 +289,18 @@
X // read the port
X return *priv->port;
X case IO_SETBITS:
+ save_flags(flags); cli();
X // set changeable bits with a 1 in arg
X *priv->port = *priv->shadow |=
X ((unsigned char)arg & priv->changeable_bits);
+ restore_flags(flags);
X break;
X case IO_CLRBITS:
+ save_flags(flags); cli();
X // clear changeable bits with a 1 in arg
X *priv->port = *priv->shadow &=
X ~((unsigned char)arg & priv->changeable_bits);
+ restore_flags(flags);
X break;
X case IO_HIGHALARM:
X // set alarm when bits with 1 in arg go high
@@ -246,14 +319,18 @@
X /* Read direction 0=input 1=output */
X return *priv->dir_shadow;
X case IO_SETINPUT:
+ save_flags(flags); cli();
X /* Set direction 0=unchanged 1=input */
X *priv->dir = *priv->dir_shadow &=
X ~((unsigned char)arg & priv->changeable_dir);
+ restore_flags(flags);
X return *priv->dir_shadow;
X case IO_SETOUTPUT:
+ save_flags(flags); cli();
X /* Set direction 0=unchanged 1=output */
X *priv->dir = *priv->dir_shadow |=
X ((unsigned char)arg & priv->changeable_dir);
+ restore_flags(flags);
X return *priv->dir_shadow;
X case IO_SHUTDOWN:
X SOFT_SHUTDOWN();
@@ -265,6 +342,24 @@
X #else
X return 0;
X #endif
+ break;
+ case IO_CFG_WRITE_MODE:
+ priv->clk_mask = arg & 0xFF;
+ priv->data_mask = (arg >> 8) & 0xFF;
+ priv->write_msb = (arg >> 16) & 0x01;
+ /* Check if we're allowed to change the bits and
+ * the direction is correct
+ */
+ if (!((priv->clk_mask & priv->changeable_bits) &&
+ (priv->data_mask & priv->changeable_bits) &&
+ (priv->clk_mask & *priv->dir_shadow) &&
+ (priv->data_mask & *priv->dir_shadow)) )
+ {
+ priv->clk_mask = 0;
+ priv->data_mask = 0;
+ return -EPERM;
+ }
+ break;
X default:
X if(priv->minor == LEDS)
X return gpio_leds_ioctl(cmd, arg);
@@ -301,6 +396,7 @@
X owner: THIS_MODULE,
X poll: gpio_poll,
X ioctl: gpio_ioctl,
+ write: gpio_write,
X open: gpio_open,
X release: gpio_release,
X };
@@ -338,7 +434,7 @@
X
X #endif
X
- printk("ETRAX 100LX GPIO driver v2.1, (c) 2001 Axis Communications AB\n");
+ printk("ETRAX 100LX GPIO driver v2.2, (c) 2001 Axis Communications AB\n");
X
X return res;
X }
diff -u --recursive --new-file v2.4.14/linux/arch/cris/drivers/serial.c linux/arch/cris/drivers/serial.c
--- v2.4.14/linux/arch/cris/drivers/serial.c Tue Oct 9 17:06:51 2001
+++ linux/arch/cris/drivers/serial.c Fri Nov 9 13:58:02 2001
@@ -1,4 +1,4 @@
-/* $Id: serial.c,v 1.18 2001/09/24 09:27:22 pkj Exp $
+/* $Id: serial.c,v 1.23 2001/10/30 17:53:26 pkj Exp $
X *
X * Serial port driver for the ETRAX 100LX chip
X *
@@ -7,6 +7,27 @@
X * Many, many authors. Based once upon a time on serial.c for 16x50.
X *
X * $Log: serial.c,v $
+ * Revision 1.23 2001/10/30 17:53:26 pkj
+ * * Set info->uses_dma to 0 when a port is closed.
+ * * Mark the timer1 interrupt as a fast one (SA_INTERRUPT).
+ * * Call start_flush_timer() in start_receive() if
+ * CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST is defined.
+ *
+ * Revision 1.22 2001/10/30 17:44:03 pkj
+ * Use %lu for received and transmitted counters in line_info().
+ *
+ * Revision 1.21 2001/10/30 17:40:34 pkj
+ * Clean-up. The only change to functionality is that
+ * CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS(=5) is used instead of
+ * MAX_FLUSH_TIME(=8).
+ *
+ * Revision 1.20 2001/10/30 15:24:49 johana
+ * Added char_time stuff from 2.0 driver.
+ *
+ * Revision 1.19 2001/10/30 15:23:03 johana
+ * Merged with 1.13.2 branch + fixed indentation
+ * and changed CONFIG_ETRAX100_XYS to CONFIG_ETRAX_XYZ
+ *
X * Revision 1.18 2001/09/24 09:27:22 pkj
X * Completed ext_baud_table[] in cflag_to_baud() and cflag_to_etrax_baud().
X *
@@ -26,11 +47,19 @@
X * Revision 1.14 2001/08/15 07:31:23 bjarne
X * Introduced two new members to the e100_serial struct.
X * configured - Will be set to 1 if the port has been configured in .config
- * uses_dma - Should be set to 1 if the port uses DMA. Currently it is set to 1
+ * uses_dma - Should be set to 1 if the port uses DMA. Currently it is set
+ * to 1
X * when a port is opened. This is used to limit the DMA interrupt
X * routines to only manipulate DMA channels actually used by the
X * serial driver.
X *
+ * Revision 1.13.2.2 2001/10/17 13:57:13 starvik
+ * Receiver was broken by the break fixes
+ *
+ * Revision 1.13.2.1 2001/07/20 13:57:39 ronny
+ * Merge with new stuff from etrax100ser.c. Works but haven't checked stuff
+ * like break handling.
+ *
X * Revision 1.13 2001/05/09 12:40:31 johana
X * Use DMA_NBR and IRQ_NBR defines from dma.h and irq.h
X *
@@ -226,7 +255,7 @@
X *
X */
X
-static char *serial_version = "$Revision: 1.18 $";
+static char *serial_version = "$Revision: 1.23 $";
X
X #include <linux/config.h>
X #include <linux/version.h>
@@ -284,6 +313,11 @@
X #define SERIAL_TYPE_CALLOUT 2
X #endif
X
+#define DEBUG_LOG(line, string, value)
+
+/* Add an x here to log a lot of timer stuff */
+#define TIMERD(x)
+
X /* number of characters left in xmit buffer before we ask for more */
X #define WAKEUP_CHARS 256
X
@@ -299,8 +333,9 @@
X expect the first received event on the serial port to
X be an error, break or similar. Used to be able to flash IRMA
X from eLinux */
-//#define SERIAL_HANDLE_EARLY_ERRORS
+#define SERIAL_HANDLE_EARLY_ERRORS
X
+#define TTY_THROTTLE_LIMIT (TTY_FLIPBUF_SIZE/10)
X
X #ifndef CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS
X /* Default number of timer ticks before flushing rx fifo
@@ -310,8 +345,6 @@
X #define CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS 5
X #endif
X
-#define MAX_FLUSH_TIME 8
-
X #define _INLINE_ inline
X
X static void change_speed(struct e100_serial *info);
@@ -320,7 +353,7 @@
X const unsigned char *buf, int count);
X
X #define DEF_BAUD 0x99 /* 115.2 kbit/s */
-#define STD_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST )
+#define STD_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
X #define DEF_RX 0x20 /* or SERIAL_CTRL_W >> 8 */
X /* Default value of tx_ctrl register: has txd(bit 7)=1 (idle) as default */
X #define DEF_TX 0x80 /* or SERIAL_CTRL_B */
@@ -335,6 +368,22 @@
X #define REG_BAUD 3
X #define REG_XOFF 4 /* this is a 32 bit register */
X
+/* The bitfields are the same for all serial ports */
+#define SER_RXD_MASK IO_MASK(R_SERIAL0_STATUS, rxd)
+#define SER_DATA_AVAIL_MASK IO_MASK(R_SERIAL0_STATUS, data_avail)
+#define SER_FRAMING_ERR_MASK IO_MASK(R_SERIAL0_STATUS, framing_err)
+#define SER_PAR_ERR_MASK IO_MASK(R_SERIAL0_STATUS, par_err)
+#define SER_OVERRUN_MASK IO_MASK(R_SERIAL0_STATUS, overrun)
+
+#define SER_ERROR_MASK (SER_OVERRUN_MASK | SER_PAR_ERR_MASK | SER_FRAMING_ERR_MASK)
+
+/* Values for info->errorcode */
+#define ERRCODE_SET_BREAK (TTY_BREAK)
+#define ERRCODE_INSERT 0x100
+#define ERRCODE_INSERT_BREAK (ERRCODE_INSERT | TTY_BREAK)
+
+#define FORCE_EOP(info) *R_SET_EOP = 1U << info->iseteop;
+
X /*
X * General note regarding the use of IO_* macros in this file:
X *
@@ -413,6 +462,29 @@
X static struct termios *serial_termios[NR_PORTS];
X static struct termios *serial_termios_locked[NR_PORTS];
X
+#ifdef CONFIG_SERIAL_PROC_ENTRY
+#define PROCSTAT(x) x
+struct ser_statistics_type{
+ int overrun_cnt;
+ int early_errors_cnt;
+ int ser_ints_ok_cnt;
+ int errors_cnt;
+ unsigned long int processing_flip;
+ unsigned long processing_flip_still_room;
+ unsigned long int timeout_flush_cnt;
+ int rx_dma_ints;
+ int tx_dma_ints;
+ int rx_tot;
+ int tx_tot;
+};
+
+static struct ser_statistics_type ser_stat[NR_PORTS];
+
+#else
+
+#define PROCSTAT(x)
+
+#endif /* CONFIG_SERIAL_PROC_ENTRY */
X
X /* RS-485 */
X #if defined(CONFIG_ETRAX_RS485)
@@ -577,10 +649,34 @@
X /* enable timer1 irq */
X
X *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, timer1, set);
+
X fast_timer_started = 1;
X }
X #endif /* CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST */
X
+/* Calculate the chartime depending on baudrate, numbor of bits etc. */
+static void update_char_time(struct e100_serial * info)
+{
+ tcflag_t cflags = info->tty->termios->c_cflag;
+ int bits;
+
+ /* calc. number of bits / data byte */
+ /* databits + startbit and 1 stopbit */
+ if ((cflags & CSIZE) == CS7)
+ bits = 9;
+ else
+ bits = 10;
+
+ if (cflags & CSTOPB) /* 2 stopbits ? */
+ bits++;
+
+ if (cflags & PARENB) /* parity bit ? */
+ bits++;
+
+ /* calc timeout */
+ info->char_time_usec = ((bits * 1000000) / info->baud) + 1;
+}
+
X /*
X * This function maps from the Bxxxx defines in asm/termbits.h into real
X * baud rates.
@@ -642,7 +738,8 @@
X e100_dtr(struct e100_serial *info, int set)
X {
X #ifndef CONFIG_SVINTO_SIM
- unsigned char mask = ( 1 << e100_modem_pins[info->line].dtr_bit);
+ unsigned char mask = (1 << e100_modem_pins[info->line].dtr_bit);
+
X #ifdef SERIAL_DEBUG_IO
X printk("ser%i dtr %i mask: 0x%02X\n", info->line, set, mask);
X printk("ser%i shadow before 0x%02X get: %i\n",
@@ -651,7 +748,8 @@
X #endif
X /* DTR is active low */
X {
- unsigned long flags;
+ unsigned long flags;
+
X save_flags(flags);
X cli();
X *e100_modem_pins[info->line].shadow &= ~mask;
@@ -696,8 +794,9 @@
X #ifndef CONFIG_SVINTO_SIM
X /* RI is active low */
X {
- unsigned char mask = ( 1 << e100_modem_pins[info->line].ri_bit);
- unsigned long flags;
+ unsigned char mask = (1 << e100_modem_pins[info->line].ri_bit);
+ unsigned long flags;
+
X save_flags(flags);
X cli();
X *e100_modem_pins[info->line].shadow &= ~mask;
@@ -718,8 +817,9 @@
X #ifndef CONFIG_SVINTO_SIM
X /* CD is active low */
X {
- unsigned char mask = ( 1 << e100_modem_pins[info->line].cd_bit);
- unsigned long flags;
+ unsigned char mask = (1 << e100_modem_pins[info->line].cd_bit);
+ unsigned long flags;
+
X save_flags(flags);
X cli();
X *e100_modem_pins[info->line].shadow &= ~mask;
@@ -797,7 +897,7 @@
X
X #ifdef SERIAL_HANDLE_EARLY_ERRORS
X /* in order to detect and fix errors on the first byte
- we have to use the serial interrupts as well. */
+ we have to use the serial interrupts as well. */
X
X static inline void
X e100_disable_serial_data_irq(struct e100_serial *info)
@@ -860,7 +960,7 @@
X e100_disable_rxdma_irq(info);
X #endif
X
- if (info->rs485.delay_rts_before_send > 0){
+ if (info->rs485.delay_rts_before_send > 0) {
X current->timeout = jiffies + (info->rs485.delay_rts_before_send * HZ)/1000;
X current->state = TASK_INTERRUPTIBLE;
X schedule();
@@ -880,36 +980,38 @@
X
X /* calc. number of bits / data byte */
X cflags = info->tty->termios->c_cflag;
+
X /* databits + startbit and 1 stopbit */
- if((cflags & CSIZE) == CS7)
- bits = 9;
+ if ((cflags & CSIZE) == CS7)
+ bits = 9;
X else
- bits = 10;
+ bits = 10;
X
- if(cflags & CSTOPB) /* 2 stopbits ? */
- bits++;
+ if (cflags & CSTOPB) /* 2 stopbits ? */
+ bits++;
X
- if(cflags & PARENB) /* parity bit ? */
- bits++;
+ if (cflags & PARENB) /* parity bit ? */
+ bits++;
X
X /* calc timeout */
X delay_ms = ((bits * size * 1000) / info->baud) + 1;
X max_j = jiffies + (delay_ms * HZ)/1000 + 10;
X
- while (jiffies < max_j ) {
- if (info->port[REG_STATUS] &
- IO_STATE(R_SERIAL0_STATUS, tr_ready, ready)) {
- for( i=0 ; i<100; i++ ) {};
- if (info->port[REG_STATUS] &
- IO_STATE(R_SERIAL0_STATUS, tr_ready, ready)) {
- /* ~25 for loops per usec */
- stop_delay = 1000000 / info->baud;
- if(cflags & CSTOPB)
- stop_delay *= 2;
- udelay(stop_delay);
- break;
- }
- }
+ while (jiffies < max_j) {
+ if (info->port[REG_STATUS] &
+ IO_STATE(R_SERIAL0_STATUS, tr_ready, ready)) {
+ for (i = 0; i < 100; i++)
+ ;
+ if (info->port[REG_STATUS] &
+ IO_STATE(R_SERIAL0_STATUS, tr_ready, ready)) {
+ /* ~25 for loops per usec */
+ stop_delay = 1000000 / info->baud;
+ if (cflags & CSTOPB)
+ stop_delay *= 2;
+ udelay(stop_delay);
+ break;
+ }
+ }
X }
X
X e100_rts(info, info->rs485.rts_after_sent);
@@ -1004,9 +1106,9 @@
X * no-op - transmit_chars would never really be called during sim
X * since rs_write does not write into the xmit buffer then.
X */
- if(info->xmit.tail)
+ if (info->xmit.tail)
X printk("Error in serial.c:transmit_chars(), tail!=0\n");
- if(info->xmit.head != info->xmit.tail) {
+ if (info->xmit.head != info->xmit.tail) {
X SIMCOUT(info->xmit.buf + info->xmit.tail,
X CIRC_CNT(info->xmit.head,
X info->xmit.tail,
@@ -1022,10 +1124,10 @@
X IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
X
X #ifdef SERIAL_DEBUG_INTR
- if(info->line == SERIAL_DEBUG_LINE)
+ if (info->line == SERIAL_DEBUG_LINE)
X printk("tc\n");
X #endif
- if(!info->tr_running) {
+ if (!info->tr_running) {
X /* weirdo... we shouldn't get here! */
X printk("Achtung: transmit_chars with !tr_running\n");
X return;
@@ -1037,7 +1139,7 @@
X and update xmit accordingly */
X
X /* if the stop bit was not set, all data has been sent */
- if(!(descr->status & d_stop)) {
+ if (!(descr->status & d_stop)) {
X sentl = descr->sw_len;
X } else
X /* otherwise we find the amount of data sent here */
@@ -1060,7 +1162,7 @@
X
X c = CIRC_CNT_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
X
- if(c <= 0) {
+ if (c <= 0) {
X /* our job here is done, don't schedule any new DMA transfer */
X info->tr_running = 0;
X
@@ -1106,7 +1208,7 @@
X start_transmit(struct e100_serial *info)
X {
X #if 0
- if(info->line == SERIAL_DEBUG_LINE)
+ if (info->line == SERIAL_DEBUG_LINE)
X printk("x\n");
X #endif
X
@@ -1118,7 +1220,6 @@
X transmit_chars(info);
X }
X
-
X static _INLINE_ void
X receive_chars(struct e100_serial *info)
X {
@@ -1138,79 +1239,128 @@
X
X /* acknowledge both a dma_descr and dma_eop irq in R_DMAx_CLRINTR */
X
+ // ?
X *info->iclrintradr =
X IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
X IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
X
- if(!tty) /* something wrong... */
+ if (!tty) /* something wrong... */
X return;
X
X descr = &info->rec_descr;
-
+
X /* find out how many bytes were read */
X
X /* if the eop bit was not set, all data has been received */
- if(!(descr->status & d_eop)) {
+ if (!(descr->status & d_eop)) {
X recvl = descr->sw_len;
X } else {
X /* otherwise we find the amount of data received here */
X recvl = descr->hw_len;
X }
- if(recvl) {
- unsigned char *buf;
- struct async_icount *icount;
X
- icount = &info->icount;
-
- /* update stats */
- icount->rx += recvl;
+ /* read the status register so we can detect errors,
+ * but we can't really do anything about those errors
+ * anyway, since we have the DMA in "force eop at error" mode
+ * the fault characters are not in the buffer anyway.
+ */
X
- /* read the status register so we can detect errors */
- rstat = info->port[REG_STATUS];
+ rstat = info->port[REG_STATUS];
+
+ if ((rstat & SER_ERROR_MASK) != 0) {
+ unsigned char data;
+ /* if we got an error, we must reset it by reading the
+ * data_in field
+ */
+ data = info->port[REG_DATA];
+ PROCSTAT(ser_stat[info->line].errors_cnt++);
+ DEBUG_LOG(info->line, " #dERR: s d 0x%04X\n",
+ ((rstat & SER_ERROR_MASK) << 8) | data);
+ /* Only handle the saved error code, that indicates that we got
+ * the last character of a break that looks like it's ok, but
+ * is not
+ */
X
- if(rstat & (IO_MASK(R_SERIAL0_STATUS, overrun) |
- IO_MASK(R_SERIAL0_STATUS, par_err) |
- IO_MASK(R_SERIAL0_STATUS, framing_err))) {
- /* if we got an error, we must reset it by reading the
- * data_in field
+ if (info->errorcode == 0) {
+ *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ } else {
+ unsigned char data;
+ data = info->port[REG_DATA];
+ if (info->errorcode & ERRCODE_INSERT) {
+ unsigned char *currbuf;
+ /* Get the current buffer */
+ if (tty->flip.buf_num) {
+ currbuf = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
+ } else {
+ currbuf = tty->flip.char_buf;
+ }
+ /* We should insert a character in the buffer! */
+ if (recvl == 0) {
+ recvl = 1;
+ DEBUG_LOG(info->line, "insert to %lu\n", recvl);
+ } else {
+ /* Move stuff around.. */
+ DEBUG_LOG(info->line, "#insert to %lu!\n", recvl);
+ if (recvl < TTY_FLIPBUF_SIZE) {
+ int i;
+ /* Move the data 1 step right */
+ i = recvl;
+ while (i) {
+ currbuf[i] = currbuf[i-1];
+ i--;
+ }
+ recvl++;
+ } else {
+ /* We can't move it all! Skip break! */
+ /* TODO: Handle full buffer? */
+ DEBUG_LOG(info->line, "#BRK skipped! %lu!\n", recvl);
+ info->errorcode = 0;
+ }
+ }
+ }
+
+ PROCSTAT(ser_stat[info->line].errors_cnt++);
+ DEBUG_LOG(info->line, " #bERR: s d 0x%04X\n",
+ ((rstat & SER_ERROR_MASK) << 8) | data);
+ *tty->flip.flag_buf_ptr = (info->errorcode & 0xFF);
+ info->errorcode = 0;
+#if 0
+ printk("SERERR: 0x%02X data: 0x%02X\n", rstat & SER_ERROR_MASK, data);
+#endif
+ /* we only ever write errors into the first byte in
+ * the flip flag buffer, so we dont have to clear it
+ * all every time
X */
- (void)info->port[REG_DATA];
X }
-
- /* we only ever write errors into the first byte in the flip
- * flag buffer, so we dont have to clear it all every time
- */
+ }
X
- if(rstat & 0x04) {
- icount->parity++;
- *tty->flip.flag_buf_ptr = TTY_PARITY;
- } else if(rstat & 0x08) {
- icount->overrun++;
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- } else if(rstat & 0x02) {
- icount->frame++;
- *tty->flip.flag_buf_ptr = TTY_FRAME;
- } else
- *tty->flip.flag_buf_ptr = 0;
+ DEBUG_LOG(info->line, "recvl %lu\n", recvl);
+
+ if (recvl) {
+ unsigned char *buf;
+ struct async_icount *icount = &info->icount;
+
+ /* update stats */
+ icount->rx += recvl;
X
X /* use the flip buffer next in turn to restart DMA into */
-
+
X if (tty->flip.buf_num) {
X buf = tty->flip.char_buf;
X } else {
X buf = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
X }
X
- if(buf == phys_to_virt(descr->buf)) {
+ if (buf == phys_to_virt(descr->buf)) {
X printk("ttyS%d flip-buffer overrun!\n", info->line);
X icount->overrun++;
X *tty->flip.flag_buf_ptr = TTY_OVERRUN;
X /* restart old buffer */
X } else {
X descr->buf = virt_to_phys(buf);
-
+
X /* schedule or push a flip of the buffer */
-
+
X info->tty->flip.count = recvl;
X
X #if (LINUX_VERSION_CODE > 131394) /* 2.1.66 */
@@ -1221,9 +1371,9 @@
X #endif
X }
X }
-
+
X /* restart the receiving dma */
-
+
X descr->sw_len = TTY_FLIPBUF_SIZE;
X descr->ctrl = d_int | d_eol | d_eop;
X descr->hw_len = 0;
@@ -1236,6 +1386,10 @@
X e100_enable_serial_data_irq(info);
X #endif
X /* input dma should be running now */
+
+ /* unthrottle if we have throttled */
+ if (E100_RTS_GET(info))
+ tty->driver.unthrottle(info->tty);
X }
X
X static void
@@ -1253,8 +1407,8 @@
X /* reset the input dma channel to be sure it works */
X
X *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
- while(IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
- IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
+ while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
+ IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
X
X descr = &info->rec_descr;
X
@@ -1270,7 +1424,10 @@
X
X *info->ifirstadr = virt_to_phys(descr);
X *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, start);
-
+
+#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
+ start_flush_timer();
+#endif
X }
X
X
@@ -1313,12 +1470,12 @@
X
X ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */
X
- for(i = 0; i < NR_PORTS; i++) {
+ for (i = 0; i < NR_PORTS; i++) {
X info = rs_table + i;
X if (!info->uses_dma)
X continue;
X /* check for dma_descr (dont need to check for dma_eop in output dma for serial */
- if(ireg & info->irq) {
+ if (ireg & info->irq) {
X /* we can send a new dma bunch. make it so. */
X transmit_chars(info);
X }
@@ -1352,12 +1509,12 @@
X
X ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */
X
- for(i = 0; i < NR_PORTS; i++) {
+ for (i = 0; i < NR_PORTS; i++) {
X info = rs_table + i;
X if (!info->uses_dma)
X continue;
X /* check for both dma_eop and dma_descr for the input dma channel */
- if(ireg & ((info->irq << 2) | (info->irq << 3))) {
+ if (ireg & ((info->irq << 2) | (info->irq << 3))) {
X /* we have received something */
X receive_chars(info);
X }
@@ -1367,17 +1524,156 @@
X }
X }
X
+#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
+static int serial_fast_timer_started = 0;
+static int serial_fast_timer_expired = 0;
+static void flush_timeout_function(unsigned long data);
+#define START_FLUSH_FAST_TIMER(info, string) {\
+ unsigned long timer_flags; \
+ save_flags(timer_flags); \
+ cli(); \
+ TIMERD(DEBUG_LOG(info->line, "start_timer? %i ", info->line)); \
+ if (fast_timers[info->line].function == NULL) { \
+ serial_fast_timer_started++; \
+ TIMERD(DEBUG_LOG(info->line, "start_timer %i ", info->line)); \
+ TIMERD(DEBUG_LOG(info->line, "num started: %i\n", serial_fast_timer_started)); \
+ start_one_shot_timer(&fast_timers[info->line], \
+ flush_timeout_function, \
+ (unsigned long)info, \
+ info->char_time_usec*4, \
+ string); \
+ } \
+ else { \
+ /* DEBUG_LOG(info->line, " ## timer %i running ##\n", info->line); */ \
+ } \
+ restore_flags(timer_flags); \
+}
+
+#else
+#define START_FLUSH_FAST_TIMER(info, string)
+#endif
+
+void _INLINE_ check_flush_timeout(struct e100_serial *info)
+{
+ unsigned char rstat;
+ unsigned int magic;
+
+ if (0 /*info->tty->processing_flip*/) {
+ if (!E100_RTS_GET(info)) {
+ int left = (*info->ihwswadr >> 16) - (*info->istatusadr & 0x3F);
+
+ if (left < TTY_THROTTLE_LIMIT)
+ info->tty->driver.throttle(info->tty);
+ }
+
+ PROCSTAT(ser_stat[info->line].processing_flip++);
+ START_FLUSH_FAST_TIMER(info, "flip");
+ return;
+ }
+
+ /* We check data_avail bit to determine if data has
+ * arrived since last time
+ */
+ magic = info->fifo_magic;
+#ifdef SERIAL_DEBUG_DATA
+ if (info->fifo_magic || info->fifo_didmagic) {
+ DEBUG_LOG(info->line, "timeout_int: did fifo_magic %03X\n",
+ (info->fifo_didmagic << 8) | info->fifo_magic);
+ }
+#endif
+ rstat = info->port[REG_STATUS];
+ /* error or datavail? */
+ if (rstat & SER_ERROR_MASK) {
+ /* Some error has occured */
+ /* If there has been valid data,
+ * an EOP interrupt will be made automatically.
+ * If no data, the normal ser_interrupt should be enabled
+ * and handle it.
+ * So do nothing!
+ */
+ DEBUG_LOG(info->line, "timeout err: rstat 0x%03X\n",
+ rstat | (info->line << 8));
+ return;
+ }
+ if (rstat & SER_DATA_AVAIL_MASK) {
+ /* Ok data, no error, count it */
+ TIMERD(DEBUG_LOG(info->line, "timeout: rstat 0x%03X\n",
+ rstat | (info->line << 8)));
+ /* Read data to clear status flags */
+ (void)info->port[REG_DATA];
+
+ magic++;
+ }
+
+ if (magic != info->fifo_magic) {
+ info->fifo_magic = magic;
+ info->fifo_didmagic = 0;
+ START_FLUSH_FAST_TIMER(info, "magic");
+ } else {
+ /* hit the timeout, force an EOP for the input
+ * dma channel if we haven't already
+ */
+ if (!info->fifo_didmagic && magic) {
+ info->fifo_didmagic = 1;
+ info->fifo_magic = 0;
+ PROCSTAT(ser_stat[info->line].timeout_flush_cnt++);
+ DEBUG_LOG(info->line, "timeout EOP %i\n", info->line);
+ TIMERD(DEBUG_LOG(info->line, "timeout magic %i\n", magic));
+ FORCE_EOP(info);
+ }
+ }
+} /* check_flush_timeout */
+
+#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
+static void flush_timeout_function(unsigned long data)
+{
+ struct e100_serial *info = (struct e100_serial *)data;
+ fast_timers[info->line].function = NULL;
+ serial_fast_timer_expired++;
+ TIMERD(DEBUG_LOG(info->line, "flush_timout %i ", info->line));
+ TIMERD(DEBUG_LOG(info->line, "num expired: %i\n", serial_fast_timer_expired));
+ check_flush_timeout(info);
+}
+
+#elif defined(CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST)
+
+static void
+timeout_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct e100_serial *info;
+ int i;
+
+#ifdef CONFIG_SVINTO_SIM
+ /* No receive in the simulator. Will probably be when the rest of
+ * the serial interface works, and this piece will just be removed.
+ */
+ {
+ const char *s = "What? timeout_interrupt in simulator??\n";
+ SIMCOUT(s,strlen(s));
+ }
+ return;
+#endif
+
+ /* acknowledge the timer1 irq */
+ *R_TIMER_CTRL = r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i1, clr);
+ PROCSTAT(fast_timer_ints++);
+
+ for (i = 0; i < NR_PORTS; i++) {
+ info = rs_table + i;
+ if (info->uses_dma)
+ check_flush_timeout(info);
+ }
+} /* timeout_interrupt */
+
+#else
+
X /* dma fifo/buffer timeout handler
X forces an end-of-packet for the dma input channel if no chars
- have been received for CONFIG_ETRAX_RX_TIMEOUT_TICKS/100 s.
+ have been received for CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS/100 s.
X If CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST is configured then this
X handler is instead run at 15360 Hz.
X */
X
-#ifndef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
-static int timeout_divider = 0;
-#endif
-
X static struct timer_list flush_timer;
X
X static void
@@ -1391,9 +1687,9 @@
X return;
X #endif
X
- for(i = 0; i < NR_PORTS; i++) {
+ for (i = 0; i < NR_PORTS; i++) {
X info = rs_table + i;
- if(!info->enabled || !(info->flags & ASYNC_INITIALIZED))
+ if (!info->enabled || !(info->flags & ASYNC_INITIALIZED))
X continue;
X
X /* istatusadr (bit 6-0) hold number of bytes in fifo
@@ -1402,33 +1698,32 @@
X */
X
X magic = (*info->istatusadr & 0x3f);
- magic += ((*info->ihwswadr&0xffff ) - (*info->ihwswadr >> 16));
+ magic += ((*info->ihwswadr & 0xffff) - (*info->ihwswadr >> 16));
X
X /* if magic is equal to fifo_magic (magic in previous
X * timeout_interrupt) then no new data has arrived since last
X * interrupt and we'll force eop to flush fifo+dma buffers
X */
X
- if(magic != info->fifo_magic) {
+ if (magic != info->fifo_magic) {
X info->fifo_magic = magic;
X info->fifo_didmagic = 0;
X } else {
X /* hit the timeout, force an EOP for the input
X * dma channel if we haven't already
X */
- if(!info->fifo_didmagic && magic) {
+ if (!info->fifo_didmagic && magic) {
X info->fifo_didmagic = 1;
X info->fifo_magic = 0;
- *R_SET_EOP = 1U << info->iseteop;
+ FORCE_EOP(info);
X }
X }
X }
X
X /* restart flush timer */
-
- mod_timer(&flush_timer, jiffies + MAX_FLUSH_TIME);
+ mod_timer(&flush_timer, jiffies + CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS);
X }
-
+#endif
X
X #ifdef SERIAL_HANDLE_EARLY_ERRORS
X
@@ -1439,48 +1734,190 @@
X * interrupts off.
X */
X
+/*
+BREAK handling on ETRAX 100:
+ETRAX will generate interrupt although there is no stop bit between the
+characters.
+
+Depending on how long the break sequence is, the end of the breaksequence
+will look differently:
+| indicates start/end of a character.
+
+B= Break character (0x00) with framing error.
+E= Error byte with parity error received after B characters.
+F= "Faked" valid byte received immediatly after B characters.
+V= Valid byte
+
+1.
+ B BL ___________________________ V
+.._|__________|__________| |valid data |
+
+Multiple frame errors with data == 0x00 (B),
+the timing matches up "perfectly" so no extra ending char is detected.
+The RXD pin is 1 in the last interrupt, in that case
+we set info->errorcode = ERRCODE_INSERT_BREAK, but we can't really
+know if another byte will come and this really is case 2. below
+(e.g F=0xFF or 0xFE)
+If RXD pin is 0 we can expect another character (see 2. below).
+
+
+2.
+
+ B B E or F__________________..__ V
+.._|__________|__________|______ | |valid data
+ "valid" or
+ parity error
+
+Multiple frame errors with data == 0x00 (B),
+but the part of the break trigs is interpreted as a start bit (and possibly
+som 0 bits followed by a number of 1 bits and a stop bit).
+Depending on parity settings etc. this last character can be either
+a fake "valid" char (F) or have a parity error (E).
+
+If the character is valid it will be put in the buffer,
+we set info->errorcode = ERRCODE_SET_BREAK so the receive interrupt
+will set the flags so the tty will handle it,
+if it's an error byte it will not be put in the buffer
+and we set info->errorcode = ERRCODE_INSERT_BREAK.
+
+To distinguish a V byte in 1. from an F byte in 2. we keep a timestamp
+of the last faulty char (B) and compares it with the current time:
+If the time elapsed time is less then 2*char_time_usec we will assume
+it's a faked F char and not a Valid char and set
+info->errorcode = ERRCODE_SET_BREAK.
+
+Flaws in the above solution:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We use the timer to distinguish a F character from a V character,
+if a V character is to close after the break we might make the wrong decision.
+
+TODO: The break will be delayed until an F or V character is received.
+
+*/
+
+static void _INLINE_ handle_ser_interrupt(struct e100_serial *info)
+{
+ unsigned char rstat = info->port[REG_STATUS];
+
+#ifdef SERIAL_DEBUG_INTR
+ printk("Interrupt from serport %d\n", i);
+#endif
+/* DEBUG_LOG(info->line, "ser_interrupt stat %03X\n", rstat | (i << 8)); */
+ if (rstat & SER_ERROR_MASK) {
+ unsigned char data;
+ info->last_rx_active_usec = GET_JIFFIES_USEC();
+ info->last_rx_active = jiffies;
+ /* if we got an error, we must reset it by
+ * reading the data_in field
+ */
+ data = info->port[REG_DATA];
+
+ if ((data == 0x00) && (rstat & SER_FRAMING_ERR_MASK)) {
+ /* Most likely a break, but we get
+ * interrupts over and over again.
+ */
+
+ if (info->break_detected_cnt == 0) {
+ DEBUG_LOG(info->line, "#BRK start\n", 0);
+ }
+ if (rstat & SER_RXD_MASK) {
+ /* The RX pin is high now, so the break
+ * must be over, but....
+ * we can't really know if we will get another
+ * last byte ending the break or not.
+ * And we don't know if the byte (if any) will
+ * have an error or look valid.
+ */
+ DEBUG_LOG(info->line, "# BL BRK\n", 0);
+ info->errorcode = ERRCODE_INSERT_BREAK;
+ }
+ info->break_detected_cnt++;
+ } else {
+ /* Error doesn't look like a break,
+ * but could be end of a break
+ */
+ if (info->break_detected_cnt) {
+ DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt);
+ info->errorcode = ERRCODE_INSERT_BREAK;
+ }
+ info->break_detected_cnt = 0;
+ DEBUG_LOG(info->line, "#iERR s d %04X\n",
+ ((rstat & SER_ERROR_MASK) << 8) | data);
+ }
+ PROCSTAT(ser_stat[info->line].early_errors_cnt++);
+
+#if 0
+ /* Reset DMA before starting */
+ *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
+ while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
+ IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
+#endif
+ } else { /* it was a valid byte, now let the dma do the rest */
+ unsigned char data;
+ unsigned long curr_time_u = GET_JIFFIES_USEC();
+ unsigned long curr_time = jiffies;
+
+ if (info->break_detected_cnt) {
+ /* Detect if this character is a new
+ * valid char or the last char in a
+ * break sequence:
+ * If LSBits are 0 and MSBits are high
+ * AND the time is close to the
+ * previous interrupt we should discard
+ * it.
+ */
+ long elapsed_usec =
+ (curr_time - info->last_rx_active) * (1000000/HZ) +
+ curr_time_u - info->last_rx_active_usec;
+ if (elapsed_usec<2*info->char_time_usec) {
+ DEBUG_LOG(info->line, "FBRK %i\n", info->line);
+ /* Report as BREAK (error) and
+ * let receive_chars handle it
+ */
+ info->errorcode = ERRCODE_SET_BREAK;
+ } else {
+ DEBUG_LOG(info->line, "Not end of BRK (V)%i\n", info->line);
+ }
+ DEBUG_LOG(info->line, "num brk %i\n", info->break_detected_cnt);
+ }
+ /* Reset data_avail by
+ * reading the data_in field
+ */
+ data = info->port[REG_DATA];
+ info->break_detected_cnt = 0;
+ info->fifo_magic++; /* Count received chars */
+#ifdef SERIAL_DEBUG_INTR
+ printk("** OK, disabling ser_interupts\n");
+#endif
+ PROCSTAT(ser_stat[info->line].ser_ints_ok_cnt++);
+ DEBUG_LOG(info->line, " ser_int OK %03X\n",
+ (info->line << 8) | data);
+ e100_disable_serial_data_irq(info);
+ }
+
+ /* restart the DMA never hurts */
+ *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart);
+ START_FLUSH_FAST_TIMER(info, "ser_int");
+} /* handle_ser_interrupt */
+
X static void
X ser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
X {
X struct e100_serial *info;
X int i;
- unsigned char rstat;
X
- for(i = 0; i < NR_PORTS; i++) {
+ for (i = 0; i < NR_PORTS; i++) {
X info = rs_table + i;
+
X if (!info->uses_dma)
X continue;
- rstat = info->port[REG_STATUS];
-
- if(*R_IRQ_MASK1_RD & (1U << (8+2*info->line))) { /* This line caused the irq */
-#ifdef SERIAL_DEBUG_INTR
- printk("Interrupt from serport %d\n", i);
-#endif
- if(rstat & 0x0e) {
- /* FIXME: This is weird, but if this delay is
- * not present then irmaflash does not work...
- */
- udelay(2300);
X
- /* if we got an error, we must reset it by
- * reading the data_in field
- */
- (void)info->port[REG_DATA];
-
- PROCSTAT(early_errors_cnt[info->line]++);
-
- /* restart the DMA */
- *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart);
- }
- else { /* it was a valid byte, now let the dma do the rest */
-#ifdef SERIAL_DEBUG_INTR
- printk("** OK, disabling ser_interrupts\n");
-#endif
- e100_disable_serial_data_irq(info);
- }
+ /* Which line caused the irq? */
+ if (*R_IRQ_MASK1_RD & (1U << (8+2*info->line))) {
+ handle_ser_interrupt(info);
X }
X }
-}
+} /* ser_interrupt */
X #endif
X
X /*
@@ -1573,7 +2010,7 @@
X printk("starting up ttyS%d (xmit_buf 0x%x)...\n", info->line, info->xmit.buf);
X #endif
X
- if(info->tty) {
+ if (info->tty) {
X
X /* clear the tty flip flag buffer since we will not
X * be using it (we only use the first byte..)
@@ -1612,11 +2049,11 @@
X *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
X
X /* wait until reset cycle is complete */
- while(IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
- IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
+ while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
+ IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
X
- while(IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->ocmdadr) ==
- IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
+ while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->ocmdadr) ==
+ IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
X
X *info->iclrintradr =
X IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
@@ -1697,6 +2134,7 @@
X
X *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
X *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
+ info->uses_dma = 0;
X
X #endif /* CONFIG_SVINTO_SIM */
X
@@ -1740,7 +2178,7 @@
X
X /* first some safety checks */
X
- if(!info->tty || !info->tty->termios)
+ if (!info->tty || !info->tty->termios)
X return;
X if (!info->port)
X return;
@@ -1807,9 +2245,10 @@
X info->port[REG_TR_CTRL] = info->tx_ctrl;
X info->port[REG_REC_CTRL] = info->rx_ctrl;
X *((unsigned long *)&info->port[REG_XOFF]) = 0;
+#endif /* !CONFIG_SVINTO_SIM */
X
-#endif /* CONFIG_SVINTO_SIM */
-}
+ update_char_time(info);
+} /* change_speed */
X
X /* start transmitting chars NOW */
X
@@ -1852,7 +2291,7 @@
X return 0;
X
X #ifdef SERIAL_DEBUG_DATA
- if(info->line == SERIAL_DEBUG_LINE)
+ if (info->line == SERIAL_DEBUG_LINE)
X printk("rs_write (%d), status %d\n",
X count, info->port[REG_STATUS]);
X #endif
@@ -1871,7 +2310,7 @@
X * atomic operation... this could perhaps be avoided by more clever
X * design.
X */
- if(from_user) {
+ if (from_user) {
X down(&tmp_buf_sem);
X while (1) {
X int c1;
@@ -1906,7 +2345,7 @@
X up(&tmp_buf_sem);
X } else {
X cli();
- while(1) {
+ while (1) {
X c = CIRC_SPACE_TO_END(info->xmit.head,
X info->xmit.tail,
X SERIAL_XMIT_SIZE);
@@ -1931,10 +2370,10 @@
X * the IRQ's are not running anyway for this port.
X */
X
- if(info->xmit.head != info->xmit.tail
- && !tty->stopped &&
- !tty->hw_stopped &&
- !info->tr_running) {
+ if (info->xmit.head != info->xmit.tail
+ && !tty->stopped &&
+ !tty->hw_stopped &&
+ !info->tr_running) {
X start_transmit(info);
X }
X
@@ -2107,11 +2546,11 @@
X
X old_info = *info;
X
- if(!capable(CAP_SYS_ADMIN)) {
- if((new_serial.type != info->type) ||
- (new_serial.close_delay != info->close_delay) ||
- ((new_serial.flags & ~ASYNC_USR_MASK) !=
- (info->flags & ~ASYNC_USR_MASK)))
+ if (!capable(CAP_SYS_ADMIN)) {
+ if ((new_serial.type != info->type) ||
+ (new_serial.close_delay != info->close_delay) ||
+ ((new_serial.flags & ~ASYNC_USR_MASK) !=
+ (info->flags & ~ASYNC_USR_MASK)))
X return -EPERM;
X info->flags = ((info->flags & ~ASYNC_USR_MASK) |
X (new_serial.flags & ASYNC_USR_MASK));
@@ -2136,7 +2575,7 @@
X #endif
X
X check_and_exit:
- if(info->flags & ASYNC_INITIALIZED) {
+ if (info->flags & ASYNC_INITIALIZED) {
X change_speed(info);
X } else
X retval = startup(info);
@@ -2156,16 +2595,18 @@
X static int
X get_lsr_info(struct e100_serial * info, unsigned int *value)
X {
- unsigned int result;
+ unsigned int result = TIOCSER_TEMT;
+#ifndef CONFIG_SVINTO_SIM
+ unsigned long curr_time = jiffies;
+ unsigned long curr_time_usec = GET_JIFFIES_USEC();
+ unsigned long elapsed_usec =
+ (curr_time - info->last_tx_active) * 1000000/HZ +
+ curr_time_usec - info->last_tx_active_usec;
X
-#ifdef CONFIG_SVINTO_SIM
- /* Always open. */
- result = TIOCSER_TEMT;
-#else
- if (*info->ostatusadr & 0x007F) /* something in fifo */
+ if (info->xmit.head != info->xmit.tail ||
+ elapsed_usec < 2*info->char_time_usec) {
X result = 0;
- else
- result = TIOCSER_TEMT;
+ }
X #endif
X
X if (copy_to_user(value, &result, sizeof(int)))
@@ -2178,10 +2619,9 @@
X {
X int state;
X const char *str;
-
X };
X
-const struct state_str control_state_str[]={
+const struct state_str control_state_str[] = {
X {TIOCM_DTR, "DTR" },
X {TIOCM_RTS, "RTS"},
X {TIOCM_ST, "ST?" },
@@ -2612,20 +3052,31 @@
X {
X unsigned long orig_jiffies;
X struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+ unsigned long curr_time = jiffies;
+ unsigned long curr_time_usec = GET_JIFFIES_USEC();
+ long elapsed_usec =
+ (curr_time - info->last_tx_active) * (1000000/HZ) +
+ curr_time_usec - info->last_tx_active_usec;
X
X /*
X * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO
X * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k)
X */
X orig_jiffies = jiffies;
- while(info->xmit.head != info->xmit.tail || /* More in send queue */
- (*info->ostatusadr & 0x007f)) { /* more in FIFO */
+ while (info->xmit.head != info->xmit.tail || /* More in send queue */
+ (*info->ostatusadr & 0x007f) || /* more in FIFO */
+ (elapsed_usec < 2*info->char_time_usec)) {
X set_current_state(TASK_INTERRUPTIBLE);
X schedule_timeout(1);
X if (signal_pending(current))
X break;
X if (timeout && time_after(jiffies, orig_jiffies + timeout))
X break;
+ curr_time = jiffies;
+ curr_time_usec = GET_JIFFIES_USEC();
+ elapsed_usec =
+ (curr_time - info->last_tx_active) * (1000000/HZ) +
+ curr_time_usec - info->last_tx_active_usec;
X }
X set_current_state(TASK_RUNNING);
X }
@@ -2809,10 +3260,11 @@
X return -ENODEV;
X
X /* find the corresponding e100_serial struct in the table */
-
X info = rs_table + line;
- /* dont allow the opening of ports that are not enabled in the HW config */
- if (!info->enabled) return -ENODEV;
+
+ /* don't allow the opening of ports that are not enabled in the HW config */
+ if (!info->enabled)
+ return -ENODEV;
X
X #ifdef SERIAL_DEBUG_OPEN
X printk("[%d] rs_open %s%d, count = %d\n", current->pid,
@@ -2923,20 +3375,20 @@
X
X ret += sprintf(buf+ret, " baud:%d", info->baud);
X
- ret += sprintf(buf+ret, " tx:%d rx:%d",
- info->icount.tx, info->icount.rx);
+ ret += sprintf(buf+ret, " tx:%lu rx:%lu",
+ info->icount.tx, info->icount.rx);
X
X if (info->icount.frame)
- ret += sprintf(buf+ret, " fe:%d", info->icount.frame);
+ ret += sprintf(buf+ret, " fe:%lu", info->icount.frame);
X
X if (info->icount.parity)
- ret += sprintf(buf+ret, " pe:%d", info->icount.parity);
+ ret += sprintf(buf+ret, " pe:%lu", info->icount.parity);
X
X if (info->icount.brk)
- ret += sprintf(buf+ret, " brk:%d", info->icount.brk);
+ ret += sprintf(buf+ret, " brk:%lu", info->icount.brk);
X
X if (info->icount.overrun)
- ret += sprintf(buf+ret, " oe:%d", info->icount.overrun);
+ ret += sprintf(buf+ret, " oe:%lu", info->icount.overrun);
X
X /*
X * Last thing is the RS-232 status lines
@@ -2996,9 +3448,11 @@
X
X /* Setup the timed flush handler system */
X
+#if !defined(CONFIG_ETRAX_SERIAL_FAST_TIMER) && !defined(CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST)
X init_timer(&flush_timer);
X flush_timer.function = timed_flush_handler;
- mod_timer(&flush_timer, jiffies + MAX_FLUSH_TIME);
+ mod_timer(&flush_timer, jiffies + CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS);
+#endif
X
X /* Initialize the tty_driver structure */
X
@@ -3089,6 +3543,7 @@
X init_waitqueue_head(&info->close_wait);
X info->xmit.buf = 0;
X info->xmit.tail = info->xmit.head = 0;
+
X if (info->enabled) {
X printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n",
X serial_driver.name, info->line, (unsigned int)info->port);
@@ -3099,38 +3554,38 @@
X /* Not needed in simulator. May only complicate stuff. */
X /* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */
X #ifdef CONFIG_ETRAX_SERIAL_PORT0
- if(request_irq(SER0_DMA_TX_IRQ_NBR, tr_interrupt, SA_INTERRUPT, "serial 0 dma tr", NULL))
+ if (request_irq(SER0_DMA_TX_IRQ_NBR, tr_interrupt, SA_INTERRUPT, "serial 0 dma tr", NULL))
X panic("irq22");
- if(request_irq(SER0_DMA_RX_IRQ_NBR, rec_interrupt, SA_INTERRUPT, "serial 0 dma rec", NULL))
+ if (request_irq(SER0_DMA_RX_IRQ_NBR, rec_interrupt, SA_INTERRUPT, "serial 0 dma rec", NULL))
X panic("irq23");
X #endif
X #ifdef SERIAL_HANDLE_EARLY_ERRORS
- if(request_irq(SERIAL_IRQ_NBR, ser_interrupt, SA_INTERRUPT, "serial ", NULL))
+ if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, SA_INTERRUPT, "serial ", NULL))
X panic("irq8");
X #endif
X #ifdef CONFIG_ETRAX_SERIAL_PORT1
- if(request_irq(SER1_DMA_TX_IRQ_NBR, tr_interrupt, SA_INTERRUPT, "serial 1 dma tr", NULL))
+ if (request_irq(SER1_DMA_TX_IRQ_NBR, tr_interrupt, SA_INTERRUPT, "serial 1 dma tr", NULL))
X panic("irq24");
- if(request_irq(SER1_DMA_RX_IRQ_NBR, rec_interrupt, SA_INTERRUPT, "serial 1 dma rec", NULL))
+ if (request_irq(SER1_DMA_RX_IRQ_NBR, rec_interrupt, SA_INTERRUPT, "serial 1 dma rec", NULL))
X panic("irq25");
X #endif
X #ifdef CONFIG_ETRAX_SERIAL_PORT2
X /* DMA Shared with par0 (and SCSI0 and ATA) */
- if(request_irq(SER2_DMA_TX_IRQ_NBR, tr_interrupt, SA_SHIRQ, "serial 2 dma tr", NULL))
+ if (request_irq(SER2_DMA_TX_IRQ_NBR, tr_interrupt, SA_SHIRQ, "serial 2 dma tr", NULL))
X panic("irq18");
- if(request_irq(SER2_DMA_RX_IRQ_NBR, rec_interrupt, SA_SHIRQ, "serial 2 dma rec", NULL))
+ if (request_irq(SER2_DMA_RX_IRQ_NBR, rec_interrupt, SA_SHIRQ, "serial 2 dma rec", NULL))
X panic("irq19");
X #endif
X #ifdef CONFIG_ETRAX_SERIAL_PORT3
X /* DMA Shared with par1 (and SCSI1 and Extern DMA 0) */
- if(request_irq(SER3_DMA_TX_IRQ_NBR, tr_interrupt, SA_SHIRQ, "serial 3 dma tr", NULL))
+ if (request_irq(SER3_DMA_TX_IRQ_NBR, tr_interrupt, SA_SHIRQ, "serial 3 dma tr", NULL))
X panic("irq20");
- if(request_irq(SER3_DMA_RX_IRQ_NBR, rec_interrupt, SA_SHIRQ, "serial 3 dma rec", NULL))
+ if (request_irq(SER3_DMA_RX_IRQ_NBR, rec_interrupt, SA_SHIRQ, "serial 3 dma rec", NULL))
X panic("irq21");
X #endif
+
X #ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
- /* TODO: a timeout_interrupt needs to be written that calls timeout_handler */
- if(request_irq(TIMER1_IRQ_NBR, timeout_interrupt, SA_SHIRQ,
+ if (request_irq(TIMER1_IRQ_NBR, timeout_interrupt, SA_SHIRQ | SA_INTERRUPT,
X "fast serial dma timeout", NULL)) {
X printk("err: timer1 irq\n");
X }
diff -u --recursive --new-file v2.4.14/linux/arch/cris/drivers/serial.h linux/arch/cris/drivers/serial.h
--- v2.4.14/linux/arch/cris/drivers/serial.h Tue Oct 9 17:06:51 2001
+++ linux/arch/cris/drivers/serial.h Fri Nov 9 13:58:02 2001
@@ -87,6 +87,15 @@
X struct wait_queue *close_wait;
X #endif
X
+ unsigned long char_time_usec; /* The time for 1 char, in usecs */
+ unsigned long last_tx_active_usec; /* Last tx usec in the jiffies */
+ unsigned long last_tx_active; /* Last tx time in jiffies */
+ unsigned long last_rx_active_usec; /* Last rx usec in the jiffies */
+ unsigned long last_rx_active; /* Last rx time in jiffies */
+
+ int break_detected_cnt;
+ int errorcode;
+
X #ifdef CONFIG_RS485
X struct rs485_control rs485; /* RS-485 support */
X #endif
diff -u --recursive --new-file v2.4.14/linux/arch/cris/kernel/Makefile linux/arch/cris/kernel/Makefile


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

echo 'End of part 022'
echo 'File patch-2.4.15 is continued in part 023'
echo "023" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:59 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part023

#!/bin/sh -x
# this is part 023 of a 115 - part archive


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

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

--- v2.4.14/linux/arch/cris/kernel/Makefile Tue Oct 9 17:06:51 2001
+++ linux/arch/cris/kernel/Makefile Fri Nov 9 13:58:02 2001
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.8 2001/10/01 14:44:07 bjornw Exp $
+# $Id: Makefile,v 1.9 2001/10/22 13:10:21 pkj Exp $
X #
X # Makefile for the linux kernel.
X #
@@ -16,6 +16,9 @@
X all: kernel.o head.o
X
X O_TARGET := kernel.o
+
+export-objs := ksyms.o
+
X obj-y := process.o signal.o entry.o traps.o irq.o \
X ptrace.o setup.o time.o sys_cris.o shadows.o \
X debugport.o semaphore.o
diff -u --recursive --new-file v2.4.14/linux/arch/cris/kernel/entry.S linux/arch/cris/kernel/entry.S
--- v2.4.14/linux/arch/cris/kernel/entry.S Tue Oct 9 17:06:51 2001
+++ linux/arch/cris/kernel/entry.S Fri Nov 9 13:58:02 2001
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.34 2001/10/01 14:45:03 bjornw Exp $
+/* $Id: entry.S,v 1.35 2001/10/30 17:10:15 bjornw Exp $
X *
X * linux/arch/cris/entry.S
X *
@@ -7,6 +7,9 @@
X * Authors: Bjorn Wesen (bjo...@axis.com)
X *
X * $Log: entry.S,v $
+ * Revision 1.35 2001/10/30 17:10:15 bjornw
+ * Add some syscalls
+ *
X * Revision 1.34 2001/10/01 14:45:03 bjornw
X * Removed underscores and added register prefixes
X *
@@ -981,6 +984,9 @@
X .long SYMBOL_NAME(sys_getdents64) /* 220 */
X .long SYMBOL_NAME(sys_fcntl64)
X .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */
+ .long SYMBOL_NAME(sys_ni_syscall) /* Reserved for Security */
+ .long SYMBOL_NAME(sys_gettid)
+ .long SYMBOL_NAME(sys_readahead) /* 225 */
X
X /*
X * NOTE!! This doesn't have to be exact - we just have
@@ -989,7 +995,7 @@
X * been shrunk every time we add a new system call.
X */
X
- .rept NR_syscalls-222
+ .rept NR_syscalls-(.-sys_call_table)/4
X .long SYMBOL_NAME(sys_ni_syscall)
X .endr
X
diff -u --recursive --new-file v2.4.14/linux/arch/cris/kernel/head.S linux/arch/cris/kernel/head.S
--- v2.4.14/linux/arch/cris/kernel/head.S Tue Oct 9 17:06:51 2001
+++ linux/arch/cris/kernel/head.S Fri Nov 9 13:58:02 2001
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.40 2001/10/03 14:59:57 pkj Exp $
+/* $Id: head.S,v 1.41 2001/10/29 14:55:58 pkj Exp $
X *
X * Head of the kernel - alter with care
X *
@@ -7,6 +7,9 @@
X * Authors: Bjorn Wesen (bjo...@axis.com)
X *
X * $Log: head.S,v $
+ * Revision 1.41 2001/10/29 14:55:58 pkj
+ * Corrected pa$r0 to par0.
+ *
X * Revision 1.40 2001/10/03 14:59:57 pkj
X * Added support for resetting the Bluetooth hardware.
X *
@@ -520,7 +523,7 @@
X moveq 0,$r0
X #if (!defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT0)) \
X && !defined(CONFIG_DMA_MEMCPY)
- ; DMA channels 6 and 7 to se$r0, kgdb doesnt want DMA
+ ; DMA channels 6 and 7 to ser0, kgdb doesnt want DMA
X or.d IO_STATE (R_GEN_CONFIG, dma7, serial0) \
X | IO_STATE (R_GEN_CONFIG, dma6, serial0),$r0
X #endif
@@ -554,7 +557,7 @@
X #endif
X #if defined(CONFIG_ETRAX_PARALLEL_PORT0) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
X ; parport 0 enabled using DMA 2/3
- or.w IO_STATE (R_GEN_CONFIG, pa$r0, select),$r0
+ or.w IO_STATE (R_GEN_CONFIG, par0, select),$r0
X #endif
X #if defined(CONFIG_ETRAX_PARALLEL_PORT1) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
X ; parport 1 enabled using DMA 4/5
diff -u --recursive --new-file v2.4.14/linux/arch/cris/kernel/kgdb.c linux/arch/cris/kernel/kgdb.c
--- v2.4.14/linux/arch/cris/kernel/kgdb.c Tue May 1 16:04:56 2001
+++ linux/arch/cris/kernel/kgdb.c Fri Nov 9 13:58:02 2001
@@ -18,6 +18,9 @@
X *! Jul 21 1999 Bjorn Wesen eLinux port
X *!
X *! $Log: kgdb.c,v $
+*! Revision 1.6 2001/10/09 13:10:03 matsfg
+*! Added $ on registers and removed some underscores
+*!
X *! Revision 1.5 2001/04/17 13:58:39 orjanf
X *! * Renamed CONFIG_KGDB to CONFIG_ETRAX_KGDB.
X *!
@@ -52,7 +55,7 @@
X *!
X *!---------------------------------------------------------------------------
X *!
-*! $Id: kgdb.c,v 1.5 2001/04/17 13:58:39 orjanf Exp $
+*! $Id: kgdb.c,v 1.6 2001/10/09 13:10:03 matsfg Exp $
X *!
X *! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN
X *!
@@ -1343,90 +1346,90 @@
X void kgdb_handle_breakpoint(void);
X
X asm ("
- .global _kgdb_handle_breakpoint
-_kgdb_handle_breakpoint:
+ .global kgdb_handle_breakpoint
+kgdb_handle_breakpoint:
X ;;
X ;; Response to the break-instruction
X ;;
X ;; Create a register image of the caller
X ;;
- move dccr,[_reg+0x5E] ; Save the flags in DCCR before disable interrupts
+ move $dccr,[reg+0x5E] ; Save the flags in DCCR before disable interrupts
X di ; Disable interrupts
- move.d r0,[_reg] ; Save R0
- move.d r1,[_reg+0x04] ; Save R1
- move.d r2,[_reg+0x08] ; Save R2
- move.d r3,[_reg+0x0C] ; Save R3
- move.d r4,[_reg+0x10] ; Save R4
- move.d r5,[_reg+0x14] ; Save R5
- move.d r6,[_reg+0x18] ; Save R6
- move.d r7,[_reg+0x1C] ; Save R7
- move.d r8,[_reg+0x20] ; Save R8
- move.d r9,[_reg+0x24] ; Save R9
- move.d r10,[_reg+0x28] ; Save R10
- move.d r11,[_reg+0x2C] ; Save R11
- move.d r12,[_reg+0x30] ; Save R12
- move.d r13,[_reg+0x34] ; Save R13
- move.d sp,[_reg+0x38] ; Save SP (R14)
+ move.d $r0,[reg] ; Save R0
+ move.d $r1,[reg+0x04] ; Save R1
+ move.d $r2,[reg+0x08] ; Save R2
+ move.d $r3,[reg+0x0C] ; Save R3
+ move.d $r4,[reg+0x10] ; Save R4
+ move.d $r5,[reg+0x14] ; Save R5
+ move.d $r6,[reg+0x18] ; Save R6
+ move.d $r7,[reg+0x1C] ; Save R7
+ move.d $r8,[reg+0x20] ; Save R8
+ move.d $r9,[reg+0x24] ; Save R9
+ move.d $r10,[reg+0x28] ; Save R10
+ move.d $r11,[reg+0x2C] ; Save R11
+ move.d $r12,[reg+0x30] ; Save R12
+ move.d $r13,[reg+0x34] ; Save R13
+ move.d $sp,[reg+0x38] ; Save SP (R14)
X ;; Due to the old assembler-versions BRP might not be recognized
- .word 0xE670 ; move brp,r0
- subq 2,r0 ; Set to address of previous instruction.
- move.d r0,[_reg+0x3c] ; Save the address in PC (R15)
- clear.b [_reg+0x40] ; Clear P0
- move vr,[_reg+0x41] ; Save special register P1
- clear.w [_reg+0x42] ; Clear P4
- move ccr,[_reg+0x44] ; Save special register CCR
- move mof,[_reg+0x46] ; P7
- clear.d [_reg+0x4A] ; Clear P8
- move ibr,[_reg+0x4E] ; P9,
- move irp,[_reg+0x52] ; P10,
- move srp,[_reg+0x56] ; P11,
- move dtp0,[_reg+0x5A] ; P12, register BAR, assembler might not know BAR
+ .word 0xE670 ; move brp,$r0
+ subq 2,$r0 ; Set to address of previous instruction.
+ move.d $r0,[reg+0x3c] ; Save the address in PC (R15)
+ clear.b [reg+0x40] ; Clear P0
+ move $vr,[reg+0x41] ; Save special register P1
+ clear.w [reg+0x42] ; Clear P4
+ move $ccr,[reg+0x44] ; Save special register CCR
+ move $mof,[reg+0x46] ; P7
+ clear.d [reg+0x4A] ; Clear P8
+ move $ibr,[reg+0x4E] ; P9,
+ move $irp,[reg+0x52] ; P10,
+ move $srp,[reg+0x56] ; P11,
+ move $dtp0,[reg+0x5A] ; P12, register BAR, assembler might not know BAR
X ; P13, register DCCR already saved
X ;; Due to the old assembler-versions BRP might not be recognized
X .word 0xE670 ; move brp,r0
X ;; Static (compiled) breakpoints must return to the next instruction in order
X ;; to avoid infinite loops. Dynamic (gdb-invoked) must restore the instruction
X ;; in order to execute it when execution is continued.
- test.b [_is_dyn_brkp] ; Is this a dynamic breakpoint?
+ test.b [is_dyn_brkp] ; Is this a dynamic breakpoint?
X beq is_static ; No, a static breakpoint
X nop
- subq 2,r0 ; rerun the instruction the break replaced
+ subq 2,$r0 ; rerun the instruction the break replaced
X is_static:
- moveq 1,r1
- move.b r1,[_is_dyn_brkp] ; Set the state variable to dynamic breakpoint
- move.d r0,[_reg+0x62] ; Save the return address in BRP
- move usp,[_reg+0x66] ; USP
+ moveq 1,$r1
+ move.b $r1,[is_dyn_brkp] ; Set the state variable to dynamic breakpoint
+ move.d $r0,[reg+0x62] ; Save the return address in BRP
+ move $usp,[reg+0x66] ; USP
X ;;
X ;; Handle the communication
X ;;
- move.d _internal_stack+1020,sp ; Use the internal stack which grows upward
- moveq 5,r10 ; SIGTRAP
- jsr _handle_exception ; Interactive routine
+ move.d internal_stack+1020,$sp ; Use the internal stack which grows upward
+ moveq 5,$r10 ; SIGTRAP
+ jsr handle_exception ; Interactive routine
X ;;
X ;; Return to the caller
X ;;
- move.d [_reg],r0 ; Restore R0
- move.d [_reg+0x04],r1 ; Restore R1
- move.d [_reg+0x08],r2 ; Restore R2
- move.d [_reg+0x0C],r3 ; Restore R3
- move.d [_reg+0x10],r4 ; Restore R4
- move.d [_reg+0x14],r5 ; Restore R5
- move.d [_reg+0x18],r6 ; Restore R6
- move.d [_reg+0x1C],r7 ; Restore R7
- move.d [_reg+0x20],r8 ; Restore R8
- move.d [_reg+0x24],r9 ; Restore R9
- move.d [_reg+0x28],r10 ; Restore R10
- move.d [_reg+0x2C],r11 ; Restore R11
- move.d [_reg+0x30],r12 ; Restore R12
- move.d [_reg+0x34],r13 ; Restore R13
+ move.d [reg],$r0 ; Restore R0
+ move.d [reg+0x04],$r1 ; Restore R1
+ move.d [reg+0x08],$r2 ; Restore R2
+ move.d [reg+0x0C],$r3 ; Restore R3
+ move.d [reg+0x10],$r4 ; Restore R4
+ move.d [reg+0x14],$r5 ; Restore R5
+ move.d [reg+0x18],$r6 ; Restore R6
+ move.d [reg+0x1C],$r7 ; Restore R7
+ move.d [reg+0x20],$r8 ; Restore R8
+ move.d [reg+0x24],$r9 ; Restore R9
+ move.d [reg+0x28],$r10 ; Restore R10
+ move.d [reg+0x2C],$r11 ; Restore R11
+ move.d [reg+0x30],$r12 ; Restore R12
+ move.d [reg+0x34],$r13 ; Restore R13
X ;;
X ;; FIXME: Which registers should be restored?
X ;;
- move.d [_reg+0x38],sp ; Restore SP (R14)
- move [_reg+0x56],srp ; Restore the subroutine return pointer.
- move [_reg+0x5E],dccr ; Restore DCCR
- move [_reg+0x66],usp ; Restore USP
- jump [_reg+0x62] ; A jump to the content in register BRP works.
+ move.d [reg+0x38],$sp ; Restore SP (R14)
+ move [reg+0x56],$srp ; Restore the subroutine return pointer.
+ move [reg+0x5E],$dccr ; Restore DCCR
+ move [reg+0x66],$usp ; Restore USP
+ jump [reg+0x62] ; A jump to the content in register BRP works.
X nop ;
X ");
X
@@ -1440,85 +1443,85 @@
X void kgdb_handle_serial(void);
X
X asm ("
- .global _kgdb_handle_serial
-_kgdb_handle_serial:
+ .global kgdb_handle_serial
+kgdb_handle_serial:
X ;;
X ;; Response to a serial interrupt
X ;;
X
- move dccr,[_reg+0x5E] ; Save the flags in DCCR
+ move $dccr,[reg+0x5E] ; Save the flags in DCCR
X di ; Disable interrupts
- move.d r0,[_reg] ; Save R0
- move.d r1,[_reg+0x04] ; Save R1
- move.d r2,[_reg+0x08] ; Save R2
- move.d r3,[_reg+0x0C] ; Save R3
- move.d r4,[_reg+0x10] ; Save R4
- move.d r5,[_reg+0x14] ; Save R5
- move.d r6,[_reg+0x18] ; Save R6
- move.d r7,[_reg+0x1C] ; Save R7
- move.d r8,[_reg+0x20] ; Save R8
- move.d r9,[_reg+0x24] ; Save R9
- move.d r10,[_reg+0x28] ; Save R10
- move.d r11,[_reg+0x2C] ; Save R11
- move.d r12,[_reg+0x30] ; Save R12
- move.d r13,[_reg+0x34] ; Save R13
- move.d sp,[_reg+0x38] ; Save SP (R14)
- move irp,[_reg+0x3c] ; Save the address in PC (R15)
- clear.b [_reg+0x40] ; Clear P0
- move vr,[_reg+0x41] ; Save special register P1,
- clear.w [_reg+0x42] ; Clear P4
- move ccr,[_reg+0x44] ; Save special register CCR
- move mof,[_reg+0x46] ; P7
- clear.d [_reg+0x4A] ; Clear P8
- move ibr,[_reg+0x4E] ; P9,
- move irp,[_reg+0x52] ; P10,
- move srp,[_reg+0x56] ; P11,
- move dtp0,[_reg+0x5A] ; P12, register BAR, assembler might not know BAR
+ move.d $r0,[reg] ; Save R0
+ move.d $r1,[reg+0x04] ; Save R1
+ move.d $r2,[reg+0x08] ; Save R2
+ move.d $r3,[reg+0x0C] ; Save R3
+ move.d $r4,[reg+0x10] ; Save R4
+ move.d $r5,[reg+0x14] ; Save R5
+ move.d $r6,[reg+0x18] ; Save R6
+ move.d $r7,[reg+0x1C] ; Save R7
+ move.d $r8,[reg+0x20] ; Save R8
+ move.d $r9,[reg+0x24] ; Save R9
+ move.d $r10,[reg+0x28] ; Save R10
+ move.d $r11,[reg+0x2C] ; Save R11
+ move.d $r12,[reg+0x30] ; Save R12
+ move.d $r13,[reg+0x34] ; Save R13
+ move.d $sp,[reg+0x38] ; Save SP (R14)
+ move $irp,[reg+0x3c] ; Save the address in PC (R15)
+ clear.b [reg+0x40] ; Clear P0
+ move $vr,[reg+0x41] ; Save special register P1,
+ clear.w [reg+0x42] ; Clear P4
+ move $ccr,[reg+0x44] ; Save special register CCR
+ move $mof,[reg+0x46] ; P7
+ clear.d [reg+0x4A] ; Clear P8
+ move $ibr,[reg+0x4E] ; P9,
+ move $irp,[reg+0x52] ; P10,
+ move $srp,[reg+0x56] ; P11,
+ move $dtp0,[reg+0x5A] ; P12, register BAR, assembler might not know BAR
X ; P13, register DCCR already saved
X ;; Due to the old assembler-versions BRP might not be recognized
X .word 0xE670 ; move brp,r0
- move.d r0,[_reg+0x62] ; Save the return address in BRP
- move usp,[_reg+0x66] ; USP
+ move.d $r0,[reg+0x62] ; Save the return address in BRP
+ move $usp,[reg+0x66] ; USP
X
X ;; get the serial character (from debugport.c) and check if its a ctrl-c
X
- jsr _getDebugChar
- cmp.b 3, r10
+ jsr getDebugChar
+ cmp.b 3, $r10
X bne goback
X nop
X
X ;;
X ;; Handle the communication
X ;;
- move.d _internal_stack+1020,sp ; Use the internal stack
- moveq 2,r10 ; SIGINT
- jsr _handle_exception ; Interactive routine
+ move.d internal_stack+1020,$sp ; Use the internal stack
+ moveq 2,$r10 ; SIGINT
+ jsr handle_exception ; Interactive routine
X
X goback:
X ;;
X ;; Return to the caller
X ;;
- move.d [_reg],r0 ; Restore R0
- move.d [_reg+0x04],r1 ; Restore R1
- move.d [_reg+0x08],r2 ; Restore R2
- move.d [_reg+0x0C],r3 ; Restore R3
- move.d [_reg+0x10],r4 ; Restore R4
- move.d [_reg+0x14],r5 ; Restore R5
- move.d [_reg+0x18],r6 ; Restore R6
- move.d [_reg+0x1C],r7 ; Restore R7
- move.d [_reg+0x20],r8 ; Restore R8
- move.d [_reg+0x24],r9 ; Restore R9
- move.d [_reg+0x28],r10 ; Restore R10
- move.d [_reg+0x2C],r11 ; Restore R11
- move.d [_reg+0x30],r12 ; Restore R12
- move.d [_reg+0x34],r13 ; Restore R13
+ move.d [reg],$r0 ; Restore R0
+ move.d [reg+0x04],$r1 ; Restore R1
+ move.d [reg+0x08],$r2 ; Restore R2
+ move.d [reg+0x0C],$r3 ; Restore R3
+ move.d [reg+0x10],$r4 ; Restore R4
+ move.d [reg+0x14],$r5 ; Restore R5
+ move.d [reg+0x18],$r6 ; Restore R6
+ move.d [reg+0x1C],$r7 ; Restore R7
+ move.d [reg+0x20],$r8 ; Restore R8
+ move.d [reg+0x24],$r9 ; Restore R9
+ move.d [reg+0x28],$r10 ; Restore R10
+ move.d [reg+0x2C],$r11 ; Restore R11
+ move.d [reg+0x30],$r12 ; Restore R12
+ move.d [reg+0x34],$r13 ; Restore R13
X ;;
X ;; FIXME: Which registers should be restored?
X ;;
- move.d [_reg+0x38],sp ; Restore SP (R14)
- move [_reg+0x56],srp ; Restore the subroutine return pointer.
- move [_reg+0x5E],dccr ; Restore DCCR
- move [_reg+0x66],usp ; Restore USP
+ move.d [reg+0x38],$sp ; Restore SP (R14)
+ move [reg+0x56],$srp ; Restore the subroutine return pointer.
+ move [reg+0x5E],$dccr ; Restore DCCR
+ move [reg+0x66],$usp ; Restore USP
X reti ; Return from the interrupt routine
X nop
X ");
diff -u --recursive --new-file v2.4.14/linux/arch/cris/kernel/ksyms.c linux/arch/cris/kernel/ksyms.c
--- v2.4.14/linux/arch/cris/kernel/ksyms.c Tue Oct 9 17:06:51 2001
+++ linux/arch/cris/kernel/ksyms.c Fri Nov 9 13:58:02 2001
@@ -24,6 +24,7 @@
X extern void dump_thread(struct pt_regs *, struct user *);
X extern unsigned long get_cmos_time(void);
X extern void __ashrdi3(void);
+extern void iounmap(void *addr);
X
X /* platform dependent support */
X
@@ -44,6 +45,19 @@
X EXPORT_SYMBOL(strncat);
X EXPORT_SYMBOL(strncmp);
X EXPORT_SYMBOL(__ashrdi3);
+
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(iounmap);
+
+/* export shadow registers for the CPU I/O pins */
+
+EXPORT_SYMBOL(genconfig_shadow);
+EXPORT_SYMBOL(port_pa_data_shadow);
+EXPORT_SYMBOL(port_pa_dir_shadow);
+EXPORT_SYMBOL(port_pb_data_shadow);
+EXPORT_SYMBOL(port_pb_dir_shadow);
+EXPORT_SYMBOL(port_pb_config_shadow);
+EXPORT_SYMBOL(port_g_data_shadow);
X
X /* other stuff */
X
diff -u --recursive --new-file v2.4.14/linux/arch/cris/kernel/process.c linux/arch/cris/kernel/process.c
--- v2.4.14/linux/arch/cris/kernel/process.c Tue Oct 9 17:06:51 2001
+++ linux/arch/cris/kernel/process.c Fri Nov 9 13:58:02 2001
@@ -77,6 +77,7 @@
X * setup.
X */
X
+static struct vm_area_struct init_mmap = INIT_MMAP;
X static struct fs_struct init_fs = INIT_FS;
X static struct files_struct init_files = INIT_FILES;
X static struct signal_struct init_signals = INIT_SIGNALS;
diff -u --recursive --new-file v2.4.14/linux/arch/cris/kernel/setup.c linux/arch/cris/kernel/setup.c
--- v2.4.14/linux/arch/cris/kernel/setup.c Tue Oct 9 17:06:51 2001
+++ linux/arch/cris/kernel/setup.c Fri Nov 9 13:58:02 2001
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.21 2001/10/01 14:45:35 bjornw Exp $
+/* $Id: setup.c,v 1.22 2001/10/23 17:42:58 pkj Exp $
X *
X * linux/arch/cris/kernel/setup.c
X *
@@ -202,32 +202,58 @@
X } cpu_info[] = {
X /* The first four models will never ever run this code and are
X only here for display. */
- { "ETRAX 1", 0, 0 },
- { "ETRAX 2", 0, 0 },
- { "ETRAX 3", 0, HAS_TOKENRING },
- { "ETRAX 4", 0, HAS_TOKENRING | HAS_SCSI },
- { "Unknown", 0, 0 },
- { "Unknown", 0, 0 },
- { "Unknown", 0, 0 },
- { "Simulator", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA },
- { "ETRAX 100", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_IRQ_BUG },
- { "ETRAX 100", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA },
- { "ETRAX 100LX", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU | HAS_MMU_BUG },
+ { "ETRAX 1", 0, 0 },
+ { "ETRAX 2", 0, 0 },
+ { "ETRAX 3", 0, HAS_TOKENRING },
+ { "ETRAX 4", 0, HAS_TOKENRING | HAS_SCSI },
+ { "Unknown", 0, 0 },
+ { "Unknown", 0, 0 },
+ { "Unknown", 0, 0 },
+ { "Simulator", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA },
+ { "ETRAX 100", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_IRQ_BUG },
+ { "ETRAX 100", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA },
+ { "ETRAX 100LX", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU | HAS_MMU_BUG },
X { "ETRAX 100LX v2", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU },
- { "Unknown", 0, 0 },
+ { "Unknown", 0, 0 } /* This entry MUST be the last */
X };
X
X /*


- * BUFFER is PAGE_SIZE bytes long.

+ * get_cpuinfo - Get information on one CPU for use by the procfs.
+ *
+ * Prints info on the next CPU into buffer. Beware, doesn't check for
+ * buffer overflow. Current implementation of procfs assumes that the
+ * resulting data is <= 1K.
+ *
+ * BUFFER is PAGE_SIZE - 1K bytes long.
+ *
+ * Args:
+ * buffer -- you guessed it, the data buffer
+ * cpu_np -- Input: next cpu to get (start at 0). Output: Updated.
+ *
+ * Returns number of bytes written to buffer.
X */
-int get_cpuinfo(char *buffer)
+int get_cpuinfo(char *buffer, unsigned *cpu_np)
X {
X int revision;
+ struct cpu_info *info;
+ unsigned n;
X
X /* read the version register in the CPU and print some stuff */
X
X revision = rdvr();
X
+ if (revision < 0 || revision >= sizeof cpu_info/sizeof *cpu_info) {
+ info = &cpu_info[sizeof cpu_info/sizeof *cpu_info - 1];
+ } else
+ info = &cpu_info[revision];
+
+ /* No SMP at the moment, so just toggle 0/1 */
+ n = *cpu_np;
+ *cpu_np = 1;
+ if (n != 0) {
+ return (0);
+ }
+
X return sprintf(buffer,
X "cpu\t\t: CRIS\n"
X "cpu revision\t: %d\n"
@@ -244,16 +270,16 @@
X "bogomips\t: %lu.%02lu\n",
X
X revision,
- cpu_info[revision].model,
- cpu_info[revision].cache,
- cpu_info[revision].flags & HAS_FPU ? "yes" : "no",
- cpu_info[revision].flags & HAS_MMU ? "yes" : "no",
- cpu_info[revision].flags & HAS_MMU_BUG ? "yes" : "no",
- cpu_info[revision].flags & HAS_ETHERNET100 ? "10/100" : "10",
- cpu_info[revision].flags & HAS_TOKENRING ? "4/16 Mbps" : "no",
- cpu_info[revision].flags & HAS_SCSI ? "yes" : "no",
- cpu_info[revision].flags & HAS_ATA ? "yes" : "no",
- cpu_info[revision].flags & HAS_USB ? "yes" : "no",
+ info->model,
+ info->cache,
+ info->flags & HAS_FPU ? "yes" : "no",
+ info->flags & HAS_MMU ? "yes" : "no",
+ info->flags & HAS_MMU_BUG ? "yes" : "no",
+ info->flags & HAS_ETHERNET100 ? "10/100" : "10",
+ info->flags & HAS_TOKENRING ? "4/16 Mbps" : "no",
+ info->flags & HAS_SCSI ? "yes" : "no",
+ info->flags & HAS_ATA ? "yes" : "no",
+ info->flags & HAS_USB ? "yes" : "no",
X (loops_per_jiffy * HZ + 500) / 500000,
X ((loops_per_jiffy * HZ + 500) / 5000) % 100);
X }
diff -u --recursive --new-file v2.4.14/linux/arch/cris/kernel/time.c linux/arch/cris/kernel/time.c
--- v2.4.14/linux/arch/cris/kernel/time.c Sun Aug 12 13:27:58 2001
+++ linux/arch/cris/kernel/time.c Fri Nov 9 13:58:02 2001
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.8 2001/07/18 14:01:03 bjornw Exp $
+/* $Id: time.c,v 1.9 2001/10/25 10:26:37 johana Exp $
X *
X * linux/arch/cris/kernel/time.c
X *
@@ -51,6 +51,11 @@
X
X extern int setup_etrax_irq(int, struct irqaction *);
X
+/* Lookup table to convert *R_TIMER0 to microseconds (us)
+ * Timer goes from TIMER0_DIV down to 1 meaning 0-10000us in step of approx 52us
+ */
+unsigned short cris_timer0_value_us[TIMER0_DIV+1];
+
X #define TICK_SIZE tick
X
X static unsigned long do_slow_gettimeoffset(void)
@@ -380,6 +385,7 @@
X void __init
X time_init(void)
X {
+ int i;
X /* probe for the RTC and read it if it exists */
X
X if(RTC_INIT() < 0) {
@@ -442,6 +448,13 @@
X IO_STATE(R_TIMER_CTRL, tm0, run) |
X IO_STATE(R_TIMER_CTRL, clksel0, c19k2Hz);
X #endif
+
+ for (i=0; i <= TIMER0_DIV; i++) {
+ /* We must be careful not to get overflow... */
+ cris_timer0_value_us[TIMER0_DIV-i] =
+ (unsigned short)((unsigned long)
+ ((i*(1000000/HZ))/TIMER0_DIV)&0x0000FFFFL);
+ }
X
X *R_IRQ_MASK0_SET =
X IO_STATE(R_IRQ_MASK0_SET, timer0, set); /* unmask the timer irq */
diff -u --recursive --new-file v2.4.14/linux/arch/cris/kernel/traps.c linux/arch/cris/kernel/traps.c
--- v2.4.14/linux/arch/cris/kernel/traps.c Tue Oct 9 17:06:51 2001
+++ linux/arch/cris/kernel/traps.c Fri Nov 9 13:58:02 2001
@@ -138,8 +138,8 @@
X register. */
X unsigned long usp = rdusp();
X
- printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx %s\n",
- regs->irp, regs->srp, regs->dccr, usp, regs->mof, print_tainted());
+ printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
+ regs->irp, regs->srp, regs->dccr, usp, regs->mof );
X printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
X regs->r0, regs->r1, regs->r2, regs->r3);
X printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
diff -u --recursive --new-file v2.4.14/linux/arch/i386/boot/bootsect.S linux/arch/i386/boot/bootsect.S
--- v2.4.14/linux/arch/i386/boot/bootsect.S Sun Sep 23 11:40:55 2001
+++ linux/arch/i386/boot/bootsect.S Fri Nov 9 13:58:02 2001
@@ -395,9 +395,15 @@
X # NOTE: Doesn't save %ax or %dx; do it yourself if you need to.
X
X kill_motor:
+#if 1
+ xorw %ax, %ax # reset FDC
+ xorb %dl, %dl
+ int $0x13
+#else
X movw $0x3f2, %dx
X xorb %al, %al
X outb %al, %dx
+#endif
X ret
X
X sectors: .word 0
diff -u --recursive --new-file v2.4.14/linux/arch/i386/boot/compressed/misc.c linux/arch/i386/boot/compressed/misc.c
--- v2.4.14/linux/arch/i386/boot/compressed/misc.c Tue Oct 9 17:06:51 2001
+++ linux/arch/i386/boot/compressed/misc.c Mon Nov 12 09:59:43 2001
@@ -9,6 +9,7 @@
X * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
X */
X
+#include <linux/linkage.h>
X #include <linux/vmalloc.h>
X #include <linux/tty.h>
X #include <asm/io.h>
@@ -304,7 +305,7 @@
X short b;
X } stack_start = { & user_stack [STACK_SIZE] , __KERNEL_DS };
X
-void setup_normal_output_buffer(void)
+static void setup_normal_output_buffer(void)
X {
X #ifdef STANDARD_MEMORY_BIOS_CALL
X if (EXT_MEM_K < 1024) error("Less than 2MB of memory.\n");
@@ -320,7 +321,7 @@
X uch *high_buffer_start; int hcount;
X };
X
-void setup_output_buffer_if_we_run_high(struct moveparams *mv)
+static void setup_output_buffer_if_we_run_high(struct moveparams *mv)
X {
X high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE);
X #ifdef STANDARD_MEMORY_BIOS_CALL
@@ -342,7 +343,7 @@
X mv->high_buffer_start = high_buffer_start;
X }
X
-void close_output_buffer_if_we_run_high(struct moveparams *mv)
+static void close_output_buffer_if_we_run_high(struct moveparams *mv)
X {
X if (bytes_out > low_buffer_size) {
X mv->lcount = low_buffer_size;
@@ -355,7 +356,7 @@
X }
X
X
-int decompress_kernel(struct moveparams *mv, void *rmode)
+asmlinkage int decompress_kernel(struct moveparams *mv, void *rmode)
X {
X real_mode = rmode;
X
diff -u --recursive --new-file v2.4.14/linux/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S
--- v2.4.14/linux/arch/i386/boot/setup.S Sun Aug 12 13:27:58 2001
+++ linux/arch/i386/boot/setup.S Fri Nov 9 13:58:02 2001
@@ -232,8 +232,8 @@
X # Move rest of setup code/data to here
X movw $2048, %di # four sectors loaded by LILO
X subw %si, %si
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %es
+ pushw %cs
+ popw %es
X movw $SYSSEG, %ax
X movw %ax, %ds
X rep
@@ -253,6 +253,7 @@
X call prtstr
X
X no_sig_loop:
+ hlt
X jmp no_sig_loop
X
X good_sig:
@@ -641,18 +642,40 @@
X movw %ax, %ds
X movw %dx, %ss
X end_move_self: # now we are at the right place
- lidt idt_48 # load idt with 0,0
- xorl %eax, %eax # Compute gdt_base
- movw %ds, %ax # (Convert %ds:gdt to a linear ptr)
- shll $4, %eax
- addl $gdt, %eax
- movl %eax, (gdt_48+2)
- lgdt gdt_48 # load gdt with whatever is
- # appropriate
X
-# that was painless, now we enable a20
+#
+# Enable A20. This is at the very best an annoying procedure.
+# A20 code ported from SYSLINUX 1.52-1.63 by H. Peter Anvin.
+#
+
+A20_TEST_LOOPS = 32 # Iterations per wait
+A20_ENABLE_LOOPS = 255 # Total loops to try
+
+
+a20_try_loop:
+
+ # First, see if we are on a system with no A20 gate.
+a20_none:
+ call a20_test
+ jnz a20_done
+
+ # Next, try the BIOS (INT 0x15, AX=0x2401)
+a20_bios:
+ movw $0x2401, %ax
+ pushfl # Be paranoid about flags
+ int $0x15
+ popfl
+
+ call a20_test
+ jnz a20_done
+
+ # Try enabling A20 through the keyboard controller
+a20_kbc:
X call empty_8042
X
+ call a20_test # Just in case the BIOS worked
+ jnz a20_done # but had a delayed reaction.
+
X movb $0xD1, %al # command write
X outb %al, $0x64
X call empty_8042
@@ -661,29 +684,62 @@
X outb %al, $0x60
X call empty_8042
X
-#
-# You must preserve the other bits here. Otherwise embarrasing things
-# like laptops powering off on boot happen. Corrected version by Kira
-# Brown from Linux 2.2
-#
- inb $0x92, %al #
- orb $02, %al # "fast A20" version
- outb %al, $0x92 # some chips have only this
-
-# wait until a20 really *is* enabled; it can take a fair amount of
-# time on certain systems; Toshiba Tecras are known to have this
-# problem. The memory location used here (0x200) is the int 0x80
-# vector, which should be safe to use.
-
- xorw %ax, %ax # segment 0x0000
- movw %ax, %fs
- decw %ax # segment 0xffff (HMA)
- movw %ax, %gs
-a20_wait:
- incw %ax # unused memory location <0xfff0
- movw %ax, %fs:(0x200) # we use the "int 0x80" vector
- cmpw %gs:(0x210), %ax # and its corresponding HMA addr
- je a20_wait # loop until no longer aliased
+ # Wait until a20 really *is* enabled; it can take a fair amount of
+ # time on certain systems; Toshiba Tecras are known to have this
+ # problem.
+a20_kbc_wait:
+ xorw %cx, %cx
+a20_kbc_wait_loop:
+ call a20_test
+ jnz a20_done
+ loop a20_kbc_wait_loop
+
+ # Final attempt: use "configuration port A"
+a20_fast:
+ inb $0x92, %al # Configuration Port A
+ orb $0x02, %al # "fast A20" version
+ andb $0xFE, %al # don't accidentally reset
+ outb %al, $0x92
+
+ # Wait for configuration port A to take effect
+a20_fast_wait:
+ xorw %cx, %cx
+a20_fast_wait_loop:
+ call a20_test
+ jnz a20_done
+ loop a20_fast_wait_loop
+
+ # A20 is still not responding. Try frobbing it again.
+ #
+ decb (a20_tries)
+ jnz a20_try_loop
+
+ movw $a20_err_msg, %si
+ call prtstr
+
+a20_die:
+ hlt
+ jmp a20_die
+
+a20_tries:
+ .byte A20_ENABLE_LOOPS
+
+a20_err_msg:
+ .ascii "linux: fatal error: A20 gate not responding!"
+ .byte 13, 10, 0
+
+ # If we get here, all is good
+a20_done:
+
+# set up gdt and idt
+ lidt idt_48 # load idt with 0,0
+ xorl %eax, %eax # Compute gdt_base
+ movw %ds, %ax # (Convert %ds:gdt to a linear ptr)
+ shll $4, %eax
+ addl $gdt, %eax
+ movl %eax, (gdt_48+2)
+ lgdt gdt_48 # load gdt with whatever is
+ # appropriate
X
X # make sure any possible coprocessor is properly reset..
X xorw %ax, %ax
@@ -839,6 +895,37 @@
X
X bootsect_panic_mess:
X .string "INT15 refuses to access high mem, giving up."
+
+
+# This routine tests whether or not A20 is enabled. If so, it
+# exits with zf = 0.
+#
+# The memory address used, 0x200, is the int $0x80 vector, which
+# should be safe.
+
+A20_TEST_ADDR = 4*0x80
+
+a20_test:
+ pushw %cx
+ pushw %ax
+ xorw %cx, %cx
+ movw %cx, %fs # Low memory
+ decw %cx
+ movw %cx, %gs # High memory area
+ movw $A20_TEST_LOOPS, %cx
+ movw %fs:(A20_TEST_ADDR), %ax
+ pushw %ax
+a20_test_wait:
+ incw %ax
+ movw %ax, %fs:(A20_TEST_ADDR)
+ call delay # Serialize and make delay constant
+ cmpw %gs:(A20_TEST_ADDR+0x10), %ax
+ loope a20_test_wait
+
+ popw %fs:(A20_TEST_ADDR)
+ popw %ax
+ popw %cx
+ ret
X
X # This routine checks that the keyboard command queue is empty
X # (after emptying the output buffers)
diff -u --recursive --new-file v2.4.14/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.4.14/linux/arch/i386/config.in Mon Nov 5 15:55:26 2001
+++ linux/arch/i386/config.in Mon Nov 12 11:58:08 2001
@@ -234,8 +234,10 @@
X
X if [ "$CONFIG_HOTPLUG" = "y" ] ; then
X source drivers/pcmcia/Config.in
+ source drivers/hotplug/Config.in
X else
X define_bool CONFIG_PCMCIA n
+ define_bool CONFIG_HOTPLUG_PCI n
X fi
X
X bool 'System V IPC' CONFIG_SYSVIPC
diff -u --recursive --new-file v2.4.14/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.4.14/linux/arch/i386/defconfig Mon Nov 5 15:55:26 2001
+++ linux/arch/i386/defconfig Mon Nov 12 11:59:03 2001
@@ -88,6 +88,13 @@
X # CONFIG_I82092 is not set
X # CONFIG_I82365 is not set
X # CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HOTPLUG_PCI_COMPAQ is not set
+# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
X CONFIG_SYSVIPC=y
X # CONFIG_BSD_PROCESS_ACCT is not set
X CONFIG_SYSCTL=y
@@ -315,6 +322,7 @@
X # CONFIG_SCSI_INIA100 is not set
X # CONFIG_SCSI_NCR53C406A is not set
X # CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
X # CONFIG_SCSI_NCR53C8XX is not set
X CONFIG_SCSI_SYM53C8XX=y
X CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=4
@@ -468,6 +476,7 @@
X # CONFIG_PCMCIA_NMCLAN is not set
X # CONFIG_PCMCIA_SMC91C92 is not set
X # CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
X # CONFIG_ARCNET_COM20020_CS is not set
X # CONFIG_PCMCIA_IBMTR is not set
X # CONFIG_PCMCIA_XIRCOM is not set
@@ -597,11 +606,15 @@
X CONFIG_AUTOFS4_FS=y
X # CONFIG_REISERFS_FS is not set
X # CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set


X # CONFIG_ADFS_FS is not set
X # CONFIG_ADFS_FS_RW is not set
X # CONFIG_AFFS_FS is not set

X # CONFIG_HFS_FS is not set
X # CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
X # CONFIG_FAT_FS is not set
X # CONFIG_MSDOS_FS is not set
X # CONFIG_UMSDOS_FS is not set
@@ -639,6 +652,7 @@
X # Network File Systems
X #
X # CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
X CONFIG_NFS_FS=y
X # CONFIG_NFS_V3 is not set
X # CONFIG_ROOT_NFS is not set
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile
--- v2.4.14/linux/arch/i386/kernel/Makefile Sun Sep 23 11:40:55 2001
+++ linux/arch/i386/kernel/Makefile Fri Nov 9 14:21:21 2001
@@ -38,7 +38,7 @@
X obj-$(CONFIG_APM) += apm.o
X obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o
X obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o apic.o nmi.o
-obj-$(CONFIG_X86_IO_APIC) += io_apic.o
+obj-$(CONFIG_X86_IO_APIC) += io_apic.o acpitable.o
X obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o
X
X include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/acpitable.c linux/arch/i386/kernel/acpitable.c
--- v2.4.14/linux/arch/i386/kernel/acpitable.c Wed Dec 31 16:00:00 1969
+++ linux/arch/i386/kernel/acpitable.c Sun Nov 11 19:15:06 2001
@@ -0,0 +1,550 @@
+/*
+ * acpitable.c - IA32-specific ACPI boot-time initialization (Revision: 1)
+ *
+ * Copyright (C) 1999 Andrew Henroid
+ * Copyright (C) 2001 Richard Schaal
+ * Copyright (C) 2001 Paul Diefenbaugh <paul.s.di...@intel.com>
+ * Copyright (C) 2001 Jun Nakajima <jun.na...@intel.com>
+ * Copyright (C) 2001 Arjan van de Ven <arj...@redhat.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.
+ *
+ * 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
+ *

+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * $Id: acpitable.c,v 1.7 2001/11/04 12:21:18 fenrus Exp $
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <asm/mpspec.h>
+#include <asm/io.h>
+#include <asm/apic.h>
+#include <asm/apicdef.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include "acpitable.h"
+
+static acpi_table_handler acpi_boot_ops[ACPI_TABLE_COUNT];
+
+
+static unsigned char __init
+acpi_checksum(void *buffer, int length)
+{
+ int i;
+ unsigned char *bytebuffer;
+ unsigned char sum = 0;
+
+ if (!buffer || length <= 0)
+ return 0;
+
+ bytebuffer = (unsigned char *) buffer;
+
+ for (i = 0; i < length; i++)
+ sum += *(bytebuffer++);
+
+ return sum;
+}
+
+static void __init
+acpi_print_table_header(acpi_table_header * header)
+{
+ if (!header)
+ return;
+
+ printk(KERN_INFO "ACPI table found: %.4s v%d [%.6s %.8s %d.%d]\n",
+ header->signature, header->revision, header->oem_id,
+ header->oem_table_id, header->oem_revision >> 16,
+ header->oem_revision & 0xffff);
+
+ return;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_scan_memory_for_rsdp
+ *
+ * PARAMETERS: address - Starting pointer for search
+ * length - Maximum length to search
+ *
+ * RETURN: Pointer to the RSDP if found and valid, otherwise NULL.
+ *
+ * DESCRIPTION: Search a block of memory for the RSDP signature
+ *
+ ******************************************************************************/
+
+static void *__init
+acpi_tb_scan_memory_for_rsdp(void *address, int length)
+{
+ u32 offset;
+
+ if (length <= 0)
+ return NULL;
+
+ /* Search from given start addr for the requested length */
+
+ offset = 0;
+
+ while (offset < length) {
+ /* The signature must match and the checksum must be correct */
+ if (strncmp(address, RSDP_SIG, sizeof(RSDP_SIG) - 1) == 0 &&
+ acpi_checksum(address, RSDP_CHECKSUM_LENGTH) == 0) {
+ /* If so, we have found the RSDP */
+ printk(KERN_INFO "ACPI: RSDP located at physical address %p\n",
+ address);
+ return address;
+ }
+ offset += RSDP_SCAN_STEP;
+ address += RSDP_SCAN_STEP;
+ }
+
+ /* Searched entire block, no RSDP was found */
+ printk(KERN_INFO "ACPI: Searched entire block, no RSDP was found.\n");
+ return NULL;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_find_root_pointer
+ *
+ * PARAMETERS: none
+ *
+ * RETURN: physical address of the RSDP
+ *
+ * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor
+ * pointer structure. If it is found, set *RSDP to point to it.
+ *
+ * NOTE: The RSDP must be either in the first 1_k of the Extended
+ * BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section
+ * 5.2.2; assertion #421).
+ *
+ ******************************************************************************/
+
+static struct acpi_table_rsdp * __init
+acpi_find_root_pointer(void)
+{
+ struct acpi_table_rsdp * rsdp;
+
+ /*
+ * Physical address is given
+ */
+ /*
+ * Region 1) Search EBDA (low memory) paragraphs
+ */
+ rsdp = acpi_tb_scan_memory_for_rsdp(__va(LO_RSDP_WINDOW_BASE),
+ LO_RSDP_WINDOW_SIZE);
+
+ if (rsdp)
+ return rsdp;
+
+ /*
+ * Region 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
+ */
+ rsdp = acpi_tb_scan_memory_for_rsdp(__va(HI_RSDP_WINDOW_BASE),
+ HI_RSDP_WINDOW_SIZE);
+
+
+
+ if (rsdp)
+ return rsdp;
+
+ printk(KERN_ERR "ACPI: System description tables not found\n");
+ return NULL;
+}
+
+
+/*
+ * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_0,
+ * to map the target physical address. The problem is that set_fixmap()
+ * provides a single page, and it is possible that the page is not
+ * sufficient.
+ * By using this area, we can map up to MAX_IO_APICS pages temporarily,
+ * i.e. until the next __va_range() call.
+ */
+static __inline__ char *
+__va_range(unsigned long phys, unsigned long size)
+{
+ unsigned long base, offset, mapped_size, mapped_phys = phys;
+ int idx = FIX_IO_APIC_BASE_0;
+
+ offset = phys & (PAGE_SIZE - 1);
+ mapped_size = PAGE_SIZE - offset;
+ set_fixmap(idx, mapped_phys);
+ base = fix_to_virt(FIX_IO_APIC_BASE_0);
+
+ /*
+ * Most cases can be covered by the below.
+ */
+ if (mapped_size >= size)
+ return ((unsigned char *) base + offset);
+
+ dprintk("__va_range: mapping more than a single page, size = 0x%lx\n",
+ size);
+
+ do {
+ if (idx++ == FIX_IO_APIC_BASE_END)
+ return 0; /* cannot handle this */
+ mapped_phys = mapped_phys + PAGE_SIZE;
+ set_fixmap(idx, mapped_phys);
+ mapped_size = mapped_size + PAGE_SIZE;
+ } while (mapped_size < size);
+
+ return ((unsigned char *) base + offset);
+}
+
+static int __init acpi_tables_init(void)
+{
+ int result = -ENODEV;
+ acpi_table_header *header = NULL;
+ struct acpi_table_rsdp *rsdp = NULL;
+ struct acpi_table_rsdt *rsdt = NULL;
+ struct acpi_table_rsdt saved_rsdt;
+ int tables = 0;
+ int type = 0;
+ int i = 0;
+
+
+ rsdp = (struct acpi_table_rsdp *) acpi_find_root_pointer();
+
+ if (!rsdp)
+ return -ENODEV;
+
+ printk(KERN_INFO "%.8s v%d [%.6s]\n", rsdp->signature, rsdp->revision,
+ rsdp->oem_id);
+
+ if (strncmp(rsdp->signature, RSDP_SIG,strlen(RSDP_SIG))) {
+ printk(KERN_WARNING "RSDP table signature incorrect\n");
+ return -EINVAL;
+ }
+
+ rsdt = (struct acpi_table_rsdt *)
+ __va_range(rsdp->rsdt_address, sizeof(struct acpi_table_rsdt));
+
+ if (!rsdt) {
+ printk(KERN_WARNING "ACPI: Invalid root system description tables (RSDT)\n");
+ return -ENODEV;
+ }
+
+ header = & rsdt->header;
+ acpi_print_table_header(header);
+
+ if (strncmp(header->signature, RSDT_SIG, strlen(RSDT_SIG))) {
+ printk(KERN_WARNING "ACPI: RSDT signature incorrect\n");
+ return -ENODEV;
+ }
+
+ /*
+ * The number of tables is computed by taking the
+ * size of all entries (header size minus total
+ * size of RSDT) divided by the size of each entry
+ * (4-byte table pointers).
+ */
+ tables = (header->length - sizeof(acpi_table_header)) / 4;
+
+ memcpy(&saved_rsdt, rsdt, sizeof(saved_rsdt));
+
+ if (saved_rsdt.header.length > sizeof(saved_rsdt)) {
+ printk(KERN_WARNING "ACPI: Too big length in RSDT: %d\n", saved_rsdt.header.length);
+ return -ENODEV;
+ }
+
+ for (i = 0; i < tables; i++) {
+
+ header = (acpi_table_header *)
+ __va_range(saved_rsdt.entry[i],
+ sizeof(acpi_table_header));
+
+ if (!header)
+ break;
+
+ acpi_print_table_header(header);
+
+ if (acpi_checksum(header,header->length)) {
+ printk(KERN_WARNING "ACPI %s has invalid checksum\n",
+ acpi_table_signatures[i]);
+ continue;
+ }
+
+ for (type = 0; type < ACPI_TABLE_COUNT; type++)
+ if (!strncmp((char *) &header->signature,
+ acpi_table_signatures[type],strlen(acpi_table_signatures[type])))
+ break;
+
+ if (type >= ACPI_TABLE_COUNT) {
+ printk(KERN_WARNING "ACPI: Unsupported table %.4s\n",
+ header->signature);


+ continue;
+ }
+
+

+ if (!acpi_boot_ops[type])
+ continue;
+
+ result = acpi_boot_ops[type] (header,
+ (unsigned long) saved_rsdt.
+ entry[i]);
+ }
+
+ return result;
+}
+
+static int total_cpus __initdata = 0;
+int have_acpi_tables;
+
+extern void __init MP_processor_info(struct mpc_config_processor *);
+
+static void __init
+acpi_parse_lapic(struct acpi_table_lapic *local_apic)
+{
+ struct mpc_config_processor proc_entry;
+ int ix = 0;
+
+ if (!local_apic)
+ return;
+
+ printk(KERN_INFO "LAPIC (acpi_id[0x%04x] id[0x%x] enabled[%d])\n",
+ local_apic->acpi_id, local_apic->id, local_apic->flags.enabled);
+
+ printk(KERN_INFO "CPU %d (0x%02x00)", total_cpus, local_apic->id);
+
+ if (local_apic->flags.enabled) {
+ printk(" enabled");
+ ix = local_apic->id;
+ if (ix >= MAX_APICS) {
+ printk(KERN_WARNING
+ "Processor #%d INVALID - (Max ID: %d).\n", ix,
+ MAX_APICS);
+ return;
+ }
+ /*
+ * Fill in the info we want to save. Not concerned about
+ * the processor ID. Processor features aren't present in
+ * the table.
+ */
+ proc_entry.mpc_type = MP_PROCESSOR;
+ proc_entry.mpc_apicid = local_apic->id;
+ proc_entry.mpc_cpuflag = CPU_ENABLED;
+ if (proc_entry.mpc_apicid == boot_cpu_physical_apicid) {
+ printk(" (BSP)");
+ proc_entry.mpc_cpuflag |= CPU_BOOTPROCESSOR;
+ }
+ proc_entry.mpc_cpufeature =
+ (boot_cpu_data.x86 << 8) |
+ (boot_cpu_data.x86_model << 4) |
+ boot_cpu_data.x86_mask;
+ proc_entry.mpc_featureflag = boot_cpu_data.x86_capability[0];
+ proc_entry.mpc_reserved[0] = 0;
+ proc_entry.mpc_reserved[1] = 0;
+ proc_entry.mpc_apicver = 0x10; /* integrated APIC */
+ MP_processor_info(&proc_entry);
+ } else {
+ printk(" disabled");
+ }
+ printk("\n");
+
+ total_cpus++;
+ return;
+}
+
+static void __init
+acpi_parse_ioapic(struct acpi_table_ioapic *ioapic)
+{
+
+ if (!ioapic)
+ return;
+
+ printk(KERN_INFO
+ "IOAPIC (id[0x%x] address[0x%x] global_irq_base[0x%x])\n",
+ ioapic->id, ioapic->address, ioapic->global_irq_base);
+
+ if (nr_ioapics >= MAX_IO_APICS) {
+ printk(KERN_WARNING
+ "Max # of I/O APICs (%d) exceeded (found %d).\n",
+ MAX_IO_APICS, nr_ioapics);
+/* panic("Recompile kernel with bigger MAX_IO_APICS!\n"); */
+ }
+}
+
+
+/* Interrupt source overrides inform the machine about exceptions
+ to the normal "PIC" mode interrupt routing */
+
+static void __init
+acpi_parse_int_src_ovr(struct acpi_table_int_src_ovr *intsrc)
+{
+ if (!intsrc)
+ return;
+
+ printk(KERN_INFO
+ "INT_SRC_OVR (bus[%d] irq[0x%x] global_irq[0x%x] polarity[0x%x] trigger[0x%x])\n",
+ intsrc->bus, intsrc->bus_irq, intsrc->global_irq,
+ intsrc->flags.polarity, intsrc->flags.trigger);
+}
+
+/*
+ * At this point, we look at the interrupt assignment entries in the MPS
+ * table.
+ */
+
+static void __init acpi_parse_nmi_src(struct acpi_table_nmi_src *nmisrc)
+{
+ if (!nmisrc)
+ return;
+
+ printk(KERN_INFO
+ "NMI_SRC (polarity[0x%x] trigger[0x%x] global_irq[0x%x])\n",
+ nmisrc->flags.polarity, nmisrc->flags.trigger,
+ nmisrc->global_irq);
+
+}
+static void __init
+acpi_parse_lapic_nmi(struct acpi_table_lapic_nmi *localnmi)
+{
+ if (!localnmi)
+ return;
+
+ printk(KERN_INFO
+ "LAPIC_NMI (acpi_id[0x%04x] polarity[0x%x] trigger[0x%x] lint[0x%x])\n",
+ localnmi->acpi_id, localnmi->flags.polarity,
+ localnmi->flags.trigger, localnmi->lint);
+}
+static void __init
+acpi_parse_lapic_addr_ovr(struct acpi_table_lapic_addr_ovr *lapic_addr_ovr)
+{
+ if (!lapic_addr_ovr)
+ return;
+
+ printk(KERN_INFO "LAPIC_ADDR_OVR (address[0x%lx])\n",
+ (unsigned long) lapic_addr_ovr->address);
+
+}
+
+static void __init
+acpi_parse_plat_int_src(struct acpi_table_plat_int_src *plintsrc)
+{
+ if (!plintsrc)
+ return;
+
+ printk(KERN_INFO
+ "PLAT_INT_SRC (polarity[0x%x] trigger[0x%x] type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n",
+ plintsrc->flags.polarity, plintsrc->flags.trigger,
+ plintsrc->type, plintsrc->id, plintsrc->eid,
+ plintsrc->iosapic_vector, plintsrc->global_irq);
+}
+static int __init
+acpi_parse_madt(acpi_table_header * header, unsigned long phys)
+{
+
+ struct acpi_table_madt *madt;
+ acpi_madt_entry_header *entry_header;
+ int table_size;
+
+ madt = (struct acpi_table_madt *) __va_range(phys, header->length);
+
+ if (!madt)
+ return -EINVAL;
+
+ table_size = (int) (header->length - sizeof(*madt));
+ entry_header =
+ (acpi_madt_entry_header *) ((void *) madt + sizeof(*madt));
+
+ while (entry_header && (table_size > 0)) {
+ switch (entry_header->type) {
+ case ACPI_MADT_LAPIC:
+ acpi_parse_lapic((struct acpi_table_lapic *)
+ entry_header);
+ break;
+ case ACPI_MADT_IOAPIC:
+ acpi_parse_ioapic((struct acpi_table_ioapic *)
+ entry_header);
+ break;
+ case ACPI_MADT_INT_SRC_OVR:
+ acpi_parse_int_src_ovr((struct acpi_table_int_src_ovr *)
+ entry_header);
+ break;
+ case ACPI_MADT_NMI_SRC:
+ acpi_parse_nmi_src((struct acpi_table_nmi_src *)
+ entry_header);
+ break;
+ case ACPI_MADT_LAPIC_NMI:
+ acpi_parse_lapic_nmi((struct acpi_table_lapic_nmi *)
+ entry_header);
+ break;
+ case ACPI_MADT_LAPIC_ADDR_OVR:
+ acpi_parse_lapic_addr_ovr((struct
+ acpi_table_lapic_addr_ovr *)
+ entry_header);
+ break;
+ case ACPI_MADT_PLAT_INT_SRC:
+ acpi_parse_plat_int_src((struct acpi_table_plat_int_src
+ *) entry_header);
+ break;
+ default:
+ printk(KERN_WARNING
+ "Unsupported MADT entry type 0x%x\n",
+ entry_header->type);
+ break;
+ }
+ table_size -= entry_header->length;
+ entry_header =
+ (acpi_madt_entry_header *) ((void *) entry_header +
+ entry_header->length);
+ }
+
+ if (!total_cpus) {
+ printk("ACPI: No Processors found in the APCI table.\n");
+ return -EINVAL;
+ }
+
+ printk(KERN_INFO "%d CPUs total\n", total_cpus);
+
+ if (madt->lapic_address)
+ mp_lapic_addr = madt->lapic_address;
+ else
+ mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+
+ printk(KERN_INFO "Local APIC address %x\n", madt->lapic_address);
+


+ return 0;
+}
+

+extern int enable_acpi_smp_table;
+
+/*
+ * Configure the processor info using MADT in the ACPI tables. If we fail to
+ * configure that, then we use the MPS tables.
+ */
+void __init
+config_acpi_tables(void)
+{
+
+ memset(&acpi_boot_ops, 0, sizeof(acpi_boot_ops));
+ acpi_boot_ops[ACPI_APIC] = acpi_parse_madt;
+
+ /*
+ * Only do this when requested, either because of CPU/Bios type or from the command line
+ */
+
+ if (enable_acpi_smp_table && !acpi_tables_init()) {
+ have_acpi_tables = 1;
+ printk("Enabling the CPU's according to the ACPI table\n");
+ }
+}
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/acpitable.h linux/arch/i386/kernel/acpitable.h
--- v2.4.14/linux/arch/i386/kernel/acpitable.h Wed Dec 31 16:00:00 1969
+++ linux/arch/i386/kernel/acpitable.h Sun Nov 11 19:04:33 2001
@@ -0,0 +1,260 @@
+/*
+ * acpitable.c - IA32-specific ACPI boot-time initialization (Revision: 1)
+ *
+ * Copyright (C) 1999 Andrew Henroid
+ * Copyright (C) 2001 Richard Schaal
+ * Copyright (C) 2001 Paul Diefenbaugh <paul.s.di...@intel.com>
+ * Copyright (C) 2001 Jun Nakajima <jun.na...@intel.com>
+ * Copyright (C) 2001 Arjan van de Ven <arj...@redhat.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.
+ *
+ * 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
+ *

+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * $Id: acpitable.h,v 1.3 2001/11/03 22:41:34 fenrus Exp $
+ */
+
+/*
+ * The following codes are cut&pasted from drivers/acpi. Part of the code
+ * there can be not updated or delivered yet.
+ * To avoid conflicts when CONFIG_ACPI is defined, the following codes are
+ * modified so that they are self-contained in this file.
+ * -- jun
+ */
+
+#ifndef _HEADER_ACPITABLE_H_
+#define _HEADER_ACPITABLE_H_
+
+#define dprintk printk
+typedef unsigned int ACPI_TBLPTR;
+
+typedef struct { /* ACPI common table header */
+ char signature[4]; /* identifies type of table */
+ u32 length; /* length of table,
+ in bytes, * including header */
+ u8 revision; /* specification minor version # */
+ u8 checksum; /* to make sum of entire table == 0 */
+ char oem_id[6]; /* OEM identification */
+ char oem_table_id[8]; /* OEM table identification */
+ u32 oem_revision; /* OEM revision number */
+ char asl_compiler_id[4]; /* ASL compiler vendor ID */
+ u32 asl_compiler_revision; /* ASL compiler revision number */
+} acpi_table_header __attribute__ ((packed));;
+
+enum {
+ ACPI_APIC = 0,
+ ACPI_BOOT,
+ ACPI_DBGP,
+ ACPI_DSDT,
+ ACPI_ECDT,
+ ACPI_ETDT,
+ ACPI_FACP,
+ ACPI_FACS,
+ ACPI_OEMX,
+ ACPI_PSDT,
+ ACPI_SBST,
+ ACPI_SLIT,
+ ACPI_SPCR,
+ ACPI_SRAT,
+ ACPI_SSDT,
+ ACPI_SPMI,
+ ACPI_XSDT,
+ ACPI_TABLE_COUNT
+};
+
+static char *acpi_table_signatures[ACPI_TABLE_COUNT] = {
+ "APIC",
+ "BOOT",
+ "DBGP",
+ "DSDT",
+ "ECDT",
+ "ETDT",
+ "FACP",
+ "FACS",
+ "OEM",
+ "PSDT",
+ "SBST",
+ "SLIT",
+ "SPCR",
+ "SRAT",
+ "SSDT",
+ "SPMI",
+ "XSDT"
+};
+
+struct acpi_table_madt {
+ acpi_table_header header;
+ u32 lapic_address;
+ struct {
+ u32 pcat_compat:1;
+ u32 reserved:31;
+ } flags __attribute__ ((packed));
+} __attribute__ ((packed));;
+
+enum {
+ ACPI_MADT_LAPIC = 0,
+ ACPI_MADT_IOAPIC,
+ ACPI_MADT_INT_SRC_OVR,
+ ACPI_MADT_NMI_SRC,
+ ACPI_MADT_LAPIC_NMI,
+ ACPI_MADT_LAPIC_ADDR_OVR,
+ ACPI_MADT_IOSAPIC,
+ ACPI_MADT_LSAPIC,
+ ACPI_MADT_PLAT_INT_SRC,
+ ACPI_MADT_ENTRY_COUNT
+};
+
+#define RSDP_SIG "RSD PTR "
+#define RSDT_SIG "RSDT"
+
+#define ACPI_DEBUG_PRINT(pl)
+
+#define ACPI_MEMORY_MODE 0x01
+#define ACPI_LOGICAL_ADDRESSING 0x00
+#define ACPI_PHYSICAL_ADDRESSING 0x01
+
+#define LO_RSDP_WINDOW_BASE 0 /* Physical Address */
+#define HI_RSDP_WINDOW_BASE 0xE0000 /* Physical Address */
+#define LO_RSDP_WINDOW_SIZE 0x400
+#define HI_RSDP_WINDOW_SIZE 0x20000
+#define RSDP_SCAN_STEP 16
+#define RSDP_CHECKSUM_LENGTH 20
+
+typedef int (*acpi_table_handler) (acpi_table_header * header, unsigned long);
+
+struct acpi_table_rsdp {
+ char signature[8];
+ u8 checksum;
+ char oem_id[6];
+ u8 revision;
+ u32 rsdt_address;
+} __attribute__ ((packed));
+
+struct acpi_table_rsdt {
+ acpi_table_header header;
+ u32 entry[ACPI_TABLE_COUNT];
+} __attribute__ ((packed));
+
+typedef struct {
+ u8 type;
+ u8 length;
+} acpi_madt_entry_header __attribute__ ((packed));
+
+typedef struct {
+ u16 polarity:2;
+ u16 trigger:2;
+ u16 reserved:12;
+} acpi_madt_int_flags __attribute__ ((packed));
+
+struct acpi_table_lapic {
+ acpi_madt_entry_header header;
+ u8 acpi_id;
+ u8 id;
+ struct {
+ u32 enabled:1;
+ u32 reserved:31;
+ } flags __attribute__ ((packed));
+} __attribute__ ((packed));
+
+struct acpi_table_ioapic {
+ acpi_madt_entry_header header;
+ u8 id;
+ u8 reserved;
+ u32 address;
+ u32 global_irq_base;
+} __attribute__ ((packed));
+
+struct acpi_table_int_src_ovr {
+ acpi_madt_entry_header header;
+ u8 bus;
+ u8 bus_irq;
+ u32 global_irq;
+ acpi_madt_int_flags flags;
+} __attribute__ ((packed));
+
+struct acpi_table_nmi_src {
+ acpi_madt_entry_header header;
+ acpi_madt_int_flags flags;
+ u32 global_irq;
+} __attribute__ ((packed));
+
+struct acpi_table_lapic_nmi {
+ acpi_madt_entry_header header;
+ u8 acpi_id;
+ acpi_madt_int_flags flags;
+ u8 lint;
+} __attribute__ ((packed));
+
+struct acpi_table_lapic_addr_ovr {
+ acpi_madt_entry_header header;
+ u8 reserved[2];
+ u64 address;
+} __attribute__ ((packed));
+
+struct acpi_table_iosapic {
+ acpi_madt_entry_header header;
+ u8 id;
+ u8 reserved;
+ u32 global_irq_base;
+ u64 address;
+} __attribute__ ((packed));
+
+struct acpi_table_lsapic {
+ acpi_madt_entry_header header;
+ u8 acpi_id;
+ u8 id;
+ u8 eid;
+ u8 reserved[3];
+ struct {
+ u32 enabled:1;
+ u32 reserved:31;
+ } flags;
+} __attribute__ ((packed));
+
+struct acpi_table_plat_int_src {
+ acpi_madt_entry_header header;
+ acpi_madt_int_flags flags;
+ u8 type;
+ u8 id;
+ u8 eid;
+ u8 iosapic_vector;
+ u32 global_irq;
+ u32 reserved;
+} __attribute__ ((packed));
+
+/*
+ * ACPI Table Descriptor. One per ACPI table
+ */
+typedef struct acpi_table_desc {
+ struct acpi_table_desc *prev;
+ struct acpi_table_desc *next;
+ struct acpi_table_desc *installed_desc;
+ acpi_table_header *pointer;
+ void *base_pointer;
+ u8 *aml_pointer;
+ u64 physical_address;
+ u32 aml_length;
+ u32 length;
+ u32 count;
+ u16 table_id;
+ u8 type;
+ u8 allocation;
+ u8 loaded_into_namespace;
+
+} acpi_table_desc __attribute__ ((packed));;
+
+#endif
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c
--- v2.4.14/linux/arch/i386/kernel/apic.c Mon Nov 5 15:55:26 2001
+++ linux/arch/i386/kernel/apic.c Fri Nov 9 14:12:55 2001
@@ -575,7 +575,6 @@
X static int __init detect_init_APIC (void)
X {
X u32 h, l, features;
- int needs_pm = 0;
X extern void get_cpu_vendor(struct cpuinfo_x86*);
X
X /* Workaround for us being called before identify_cpu(). */
@@ -608,7 +607,6 @@
X l &= ~MSR_IA32_APICBASE_BASE;
X l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
X wrmsr(MSR_IA32_APICBASE, l, h);
- needs_pm = 1;
X }
X }
X /*
@@ -628,8 +626,7 @@
X
X printk("Found and enabled local APIC!\n");
X
- if (needs_pm)
- apic_pm_init1();
+ apic_pm_init1();
X
X return 0;
X
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.4.14/linux/arch/i386/kernel/apm.c Tue Oct 23 22:48:49 2001
+++ linux/arch/i386/kernel/apm.c Fri Nov 9 13:58:02 2001
@@ -1471,7 +1471,7 @@
X as = filp->private_data;
X if (check_apm_user(as, "ioctl"))
X return -EIO;
- if (!as->suser)
+ if ((!as->suser) || (!as->writer))
X return -EPERM;
X switch (cmd) {
X case APM_IOC_STANDBY:
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/bluesmoke.c linux/arch/i386/kernel/bluesmoke.c
--- v2.4.14/linux/arch/i386/kernel/bluesmoke.c Tue Oct 23 22:48:49 2001
+++ linux/arch/i386/kernel/bluesmoke.c Mon Nov 12 09:59:43 2001
@@ -100,11 +100,11 @@
X
X /*
X * Call the installed machine check handler for this CPU setup.
- */
-
+ */
+
X static void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
X
-void do_machine_check(struct pt_regs * regs, long error_code)
+asmlinkage void do_machine_check(struct pt_regs * regs, long error_code)
X {
X machine_check_vector(regs, error_code);
X }
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/dmi_scan.c linux/arch/i386/kernel/dmi_scan.c
--- v2.4.14/linux/arch/i386/kernel/dmi_scan.c Tue Oct 23 22:48:49 2001
+++ linux/arch/i386/kernel/dmi_scan.c Sun Nov 11 10:38:46 2001
@@ -7,9 +7,10 @@
X #include <linux/slab.h>
X #include <asm/io.h>
X #include <linux/pm.h>
-#include <linux/keyboard.h>
X #include <asm/keyboard.h>
+#include <asm/system.h>
X
+unsigned long dmi_broken;
X int is_sony_vaio_laptop;
X
X struct dmi_header
@@ -87,7 +88,7 @@
X }
X
X
-int __init dmi_iterate(void (*decode)(struct dmi_header *))
+static int __init dmi_iterate(void (*decode)(struct dmi_header *))
X {
X unsigned char buf[20];
X long fp=0xE0000L;
@@ -98,7 +99,7 @@
X * Skip on x86/64 with simnow. Will eventually go away
X * If you see this ifdef in 2.6pre mail me !
X */
- return;


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

echo 'End of part 023'
echo 'File patch-2.4.15 is continued in part 024'
echo "024" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:51 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part015

#!/bin/sh -x
# this is part 015 of a 115 - part archive


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

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

+ please read <file:Documentation/joystick.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called grip.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt.
+ The module will be called grip.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X InterAct digital joysticks and gamepads
X CONFIG_INPUT_INTERACT
X Say Y hereif you have an InterAct gameport or joystick
- communicating digitally over the gameport. For more information on
- how to use the driver please read Documentation/joystick.txt
+ communicating digitally over the gameport. For more information on
+ how to use the driver please read <file:Documentation/joystick.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called interact.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt.
+ The module will be called interact.o. If you want to compile it as


+ a module, say M here and read <file:Documentation/modules.txt>.
X

X ThrustMaster DirectConnect joysticks and gamepads
X CONFIG_INPUT_TMDC
X Say Y here if you have a ThrustMaster controller using the
- DirectConnect (BSP) protocol over the PC gameport. For more
+ DirectConnect (BSP) protocol over the PC gameport. For more
X information on how to use the driver please read
- Documentation/joystick.txt
+ <file:Documentation/joystick.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called tmdc.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt.
+ The module will be called tmdc.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X Microsoft SideWinder digital joysticks and gamepads
X CONFIG_INPUT_SIDEWINDER
X Say Y here if you have a Microsoft controller using the Digital
- Overdrive protocol over PC gameport. For more information on how to
- use the driver please read Documentation/joystick.txt
+ Overdrive protocol over PC gameport. For more information on how to
+ use the driver please read <file:Documentation/joystick.txt>.
+
+ This driver is also available as a module ( = code which can be


+ inserted in and removed from the running kernel whenever you want).

+ The module will be called sidewinder.o. If you want to compile it


+ as a module, say M here and read <file:Documentation/modules.txt>.
+

+Serial port device support
+CONFIG_INPUT_SERIO
+ Say Y here and to the Serial port input line discipline option if
+ you plan to use a joystick that communicates over the serial (COM)
+ port. For more information on how to use the driver please read
+ <file:Documentation/joystick.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called sidewinder.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt.
+ The module will be called sidewinder.o. If you want to compile it


+ as a module, say M here and read <file:Documentation/modules.txt>.

X
X Serial port input line discipline
X CONFIG_INPUT_SERPORT
- Say Y hereif you plan to use a joystick that communicates over the
- serial (COM) port. For more information on how to use the driver
- please read Documentation/joystick.txt
+ Say Y here if you plan to use a joystick that communicates over the
+ serial (COM) port. For more information on how to use the driver
+ please read <file:Documentation/joystick.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called serport.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt.
+ The module will be called serport.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X Logitech WingMan Warrior joystick
X CONFIG_INPUT_WARRIOR
- Say Y here if you have a Logitech WingMan Warrior joystick
- connected to your computer's serial port. For more information on
- how to use the driver please read Documentation/joystick.txt
+ Say Y here if you have a Logitech WingMan Warrior joystick connected
+ to your computer's serial port. For more information on how to use
+ the driver please read <file:Documentation/joystick.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called warrior.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt.
+ The module will be called warrior.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X LogiCad3d Magellan/SpaceMouse 6dof controller
X CONFIG_INPUT_MAGELLAN
X Say Y here if you have a Magellan or Space Mouse 6DOF controller
X connected to your computer's serial port. For more information on
- how to use the driver please read Documentation/joystick.txt
+ how to use the driver please read <file:Documentation/joystick.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called magellan.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt.
+ The module will be called magellan.o. If you want to compile it as


+ a module, say M here and read <file:Documentation/modules.txt>.
X

X SpaceTec SpaceOrb/Avenger 6dof controller
X CONFIG_INPUT_SPACEORB
X Say Y here if you have a SpaceOrb 360 or SpaceBall Avenger 6DOF
X controller connected to your computer's serial port. For more
X information on how to use the driver please read
- Documentation/joystick.txt
+ <file:Documentation/joystick.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called spaceorb.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt.
-
+ The module will be called spaceorb.o. If you want to compile it as


+ a module, say M here and read <file:Documentation/modules.txt>.

+
X SpaceTec SpaceBall 4000 FLX 6dof controller
X CONFIG_INPUT_SPACEBALL
X Say Y here if you have a SpaceTec SpaceBall 4000 FLX controller
- connected to your computer's serial port. For more information on
- how to use the driver please read Documentation/joystick.txt
+ connected to your computer's serial port. For more information on
+ how to use the driver please read <file:Documentation/joystick.txt>.
+
+ This driver is also available as a module ( = code which can be


+ inserted in and removed from the running kernel whenever you want).

+ The module will be called spaceball.o. If you want to compile it as


+ a module, say M here and read <file:Documentation/modules.txt>.

+
+Gravis Stinger gamepad
+CONFIG_INPUT_STINGER
+ Say Y here if you have a Gravis Stinger connected to one of your
+ serial ports. For more information on how to use the driver please
+ read <file:Documentation/joystick.txt>.
+
+ This driver is also available as a module ( = code which can be


+ inserted in and removed from the running kernel whenever you want).

+ The module will be called stinger.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X I-Force joysticks/wheels
X CONFIG_INPUT_IFORCE_232
X Say Y here if you have an I-Force joystick or steering wheel
- connected to your serial (COM) port. For more information on
- how to use the driver please read Documentation/joystick.txt
+ connected to your serial (COM) port. For more information on how
+ to use the driver please read <file:Documentation/joystick.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called iforce.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt.
+ The module will be called iforce.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X I-Force joysticks/wheels
X CONFIG_INPUT_IFORCE_USB
X Say Y here if you have an I-Force joystick or steering wheel
- connected to your USB port. For more information on how to use the
- driver please read Documentation/joystick.txt
+ connected to your USB port. For more information on how to use the
+ driver please read <file:Documentation/joystick.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called iforce.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt.
-
+ The module will be called iforce.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.

+
X Multisystem, Sega Genesis, Saturn joysticks and gamepads
X CONFIG_INPUT_DB9
X Say Y here if you have a Sega Master System gamepad, Sega Genesis
X gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga,
- Commodore, Amstrad CPC joystick connected to your parallel port.
- For more information on how to use the driver please read
- Documentation/joystick.txt and Documentation/joystick-parport.txt.
+ Commodore, Amstrad CPC joystick connected to your parallel port.
+ For more information on how to use the driver please read
+ <file:Documentation/joystick.txt> and
+ <file:Documentation/joystick-parport.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called db9.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt.
+ The module will be called db9.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X Multisystem, NES, SNES, N64, PSX joysticks and gamepads
X CONFIG_INPUT_GAMECON
@@ -15420,47 +17755,48 @@
X Sony PlayStation gamepad or a Multisystem -- Atari, Amiga,
X Commodore, Amstrad CPC joystick connected to your parallel port.
X For more information on how to use the driver please read
- Documentation/joystick.txt and Documentation/joystick-parport.txt
+ <file:Documentation/joystick.txt> and
+ <file:Documentation/joystick-parport.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called gamecon.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt.
+ The module will be called gamecon.o. If you want to compile it as a


+ module, say M here and read <file:Documentation/modules.txt>.
X

X Multisystem joysticks via TurboGraFX device
X CONFIG_INPUT_TURBOGRAFX
- Say Y here if you have the TurboGraFX interface by Steffen
- Schwenke, and want to use it with Multiststem -- Atari, Amiga,
- Commodore, Amstrad CPC joystick. For more information on how to use
- the driver please read Documentation/joystick.txt and
- Documentation/joystick-parport.txt
+ Say Y here if you have the TurboGraFX interface by Steffen Schwenke,
+ and want to use it with Multisystem -- Atari, Amiga, Commodore,
+ Amstrad CPC joystick. For more information on how to use the driver
+ please read <file:Documentation/joystick.txt> and
+ <file:Documentation/joystick-parport.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called turbografx.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt.
+ The module will be called turbografx.o. If you want to compile it


+ as a module, say M here and read <file:Documentation/modules.txt>.

X
X Amiga joysticks
X CONFIG_INPUT_AMIJOY
X Say Y here if you have an Amiga with a digital joystick connected
- to it. For more information on how to use the driver please read
- Documentation/joystick.txt
+ to it. For more information on how to use the driver please read
+ <file:Documentation/joystick.txt>.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

- The module will be called joy-amiga.o. If you want to compile
- it as a module, say M here and read Documentation/modules.txt.
+ The module will be called joy-amiga.o. If you want to compile it as


+ a module, say M here and read <file:Documentation/modules.txt>.
X

-Atomwide Serial Support
+Atomwide serial port support
X CONFIG_ATOMWIDE_SERIAL
X If you have an Atomwide Serial card for an Acorn system, say Y to
- this option. The driver can handle 1, 2, or 3 port cards.


- If unsure, say N

+ this option. The driver can handle 1, 2, or 3 port cards.
+ If unsure, say N.
X
-The Serial Port Dual Serial Port
+Dual serial port support
X CONFIG_DUALSP_SERIAL
X If you have the Serial Port's dual serial card for an Acorn system,
- say Y to this option. If unsure, say N
+ say Y to this option. If unsure, say N.
X
X NetWinder Button
X CONFIG_NWBUTTON
@@ -15481,7 +17817,8 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X If you want to compile it as a module, say M here and read

- Documentation/modules.txt. The module will be called nwbutton.o.


+ <file:Documentation/modules.txt>. The module will be called

+ nwbutton.o.
X
X Most people will answer Y to this question and "Reboot Using Button"
X below to be able to initiate a system shutdown from the button.
@@ -15499,37 +17836,37 @@
X Sound card support
X CONFIG_SOUND
X If you have a sound card in your computer, i.e. if it can say more
- than an occasional beep, say Y. Be sure to have all the information
+ than an occasional beep, say Y. Be sure to have all the information
X about your sound card and its configuration down (I/O port,
- interrupt and DMA channel), because you will be asked for it.
+ interrupt and DMA channel), because you will be asked for it.
X
X You want to read the Sound-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . General information
- about the modular sound system is contained in the files
- Documentation/sound/Introduction. The file
- Documentation/sound/README.OSS contains some slightly outdated but
- still useful information as well.
+ <http://www.linuxdoc.org/docs.html#howto>. General information about
+ the modular sound system is contained in the files
+ <file:Documentation/sound/Introduction>. The file
+ <file:Documentation/sound/README.OSS> contains some slightly
+ outdated but still useful information as well.
X
X If you have a PnP sound card and you want to configure it at boot
X time using the ISA PnP tools (read
- http://www.roestock.demon.co.uk/isapnptools/ ), then you need to
+ <http://www.roestock.demon.co.uk/isapnptools/>), then you need to
X compile the sound card support as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want)
- and load that module after the PnP configuration is finished. To do
- this, say M here and read Documentation/modules.txt as well as
- Documentation/sound/README.modules; the module will be called
- soundcore.o.
+ and load that module after the PnP configuration is finished. To do
+ this, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/sound/README.modules>; the module will be
+ called soundcore.o.
X
X I'm told that even without a sound card, you can make your computer
X say more than an occasional beep, by programming the PC speaker.
X Kernel patches and supporting utilities to do that are in the pcsp
- package, available at ftp://ftp.infradead.org/pub/pcsp/ .
+ package, available at <ftp://ftp.infradead.org/pub/pcsp/>.
X
X OSS sound modules
X CONFIG_SOUND_OSS
- OSS is the Open Sound System suite of sound card drivers. They make
- sound programming easier since they provide a common API. Say Y or M
- here (the module will be called sound.o) if you haven't found a
+ OSS is the Open Sound System suite of sound card drivers. They make
+ sound programming easier since they provide a common API. Say Y or
+ M here (the module will be called sound.o) if you haven't found a
X driver for your sound card above, then pick your driver from the
X list below.
X
@@ -15546,7 +17883,7 @@
X then you can get the persistent DMA buffer functionality by passing
X the command-line argument "dmabuf=1" to the sound.o module.
X
- Say Y unless you have 16MB or less RAM or a PCI sound card.
+ Say Y unless you have 16MB or more RAM or a PCI sound card.
X
X Support for Aztech Sound Galaxy (non-PnP) cards
X CONFIG_SOUND_SGALAXY
@@ -15558,9 +17895,9 @@
X "sgalaxy=<io>,<irq>,<dma>,<dma2>,<sgbase>" to the kernel command
X line.
X
-Support for AD1816(A) based cards (EXPERIMENTAL)
+Support for AD1816(A) based cards
X CONFIG_SOUND_AD1816
- Say M here if you have a sound card based on the Analog Devices
+ Say M here if you have a sound card based on the Analog Devices
X AD1816(A) chip.
X
X If you compile the driver into the kernel, you have to add
@@ -15569,8 +17906,8 @@
X Yamaha OPL3-SA1 audio controller
X CONFIG_SOUND_OPL3SA1
X Say Y or M if you have a Yamaha OPL3-SA1 sound chip, which is
- usually built into motherboards. Read Documentation/sound/OPL3-SA
- for details.
+ usually built into motherboards. Read
+ <file:Documentation/sound/OPL3-SA> for details.
X
X If you compile the driver into the kernel, you have to add
X "opl3sa=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
@@ -15581,7 +17918,7 @@
X Answer Y only if you have a Pro Audio Spectrum 16, ProAudio Studio
X 16 or Logitech SoundMan 16 sound card. Answer N if you have some
X other card made by Media Vision or Logitech since those are not
- PAS16 compatible. Please read Documentation/sound/PAS16.
+ PAS16 compatible. Please read <file:Documentation/sound/PAS16>.
X It is not necessary to add Sound Blaster support separately; it
X is included in PAS support.
X
@@ -15589,6 +17926,11 @@
X "pas2=<io>,<irq>,<dma>,<dma2>,<sbio>,<sbirq>,<sbdma>,<sbdma2>
X to the kernel command line.
X
+Enable PAS16 joystick port
+CONFIG_PAS_JOYSTICK
+ Say Y here to enable the Pro Audio Spectrum 16's auxiliary joystick
+ port.
+
X 100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support
X CONFIG_SOUND_SB
X Answer Y if you have an original Sound Blaster card made by Creative
@@ -15596,48 +17938,43 @@
X SM Games). For an unknown card you may answer Y if the card claims
X to be Sound Blaster-compatible.
X
- Please read the file Documentation/sound/Soundblaster.
+ Please read the file <file:Documentation/sound/Soundblaster>.
X
X You should also say Y here for cards based on the Avance Logic
- ALS-007 and ALS-1X0 chips (read Documentation/sound/ALS) and for cards
- based on ESS chips (read Documentation/sound/ESS1868 and
- Documentation/sound/ESS). If you have an SB AWE 32 or SB AWE 64, say
- Y here and also to "AWE32 synth" below and read
- Documentation/sound/INSTALL.awe. If you have an IBM Mwave card, say
- Y here and read Documentation/sound/mwave.
+ ALS-007 and ALS-1X0 chips (read <file:Documentation/sound/ALS>) and
+ for cards based on ESS chips (read
+ <file:Documentation/sound/ESS1868> and
+ <file:Documentation/sound/ESS>). If you have an SB AWE 32 or SB AWE
+ 64, say Y here and also to "AWE32 synth" below and read
+ <file:Documentation/sound/INSTALL.awe>. If you have an IBM Mwave
+ card, say Y here and read <file:Documentation/sound/mwave>.
X
X If you compile the driver into the kernel and don't want to use
X isapnp, you have to add "sb=<io>,<irq>,<dma>,<dma2>" to the kernel
X command line.
-
+
X You can say M here to compile this driver as a module; the module is
X called sb.o.
X
-#Loopback MIDI device support
-#CONFIG_SOUND_VMIDI
-###
-### somebody please fill this in.
-###
-#
X Gravis Ultrasound support
X CONFIG_SOUND_GUS
- Say Y here for any type of Gravis Ultrasound card, including
- the GUS or GUS MAX. See also Documentation/sound/ultrasound for
- more information on configuring this card with modules.
+ Say Y here for any type of Gravis Ultrasound card, including the GUS
+ or GUS MAX. See also <file:Documentation/sound/ultrasound> for more
+ information on configuring this card with modules.
X
X If you compile the driver into the kernel, you have to add
X "gus=<io>,<irq>,<dma>,<dma2>" to the kernel command line.
X
X MPU-401 support (NOT for SB16)
X CONFIG_SOUND_MPU401
- Be careful with this question. The MPU401 interface is supported by
- all sound cards. However, some natively supported cards have their
- own driver for MPU401. Enabling this MPU401 option with these cards
- will cause a conflict. Also, enabling MPU401 on a system that
- doesn't really have a MPU401 could cause some trouble. If your card
+ Be careful with this question. The MPU401 interface is supported by
+ all sound cards. However, some natively supported cards have their
+ own driver for MPU401. Enabling this MPU401 option with these cards
+ will cause a conflict. Also, enabling MPU401 on a system that
+ doesn't really have a MPU401 could cause some trouble. If your card
X was in the list of supported cards, look at the card specific
- instructions in the drivers/sound/Readme.cards file. It's safe to
- answer Y if you have a true MPU401 MIDI interface card.
+ instructions in the <file:Documentation/sound/README.OSS> file. It
+ is safe to answer Y if you have a true MPU401 MIDI interface card.
X
X If you compile the driver into the kernel, you have to add
X "mpu401=<io>,<irq>" to the kernel command line.
@@ -15657,7 +17994,7 @@
X ADSP-16 or some other card based on the PSS chipset (AD1848 codec +
X ADSP-2115 DSP chip + Echo ESC614 ASIC CHIP). For more information on
X how to compile it into the kernel or as a module see the file
- Documentation/sound/PSS.
+ <file:Documentation/sound/PSS>.
X
X If you compile the driver into the kernel, you have to add
X "pss=<io>,<mssio>,<mssirq>,<mssdma>,<mpuio>,<mpuirq>" to the kernel
@@ -15672,7 +18009,7 @@
X
X If you said M to "PSS support" above, you may enable or disable this
X PSS mixer with the module parameter pss_mixer. For more information
- see the file Documentation/sound/PSS.
+ see the file <file:Documentation/sound/PSS>.
X
X Have DSPxxx.LD firmware file
X CONFIG_PSS_HAVE_BOOT
@@ -15687,10 +18024,10 @@
X
X Microsoft Sound System support
X CONFIG_SOUND_MSS
- Again think carefully before answering Y to this question. It's safe
- to answer Y if you have the original Windows Sound System card made
- by Microsoft or Aztech SG 16 Pro (or NX16 Pro). Also you may say Y
- in case your card is NOT among these:
+ Again think carefully before answering Y to this question. It's
+ safe to answer Y if you have the original Windows Sound System card
+ made by Microsoft or Aztech SG 16 Pro (or NX16 Pro). Also you may
+ say Y in case your card is NOT among these:
X
X ATI Stereo F/X, AdLib, Audio Excell DSP16, Cardinal DSP16,
X Ensoniq SoundScape (and compatibles made by Reveal and Spea),
@@ -15707,9 +18044,9 @@
X synthesizers (OPL2, OPL3 and OPL4), 6850 UART MIDI Interface.
X
X For cards having native support in VoxWare, consult the card
- specific instructions in drivers/sound/Readme.cards. Some drivers
- have their own MSS support and saying Y to this option will cause a
- conflict.
+ specific instructions in <file:Documentation/sound/README.OSS>.
+ Some drivers have their own MSS support and saying Y to this option
+ will cause a conflict.
X
X If you compile the driver into the kernel, you have to add
X "ad1848=<io>,<irq>,<dma>,<dma2>[,<type>]" to the kernel command
@@ -15717,11 +18054,12 @@
X
X SGI Visual Workstation on-board audio
X CONFIG_SOUND_VWSND
- Say Y or M if you have an SGI Visual Workstation and you want to
- be able to use its on-board audio. Read Documentation/sound/vwsnd
- for more info on this driver's capabilities.
+ Say Y or M if you have an SGI Visual Workstation and you want to be
+ able to use its on-board audio. Read
+ <file:Documentation/sound/vwsnd> for more info on this driver's
+ capabilities.
X
-Ensoniq Soundscape support
+Ensoniq SoundScape support
X CONFIG_SOUND_SSCAPE
X Answer Y if you have a sound card based on the Ensoniq SoundScape
X chipset. Such cards are being manufactured at least by Ensoniq, Spea
@@ -15751,27 +18089,28 @@
X Support for OPTi MAD16 and/or Mozart based cards
X CONFIG_SOUND_MAD16
X Answer Y if your card has a Mozart (OAK OTI-601) or MAD16 (OPTi
- 82C928 or 82C929 or 82C931) audio interface chip. These chips are
+ 82C928 or 82C929 or 82C931) audio interface chip. These chips are
X quite common so it's possible that many no-name cards have one of
X them. In addition the MAD16 chip is used in some cards made by known
X manufacturers such as Turtle Beach (Tropez), Reveal (some models)
X and Diamond (latest ones). Note however that the Tropez sound cards
X have their own driver; if you have one of those, say N here and Y or
- M to "Full support for Turtle Beach WaveFront", below.
+ M to "Full support for Turtle Beach WaveFront", below.
X
X If you compile the driver into the kernel, you have to add
X "mad16=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the
X kernel command line.
X
- See also Documentation/sound/Opti and Documentation/sound/MAD16 for
- more information on setting these cards up as modules.
+ See also <file:Documentation/sound/Opti> and
+ <file:Documentation/sound/MAD16> for more information on setting
+ these cards up as modules.
X
-Full support for Turtle Beach WaveFront synth/sound cards
+Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/sound cards
X CONFIG_SOUND_WAVEFRONT
X Answer Y or M if you have a Tropez Plus, Tropez or Maui sound card
- and read the files Documentation/sound/Wavefront and
- Documentation/sound/Tropez+.
-
+ and read the files <file:Documentation/sound/Wavefront> and
+ <file:Documentation/sound/Tropez+>.
+
X Support MIDI in older MAD16 based cards (requires SB)
X CONFIG_MAD16_OLDCARD
X Answer Y (or M) if you have an older card based on the C928 or
@@ -15787,15 +18126,15 @@
X "cs4232=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
X command line.
X
- See Documentation/sound/CS4232 for more information on configuring
- this card.
+ See <file:Documentation/sound/CS4232> for more information on
+ configuring this card.
X
X Support for Yamaha OPL3-SA2 and SA3 based PnP cards
X CONFIG_SOUND_OPL3SA2
- Say Y or M if you have a card based on one of these Yamaha
- sound chipsets or the "SAx", which is actually a SA3. Read
- Documentation/sound/OPL3-SA2 for more information on configuring
- these cards.
+ Say Y or M if you have a card based on one of these Yamaha sound
+ chipsets or the "SAx", which is actually a SA3. Read
+ <file:Documentation/sound/OPL3-SA2> for more information on
+ configuring these cards.
X
X If you compile the driver into the kernel and do not also
X configure in the optional ISA PnP support, you will have to add
@@ -15824,52 +18163,118 @@
X Support for Turtle Beach MultiSound Classic, Tahiti, Monterey
X CONFIG_SOUND_MSNDCLAS
X Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or
- Monterey (not for the Pinnacle or Fiji).
+ Monterey (not for the Pinnacle or Fiji).
X
- See Documentation/sound/MultiSound for important information about
- this driver.
+ See <file:Documentation/sound/MultiSound> for important information
+ about this driver. Note that it has been discontinued, but the
+ Voyetra Turtle Beach knowledge base entry for it is still available
+ at <http://www.voyetra-turtle-beach.com/site/kb_ftp/790.asp>.
+
+MSND Classic I/O
+CONFIG_MSNDCLAS_IO
+ I/O port address for the MultiSound Classic and related cards.
+
+MSND Classic IRQ
+CONFIG_MSNDCLAS_IRQ
+ Interrupt Request line for the MultiSound Classic and related cards.
+
+MSND Classic memory address
+CONFIG_MSNDCLAS_MEM
+ Memory-mapped I/O base address for the MultiSound Classic and
+ related cards.
X
X Full pathname of MSNDINIT.BIN firmware file
X CONFIG_MSNDCLAS_INIT_FILE
X The MultiSound cards have two firmware files which are required for
X operation, and are not currently included. These files can be
- obtained from Turtle Beach. See Documentation/sound/MultiSound for
- information on how to obtain this.
+ obtained from Turtle Beach. See
+ <file:Documentation/sound/MultiSound> for information on how to
+ obtain this.
X
X Full pathname of MSNDPERM.BIN firmware file
X CONFIG_MSNDCLAS_PERM_FILE
X The MultiSound cards have two firmware files which are required for
X operation, and are not currently included. These files can be
- obtained from Turtle Beach. See Documentation/sound/MultiSound for
- information on how to obtain this.
+ obtained from Turtle Beach. See
+ <file:Documentation/sound/MultiSound> for information on how to
+ obtain this.
X
X Support for Turtle Beach MultiSound Pinnacle, Fiji
X CONFIG_SOUND_MSNDPIN
X Say M here if you have a Turtle Beach MultiSound Pinnacle or Fiji.
- See Documentation/sound/MultiSound for important information about
- this driver.
+ See <file:Documentation/sound/MultiSound> for important information
+ about this driver. Note that it has been discontinued, but the
+ Voyetra Turtle Beach knowledge base entry for it is still available
+ at <http://www.voyetra-turtle-beach.com/site/kb_ftp/600.asp>.
+
+MSND Pinnacle IDE I/O 0
+CONFIG_MSNDPIN_IDE_IO0
+ CD-ROM drive 0 memory-mapped I/O base address for the MultiSound
+ Pinnacle and Fiji sound cards.
+
+MSND Pinnacle IDE I/O 1
+CONFIG_MSNDPIN_IDE_IO1
+ CD-ROM drive 1 memory-mapped I/O base address for the MultiSound
+ Pinnacle and Fiji sound cards.
+
+MSND Pinnacle IDE IRQ
+CONFIG_MSNDPIN_IDE_IRQ
+ Interrupt request number for the IDE CD-ROM interface on the
+ MultiSound Pinnacle and Fiji sound cards.
+
+MSND Pinnacle I/O
+CONFIG_MSNDPIN_IO
+ Memory-mapped I/O base address for the primary synthesizer on
+ MultiSound Pinnacle and Fiji sound cards.
+
+MSND Pinnacle MPU I/O
+CONFIG_MSNDPIN_MPU_IO
+ Memory-mapped I/O base address for the Kurzweil daughterboard
+ synthesizer on MultiSound Pinnacle and Fiji sound cards.
+
+MSND Pinnacle MPU IRQ
+CONFIG_MSNDPIN_MPU_IRQ
+ Iinterrupt request number for the Kurzweil daughterboard
+ synthesizer on MultiSound Pinnacle and Fiji sound cards.
+
+MSND Pinnacle IRQ
+CONFIG_MSNDPIN_IRQ
+ Interrupt request line for the primary synthesizer on MultiSound
+ Pinnacle and Fiji sound cards.
+
+MSND Pinnacle joystick I/O
+CONFIG_MSNDPIN_JOYSTICK_IO
+ Memory-mapped I/O base address for the joystick port on MultiSound
+ Pinnacle and Fiji sound cards.
+
+MSND Pinnacle memory
+CONFIG_MSNDPIN_MEM
+ Memory-mapped I/O base address for the primary synthesizer on
+ MultiSound Pinnacle and Fiji sound cards.
X
X Full pathname of PNDSPINI.BIN firmware file
X CONFIG_MSNDPIN_INIT_FILE
- The MultiSound cards have two firmware files which are required for
- operation, and are not currently included. These files can be
- obtained from Turtle Beach. See Documentation/sound/MultiSound for
- information on how to obtain this.
+ The MultiSound cards have two firmware files which are required
+ for operation, and are not currently included. These files can be
+ obtained from Turtle Beach. See
+ <file:Documentation/sound/MultiSound> for information on how to
+ obtain this.
X
X Full pathname of PNDSPERM.BIN firmware file
X CONFIG_MSNDPIN_PERM_FILE
X The MultiSound cards have two firmware files which are required for
X operation, and are not currently included. These files can be
- obtained from Turtle Beach. See Documentation/sound/MultiSound for
- information on how to obtain this.
+ obtained from Turtle Beach. See
+ <file:Documentation/sound/MultiSound> for information on how to
+ obtain this.
X
-MSND Pinnacle have S/PDIF I/O
+MSND Pinnacle has S/PDIF I/O
X CONFIG_MSNDPIN_DIGITAL
X If you have the S/PDIF daughter board for the Pinnacle or Fiji,
X answer Y here; otherwise, say N. If you have this, you will be able
X to play and record from the S/PDIF port (digital signal). See
- Documentation/sound/MultiSound for information on how to make use of
- this capability.
+ <file:Documentation/sound/MultiSound> for information on how to make
+ use of this capability.
X
X MSND Pinnacle non-PnP Mode
X CONFIG_MSNDPIN_NONPNP
@@ -15896,15 +18301,14 @@
X and Pinnacle). Larger values reduce the chance of data overruns at
X the expense of overall latency. If unsure, use the default.
X
-FM synthesizer (YM3812/OPL-3) support
+Yamaha FM synthesizer (YM3812/OPL-3) support
X CONFIG_SOUND_YM3812
X Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
X Answering Y is usually a safe and recommended choice, however some
X cards may have software (TSR) FM emulation. Enabling FM support with
X these cards may cause trouble (I don't currently know of any such
- cards, however).
- Please read the file Documentation/sound/OPL3 if your card has an
- OPL3 chip.
+ cards, however). Please read the file
+ <file:Documentation/sound/OPL3> if your card has an OPL3 chip.
X
X If you compile the driver into the kernel, you have to add
X "opl3=<io>" to the kernel command line.
@@ -15914,27 +18318,27 @@
X ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio)
X CONFIG_SOUND_ACI_MIXER
X ACI (Audio Command Interface) is a protocol used to communicate with
- the microcontroller on some sound cards produced by miro and Cardinal
- Technologies. The main function of the ACI is to control the mixer
- and to get a product identification.
+ the microcontroller on some sound cards produced by miro and
+ Cardinal Technologies. The main function of the ACI is to control
+ the mixer and to get a product identification.
X
- This Voxware ACI driver currently supports the ACI functions on the
+ This VoxWare ACI driver currently supports the ACI functions on the
X miroSOUND PCM1-pro, PCM12 and PCM20 radio. On the PCM20 radio, ACI
X also controls the radio tuner. This is supported in the video4linux
- miropcm20 driver (say M or Y here and go back to "Multimedia devices"
- -> "Radio Adapters").
+ miropcm20 driver (say M or Y here and go back to "Multimedia
+ devices" -> "Radio Adapters").
X
X This driver is also available as a module and will be called aci.o.
X
X SB32/AWE support
X CONFIG_SOUND_AWE32_SYNTH
X Say Y here if you have a Sound Blaster SB32, AWE32-PnP, SB AWE64 or
- similar sound card. See Documentation/sound/README.awe,
- Documentation/sound/AWE32 and the Soundblaster-AWE mini-HOWTO,
- available from http://www.linuxdoc.org/docs.html#howto for more
- info.
+ similar sound card. See <file:Documentation/sound/README.awe>,
+ <file:Documentation/sound/AWE32> and the Soundblaster-AWE
+ mini-HOWTO, available from <http://www.linuxdoc.org/docs.html#howto>


+ for more info.
X

-Gallant's Audio Excel DSP 16 support (SC-6000 and SC-6600)
+Gallant Audio Cards (SC-6000 and SC-6600 based)
X CONFIG_SOUND_AEDSP16
X Answer Y if you have a Gallant's Audio Excel DSP 16 card. This
X driver supports Audio Excel DSP 16 but not the III nor PnP versions
@@ -15948,10 +18352,10 @@
X accordingly. You should say Y to one and only one of these two
X questions.
X
- Read the drivers/sound/lowlevel/README.aedsp16 file and the head of
- drivers/sound/lowlevel/aedsp16.c as well as
- Documentation/sound/AudioExcelDSP16 to get more information about
- this driver and its configuration.
+ Read the <file:Documentation/sound/README.OSS> file and the head of
+ <file:drivers/sound/lowlevel/aedsp16.c> as well as
+ <file:Documentation/sound/AudioExcelDSP16> to get more information
+ about this driver and its configuration.
X
X Audio Excel DSP 16 (SBPro emulation)
X CONFIG_AEDSP16_SBPRO
@@ -15981,17 +18385,22 @@
X Say Y here in order to use the joystick interface of the Audio Excel
X DSP 16 card.
X
-SC-6600 CDROM Interface
-CONFIG_SC6600_CDROM
- This is used to activate the CDROM interface of the Audio Excel
+SC-6600 CD-ROM Interface
+CONFIG_SC6600_CDROM (4=None, 3=IDE, 1=Panasonic, 0=Sony)
+ This is used to activate the CD-ROM interface of the Audio Excel
X DSP 16 card. Enter: 0 for Sony, 1 for Panasonic, 2 for IDE, 4 for no
- CDROM present.
+ CD-ROM present.
+
+SC-6600 CD-ROM Interface I/O Address
+CONFIG_SC6600_CDROMBASE
+ Base I/O port address for the CD-ROM interface of the Audio Excel
+ DSP 16 card.
X
X Audio Excel DSP 16 (MPU401 emulation)
X CONFIG_AEDSP16_MPU401
X Answer Y if you want your audio card to emulate the MPU-401 midi
X interface. You should then also say Y to "MPU-401 support".
-
+
X Note that the I/O base for MPU-401 support of aedsp16 is the same
X you have selected for "MPU-401 support". If you are using this
X driver as a module you have to specify the MPU I/O base address with
@@ -16000,46 +18409,70 @@
X C-Media PCI (CMI8338/8378)
X CONFIG_SOUND_CMPCI
X Say Y or M if you have a PCI sound card using the CMI8338
- or the CMI8378 chip.set.
+ or the CMI8378 chipset. Data on these chips are available at
+ <http://www.cmedia.com.tw/>.
+
+Support CMI8738 based audio cards
+CONFIG_SOUND_CMPCI_CM8738
+ Say Y or M if you have a PCI sound card using the CMI8338
+ or the CMI8378 chipset. Data on this chip is available at
+ <http://www.cmedia.com.tw/doc8738.htm>.
+
+Enable joystick
+CONFIG_SOUND_CMPCI_JOYSTICK
+ Say here in order to enable the joystick port on a sound crd using
+ the CMI8338 or the CMI8738 chipset. Data on these chips are
+ available at <http://www.cmedia.com.tw/>.
+
+Number of speakers (2, 4, 5, 6)
+CONFIG_SOUND_CMPCI_SPEAKERS
+ Specify the number of speaker channels you want the card to drive,
+ as an integer.
+
+Enable S/PDIF loop for CMI8738
+CONFIG_SOUND_CMPCI_SPDIFLOOP
+ Enable loopback from SPDIF in to SPDIF out. For discussion, see
+ "The 8738 Audio SPDIF In/Out Technical Data" on the technical
+ support page at <http://www.cmedia.com.tw/>.
X
-Creative EMU10K1 based PCI sound cards
+Creative SBLive! (EMU10K1) based PCI sound cards
X CONFIG_SOUND_EMU10K1
X Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
- such as the various Creative SBLive!, SB PCI512 or Emu-APS.
+ such as the Creative SBLive!, SB PCI512 or Emu-APS.
X
X For more information on this driver and the degree of support for the
X different card models please check <http://opensource.creative.com>.
X
X It is now possible to load dsp microcode patches into the EMU10K1
- chip. These patches are used to implement real time sound processing
- effects which include for example: signal routing, bass/treble
- control, AC3 passthrough, ...
+ chip. These patches are used to implement real time sound
+ processing effects which include for example: signal routing,
+ bass/treble control, AC3 passthrough, ...
X Userspace tools to create new patches and load/unload them can be
X found at <http://opensource.creative.com/dist.html>.
-
+
X Creative EMU10K1 MIDI
X CONFIG_MIDI_EMU10K1
- Say Y if you want to be able to use the OSS /dev/sequencer interface.
- This code is still experimental.
+ Say Y if you want to be able to use the OSS /dev/sequencer
+ interface. This code is still experimental.
X
X Crystal SoundFusion (CS4280/461x)
X CONFIG_SOUND_FUSION
- This module drives the Crystal SoundFusion devices (CS4280/46xx series)
- when wired as native sound drivers with AC97 codecs. If this driver
- does not work try the CS4232 driver.
+ This module drives the Crystal SoundFusion devices (CS4280/46xx
+ series) when wired as native sound drivers with AC97 codecs. If
+ this driver does not work try the CS4232 driver.
X
-Ensoniq ES1370 based PCI sound cards
+Ensoniq AudioPCI (ES1370) based PCI sound cards
X CONFIG_SOUND_ES1370
X Say Y or M if you have a PCI sound card utilizing the Ensoniq
X ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find
X out if your sound card uses an ES1370 without removing your
- computer's cover, use lspci -n and look for the PCI ID
+ computer's cover, use lspci -n and look for the PCI ID
X 1274:5000. Since Ensoniq was bought by Creative Labs,
X Sound Blaster 64/PCI models are either ES1370 or ES1371 based.
X This driver differs slightly from OSS/Free, so PLEASE READ
- Documentation/sound/es1370.
+ <file:Documentation/sound/es1370>.
X
-Ensoniq ES1371 based PCI sound cards
+Ensoniq AudioPCI 97 (ES1371) based sound cards
X CONFIG_SOUND_ES1371
X Say Y or M if you have a PCI sound card utilizing the Ensoniq
X ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if
@@ -16047,25 +18480,26 @@
X cover, use lspci -n and look for the PCI ID 1274:1371. Since
X Ensoniq was bought by Creative Labs, Sound Blaster 64/PCI
X models are either ES1370 or ES1371 based. This driver differs
- slightly from OSS/Free, so PLEASE READ Documentation/sound/es1371.
+ slightly from OSS/Free, so PLEASE READ
+ <file:Documentation/sound/es1371>.
X
X ESS Solo1 based PCI sound cards (eg. SC1938)
X CONFIG_SOUND_ESSSOLO1
X Say Y or M if you have a PCI sound card utilizing the ESS Technology
X Solo1 chip. To find out if your sound card uses a
X Solo1 chip without removing your computer's cover, use
- lspci -n and look for the PCI ID 125D:1969. This driver
+ lspci -n and look for the PCI ID 125D:1969. This driver
X differs slightly from OSS/Free, so PLEASE READ
- Documentation/sound/solo1.
+ <file:Documentation/sound/solo1>.
X
X S3 SonicVibes based PCI sound cards
X CONFIG_SOUND_SONICVIBES
X Say Y or M if you have a PCI sound card utilizing the S3
X SonicVibes chipset. To find out if your sound card uses a
X SonicVibes chip without removing your computer's cover, use
- lspci -n and look for the PCI ID 5333:CA00. This driver
+ lspci -n and look for the PCI ID 5333:CA00. This driver
X differs slightly from OSS/Free, so PLEASE READ
- Documentation/sound/sonicvibes.
+ <file:Documentation/sound/sonicvibes>.
X
X Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core
X CONFIG_SOUND_TRIDENT
@@ -16082,26 +18516,29 @@
X 10B9:5451 stands for ALi5451.
X
X This driver supports S/PDIF in/out (record/playback) for ALi 5451
- embedded in ALi M1535+ and M1535D+. Note that they aren't all
+ embedded in ALi M1535+ and M1535D+. Note that they aren't all
X enabled by default; you can enable them by saying Y to "/proc file
- system support" and "Sysctl support", and after the /proc file
+ system support" and "Sysctl support", and after the /proc file
X system has been mounted, executing the command
X
X command what is enabled
-
+
X echo 0>/proc/ALi5451 pcm out is also set to S/PDIF out. (Default).
-
+
X echo 1>/proc/ALi5451 use S/PDIF out to output pcm data.
-
- echo 2>/proc/ALi5451 use S/PDIF out to output non-pcm data.(AC3...).
X
- echo 3>/proc/ALi5451 record from Ac97 in(MIC, Line in...). (Default).
-
- echo 4>/proc/ALi5451 no matter Ac97 settings, record from S/PDIF in.
-
-
+ echo 2>/proc/ALi5451 use S/PDIF out to output non-pcm data.
+ (AC3...).
+
+ echo 3>/proc/ALi5451 record from Ac97 in(MIC, Line in...).
+ (Default).
+
+ echo 4>/proc/ALi5451 no matter Ac97 settings, record from S/PDIF
+ in.
+
+
X This driver differs slightly from OSS/Free, so PLEASE READ the
- comments at the top of driver/sound/trident.c
+ comments at the top of <file:drivers/sound/trident.c>.
X
X Rockwell WaveArtist
X CONFIG_SOUND_WAVEARTIST
@@ -16119,10 +18556,10 @@
X
X VIA 82C686 MIDI
X CONFIG_MIDI_VIA82CXXX
- Answer Y to use the MIDI interface of the Via686. You may need to
- enable this in the BIOS before it will work. This is for connection
- to external MIDI hardware, and is not required for software playback
- of MIDI files.
+ Answer Y to use the MIDI interface of the Via686. You may need to
+ enable this in the BIOS before it will work. This is for connection
+ to external MIDI hardware, and is not required for software playback
+ of MIDI files.
X
X NeoMagic 256AV/256ZX sound chipsets
X CONFIG_SOUND_NM256
@@ -16132,13 +18569,76 @@
X laptops. It includes support for an AC97-compatible mixer and an
X apparently proprietary sound engine.
X
- See Documentation/sound/NM256 for further information.
+ See <file:Documentation/sound/NM256> for further information.
X
-ESS Maestro sound chipsets
+ESS Maestro, Maestro2, Maestro2E driver
X CONFIG_SOUND_MAESTRO
X Say Y or M if you have a sound system driven by ESS's Maestro line
X of PCI sound chips. These include the Maestro 1, Maestro 2, and
- Maestro 2E. See Documentation/sound/Maestro for more details.
+ Maestro 2E. See <file:Documentation/sound/Maestro> for more
+ details.
+
+ESS Maestro3/Allegro driver
+CONFIG_SOUND_MAESTRO3
+ Say Y or M if you have a sound system driven by ESS's Maestro 3
+ PCI sound chip.
+
+Adlib Cards
+CONFIG_SOUND_ADLIB
+ Includes ASB 64 4D. Information on programming AdLib cards is
+ available at <http://www.itsnet.com/home/ldragon/Specs/adlib.html>.
+
+Crystal Sound CS4281
+CONFIG_SOUND_CS4281
+ Picture and feature list at
+ <http://www.pcbroker.com/crystal4281.html>.
+
+16 bit sampling option of GUS (_NOT_ GUS MAX)
+CONFIG_SOUND_GUS16
+ Support for Gravis Ulstrasound (GUS) cards (other than the GUS),
+ sampling at 16-bit width.
+
+GUS MAX support
+CONFIG_SOUND_GUSMAX
+ Support for Gravis Ulstrasound MAX.
+
+Intel ICH audio support
+CONFIG_SOUND_ICH
+ Support for integral audio in Intel's I/O Controller Hub (ICH)
+ chipset, as used on the 810/820/840 motherboards.
+
+Verbose initialization
+CONFIG_SOUND_TRACEINIT
+ Verbose soundcard initialization -- affects the format of autoprobe
+ and initialization messages at boot time.
+
+TV card (bt848) mixer support
+CONFIG_SOUND_TVMIXER
+ Support for audio mixer facilities on the BT848 TV frame-grabber
+ card.
+
+VIDC 16-bit sound
+CONFIG_SOUND_VIDC
+ 16-bit support for the VIDC onboard sound hardware found on Acorn
+ machines.
+
+Loopback MIDI device support
+CONFIG_SOUND_VMIDI
+ Support for MIDI loopback on port 1 or 2.
+
+Yamaha YMF7xx PCI audio (native mode)
+CONFIG_SOUND_YMFPCI
+ Support for Yamaha cards including the YMF711, YMF715, YMF718,
+ YMF719, YMF724, Waveforce 192XG, and Waveforce 192 Digital.
+
+Yamaha PCI legacy ports support
+CONFIG_SOUND_YMFPCI_LEGACY
+ Support for YMF7xx PCI cards emulating an MP401.
+
+RME Hammerfall (RME96XX) support
+CONFIG_SOUND_RME96XX
+ Say Y or M if you have a Hammerfall, Hammerfall light or Hammerfall
+ DSP card from RME.
X
X Are you using a crosscompiler
X CONFIG_CROSSCOMPILE
@@ -16157,6 +18657,73 @@
X only useful for people working on the floating point exception
X handler. If you don't, say N.
X
+Galileo EV64120 Evaluation board
+CONFIG_MIPS_EV64120
+ This is an evaluation board based on the Galileo GT-64120
+ single-chip system controller that contains a MIPS R5000 compatible
+ core running at 75/100MHz. Their website is located at
+ <http://www.galileot.com/>. Say Y here if you wish to build a
+ kernel for this platform.
+
+Galileo EV96100 Evaluation board
+CONFIG_MIPS_EV96100
+ This is an evaluation board based on the Galielo GT-96100 LAN/WAN
+ communications controllers containing a MIPS R5000 compatible core
+ running at 83MHz. Their website is <http://www.galileot.com/>. Say Y
+ here if you wish to build a kernel for this platform.
+
+Support for ITE 8172G board
+CONFIG_MIPS_ITE8172
+ Ths is an evaluation board made by ITE (http://www.ite.com.tw/)
+ with ATX form factor that utilizes a MIPS R5000 to work with its
+ ITE8172G companion internet appliance chip. The MIPS core can be
+ either a NEC Vr5432 or QED RM5231. Say Y here if you wish to build
+ a kernel for this platform.
+
+Support for Globespan IVR board
+CONFIG_MIPS_IVR
+ This is an evaluation board built by Globespan to showcase thir
+ iVR (Internet Video Recorder) design. It utilizes a QED RM5231
+ R5000 MIPS core. More information can be found out their website
+ located at <http://www.globespan.net/products/product4.html>P. Say Y
+ here if you wish to build a kernel for this platform.
+
+Support for Alchemy Semi PB1000 board
+CONFIG_MIPS_PB1000
+ This is an evaluation board built by Alchemy Semiconducttor to
+ showcase their Au1000 Internet Edge Processor. It is SOC design
+ containing a MIPS32 core running at 266/400/500MHz with many
+ integrated peripherals. Further information can be found at their
+ website, <http://www.alchemysemi.com/>. Say Y here if you wish to
+ build a kernel for this platform.
+
+Support for Philips Nino
+CONFIG_NINO
+ Say Y here to select a kernel for the Philips Nino Palm PC. The
+ website at <http://www.realitydiluted.com/projects/nino/index.html>
+ will have more information.
+
+Model-500/510
+CONFIG_NINO_16MB
+ Say Y here to build a kernel specifically for Nino 500/501 color
+ Palm PCs from Philips (INCOMPLETE).
+
+Model-200/210/312/320/325/350/390
+CONFIG_NINO_8MB
+ Say Y here to build a kernel specifically for Nino Palm PCs with
+ 8MB of memory. These include models 200/210/312/320/325/350/390.
+
+Model-300/301/302/319
+CONFIG_NINO_4MB
+ Say Y here to build a kernel specifically for Nino Palm PCs with
+ 4MB of memory. These include models 300/301/302/319.
+
+Low-level debugging
+CONFIG_LL_DEBUG
+ Enable low-level debugging assertion macros in the kernel code.
+ Currently used only by the time services code in the MIPS port.
+ Don't turn this on unless you know what you are doing.
+
X Remote GDB kernel debugging
X CONFIG_REMOTE_DEBUG
X If you say Y here, it will be possible to remotely debug the MIPS
@@ -16182,34 +18749,34 @@
X by pressing various keys while holding SysRq (Alt+PrintScreen). It
X also works on a serial console (on PC hardware at least), if you
X send a BREAK and then within 5 seconds a command keypress. The
- keys are documented in Documentation/sysrq.txt. Don't say Y unless
- you really know what this hack does.
+ keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
+ unless you really know what this hack does.
X
-ISDN subsystem
+ISDN support
X CONFIG_ISDN
X ISDN ("Integrated Services Digital Networks", called RNIS in France)
X is a special type of fully digital telephone service; it's mostly
X used to connect to your Internet service provider (with SLIP or
- PPP). The main advantage is that the speed is higher than ordinary
+ PPP). The main advantage is that the speed is higher than ordinary
X modem/telephone connections, and that you can have voice
- conversations while downloading stuff. It only works if your
+ conversations while downloading stuff. It only works if your
X computer is equipped with an ISDN card and both you and your service
- provider purchased an ISDN line from the phone company. For details,
- read http://alumni.caltech.edu/~dank/isdn/ on the WWW.
+ provider purchased an ISDN line from the phone company. For
+ details, read <http://alumni.caltech.edu/~dank/isdn/> on the WWW.
X
X This driver allows you to use an ISDN-card for networking
- connections and as dialin/out device. The isdn-tty's have a built in
- AT-compatible modem emulator. Network devices support autodial,
+ connections and as dialin/out device. The isdn-tty's have a built
+ in AT-compatible modem emulator. Network devices support autodial,
X channel-bundling, callback and caller-authentication without having
- a daemon running. A reduced T.70 protocol is supported with tty's
- suitable for German BTX. On D-Channel, the protocols EDSS1
- (Euro-ISDN) and 1TR6 (German style) are supported. See
- Documentation/isdn/README for more information.
+ a daemon running. A reduced T.70 protocol is supported with tty's
+ suitable for German BTX. On D-Channel, the protocols EDSS1
+ (Euro-ISDN) and 1TR6 (German style) are supported. See
+ <file:Documentation/isdn/README> for more information.
X
X If you want to compile the ISDN code as a module ( = code which can
X be inserted in and removed from the running kernel whenever you


- want), say M here and read Documentation/modules.txt. The module

- will be called isdn.o. If unsure, say N.


+ want), say M here and read <file:Documentation/modules.txt>. The

+ module will be called isdn.o. If unsure, say N.
X
X Support synchronous PPP
X CONFIG_ISDN_PPP
@@ -16220,20 +18787,21 @@
X protocol is used by Cisco and Sun for example. So you want to say Y
X here if the other end of your ISDN connection supports it. You will
X need a special version of pppd (called ipppd) for using this
- feature. See Documentation/isdn/README.syncppp and
- Documentation/isdn/syncPPP.FAQ for more information.
+ feature. See <file:Documentation/isdn/README.syncppp> and
+ <file:Documentation/isdn/syncPPP.FAQ> for more information.
X
X Support generic MP (RFC 1717)
X CONFIG_ISDN_MPP
X With synchronous PPP enabled, it is possible to increase throughput
X by bundling several ISDN-connections, using this protocol. See
- Documentation/isdn/README.syncppp for more information.
+ <file:Documentation/isdn/README.syncppp> for more information.
X
X Use VJ-compression with synchronous PPP
X CONFIG_ISDN_PPP_VJ
X This enables Van Jacobson header compression for synchronous PPP.
X Say Y if the other end of the connection supports it.
X
+Support BSD compression
X CONFIG_ISDN_PPP_BSDCOMP
X Support for the BSD-Compress compression method for PPP, which uses
X the LZW compression method to compress each PPP packet before it is
@@ -16251,19 +18819,19 @@
X your Linux box as an ISDN-answering machine. Of course, this must be
X supported by the lowlevel driver also. Currently, the HiSax driver
X is the only voice-supporting driver. See
- Documentation/isdn/README.audio for more information.
+ <file:Documentation/isdn/README.audio> for more information.
X
X X.25 PLP on top of ISDN
X CONFIG_ISDN_X25
- This feature provides the X.25 protocol over ISDN connections.
- See Documentation/isdn/README.x25 for more information
+ This feature provides the X.25 protocol over ISDN connections.
+ See <file:Documentation/isdn/README.x25> for more information
X if you are thinking about using this.
X
X ISDN diversion services support
X CONFIG_ISDN_DIVERSION
X This option allows you to use some supplementary diversion
X services in conjunction with the HiSax driver on an EURO/DSS1
- line.
+ line.
X
X Supported options are CD (call deflection), CFU (Call forward
X unconditional), CFB (Call forward when busy) and CFNR (call forward
@@ -16274,22 +18842,23 @@
X countries. The keypad protocol is still not implemented. CD should
X work in all countries if the service has been subscribed to.
X
- Please read the file Documentation/isdn/README.diversion.
+ Please read the file <file:Documentation/isdn/README.diversion>.
X
X ICN 2B and 4B support
X CONFIG_ISDN_DRV_ICN
X This enables support for two kinds of ISDN-cards made by a German
- company called ICN. 2B is the standard version for a single ISDN
- line with two B-channels, 4B supports two ISDN lines. For running
+ company called ICN. 2B is the standard version for a single ISDN
+ line with two B-channels, 4B supports two ISDN lines. For running
X this card, additional firmware is necessary, which has to be
X downloaded into the card using a utility which is distributed
- separately. See Documentation/isdn/README and README.icn for more
- information.
+ separately. See <file:Documentation/isdn/README> and
+ <file:Documentation/isdn/README.icn> for more
+ information.
X

X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called icn.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called icn.o.
X
X isdnloop support
X CONFIG_ISDN_DRV_LOOP
@@ -16304,19 +18873,19 @@
X This is a driver supporting the Siemens chipset on various
X ISDN-cards (like AVM A1, Elsa ISDN cards, Teles S0-16.0, Teles
X S0-16.3, Teles S0-8, Teles/Creatix PnP, ITK micro ix1 and many
- compatibles).
+ compatibles).
X
X HiSax is just the name of this driver, not the name of any hardware.
-
+
X If you have a card with such a chipset, you should say Y here and
X also to the configuration option of the driver for your particular
X card, below.


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called hisax.o. See Documentation/isdn/README.HiSax for more
- information on using this driver.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called hisax.o. See <file:Documentation/isdn/README.HiSax>
+ for more information on using this driver.
X
X HiSax Support for EURO/DSS1


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

echo 'End of part 015'
echo 'File patch-2.4.15 is continued in part 016'
echo "016" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:00 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part024

#!/bin/sh -x
# this is part 024 of a 115 - part archive


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

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

+ return -1;
X #endif
X
X while( fp < 0xFFFFF)
@@ -315,15 +316,14 @@


X return 0;
X }
X

-#if defined(CONFIG_SONYPI) || defined(CONFIG_SONYPI_MODULE)
X /*
- * Check for a Sony Vaio system in order to enable the use of
- * the sonypi driver (we don't want this driver to be used on
- * other systems, even if they have the good PCI IDs).
+ * Check for a Sony Vaio system
X *
- * This one isn't a bug detect for those who asked, we simply want to
- * activate Sony specific goodies like the camera and jogdial..
+ * On a Sony system we want to enable the use of the sonypi
+ * driver for Sony-specific goodies like the camera and jogdial.
+ * We also want to avoid using certain functions of the PnP BIOS.
X */
+
X static __init int sony_vaio_laptop(struct dmi_blacklist *d)
X {
X if (is_sony_vaio_laptop == 0)
@@ -333,7 +333,6 @@


X }
X return 0;
X }

-#endif
X
X /*
X * This bios swaps the APM minute reporting bytes over (Many sony laptops
@@ -359,18 +358,49 @@
X printk(KERN_INFO " *** Possibly defective BIOS detected (irqtable)\n");
X printk(KERN_INFO " *** Many BIOSes matching this signature have incorrect IRQ routing tables.\n");
X printk(KERN_INFO " *** If you see IRQ problems, in paticular SCSI resets and hangs at boot\n");
- printk(KERN_INFO " *** contact your vendor and ask about updates.\n");
+ printk(KERN_INFO " *** contact your hardware vendor and ask about updates.\n");
X printk(KERN_INFO " *** Building an SMP kernel may evade the bug some of the time.\n");


X return 0;
X }
X

X /*
+ * ASUS K7V-RM has broken ACPI table defining sleep modes
+ */
+
+static __init int broken_acpi_Sx(struct dmi_blacklist *d)
+{
+ printk(KERN_WARNING "Detected ASUS mainboard with broken ACPI sleep table\n");
+ dmi_broken |= BROKEN_ACPI_Sx;


+ return 0;
+}
+

+/*
+ * Toshiba keyboard likes to repeat keys when they are not repeated.
+ */
+
+static __init int broken_toshiba_keyboard(struct dmi_blacklist *d)
+{
+ printk(KERN_WARNING "Toshiba with broken keyboard detected. If your keyboard sometimes generates 3 keypresses instead of one, contact pa...@ucw.cz\n");


+ return 0;
+}
+

+/*
+ * Toshiba fails to preserve interrupts over S1
+ */
+
+static __init int init_ints_after_s1(struct dmi_blacklist *d)
+{
+ printk(KERN_WARNING "Toshiba with broken S1 detected.\n");
+ dmi_broken |= BROKEN_INIT_AFTER_S1;


+ return 0;
+}
+

+/*
X * Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it
X * was disabled before the suspend. Linux gets terribly confused by that.
X */
X
X typedef void (pm_kbd_func) (void);
-extern pm_kbd_func *pm_kbd_request_override;
X
X static __init int broken_ps2_resume(struct dmi_blacklist *d)
X {
@@ -380,11 +410,20 @@
X pm_kbd_request_override = pckbd_pm_resume;
X printk(KERN_INFO "%s machine detected. Mousepad Resume Bug workaround enabled.\n", d->ident);
X }
-#endif
+#endif


X return 0;
X }
X

X
+/*
+ * Simple "print if true" callback
+ */
+
+static __init int print_if_true(struct dmi_blacklist *d)
+{
+ printk("%s\n", d->ident);
+ return 0;
+}
X
X /*
X * Process the DMI blacklists
@@ -428,10 +467,6 @@
X MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
X NO_MATCH, NO_MATCH
X } },
- { set_apm_ints, "IBM", { /* Allow interrupts during suspend on IBM laptops */
- MATCH(DMI_SYS_VENDOR, "IBM"),
- NO_MATCH, NO_MATCH, NO_MATCH
- } },
X { set_apm_ints, "Dell Inspiron", { /* Allow interrupts during suspend on Dell Inspiron laptops*/
X MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
X MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"),
@@ -459,13 +494,11 @@
X MATCH(DMI_BIOS_VENDOR,"SystemSoft"),
X MATCH(DMI_BIOS_VERSION,"Version R2.08")
X } },
-#if defined(CONFIG_SONYPI) || defined(CONFIG_SONYPI_MODULE)
X { sony_vaio_laptop, "Sony Vaio", { /* This is a Sony Vaio laptop */
X MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
X MATCH(DMI_PRODUCT_NAME, "PCG-"),
X NO_MATCH, NO_MATCH,
X } },
-#endif
X { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505X(DE) */
X MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
X MATCH(DMI_BIOS_VERSION, "R0206H"),
@@ -536,11 +569,47 @@
X MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0125.P13"),
X NO_MATCH, NO_MATCH
X } },
+ { broken_pirq, "l44GX Bios", { /* Bad $PIR */
+ MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
+ MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0066.P07.9906041405"),
+ NO_MATCH, NO_MATCH
+ } },
X
X /* Intel in disgiuse - In this case they can't hide and they don't run
X too well either... */
X { broken_pirq, "Dell PowerEdge 8450", { /* Bad $PIR */
X MATCH(DMI_PRODUCT_NAME, "Dell PowerEdge 8450"),
+ NO_MATCH, NO_MATCH, NO_MATCH
+ } },
+
+ { broken_acpi_Sx, "ASUS K7V-RM", { /* Bad ACPI Sx table */
+ MATCH(DMI_BIOS_VERSION,"ASUS K7V-RM ACPI BIOS Revision 1003A"),
+ MATCH(DMI_BOARD_NAME, "<K7V-RM>"),
+ NO_MATCH, NO_MATCH
+ } },
+
+ { broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */
+ MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
+ NO_MATCH, NO_MATCH, NO_MATCH
+ } },
+ { init_ints_after_s1, "Toshiba Satellite 4030cdt", { /* Reinitialization of 8259 is needed after S1 resume */
+ MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
+ NO_MATCH, NO_MATCH, NO_MATCH
+ } },
+
+ { print_if_true, KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.", {
+ MATCH(DMI_SYS_VENDOR, "IBM"),
+ MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"),
+ NO_MATCH, NO_MATCH
+ } },
+
+
+ /*
+ * Generic per vendor APM settings
+ */
+
+ { set_apm_ints, "IBM", { /* Allow interrupts during suspend on IBM laptops */
+ MATCH(DMI_SYS_VENDOR, "IBM"),
X NO_MATCH, NO_MATCH, NO_MATCH
X } },
X
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.4.14/linux/arch/i386/kernel/i386_ksyms.c Tue Oct 23 22:48:49 2001
+++ linux/arch/i386/kernel/i386_ksyms.c Tue Nov 13 09:13:20 2001
@@ -112,6 +112,11 @@
X EXPORT_SYMBOL(pci_mem_start);
X #endif
X
+#ifdef CONFIG_PCI_BIOS
+EXPORT_SYMBOL(pcibios_set_irq_routing);
+EXPORT_SYMBOL(pcibios_get_irq_routing_table);
+#endif
+
X #ifdef CONFIG_X86_USE_3DNOW
X EXPORT_SYMBOL(_mmx_memcpy);
X EXPORT_SYMBOL(mmx_clear_page);
@@ -157,10 +162,6 @@
X extern void * memcpy(void *,const void *,__kernel_size_t);
X EXPORT_SYMBOL_NOVERS(memcpy);
X EXPORT_SYMBOL_NOVERS(memset);
-
-#ifdef CONFIG_X86_PAE
-EXPORT_SYMBOL(empty_zero_page);
-#endif
X
X #ifdef CONFIG_HAVE_DEC_LOCK
X EXPORT_SYMBOL(atomic_dec_and_lock);
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.4.14/linux/arch/i386/kernel/io_apic.c Mon Nov 5 15:55:26 2001
+++ linux/arch/i386/kernel/io_apic.c Tue Nov 13 17:28:41 2001
@@ -753,7 +753,6 @@
X printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.PRQ);
X printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.version);
X if ( (reg_01.version != 0x01) && /* 82489DX IO-APICs */
- (reg_01.version != 0x02) && /* 82801BA IO-APICs (ICH2) */
X (reg_01.version != 0x10) && /* oldest IO-APICs */
X (reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */
X (reg_01.version != 0x13) && /* Xeon IO-APICs */
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/mpparse.c linux/arch/i386/kernel/mpparse.c
--- v2.4.14/linux/arch/i386/kernel/mpparse.c Tue Oct 9 17:06:51 2001
+++ linux/arch/i386/kernel/mpparse.c Fri Nov 9 14:58:18 2001
@@ -36,6 +36,7 @@
X */
X int apic_version [MAX_APICS];
X int mp_bus_id_to_type [MAX_MP_BUSSES];
+int mp_bus_id_to_node [MAX_MP_BUSSES];
X int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
X int mp_current_pci_id;
X
@@ -55,6 +56,7 @@
X
X /* Processor that is doing the boot up */
X unsigned int boot_cpu_physical_apicid = -1U;
+unsigned int boot_cpu_logical_apicid = -1U;
X /* Internal processor count */
X static unsigned int num_processors;
X
@@ -118,18 +120,45 @@
X return n;
X }
X
-static void __init MP_processor_info (struct mpc_config_processor *m)
-{
- int ver;
+#ifdef CONFIG_X86_IO_APIC
+extern int have_acpi_tables; /* set by acpitable.c */
+#else
+#define have_acpi_tables (0)
+#endif
+
+/*
+ * Have to match translation table entries to main table entries by counter
+ * hence the mpc_record variable .... can't see a less disgusting way of
+ * doing this ....
+ */
+
+static int mpc_record;
+static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
X
+void __init MP_processor_info (struct mpc_config_processor *m)
+{
+ int ver, quad, logical_apicid;
+
X if (!(m->mpc_cpuflag & CPU_ENABLED))
X return;
X
- printk("Processor #%d %s APIC version %d\n",
- m->mpc_apicid,
- mpc_family( (m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 ,
- (m->mpc_cpufeature & CPU_MODEL_MASK)>>4),
- m->mpc_apicver);
+ logical_apicid = m->mpc_apicid;
+ if (clustered_apic_mode) {
+ quad = translation_table[mpc_record]->trans_quad;
+ logical_apicid = (quad << 4) +
+ (m->mpc_apicid ? m->mpc_apicid << 1 : 1);
+ printk("Processor #%d %s APIC version %d (quad %d, apic %d)\n",
+ m->mpc_apicid,
+ mpc_family((m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 ,
+ (m->mpc_cpufeature & CPU_MODEL_MASK)>>4),
+ m->mpc_apicver, quad, logical_apicid);
+ } else {
+ printk("Processor #%d %s APIC version %d\n",
+ m->mpc_apicid,
+ mpc_family((m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 ,
+ (m->mpc_cpufeature & CPU_MODEL_MASK)>>4),
+ m->mpc_apicver);
+ }
X
X if (m->mpc_featureflag&(1<<0))
X Dprintk(" Floating point unit present.\n");
@@ -172,7 +201,8 @@
X Dprintk(" Willamette New Instructions present.\n");
X if (m->mpc_featureflag&(1<<27))
X Dprintk(" Self Snoop present.\n");
- /* 28 Reserved */
+ if (m->mpc_featureflag&(1<<28))
+ Dprintk(" HT present.\n");
X if (m->mpc_featureflag&(1<<29))
X Dprintk(" Thermal Monitor present.\n");
X /* 30, 31 Reserved */
@@ -181,6 +211,7 @@
X if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
X Dprintk(" Bootup CPU\n");
X boot_cpu_physical_apicid = m->mpc_apicid;
+ boot_cpu_logical_apicid = logical_apicid;
X }
X
X num_processors++;
@@ -192,12 +223,11 @@
X }
X ver = m->mpc_apicver;
X
- if (clustered_apic_mode)
- /* Crude temporary hack. Assumes processors are sequential */
- phys_cpu_present_map |= 1 << (num_processors-1);
- else
+ if (clustered_apic_mode) {
+ phys_cpu_present_map |= (logical_apicid&0xf) << (4*quad);
+ } else {
X phys_cpu_present_map |= 1 << m->mpc_apicid;
-
+ }
X /*
X * Validate version
X */
@@ -214,7 +244,13 @@
X
X memcpy(str, m->mpc_bustype, 6);
X str[6] = 0;
- Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
+
+ if (clustered_apic_mode) {
+ mp_bus_id_to_node[m->mpc_busid] = translation_table[mpc_record]->trans_quad;
+ printk("Bus #%d is %s (node %d)\n", m->mpc_busid, str, mp_bus_id_to_node[m->mpc_busid]);
+ } else {
+ Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
+ }
X
X if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
X mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
@@ -286,6 +322,63 @@
X BUG();
X }
X
+static void __init MP_translation_info (struct mpc_config_translation *m)
+{
+ printk("Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type,
+ m->trans_quad, m->trans_global, m->trans_local);
+
+ if (mpc_record >= MAX_MPC_ENTRY)
+ printk("MAX_MPC_ENTRY exceeded!\n");
+ else
+ translation_table[mpc_record] = m; /* stash this for later */
+}
+
+/*
+ * Read/parse the MPC oem tables
+ */
+
+static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \
+ unsigned short oemsize)
+{
+ int count = sizeof (*oemtable); /* the header size */
+ unsigned char *oemptr = ((unsigned char *)oemtable)+count;
+
+ printk("Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
+ if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4))
+ {
+ printk("SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
+ oemtable->oem_signature[0],
+ oemtable->oem_signature[1],
+ oemtable->oem_signature[2],
+ oemtable->oem_signature[3]);
+ return;
+ }
+ if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length))
+ {
+ printk("SMP oem mptable: checksum error!\n");
+ return;
+ }
+ while (count < oemtable->oem_length) {
+ switch (*oemptr) {
+ case MP_TRANSLATION:
+ {
+ struct mpc_config_translation *m=
+ (struct mpc_config_translation *)oemptr;
+ MP_translation_info(m);
+ oemptr += sizeof(*m);
+ count += sizeof(*m);
+ ++mpc_record;
+ break;
+ }
+ default:
+ {
+ printk("Unrecognised OEM table entry type! - %d\n", (int) *oemptr);


+ return;
+ }
+ }
+ }

+}
+
X /*
X * Read/parse the MPC
X */
@@ -327,8 +420,18 @@
X
X printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
X
- /* save the local APIC address, it might be non-default */
- mp_lapic_addr = mpc->mpc_lapic;
+ /* save the local APIC address, it might be non-default,
+ * but only if we're not using the ACPI tables
+ */
+ if (!have_acpi_tables)
+ mp_lapic_addr = mpc->mpc_lapic;
+
+ if (clustered_apic_mode && mpc->mpc_oemptr) {
+ /* We need to process the oem mpc tables to tell us which quad things are in ... */
+ mpc_record = 0;
+ smp_read_mpc_oem((struct mp_config_oemtable *) mpc->mpc_oemptr, mpc->mpc_oemsize);
+ mpc_record = 0;
+ }
X
X /*
X * Now process the configuration blocks.
@@ -339,7 +442,10 @@
X {
X struct mpc_config_processor *m=
X (struct mpc_config_processor *)mpt;
- MP_processor_info(m);
+
+ /* ACPI may already have provided this one for us */
+ if (!have_acpi_tables)
+ MP_processor_info(m);
X mpt += sizeof(*m);
X count += sizeof(*m);
X break;
@@ -381,7 +487,13 @@
X count+=sizeof(*m);
X break;
X }
+ default:
+ {
+ count = mpc->mpc_length;
+ break;
+ }
X }
+ ++mpc_record;
X }
X if (clustered_apic_mode && nr_ioapics > 2) {
X /* don't initialise IO apics on secondary quads */
@@ -550,6 +662,7 @@
X }
X
X static struct intel_mp_floating *mpf_found;
+extern void config_acpi_tables(void);
X
X /*
X * Scan the memory blocks for an SMP configuration block.
@@ -557,6 +670,18 @@
X void __init get_smp_config (void)
X {
X struct intel_mp_floating *mpf = mpf_found;
+
+#ifdef CONFIG_X86_IO_APIC
+ /*
+ * Check if the ACPI tables are provided. Use them only to get
+ * the processor information, mainly because it provides
+ * the info on the logical processor(s), rather than the physical
+ * processor(s) that are provided by the MPS. We attempt to
+ * check only if the user provided a commandline override
+ */
+ config_acpi_tables();
+#endif
+
X printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
X if (mpf->mpf_feature2 & (1<<7)) {
X printk(" IMCR and PIC compatibility mode.\n");
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.4.14/linux/arch/i386/kernel/mtrr.c Mon Nov 5 15:55:26 2001
+++ linux/arch/i386/kernel/mtrr.c Fri Nov 9 13:58:02 2001
@@ -2249,9 +2249,11 @@
X proc_root_mtrr->proc_fops = &mtrr_fops;
X }
X #endif
+#ifdef USERSPACE_INTERFACE
X devfs_handle = devfs_register (NULL, "cpu/mtrr", DEVFS_FL_DEFAULT, 0, 0,
X S_IFREG | S_IRUGO | S_IWUSR,
X &mtrr_fops, NULL);
+#endif
X init_table ();
X return 0;
X } /* End Function mtrr_init */
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/pci-i386.h linux/arch/i386/kernel/pci-i386.h
--- v2.4.14/linux/arch/i386/kernel/pci-i386.h Tue Jul 3 17:08:18 2001
+++ linux/arch/i386/kernel/pci-i386.h Sun Nov 11 10:09:32 2001
@@ -37,9 +37,6 @@
X extern struct pci_bus *pci_root_bus;
X extern struct pci_ops *pci_root_ops;
X
-struct irq_routing_table *pcibios_get_irq_routing_table(void);
-int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
-
X /* pci-irq.c */
X
X struct irq_info {
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c
--- v2.4.14/linux/arch/i386/kernel/pci-pc.c Mon Nov 5 15:55:26 2001
+++ linux/arch/i386/kernel/pci-pc.c Fri Nov 9 13:58:02 2001
@@ -309,7 +309,7 @@
X * This should be close to trivial, but it isn't, because there are buggy
X * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
X */
-static int __init pci_sanity_check(struct pci_ops *o)
+static int __devinit pci_sanity_check(struct pci_ops *o)
X {
X u16 x;
X struct pci_bus bus; /* Fake bus and device */
@@ -329,7 +329,7 @@


X return 0;
X }
X

-static struct pci_ops * __init pci_check_direct(void)
+static struct pci_ops * __devinit pci_check_direct(void)
X {
X unsigned int tmp;
X unsigned long flags;


@@ -488,7 +488,7 @@
X

X static int pci_bios_present;
X
-static int __init check_pcibios(void)
+static int __devinit check_pcibios(void)
X {
X u32 signature, eax, ebx, ecx;
X u8 status, major_ver, minor_ver, hw_mech;
@@ -538,7 +538,7 @@


X return 0;
X }
X

-static int __init pci_bios_find_device (unsigned short vendor, unsigned short device_id,
+static int __devinit pci_bios_find_device (unsigned short vendor, unsigned short device_id,
X unsigned short index, unsigned char *bus, unsigned char *device_fn)
X {
X unsigned short bx;
@@ -747,7 +747,7 @@
X * Try to find PCI BIOS.
X */
X
-static struct pci_ops * __init pci_find_bios(void)
+static struct pci_ops * __devinit pci_find_bios(void)
X {
X union bios32 *check;
X unsigned char sum;
@@ -801,7 +801,7 @@
X * which used BIOS ordering, we are bound to do this...
X */
X
-static void __init pcibios_sort(void)
+static void __devinit pcibios_sort(void)
X {
X LIST_HEAD(sorted_devices);
X struct list_head *ln;
@@ -855,7 +855,7 @@
X u16 segment;
X } __attribute__((packed));
X
-struct irq_routing_table * __init pcibios_get_irq_routing_table(void)
+struct irq_routing_table * __devinit pcibios_get_irq_routing_table(void)
X {
X struct irq_routing_options opt;
X struct irq_routing_table *rt = NULL;
@@ -929,7 +929,7 @@
X * expected to be unique) and remove the ghost devices.
X */
X
-static void __init pcibios_fixup_ghosts(struct pci_bus *b)
+static void __devinit pcibios_fixup_ghosts(struct pci_bus *b)
X {
X struct list_head *ln, *mn;
X struct pci_dev *d, *e;
@@ -979,7 +979,7 @@
X * Discover remaining PCI buses in case there are peer host bridges.
X * We use the number of last PCI bus provided by the PCI BIOS.
X */
-static void __init pcibios_fixup_peer_bridges(void)
+static void __devinit pcibios_fixup_peer_bridges(void)
X {
X int n;
X struct pci_bus bus;
@@ -1010,7 +1010,7 @@
X * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
X */
X
-static void __init pci_fixup_i450nx(struct pci_dev *d)
+static void __devinit pci_fixup_i450nx(struct pci_dev *d)
X {
X /*
X * i450NX -- Find and scan all secondary buses on all PXB's.
@@ -1032,7 +1032,7 @@
X pcibios_last_bus = -1;
X }
X
-static void __init pci_fixup_i450gx(struct pci_dev *d)
+static void __devinit pci_fixup_i450gx(struct pci_dev *d)
X {
X /*
X * i450GX and i450KX -- Find and scan all secondary buses.
@@ -1045,49 +1045,7 @@
X pcibios_last_bus = -1;
X }
X
-#if 0
-/* Until we get proper handling pray the BIOS gets it right */
-/*
- * ServerWorks host bridges -- Find and scan all secondary buses.
- * Register 0x44 contains first, 0x45 last bus number routed there.
- */
-static void __init pci_fixup_serverworks(struct pci_dev *d)
-{
- u8 busno1, busno2;
-
- pci_read_config_byte(d, 0x44, &busno1);
- pci_read_config_byte(d, 0x45, &busno2);
- if (busno2 < busno1)
- busno2 = busno1;
- if (busno2 > pcibios_last_bus) {
- pcibios_last_bus = busno2;
- printk("PCI: ServerWorks host bridge: last bus %02x\n", pcibios_last_bus);
- }
-}
-#endif
-
-#if 0
-/* Our bus code shouldnt need this fixup any more. Delete once verified */
-/*
- * Compaq host bridges -- Find and scan all secondary buses.
- * This time registers 0xc8 and 0xc9.
- */
-static void __init pci_fixup_compaq(struct pci_dev *d)
-{
- u8 busno1, busno2;
-
- pci_read_config_byte(d, 0xc8, &busno1);
- pci_read_config_byte(d, 0xc9, &busno2);
- if (busno2 < busno1)
- busno2 = busno1;
- if (busno2 > pcibios_last_bus) {
- pcibios_last_bus = busno2;
- printk("PCI: Compaq host bridge: last bus %02x\n", busno2);
- }
-}
-#endif
-
-static void __init pci_fixup_umc_ide(struct pci_dev *d)
+static void __devinit pci_fixup_umc_ide(struct pci_dev *d)
X {
X /*
X * UM8886BF IDE controller sets region type bits incorrectly,
@@ -1100,7 +1058,7 @@
X d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
X }
X
-static void __init pci_fixup_ide_bases(struct pci_dev *d)
+static void __devinit pci_fixup_ide_bases(struct pci_dev *d)
X {
X int i;
X
@@ -1119,7 +1077,7 @@
X }
X }
X
-static void __init pci_fixup_ide_trash(struct pci_dev *d)
+static void __devinit pci_fixup_ide_trash(struct pci_dev *d)
X {
X int i;
X
@@ -1132,7 +1090,7 @@
X d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0;
X }
X
-static void __init pci_fixup_latency(struct pci_dev *d)
+static void __devinit pci_fixup_latency(struct pci_dev *d)
X {
X /*
X * SiS 5597 and 5598 chipsets require latency timer set to
@@ -1142,7 +1100,7 @@
X pcibios_max_latency = 32;
X }
X
-static void __init pci_fixup_piix4_acpi(struct pci_dev *d)
+static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d)
X {
X /*
X * PIIX4 ACPI device: hardwired IRQ9
@@ -1173,16 +1131,6 @@
X struct pci_fixup pcibios_fixups[] = {
X { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx },
X { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx },
-#if 0
-/* Until we get proper handling pray the BIOS gets it right */
- { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HE, pci_fixup_serverworks },
- { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE, pci_fixup_serverworks },
- { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CMIC_HE, pci_fixup_serverworks },
-#endif
-#if 0
-/* Our bus code shouldnt need this fixup any more. Delete once verified */
- { PCI_FIXUP_HEADER, PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_6010, pci_fixup_compaq },
-#endif
X { PCI_FIXUP_HEADER, PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide },
X { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash },
X { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases },
@@ -1198,14 +1146,14 @@
X * are examined.
X */
X
-void __init pcibios_fixup_bus(struct pci_bus *b)
+void __devinit pcibios_fixup_bus(struct pci_bus *b)
X {
X pcibios_fixup_ghosts(b);
X pci_read_bridge_bases(b);
X }
X
X
-void __init pcibios_config_init(void)
+void __devinit pcibios_config_init(void)
X {
X /*
X * Try all known PCI access methods. Note that we support using
@@ -1262,7 +1210,7 @@
X #endif
X }
X
-char * __init pcibios_setup(char *str)
+char * __devinit pcibios_setup(char *str)
X {
X if (!strcmp(str, "off")) {
X pci_probe = 0;
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v2.4.14/linux/arch/i386/kernel/ptrace.c Sun Sep 23 11:40:55 2001
+++ linux/arch/i386/kernel/ptrace.c Wed Nov 21 10:42:41 2001
@@ -181,15 +181,11 @@
X ret = ptrace_attach(child);
X goto out_tsk;
X }
- ret = -ESRCH;
- if (!(child->ptrace & PT_PTRACED))
- goto out_tsk;
- if (child->state != TASK_STOPPED) {
- if (request != PTRACE_KILL)
- goto out_tsk;
- }
- if (child->p_pptr != current)
+
+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
+ if (ret < 0)
X goto out_tsk;
+
X switch (request) {
X /* when I and D space are separate, these will need to be fixed. */
X case PTRACE_PEEKTEXT: /* read word at location addr. */
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/semaphore.c linux/arch/i386/kernel/semaphore.c
--- v2.4.14/linux/arch/i386/kernel/semaphore.c Thu Apr 12 12:22:53 2001
+++ linux/arch/i386/kernel/semaphore.c Fri Nov 9 13:58:02 2001
@@ -243,7 +243,8 @@
X .globl __write_lock_failed
X __write_lock_failed:
X " LOCK "addl $" RW_LOCK_BIAS_STR ",(%eax)
-1: cmpl $" RW_LOCK_BIAS_STR ",(%eax)
+1: rep; nop
+ cmpl $" RW_LOCK_BIAS_STR ",(%eax)
X jne 1b
X
X " LOCK "subl $" RW_LOCK_BIAS_STR ",(%eax)
@@ -255,7 +256,8 @@
X .globl __read_lock_failed
X __read_lock_failed:
X lock ; incl (%eax)
-1: cmpl $1,(%eax)
+1: rep; nop
+ cmpl $1,(%eax)
X js 1b
X
X lock ; decl (%eax)
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.4.14/linux/arch/i386/kernel/setup.c Mon Nov 5 15:55:26 2001
+++ linux/arch/i386/kernel/setup.c Mon Nov 19 15:16:13 2001
@@ -67,6 +67,10 @@
X *
X * AMD Athlon/Duron/Thunderbird bluesmoke support.
X * Dave Jones <da...@suse.de>, April 2001.
+ *
+ * CacheSize bug workaround updates for AMD, Intel & VIA Cyrix.
+ * Dave Jones <da...@suse.de>, September, October 2001.
+ *
X */
X
X /*
@@ -94,6 +98,7 @@
X #endif
X #include <linux/highmem.h>


X #include <linux/bootmem.h>
+#include <linux/seq_file.h>

X #include <asm/processor.h>
X #include <linux/console.h>
X #include <asm/mtrr.h>
@@ -156,6 +161,8 @@
X static int disable_x86_serial_nr __initdata = 1;
X static int disable_x86_fxsr __initdata = 0;
X
+int enable_acpi_smp_table;
+
X /*
X * This is set up by the setup-routine at boot-time
X */
@@ -753,6 +760,10 @@
X add_memory_region(start_at, mem_size, E820_RAM);
X }
X }
+ /* acpismp=force forces parsing and use of the ACPI SMP table */
+ if (c == ' ' && !memcmp(from, "acpismp=force", 13))
+ enable_acpi_smp_table = 1;
+
X c = *(from++);
X if (!c)
X break;
@@ -1035,6 +1046,15 @@
X #endif
X }
X
+static int cachesize_override __initdata = -1;
+static int __init cachesize_setup(char *str)
+{
+ get_option (&str, &cachesize_override);
+ return 1;
+}
+__setup("cachesize=", cachesize_setup);
+
+
X #ifndef CONFIG_X86_TSC
X static int tsc_disable __initdata = 0;
X
@@ -1105,12 +1125,25 @@
X l2size = 256;
X }
X
+ /* Intel PIII Tualatin. This comes in two flavours.
+ * One has 256kb of cache, the other 512. We have no way
+ * to determine which, so we use a boottime override
+ * for the 512kb model, and assume 256 otherwise.
+ */
+ if ((c->x86_vendor == X86_VENDOR_INTEL) && (c->x86 == 6) &&
+ (c->x86_model == 11) && (l2size == 0))
+ l2size = 256;
+
X /* VIA C3 CPUs (670-68F) need further shifting. */
X if (c->x86_vendor == X86_VENDOR_CENTAUR && (c->x86 == 6) &&
X ((c->x86_model == 7) || (c->x86_model == 8))) {
X l2size = l2size >> 8;
X }
X
+ /* Allow user to override all this if necessary. */
+ if (cachesize_override != -1)
+ l2size = cachesize_override;
+
X if ( l2size == 0 )
X return; /* Again, no L2 cache is possible */
X
@@ -1200,13 +1233,12 @@
X }
X
X /* K6 with old style WHCR */
- if( c->x86_model < 8 ||
- (c->x86_model== 8 && c->x86_mask < 8))
- {
+ if (c->x86_model < 8 ||
+ (c->x86_model== 8 && c->x86_mask < 8)) {
X /* We can only write allocate on the low 508Mb */
X if(mbytes>508)
X mbytes=508;
-
+
X rdmsr(MSR_K6_WHCR, l, h);
X if ((l&0x0000FFFF)==0) {
X unsigned long flags;
@@ -1217,14 +1249,14 @@
X local_irq_restore(flags);
X printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n",
X mbytes);
-
X }
X break;
X }
- if (c->x86_model == 8 || c->x86_model == 9 || c->x86_model == 13)
- {
+
+ if ((c->x86_model == 8 && c->x86_mask >7) ||
+ c->x86_model == 9 || c->x86_model == 13) {
X /* The more serious chips .. */
-
+
X if(mbytes>4092)
X mbytes=4092;
X
@@ -1241,10 +1273,8 @@
X }
X
X /* Set MTRR capability flag if appropriate */
- if ( (c->x86_model == 13) ||
- (c->x86_model == 9) ||
- ((c->x86_model == 8) &&
- (c->x86_mask >= 8)) )
+ if (c->x86_model == 13 || c->x86_model == 9 ||
+ (c->x86_model == 8 && c->x86_mask >= 8))
X set_bit(X86_FEATURE_K6_MTRR, &c->x86_capability);
X break;
X }
@@ -2301,14 +2331,14 @@
X }
X
X
-int __init x86_serial_nr_setup(char *s)
+static int __init x86_serial_nr_setup(char *s)
X {
X disable_x86_serial_nr = 0;
X return 1;
X }
X __setup("serialnumber", x86_serial_nr_setup);
X
-int __init x86_fxsr_setup(char * s)
+static int __init x86_fxsr_setup(char * s)
X {
X disable_x86_fxsr = 1;
X return 1;
@@ -2403,7 +2433,6 @@
X {
X unsigned char ccr3, ccr4;
X unsigned long flags;
-
X printk(KERN_INFO "Enabling CPUID on Cyrix processor.\n");
X local_irq_save(flags);
X ccr3 = getCx86(CX86_CCR3);
@@ -2655,11 +2684,8 @@
X /*
X * Get CPU information for use by the procfs.
X */
-
-int get_cpuinfo(char * buffer)
+static int show_cpuinfo(struct seq_file *m, void *v)


X {
- char *p = buffer;
-

X /*
X * These flag bits must match the definitions in <asm/cpufeature.h>.
X * NULL means this bit is undefined or reserved; either way it doesn't
@@ -2693,75 +2719,88 @@
X NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
X NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
X };
- struct cpuinfo_x86 *c = cpu_data;
- int i, n;
+ struct cpuinfo_x86 *c = v;
+ int i, n = c - cpu_data;
+ int fpu_exception;
X
- for (n = 0; n < NR_CPUS; n++, c++) {
- int fpu_exception;
X #ifdef CONFIG_SMP
- if (!(cpu_online_map & (1<<n)))
- continue;
+ if (!(cpu_online_map & (1<<n)))
+ return 0;
X #endif
- /* Stupid hack */
- if (p - buffer > (3*PAGE_SIZE)/4)
- break;
+ seq_printf(m, "processor\t: %d\n"
+ "vendor_id\t: %s\n"
+ "cpu family\t: %d\n"
+ "model\t\t: %d\n"
+ "model name\t: %s\n",
+ n,
+ c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
+ c->x86,
+ c->x86_model,
+ c->x86_model_id[0] ? c->x86_model_id : "unknown");
X
- p += sprintf(p,"processor\t: %d\n"
- "vendor_id\t: %s\n"
- "cpu family\t: %d\n"
- "model\t\t: %d\n"
- "model name\t: %s\n",
- n,
- c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
- c->x86,
- c->x86_model,
- c->x86_model_id[0] ? c->x86_model_id : "unknown");
+ if (c->x86_mask || c->cpuid_level >= 0)
+ seq_printf(m, "stepping\t: %d\n", c->x86_mask);
+ else
+ seq_printf(m, "stepping\t: unknown\n");
X
- if (c->x86_mask || c->cpuid_level >= 0)
- p += sprintf(p, "stepping\t: %d\n", c->x86_mask);
- else
- p += sprintf(p, "stepping\t: unknown\n");
+ if ( test_bit(X86_FEATURE_TSC, &c->x86_capability) ) {
+ seq_printf(m, "cpu MHz\t\t: %lu.%03lu\n",
+ cpu_khz / 1000, (cpu_khz % 1000));
+ }
X
- if ( test_bit(X86_FEATURE_TSC, &c->x86_capability) ) {
- p += sprintf(p, "cpu MHz\t\t: %lu.%03lu\n",
- cpu_khz / 1000, (cpu_khz % 1000));
- }
+ /* Cache size */
+ if (c->x86_cache_size >= 0)
+ seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
+
+ /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */
+ fpu_exception = c->hard_math && (ignore_irq13 || cpu_has_fpu);
+ seq_printf(m, "fdiv_bug\t: %s\n"
+ "hlt_bug\t\t: %s\n"
+ "f00f_bug\t: %s\n"
+ "coma_bug\t: %s\n"
+ "fpu\t\t: %s\n"
+ "fpu_exception\t: %s\n"
+ "cpuid level\t: %d\n"
+ "wp\t\t: %s\n"
+ "flags\t\t:",
+ c->fdiv_bug ? "yes" : "no",
+ c->hlt_works_ok ? "no" : "yes",
+ c->f00f_bug ? "yes" : "no",
+ c->coma_bug ? "yes" : "no",
+ c->hard_math ? "yes" : "no",
+ fpu_exception ? "yes" : "no",
+ c->cpuid_level,
+ c->wp_works_ok ? "yes" : "no");
+
+ for ( i = 0 ; i < 32*NCAPINTS ; i++ )
+ if ( test_bit(i, &c->x86_capability) &&
+ x86_cap_flags[i] != NULL )
+ seq_printf(m, " %s", x86_cap_flags[i]);
+
+ seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n",
+ c->loops_per_jiffy/(500000/HZ),
+ (c->loops_per_jiffy/(5000/HZ)) % 100);


+ return 0;
+}
X

- /* Cache size */
- if (c->x86_cache_size >= 0)
- p += sprintf(p, "cache size\t: %d KB\n", c->x86_cache_size);
-
- /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */
- fpu_exception = c->hard_math && (ignore_irq13 || cpu_has_fpu);
- p += sprintf(p, "fdiv_bug\t: %s\n"
- "hlt_bug\t\t: %s\n"
- "f00f_bug\t: %s\n"
- "coma_bug\t: %s\n"
- "fpu\t\t: %s\n"
- "fpu_exception\t: %s\n"
- "cpuid level\t: %d\n"
- "wp\t\t: %s\n"
- "flags\t\t:",
- c->fdiv_bug ? "yes" : "no",
- c->hlt_works_ok ? "no" : "yes",
- c->f00f_bug ? "yes" : "no",
- c->coma_bug ? "yes" : "no",
- c->hard_math ? "yes" : "no",
- fpu_exception ? "yes" : "no",
- c->cpuid_level,
- c->wp_works_ok ? "yes" : "no");
-
- for ( i = 0 ; i < 32*NCAPINTS ; i++ )
- if ( test_bit(i, &c->x86_capability) &&
- x86_cap_flags[i] != NULL )
- p += sprintf(p, " %s", x86_cap_flags[i]);
-
- p += sprintf(p, "\nbogomips\t: %lu.%02lu\n\n",
- c->loops_per_jiffy/(500000/HZ),
- (c->loops_per_jiffy/(5000/HZ)) % 100);
- }


- return p - buffer;

+static void *c_start(struct seq_file *m, loff_t *pos)
+{

+ return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+}


+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;

+ return c_start(m, pos);
+}


+static void c_stop(struct seq_file *m, void *v)
+{
X }

+struct seq_operations cpuinfo_op = {
+ start: c_start,
+ next: c_next,
+ stop: c_stop,
+ show: show_cpuinfo,
+};

X
X unsigned long cpu_initialized __initdata = 0;
X
@@ -2834,6 +2873,53 @@
X stts();
X }
X
+/*
+ * Early probe support logic for ppro memory erratum #50
+ *
+ * This is called before we do cpu ident work
+ */
+
+int __init ppro_with_ram_bug(void)
+{
+ char vendor_id[16];
+ int ident;
+
+ /* Must have CPUID */
+ if(!have_cpuid_p())
+ return 0;
+ if(cpuid_eax(0)<1)
+ return 0;
+
+ /* Must be Intel */
+ cpuid(0, &ident,
+ (int *)&vendor_id[0],
+ (int *)&vendor_id[8],
+ (int *)&vendor_id[4]);
+
+ if(memcmp(vendor_id, "IntelInside", 12))
+ return 0;
+
+ ident = cpuid_eax(1);
+
+ /* Model 6 */
+
+ if(((ident>>8)&15)!=6)
+ return 0;
+
+ /* Pentium Pro */
+
+ if(((ident>>4)&15)!=1)
+ return 0;
+
+ if((ident&15) < 8)
+ {
+ printk(KERN_INFO "Pentium Pro with Errata#50 detected. Taking evasive action.\n");
+ return 1;
+ }
+ printk(KERN_INFO "Your Pentium Pro seems ok.\n");


+ return 0;
+}
+

X /*
X * Local Variables:
X * mode:c
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c
--- v2.4.14/linux/arch/i386/kernel/smpboot.c Tue Oct 9 17:06:51 2001
+++ linux/arch/i386/kernel/smpboot.c Wed Nov 21 10:35:48 2001
@@ -800,10 +800,10 @@
X panic("No idle process for CPU %d", cpu);
X
X idle->processor = cpu;
+ idle->cpus_runnable = 1 << cpu; /* we schedule the first task manually */
X
X map_cpu_to_boot_apicid(cpu, apicid);
X

- idle->has_cpu = 1; /* we schedule the first task manually */

X idle->thread.eip = (unsigned long) start_secondary;
X
X del_from_runqueue(idle);
diff -u --recursive --new-file v2.4.14/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- v2.4.14/linux/arch/i386/kernel/time.c Sun Sep 23 11:40:55 2001
+++ linux/arch/i386/kernel/time.c Sun Nov 11 10:20:21 2001
@@ -519,6 +519,7 @@
X unsigned int year, mon, day, hour, min, sec;
X int i;
X
+ spin_lock(&rtc_lock);
X /* The Linux interpretation of the CMOS clock register contents:
X * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
X * RTC registers show the second which has precisely just started.
@@ -548,6 +549,7 @@
X BCD_TO_BIN(mon);
X BCD_TO_BIN(year);
X }
+ spin_unlock(&rtc_lock);
X if ((year += 1900) < 1970)
X year += 100;
X return mktime(year, mon, day, hour, min, sec);
diff -u --recursive --new-file v2.4.14/linux/arch/i386/lib/usercopy.c linux/arch/i386/lib/usercopy.c
--- v2.4.14/linux/arch/i386/lib/usercopy.c Sun Sep 23 11:40:55 2001
+++ linux/arch/i386/lib/usercopy.c Fri Nov 9 13:58:02 2001
@@ -165,6 +165,8 @@
X unsigned long res, tmp;
X
X __asm__ __volatile__(
+ " testl %0, %0\n"
+ " jz 3f\n"
X " andl %0,%%ecx\n"
X "0: repne; scasb\n"
X " setne %%al\n"
@@ -173,6 +175,8 @@
X "1:\n"
X ".section .fixup,\"ax\"\n"
X "2: xorl %%eax,%%eax\n"
+ " jmp 1b\n"
+ "3: movb $1,%%al\n"
X " jmp 1b\n"
X ".previous\n"
X ".section __ex_table,\"a\"\n"
diff -u --recursive --new-file v2.4.14/linux/arch/i386/math-emu/fpu_proto.h linux/arch/i386/math-emu/fpu_proto.h
--- v2.4.14/linux/arch/i386/math-emu/fpu_proto.h Tue Dec 9 17:57:09 1997
+++ linux/arch/i386/math-emu/fpu_proto.h Mon Nov 12 09:59:43 2001
@@ -53,7 +53,7 @@
X extern void fst_i_(void);
X extern void fstp_i(void);
X /* fpu_entry.c */
-extern void math_emulate(long arg);
+asmlinkage extern void math_emulate(long arg);
X extern void math_abort(struct info *info, unsigned int signal);
X /* fpu_etc.c */
X extern void FPU_etc(void);
diff -u --recursive --new-file v2.4.14/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.4.14/linux/arch/i386/mm/init.c Sun Sep 23 11:40:55 2001
+++ linux/arch/i386/mm/init.c Sun Nov 11 10:09:32 2001
@@ -439,13 +439,24 @@


X return 0;
X }
X

+static inline int page_kills_ppro(unsigned long pagenr)
+{
+ if(pagenr >= 0x70000 && pagenr <= 0x7003F)
+ return 1;


+ return 0;
+}
+

X void __init mem_init(void)
X {
+ extern int ppro_with_ram_bug(void);
X int codesize, reservedpages, datasize, initsize;
X int tmp;
+ int bad_ppro;
X
X if (!mem_map)
X BUG();
+
+ bad_ppro = ppro_with_ram_bug();
X
X #ifdef CONFIG_HIGHMEM
X highmem_start_page = mem_map + highstart_pfn;
@@ -473,6 +484,11 @@
X struct page *page = mem_map + tmp;
X
X if (!page_is_ram(tmp)) {
+ SetPageReserved(page);
+ continue;
+ }
+ if (bad_ppro && page_kills_ppro(tmp))
+ {
X SetPageReserved(page);
X continue;
X }
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/Makefile linux/arch/ia64/Makefile
--- v2.4.14/linux/arch/ia64/Makefile Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/Makefile Fri Nov 9 14:26:17 2001
@@ -17,13 +17,15 @@
X AFLAGS_KERNEL := -mconstant-gp
X EXTRA =
X
-CFLAGS := $(CFLAGS) -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f10-f15,f32-f127 -falign-functions=32
+CFLAGS := $(CFLAGS) -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f10-f15,f32-f127 \
+ -falign-functions=32
+# -ffunction-sections
X CFLAGS_KERNEL := -mconstant-gp
X
X GCC_VERSION=$(shell $(CROSS_COMPILE)$(HOSTCC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.')
X
X ifneq ($(GCC_VERSION),2)
- CFLAGS += -frename-registers
+ CFLAGS += -frename-registers --param max-inline-insns=400
X endif
X
X ifeq ($(CONFIG_ITANIUM_BSTEP_SPECIFIC),y)
@@ -32,7 +34,7 @@
X
X ifdef CONFIG_IA64_GENERIC
X CORE_FILES := arch/$(ARCH)/hp/hp.a \
- arch/$(ARCH)/sn/sn.a \
+ arch/$(ARCH)/sn/sn.o \
X arch/$(ARCH)/dig/dig.a \
X arch/$(ARCH)/sn/io/sgiio.o \
X $(CORE_FILES)
@@ -52,15 +54,14 @@
X $(CORE_FILES)
X endif
X
-ifdef CONFIG_IA64_SGI_SN1
+ifdef CONFIG_IA64_SGI_SN
X CFLAGS += -DBRINGUP
- SUBDIRS := arch/$(ARCH)/sn/sn1 \
- arch/$(ARCH)/sn \
+ SUBDIRS := arch/$(ARCH)/sn/kernel \
X arch/$(ARCH)/sn/io \
X arch/$(ARCH)/sn/fprom \
X $(SUBDIRS)
- CORE_FILES := arch/$(ARCH)/sn/sn.a \
- arch/$(ARCH)/sn/io/sgiio.o\
+ CORE_FILES := arch/$(ARCH)/sn/kernel/sn.o \
+ arch/$(ARCH)/sn/io/sgiio.o \
X $(CORE_FILES)
X endif
X

@@ -105,7 +106,7 @@
X

X compressed: vmlinux
X $(OBJCOPY) --strip-all vmlinux vmlinux-tmp
- gzip -9 vmlinux-tmp
+ gzip vmlinux-tmp
X mv vmlinux-tmp.gz vmlinux.gz
X
X rawboot:
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/config.in linux/arch/ia64/config.in
--- v2.4.14/linux/arch/ia64/config.in Tue Oct 23 22:48:49 2001
+++ linux/arch/ia64/config.in Fri Nov 9 14:26:17 2001
@@ -28,6 +28,7 @@
X
X if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
X define_bool CONFIG_ACPI y
+ define_bool CONFIG_ACPI_EFI y
X define_bool CONFIG_ACPI_INTERPRETER y
X define_bool CONFIG_ACPI_KERNEL_CONFIG y
X fi
@@ -40,7 +41,8 @@
X "generic CONFIG_IA64_GENERIC \
X DIG-compliant CONFIG_IA64_DIG \
X HP-simulator CONFIG_IA64_HP_SIM \
- SGI-SN1 CONFIG_IA64_SGI_SN1" generic
+ SGI-SN1 CONFIG_IA64_SGI_SN1 \
+ SGI-SN2 CONFIG_IA64_SGI_SN2" generic
X
X choice 'Kernel page size' \
X "4KB CONFIG_IA64_PAGE_SIZE_4KB \
@@ -51,25 +53,6 @@
X if [ "$CONFIG_ITANIUM" = "y" ]; then
X define_bool CONFIG_IA64_BRL_EMU y
X bool ' Enable Itanium B-step specific code' CONFIG_ITANIUM_BSTEP_SPECIFIC
- if [ "$CONFIG_ITANIUM_BSTEP_SPECIFIC" = "y" ]; then
- bool ' Enable Itanium B0-step specific code' CONFIG_ITANIUM_B0_SPECIFIC
- fi
- if [ "$CONFIG_ITANIUM_BSTEP_SPECIFIC" = "y" ]; then
- bool ' Enable Itanium B1-step specific code' CONFIG_ITANIUM_B1_SPECIFIC
- fi
- if [ "$CONFIG_ITANIUM_BSTEP_SPECIFIC" = "y" ]; then
- bool ' Enable Itanium B2-step specific code' CONFIG_ITANIUM_B2_SPECIFIC
- fi
- bool ' Enable Itanium C-step specific code' CONFIG_ITANIUM_CSTEP_SPECIFIC
- if [ "$CONFIG_ITANIUM_CSTEP_SPECIFIC" = "y" ]; then
- bool ' Enable Itanium C0-step specific code' CONFIG_ITANIUM_C0_SPECIFIC
- fi
- if [ "$CONFIG_ITANIUM_B0_SPECIFIC" = "y" \
- -o "$CONFIG_ITANIUM_B1_SPECIFIC" = "y" -o "$CONFIG_ITANIUM_B2_SPECIFIC" = "y" ]; then
- define_bool CONFIG_ITANIUM_PTCG n
- else
- define_bool CONFIG_ITANIUM_PTCG y
- fi
X if [ "$CONFIG_IA64_SGI_SN1" = "y" ]; then
X define_int CONFIG_IA64_L1_CACHE_SHIFT 7 # align cache-sensitive data to 128 bytes
X else
@@ -78,7 +61,6 @@
X fi
X
X if [ "$CONFIG_MCKINLEY" = "y" ]; then
- define_bool CONFIG_ITANIUM_PTCG y
X define_int CONFIG_IA64_L1_CACHE_SHIFT 7
X bool ' Enable McKinley A-step specific code' CONFIG_MCKINLEY_ASTEP_SPECIFIC
X if [ "$CONFIG_MCKINLEY_ASTEP_SPECIFIC" = "y" ]; then
@@ -87,28 +69,32 @@
X fi
X
X if [ "$CONFIG_IA64_DIG" = "y" ]; then
- bool ' Force interrupt redirection' CONFIG_IA64_HAVE_IRQREDIR
X bool ' Enable IA-64 Machine Check Abort' CONFIG_IA64_MCA
X define_bool CONFIG_PM y
X fi
X
-if [ "$CONFIG_IA64_SGI_SN1" = "y" ]; then
- bool ' Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN1_SIM
- define_bool CONFIG_DEVFS_DEBUG y
+if [ "$CONFIG_IA64_SGI_SN1" = "y" ] || [ "$CONFIG_IA64_SGI_SN2" = "y" ]; then
+ define_bool CONFIG_IA64_SGI_SN y
+ bool ' Enable extra debugging code' CONFIG_IA64_SGI_SN_DEBUG n
+ bool ' Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN_SIM
+ bool ' Enable autotest (llsc). Option to run cache test instead of booting' \
+ CONFIG_IA64_SGI_AUTOTEST n
X define_bool CONFIG_DEVFS_FS y
- define_bool CONFIG_IA64_BRL_EMU y
+ if [ "$CONFIG_DEVFS_FS" = "y" ]; then
+ bool ' Enable DEVFS Debug Code' CONFIG_DEVFS_DEBUG n
+ fi
+ bool ' Enable protocol mode for the L1 console' CONFIG_SERIAL_SGI_L1_PROTOCOL y
+ define_bool CONFIG_DISCONTIGMEM y
X define_bool CONFIG_IA64_MCA y
- define_bool CONFIG_ITANIUM y
- define_bool CONFIG_SGI_IOC3_ETH y
+ define_bool CONFIG_NUMA y
X define_bool CONFIG_PERCPU_IRQ y
- define_int CONFIG_CACHE_LINE_SHIFT 7
- bool ' Enable DISCONTIGMEM support' CONFIG_DISCONTIGMEM
- bool ' Enable NUMA support' CONFIG_NUMA
+ tristate ' PCIBA support' CONFIG_PCIBA
X fi
X
X define_bool CONFIG_KCORE_ELF y # On IA-64, we always want an ELF /proc/kcore.
X
X bool 'SMP support' CONFIG_SMP
+tristate 'Support running of Linux/x86 binaries' CONFIG_IA32_SUPPORT
X bool 'Performance monitor support' CONFIG_PERFMON
X tristate '/proc/pal support' CONFIG_IA64_PALINFO
X tristate '/proc/efi/vars support' CONFIG_EFI_VARS
@@ -270,19 +256,23 @@
X mainmenu_option next_comment
X comment 'Kernel hacking'
X
-#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC


-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then

- tristate 'Kernel support for IA-32 emulation' CONFIG_IA32_SUPPORT


- tristate 'Kernel FP software completion' CONFIG_MATHEMU

-else
- define_bool CONFIG_MATHEMU y
+choice 'Physical memory granularity' \
+ "16MB CONFIG_IA64_GRANULE_16MB \
+ 64MB CONFIG_IA64_GRANULE_64MB" 64MB


+
+bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
+if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then

+ bool ' Print possible IA64 hazards to console' CONFIG_IA64_PRINT_HAZARDS
+ bool ' Disable VHPT' CONFIG_DISABLE_VHPT


+ bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ
+

+# early printk is currently broken for SMP: the secondary processors get stuck...
+# bool ' Early printk support (requires VGA!)' CONFIG_IA64_EARLY_PRINTK
+


+ bool ' Debug memory allocations' CONFIG_DEBUG_SLAB

+ bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK

+ bool ' Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG
+ bool ' Turn on irq debug checks (slow!)' CONFIG_IA64_DEBUG_IRQ


X fi
-
-bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ

-bool 'Early printk support (requires VGA!)' CONFIG_IA64_EARLY_PRINTK
-bool 'Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG
-bool 'Turn on irq debug checks (slow!)' CONFIG_IA64_DEBUG_IRQ
-bool 'Print possible IA64 hazards to console' CONFIG_IA64_PRINT_HAZARDS
-bool 'Disable VHPT' CONFIG_DISABLE_VHPT
X
X endmenu
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/defconfig linux/arch/ia64/defconfig
--- v2.4.14/linux/arch/ia64/defconfig Thu Jun 22 07:09:44 2000
+++ linux/arch/ia64/defconfig Fri Nov 9 14:26:17 2001
@@ -3,47 +3,125 @@
X #
X
X #
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+# CONFIG_KMOD is not set
+
+#
X # General setup
X #
X CONFIG_IA64=y
X # CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
X # CONFIG_SBUS is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_ACPI=y
+CONFIG_ACPI_EFI=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_KERNEL_CONFIG=y
+CONFIG_ITANIUM=y
+# CONFIG_MCKINLEY is not set
X # CONFIG_IA64_GENERIC is not set
-CONFIG_IA64_HP_SIM=y
-# CONFIG_IA64_SGI_SN1_SIM is not set
-# CONFIG_IA64_DIG is not set
+CONFIG_IA64_DIG=y
+# CONFIG_IA64_HP_SIM is not set
+# CONFIG_IA64_SGI_SN1 is not set
+# CONFIG_IA64_SGI_SN2 is not set
X # CONFIG_IA64_PAGE_SIZE_4KB is not set
X # CONFIG_IA64_PAGE_SIZE_8KB is not set
X CONFIG_IA64_PAGE_SIZE_16KB=y
X # CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_IA64_BRL_EMU=y
+# CONFIG_ITANIUM_BSTEP_SPECIFIC is not set
+CONFIG_IA64_L1_CACHE_SHIFT=6
+CONFIG_IA64_MCA=y
+CONFIG_PM=y
X CONFIG_KCORE_ELF=y
-# CONFIG_SMP is not set
-# CONFIG_PERFMON is not set
-# CONFIG_NET is not set
-# CONFIG_SYSVIPC is not set
+CONFIG_SMP=y
+CONFIG_IA32_SUPPORT=y
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+CONFIG_EFI_VARS=y
+CONFIG_NET=y
+CONFIG_SYSVIPC=y


X # CONFIG_BSD_PROCESS_ACCT is not set

-# CONFIG_SYSCTL is not set
-# CONFIG_BINFMT_ELF is not set
+CONFIG_SYSCTL=y
+CONFIG_BINFMT_ELF=y
X # CONFIG_BINFMT_MISC is not set
+# CONFIG_ACPI_DEBUG is not set
+# CONFIG_ACPI_BUSMGR is not set
+# CONFIG_ACPI_SYS is not set
+# CONFIG_ACPI_CPU is not set
+# CONFIG_ACPI_BUTTON is not set
+# CONFIG_ACPI_AC is not set
+# CONFIG_ACPI_EC is not set
+# CONFIG_ACPI_CMBATT is not set
+# CONFIG_ACPI_THERMAL is not set
X CONFIG_PCI=y
X CONFIG_PCI_NAMES=y
X # CONFIG_HOTPLUG is not set
X # CONFIG_PCMCIA is not set
X
X #
-# Code maturity level options
+# Parallel port support
X #
-CONFIG_EXPERIMENTAL=y
+# CONFIG_PARPORT is not set
X
X #
-# Loadable module support
+# Networking options
X #
-# CONFIG_MODULES is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER is not set
+CONFIG_FILTER=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+
+#
+#
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
X
X #
-# Parallel port support
+# QoS and/or fair queueing
X #
-# CONFIG_PARPORT is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
X
X #
X # Plug and Play configuration
@@ -58,14 +136,12 @@
X # CONFIG_BLK_DEV_XD is not set
X # CONFIG_PARIDE is not set
X # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
X # CONFIG_BLK_DEV_DAC960 is not set
-
-#
-# Additional Block Devices
-#
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
X # CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
X
X #
X # I2O device support
@@ -73,10 +149,23 @@
X # CONFIG_I2O is not set
X # CONFIG_I2O_PCI is not set
X # CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
X # CONFIG_I2O_SCSI is not set
X # CONFIG_I2O_PROC is not set
X
X #
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set


+# CONFIG_MD_MULTIPATH is not set

+# CONFIG_BLK_DEV_LVM is not set
+
+#
X # ATA/IDE/MFM/RLL support
X #
X CONFIG_IDE=y
@@ -92,12 +181,21 @@
X # CONFIG_BLK_DEV_HD_IDE is not set
X # CONFIG_BLK_DEV_HD is not set
X CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
X # CONFIG_BLK_DEV_IDECS is not set
X CONFIG_BLK_DEV_IDECD=y
X # CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=y
X
X #
X # IDE chipset support/bugfixes
@@ -109,45 +207,208 @@
X CONFIG_BLK_DEV_IDEPCI=y
X CONFIG_IDEPCI_SHARE_IRQ=y


X CONFIG_BLK_DEV_IDEDMA_PCI=y
+CONFIG_BLK_DEV_ADMA=y
X # CONFIG_BLK_DEV_OFFBOARD is not set

-CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_PCI_AUTO is not set
X CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
X # CONFIG_IDEDMA_PCI_WIP is not set
X # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-# CONFIG_AEC6210_TUNING is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
X # CONFIG_BLK_DEV_ALI15X3 is not set


X # CONFIG_WDC_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD7409 is not set
-# CONFIG_AMD7409_OVERRIDE is not set
+# CONFIG_BLK_DEV_AMD74XX is not set

+# CONFIG_AMD74XX_OVERRIDE is not set
X # CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_CMD64X_RAID is not set
X # CONFIG_BLK_DEV_CY82C693 is not set
X # CONFIG_BLK_DEV_CS5530 is not set
X # CONFIG_BLK_DEV_HPT34X is not set
X # CONFIG_HPT34X_AUTODMA is not set
X # CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_HPT366_FIP is not set
-# CONFIG_HPT366_MODE3 is not set
X CONFIG_BLK_DEV_PIIX=y
-CONFIG_PIIX_TUNING=y
+# CONFIG_PIIX_TUNING is not set
X # CONFIG_BLK_DEV_NS87415 is not set
X # CONFIG_BLK_DEV_OPTI621 is not set
X # CONFIG_BLK_DEV_PDC202XX is not set
X # CONFIG_PDC202XX_BURST is not set
-# CONFIG_PDC202XX_MASTER is not set


+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_SVWKS is not set
X # CONFIG_BLK_DEV_SIS5513 is not set

+# CONFIG_BLK_DEV_SLC90E66 is not set
X # CONFIG_BLK_DEV_TRM290 is not set
X # CONFIG_BLK_DEV_VIA82CXXX is not set
X # CONFIG_IDE_CHIPSETS is not set
-CONFIG_IDEDMA_AUTO=y
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_DMA_NONPCI is not set


X CONFIG_BLK_DEV_IDE_MODES=y
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set

+# CONFIG_BLK_DEV_ATARAID_HPT is not set
X
X #
X # SCSI support
X #
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
+# CONFIG_CHR_DEV_ST is not set


+# CONFIG_CHR_DEV_OSST is not set

+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_DEBUG_QUEUES=y
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set


+# CONFIG_SCSI_DPT_I2O is not set

+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_DMA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_NCR53C8XX is not set
+# CONFIG_SCSI_SYM53C8XX is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+CONFIG_SCSI_QLOGIC_1280=y
+# CONFIG_SCSI_QLOGIC_QLA2100 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y


+# CONFIG_SUNLANCE is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNGEM is not set

+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set


+# CONFIG_HP100 is not set

+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_TULIP is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+CONFIG_EEPRO100=y
+# CONFIG_LNE390 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set


+# CONFIG_MYRI_SBUS is not set

+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set


+# CONFIG_PLIP is not set

+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
X
X #
X # Amateur Radio support
@@ -165,13 +426,28 @@
X # CONFIG_CD_NO_IDESCSI is not set
X
X #
+# Input core support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_KEYBDEV=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768


+# CONFIG_INPUT_JOYDEV is not set

+CONFIG_INPUT_EVDEV=y
+
+#
X # Character devices
X #
-# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_ACPI is not set
X # CONFIG_SERIAL_EXTENDED is not set
X # CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
X
X #
X # I2C support
@@ -182,26 +458,55 @@
X # Mice
X #
X # CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#


+# CONFIG_INPUT_GAMEPORT is not set

+# CONFIG_INPUT_NS558 is not set
+# CONFIG_INPUT_LIGHTNING is not set
+# CONFIG_INPUT_PCIGAME is not set
+# CONFIG_INPUT_CS461X is not set
+# CONFIG_INPUT_EMU10K1 is not set
+CONFIG_INPUT_SERIO=y
+CONFIG_INPUT_SERPORT=y
X
X #


X # Joysticks
X #
-# CONFIG_JOYSTICK is not set

+# CONFIG_INPUT_ANALOG is not set
+# CONFIG_INPUT_A3D is not set
+# CONFIG_INPUT_ADI is not set
+# CONFIG_INPUT_COBRA is not set
+# CONFIG_INPUT_GF2K is not set
+# CONFIG_INPUT_GRIP is not set
+# CONFIG_INPUT_INTERACT is not set
+# CONFIG_INPUT_TMDC is not set
+# CONFIG_INPUT_SIDEWINDER is not set
+# CONFIG_INPUT_IFORCE_USB is not set
+# CONFIG_INPUT_IFORCE_232 is not set
+# CONFIG_INPUT_WARRIOR is not set
+# CONFIG_INPUT_MAGELLAN is not set
+# CONFIG_INPUT_SPACEORB is not set
+# CONFIG_INPUT_SPACEBALL is not set
+# CONFIG_INPUT_STINGER is not set
+# CONFIG_INPUT_DB9 is not set
+# CONFIG_INPUT_GAMECON is not set


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

echo 'End of part 024'
echo 'File patch-2.4.15 is continued in part 025'
echo "025" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:52 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part016

#!/bin/sh -x
# this is part 016 of a 115 - part archive


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

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

X CONFIG_HISAX_EURO
@@ -16324,9 +18893,9 @@
X telephone service company provides.
X
X The call control protocol E-DSS1 is used in most European countries.
- If unsure, say yes.
+ If unsure, say Y.
X
-Support for german charge info
+Support for German chargeinfo
X CONFIG_DE_AOC
X If you want that the HiSax hardware driver sends messages to the
X upper level of the isdn code on each AOCD (Advice Of Charge, During
@@ -16361,230 +18930,265 @@
X
X HiSax Support for US NI1
X CONFIG_HISAX_NI1
- Enable this if you like to use ISDN in US on a NI1 basic rate interface.
+ Enable this if you like to use ISDN in US on a NI1 basic rate
+ interface.
X
X Teles 16.0/8.0
X CONFIG_HISAX_16_0
X This enables HiSax support for the Teles ISDN-cards S0-16.0, S0-8
- and many compatibles.
+ and many compatibles.
X
- See Documentation/isdn/README.HiSax on how to configure it using the
- different cards, a different D-channel protocol, or non-standard
- IRQ/port/shmem settings.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using the different cards, a different D-channel protocol, or
+ non-standard IRQ/port/shmem settings.
X
X Teles 16.3 or PNP or PCMCIA
X CONFIG_HISAX_16_3
X This enables HiSax support for the Teles ISDN-cards S0-16.3 the
X Teles/Creatix PnP and the Teles PCMCIA.
-
- See Documentation/isdn/README.HiSax on how to configure it using the
- different cards, a different D-channel protocol, or non-standard
- IRQ/port settings.
+
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using the different cards, a different D-channel protocol, or
+ non-standard IRQ/port settings.
X
X Teles PCI
X CONFIG_HISAX_TELESPCI
X This enables HiSax support for the Teles PCI.
- See Documentation/isdn/README.HiSax on how to configure it.
-
+ See <file:Documentation/isdn/README.HiSax> on how to configure it.
+
X Teles S0Box
X CONFIG_HISAX_S0BOX
X This enables HiSax support for the Teles/Creatix parallel port
- S0BOX. See Documentation/isdn/README.HiSax on how to configure it.
+ S0BOX. See <file:Documentation/isdn/README.HiSax> on how to
+ configure it.
X
X AVM A1 (Fritz)
X CONFIG_HISAX_AVM_A1
X This enables HiSax support for the AVM A1 (aka "Fritz").
-
- See Documentation/isdn/README.HiSax on how to configure it using the
- different cards, a different D-channel protocol, or non-standard
- IRQ/port settings.
X
-AVM PnP/PCI (Fritz!PNP/PCI)
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using the different cards, a different D-channel protocol, or
+ non-standard IRQ/port settings.
+
+AVM PnP/PCI (Fritz!PnP/PCI)
X CONFIG_HISAX_FRITZPCI
X This enables HiSax support for the AVM "Fritz!PnP" and "Fritz!PCI".
- See Documentation/isdn/README.HiSax on how to configure it.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it.
X
X AVM A1 PCMCIA (Fritz)
X CONFIG_HISAX_AVM_A1_PCMCIA
X This enables HiSax support for the AVM A1 "Fritz!PCMCIA").
- See Documentation/isdn/README.HiSax on how to configure it.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it.
X
X Elsa cards
X CONFIG_HISAX_ELSA
X This enables HiSax support for the Elsa Mircolink ISA cards, for the
X Elsa Quickstep series cards and Elsa PCMCIA.
X
- See Documentation/isdn/README.HiSax on how to configure it using the
- different cards, a different D-channel protocol, or non-standard
- IRQ/port settings.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using the different cards, a different D-channel protocol, or
+ non-standard IRQ/port settings.
X
X ITK ix1-micro Revision 2
X CONFIG_HISAX_IX1MICROR2
X This enables HiSax support for the ITK ix1-micro Revision 2 card.
X
- See Documentation/isdn/README.HiSax on how to configure it using the
- different cards, a different D-channel protocol, or non-standard
- IRQ/port settings.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using the different cards, a different D-channel protocol, or
+ non-standard IRQ/port settings.
X
X Eicon.Diehl Diva cards
X CONFIG_HISAX_DIEHLDIVA
X This enables HiSax support for the Eicon.Diehl Diva none PRO
X versions passive ISDN cards.
X
- See Documentation/isdn/README.HiSax on how to configure it using the
- different cards, a different D-channel protocol, or non-standard
- IRQ/port settings.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using the different cards, a different D-channel protocol, or
+ non-standard IRQ/port settings.
X
X ASUSCOM ISA cards
X CONFIG_HISAX_ASUSCOM
X This enables HiSax support for the AsusCom and their OEM versions
X passive ISDN ISA cards.
X
- See Documentation/isdn/README.HiSax on how to configure it using the
- different cards, a different D-channel protocol, or non-standard
- IRQ/port settings.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using the different cards, a different D-channel protocol, or
+ non-standard IRQ/port settings.
X
X TELEINT cards
X CONFIG_HISAX_TELEINT
X This enables HiSax support for the TELEINT SA1 semiactiv ISDN card.
X
- See Documentation/isdn/README.HiSax on how to configure it using the
- different cards, a different D-channel protocol, or non-standard
- IRQ/port settings.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using the different cards, a different D-channel protocol, or
+ non-standard IRQ/port settings.
X
X HFC-S based cards
X CONFIG_HISAX_HFCS
X This enables HiSax support for the HFC-S 2BDS0 based cards, like
X teles 16.3c.
-
- See Documentation/isdn/README.HiSax on how to configure it using the
- different cards, a different D-channel protocol, or non-standard
- IRQ/port settings.
+
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using the different cards, a different D-channel protocol, or
+ non-standard IRQ/port settings.
X
X Sedlbauer cards
X CONFIG_HISAX_SEDLBAUER
X This enables HiSax support for the Sedlbauer passive ISDN cards.
X
- See Documentation/isdn/README.HiSax on how to configure it using the
- different cards, a different D-channel protocol, or non-standard
- IRQ/port settings.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using the different cards, a different D-channel protocol, or
+ non-standard IRQ/port settings.
X
X USR Sportster internal TA
X CONFIG_HISAX_SPORTSTER
X This enables HiSax support for the USR Sportster internal TA card.
X
- See Documentation/isdn/README.HiSax on how to configure it using a
- different D-channel protocol, or non-standard IRQ/port settings.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using a different D-channel protocol, or non-standard IRQ/port
+ settings.
X
X MIC card
X CONFIG_HISAX_MIC
- This enables HiSax support for the ITH MIC card.
+ This enables HiSax support for the ITH MIC card.
X
- See Documentation/isdn/README.HiSax on how to configure it using a
- different D-channel protocol, or non-standard IRQ/port settings.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using a different D-channel protocol, or non-standard IRQ/port
+ settings.
X
X NETjet card
X CONFIG_HISAX_NETJET
X This enables HiSax support for the NetJet from Traverse
X Technologies.
X
- See Documentation/isdn/README.HiSax on how to configure it using a
- different D-channel protocol, or non-standard IRQ/port settings.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using a different D-channel protocol, or non-standard IRQ/port
+ settings.
X
X NETspider U card
X CONFIG_HISAX_NETJET_U
- This enables HiSax support for the Netspider U interface ISDN card from
- Traverse Technologies.
- See Documentation/isdn/README.HiSax on how to configure it using a
- different D-channel protocol, or non-standard IRQ/port settings.
+ This enables HiSax support for the Netspider U interface ISDN card
+ from Traverse Technologies.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using a different D-channel protocol, or non-standard IRQ/port
+ settings.
X
X Niccy PnP/PCI card
X CONFIG_HISAX_NICCY
- This enables HiSax support for the Dr. Neuhaus Niccy PnP or PCI.
+ This enables HiSax support for the Dr. Neuhaus Niccy PnP or PCI.
X
- See Documentation/isdn/README.HiSax on how to configure it using a
- different D-channel protocol, or non-standard IRQ/port settings.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using a different D-channel protocol, or non-standard IRQ/port
+ settings.
X
X Siemens I-Surf card
X CONFIG_HISAX_ISURF
X This enables HiSax support for the Siemens I-Talk/I-Surf card with
X ISAR chip.
- See Documentation/isdn/README.HiSax on how to configure it using a
- different D-channel protocol, or non-standard IRQ/port settings.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using a different D-channel protocol, or non-standard IRQ/port
+ settings.
X
X HST Saphir card
X CONFIG_HISAX_HSTSAPHIR
X This enables HiSax support for the HST Saphir card.
-
- See Documentation/isdn/README.HiSax on how to configure it using a
- different D-channel protocol, or non-standard IRQ/port settings.
+
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using a different D-channel protocol, or non-standard IRQ/port
+ settings.
X
X Telekom A4T card
X CONFIG_HISAX_BKM_A4T
X This enables HiSax support for the Telekom A4T card.
-
- See Documentation/isdn/README.HiSax on how to configure it using a
- different D-channel protocol, or non-standard IRQ/port settings.
+
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using a different D-channel protocol, or non-standard IRQ/port
+ settings.
X
X Scitel Quadro card
X CONFIG_HISAX_SCT_QUADRO
X This enables HiSax support for the Scitel Quadro card.
-
- See Documentation/isdn/README.HiSax on how to configure it using a
- different D-channel protocol, or non-standard IRQ/port settings.
+
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using a different D-channel protocol, or non-standard IRQ/port
+ settings.
X
X Gazel cards
X CONFIG_HISAX_GAZEL
X This enables HiSax support for the Gazel cards.
X
- See Documentation/isdn/README.HiSax on how to configure it using a
- different D-channel protocol, or non-standard IRQ/port settings.
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using a different D-channel protocol, or non-standard IRQ/port
+ settings.
X
X HFC PCI-Bus cards
X CONFIG_HISAX_HFC_PCI
X This enables HiSax support for the HFC-S PCI 2BDS0 based cards.
-
- For more informations see under Documentation/isdn/README.hfc-pci.
+
+ For more informations see under
+ <file:Documentation/isdn/README.hfc-pci>.
X
X Winbond W6692 based cards
X CONFIG_HISAX_W6692
X This enables HiSax support for Winbond W6692 based PCI ISDN cards.
-
- See Documentation/isdn/README.HiSax on how to configure it using a
- different D-channel protocol, or non-standard IRQ/port settings.
X
-HFC-S+, HFC-SP, HFC-PCMCIA cards (EXPERIMENTAL)
+ See <file:Documentation/isdn/README.HiSax> on how to configure it
+ using a different D-channel protocol, or non-standard IRQ/port
+ settings.
+
+HFC-S+, HFC-SP, HFC-PCMCIA cards
X CONFIG_HISAX_HFC_SX
X This enables HiSax support for the HFC-S+, HFC-SP and HFC-PCMCIA
X cards. This code is not finished yet.
X
-Am7930 (EXPERIMENTAL)
+Am7930
X CONFIG_HISAX_AMD7930
X This enables HiSax support for the AMD7930 chips on some SPARCs.
X This code is not finished yet.
X
+HiSax debugging
+CONFIG_HISAX_DEBUG
+ This enables debugging code in the new-style HiSax drivers, i.e.
+ the ST5481 USB driver currently.
+ If in doubt, say yes.
+
+ELSA PCMCIA MicroLink cards
+CONFIG_HISAX_ELSA_CS
+ This enables the PCMCIA client driver for the Elsa PCMCIA MicroLink
+ card.
+
+Sedlbauer PCMCIA cards
+CONFIG_HISAX_SEDLBAUER_CS
+ This enables the PCMCIA client driver for the Sedlbauer Speed Star
+ and Speed Star II cards.
+
+ST5481 USB ISDN adapter
+CONFIG_HISAX_ST5481
+ This enables the driver for ST5481 based USB ISDN adapters,
+ e.g. the BeWan Gazel 128 USB
+
X PCBIT-D support
X CONFIG_ISDN_DRV_PCBIT
- This enables support for the PCBIT ISDN-card. This card is
- manufactured in Portugal by Octal. For running this card, additional
- firmware is necessary, which has to be downloaded into the card
- using a utility which is distributed separately. See
- Documentation/isdn/README and Documentation/isdn/README.pcbit for
- more information.
+ This enables support for the PCBIT ISDN-card. This card is
+ manufactured in Portugal by Octal. For running this card,
+ additional firmware is necessary, which has to be downloaded into
+ the card using a utility which is distributed separately. See
+ <file:Documentation/isdn/README> and
+ <file:Documentation/isdn/README.pcbit> for more information.
X

X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called pcbit.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called pcbit.o.
X
-Spellcaster support (EXPERIMENTAL)
+Spellcaster support
X CONFIG_ISDN_DRV_SC
- This enables support for the Spellcaster BRI ISDN boards. This
+ This enables support for the Spellcaster BRI ISDN boards. This
X driver currently builds only in a modularized version ( = code which
X can be inserted in and removed from the running kernel whenever you
- want, details in Documentation/modules.txt); the module will be
- called sc.o. See Documentation/isdn/README.sc and
- http://www.spellcast.com for more information.
+ want, details in <file:Documentation/modules.txt>); the module will
+ be called sc.o. See <file:Documentation/isdn/README.sc> and
+ <http://www.spellcast.com> for more information.
X
X Eicon active card support
X CONFIG_ISDN_DRV_EICON
@@ -16592,23 +19196,29 @@
X this card, additional firmware is necessary, which has to be loaded
X into the card using the eiconctrl utility which is part of the
X latest isdn4k-utils package. Please read the file
- Documentation/isdn/README.eicon for more information.
-
-Eicon Diva Server card support
+ <file:Documentation/isdn/README.eicon> for more information.
+
+Legacy Eicon driver
+CONFIG_ISDN_DRV_EICON_OLD
+ Say Y here to use your Eicon active ISDN card with ISDN4Linux
+ isdn module.
+
+Eicon PCI DIVA Server BRI/PRI/4BRI support
X CONFIG_ISDN_DRV_EICON_PCI
- Say Y here if you have an Eicon Diva Server (BRI/PRI/4BRI) ISDN card.
- Please read Documentation/isdn/README.eicon for more information.
-
-Eicon old-type card support
+ Say Y here if you have an Eicon Diva Server (BRI/PRI/4BRI) ISDN
+ card. Please read <file:Documentation/isdn/README.eicon> for more
+ information.
+
+Eicon old-type (S,SX,SCOM,Quadro,S2M) card support
X CONFIG_ISDN_DRV_EICON_ISA
X Say Y here if you have an old-type Eicon active ISDN card. In order
X to use this card, additional firmware is necessary, which has to be
X loaded into the card using the eiconctrl utility which is part of
X the latest isdn4k-utils package. Please read the file
- Documentation/isdn/README.eicon for more information.
+ <file:Documentation/isdn/README.eicon> for more information.
X
X Eicon driver type standalone
-CONFIG_ISDN_DRV_EICON_STANDALONE
+CONFIG_ISDN_DRV_EICON_DIVAS
X Enable this option if you want the eicon driver as standalone
X version with no interface to the ISDN4Linux isdn module. If you
X say Y here, the eicon module only supports the Diva Server PCI
@@ -16621,20 +19231,49 @@
X Fax Class 1 and 2 commands. Using a getty with fax-support
X (mgetty+sendfax, hylafax), you will be able to use your Linux box as
X an ISDN-fax-machine. This must be supported by the lowlevel driver
- also. See Documentation/isdn/README.fax for more information.
+ also. See <file:Documentation/isdn/README.fax> for more information.
X
X CAPI2.0 support
X CONFIG_ISDN_CAPI
X This provides the CAPI (Common ISDN Application Programming
X Interface, a standard making it easy for programs to access ISDN
- hardware, see http://www.capi.org/ . This is needed for AVM's set of
- active ISDN controllers like B1, T1, M1.
+ hardware, see <http://www.capi.org/>. This is needed for AVM's set
+ of active ISDN controllers like B1, T1, M1.
X
X This code is also available as a module ( = code which can be


X inserted in and removed from the running kernel whenever you want).

X The modules will be called capi.o and kernelcapi.o. If you want to
X compile it as a module, say M here and read
- Documentation/modules.txt.


+ <file:Documentation/modules.txt>.
+

+CAPI2.0 /dev/capi20 support
+CONFIG_ISDN_CAPI_CAPI20
+ This option will provide the CAPI 2.0 interface to userspace
+ applications via /dev/capi20. Applications should use the
+ standardized libcapi20 to access this functionality. You should say
+ Y/M here.
+
+CAPI2.0 Middleware support
+CONFIG_ISDN_CAPI_MIDDLEWARE
+ This option will enhance the capabilities of the /dev/capi20
+ interface. It will provide a means of moving a data connection,
+ established via the usual /dev/capi20 interface to a special tty
+ device. If you want to use pppd with pppdcapiplugin to dial up to
+ your ISP, say Y here.
+
+CAPI2.0 filesystem support
+CONFIG_ISDN_CAPI_CAPIFS
+ This option provides a special file system, similar to /dev/pts with
+ device nodes for the special ttys established by using the
+ middleware extension above. If you want to use pppd with
+ pppdcapiplugin to dial up to your ISP, say Y here.
+
+CAPI2.0 capidrv interface support
+CONFIG_ISDN_CAPI_CAPIDRV
+ This option provides the glue code to hook up CAPI driven cards to
+ the legacy isdn4linux link layer. If you have a card which is
+ supported by a CAPI driver, but still want to use old features like
+ ippp interfaces or ttyI emulation, say Y/M here.
X
X AVM B1 ISA support
X CONFIG_ISDN_DRV_AVMB1_B1ISA
@@ -16657,6 +19296,11 @@
X CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
X Enable support for the PCMCIA version of the AVM B1 card.
X
+AVM B1/M1/M2 PCMCIA cs module
+CONFIG_ISDN_DRV_AVMB1_AVM_CS
+ Enable the PCMCIA client driver for the AVM B1/M1/M2
+ PCMCIA cards.
+
X AVM T1/T1-B PCI support
X CONFIG_ISDN_DRV_AVMB1_T1PCI
X Enable support for the AVM T1 T1B card.
@@ -16673,40 +19317,40 @@
X disconnecting. This will increase the size of the kernel by 7 KB. If


X unsure, say Y.
X

-IBM Active 2000 support (EXPERIMENTAL)
+IBM Active 2000 support
X CONFIG_ISDN_DRV_ACT2000
X Say Y here if you have an IBM Active 2000 ISDN card. In order to use
X this card, additional firmware is necessary, which has to be loaded
X into the card using a utility which is part of the latest
X isdn4k-utils package. Please read the file
- Documentation/isdn/README.act2000 for more information.
+ <file:Documentation/isdn/README.act2000> for more information.
X
X Auvertech TurboPAM support
X CONFIG_ISDN_DRV_TPAM
X This enables support for the Auvertech TurboPAM ISDN-card.
X For running this card, additional firmware is necessary, which has
X to be downloaded into the card using a utility which is distributed
- separately from the Auvertech's web site: http://www.auvertech.fr.
+ separately from the Auvertech's web site: <http://www.auvertech.fr>.
X
X Please redirect all support questions to sup...@auvertech.fr.


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be

- called tpam.o.


+ say M here and read <file:Documentation/modules.txt>. The module

+ will be called tpam.o.
X
X Hypercope HYSDN cards (Champ, Ergo, Metro) support (module)
X CONFIG_HYSDN
X Say Y here if you have one of Hypercope's active PCI ISDN cards
X Champ, Ergo and Metro. You will then get a module called hysdn.o.
- Please read the file Documentation/isdn/README.hysdn for more
+ Please read the file <file:Documentation/isdn/README.hysdn> for more
X information.
X
X HYSDN CAPI 2.0 support
X CONFIG_HYSDN_CAPI
- Say Y here if you like to use Hypercope's CAPI 2.0 interface
+ Say Y here if you like to use Hypercope's CAPI 2.0 interface.
X
-Support for Sun4 architecture
+Support for SUN4 machines (disables SUN4[CDM] support)
X CONFIG_SUN4
X Say Y here if, and only if, your machine is a Sun4. Note that
X a kernel compiled with this option will run only on Sun4.
@@ -16720,7 +19364,7 @@
X This support is also available as a module called esp.o ( = code
X which can be inserted in and removed from the running kernel
X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X
X PTI Qlogic, ISP Driver
X CONFIG_SCSI_QLOGICPTI
@@ -16732,17 +19376,22 @@
X This support is also available as a module called qlogicpti.o ( =
X code which can be inserted in and removed from the running kernel
X whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt.
+ here and read <file:Documentation/modules.txt>.
X
-SPARC /dev/openprom compatibility driver (EXPERIMENTAL)
+Sun PROM console
+CONFIG_PROM_CONSOLE
+ Say Y to build a console driver for Sun machines that uses the
+ terminal emulation built into their console PROMS.
+
+/dev/openprom device support
X CONFIG_SUN_OPENPROMIO
X This driver provides user programs with an interface to the SPARC
X PROM device tree. The driver implements a SunOS-compatible
- interface and a NetBSD-compatible interface.
+ interface and a NetBSD-compatible interface.


X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),

- say M and read Documentation/modules.txt. If unsure, say Y.
+ say M and read <file:Documentation/modules.txt>. If unsure, say Y.
X
X Openprom tree appears in /proc/openprom
X CONFIG_SUN_OPENPROMFS
@@ -16752,8 +19401,9 @@
X
X If you want to compile the /proc/openprom support as a module ( =
X code which can be inserted in and removed from the running kernel
- whenever you want), say M here and read Documentation/modules.txt.
- The module will be called openpromfs.o. If unsure, say M.
+ whenever you want), say M here and read
+ <file:Documentation/modules.txt>.
+ The module will be called openpromfs.o. If unsure, say M.
X
X Kernel support for Linux/Sparc 32bit binary compatibility
X CONFIG_SPARC32_COMPAT
@@ -16773,11 +19423,11 @@
X
X SunOS binary emulation
X CONFIG_SUNOS_EMUL
- This allows you to run most SunOS binaries. If you want to do this,
+ This allows you to run most SunOS binaries. If you want to do this,
X say Y here and place appropriate files in /usr/gnemul/sunos. See
- http://www.ultralinux.org/faq.html for more information. If you want
- to run SunOS binaries on an Ultra you must also say Y to "Kernel
- support for 32-bit a.out binaries" above.
+ <http://www.ultralinux.org/faq.html> for more information. If you
+ want to run SunOS binaries on an Ultra you must also say Y to
+ "Kernel support for 32-bit a.out binaries" above.
X
X Mostek real time clock support
X CONFIG_SUN_MOSTEK_RTC
@@ -16802,17 +19452,37 @@
X This driver supports the serial ports on newer (PCI) Ultra systems.
X Say Y if you want to be able to use your serial ports.
X
-Aurora Multiboard 1600se (EXPERIMENTAL)
+Videopix Frame Grabber
+CONFIG_SUN_VIDEOPIX
+ Say Y here to support the Videopix Frame Grabber from Sun
+ Microsystems, commonly found on SPARCstations. This card, which is
+ based on the Phillips SAA9051, can handle NTSC and PAL/SECAM and
+ SVIDEO signals.
+
+Sun bidirectional parallel port support
+CONFIG_SUN_BPP
+ Say Y here to support Sun's obsolete variant of IEEE1284
+ bidirectional parallel port protocol as /dev/bppX. Can be built on
+ x86 machines.
+
+Aurora Multiboard 1600se
X CONFIG_SUN_AURORA
X The Aurora Multiboard is a multi-port high-speed serial controller.
X If you have one of these, say Y.
X
-Audio support (EXPERIMENTAL)
+Tadpole TS102 Microcontroller support
+CONFIG_TADPOLE_TS102_UCTRL
+ Say Y here to directly support the TS102 Microcontroller interface
+ on the Tadpole Sparcbook 3. This device handles power-management
+ events, and can also notice the attachment/detachment of external
+ monitors and mice.
+
+Audio support
X CONFIG_SPARCAUDIO
X This driver provides support for the build-in sound devices on most
X Sun machines. If you want to be able to use this, select this option
X and one or more of the lowlevel drivers below. See
- http://www.dementia.org/~shadow/sparcaudio.html for more
+ <http://www.dementia.org/~shadow/sparcaudio.html> for more
X information.
X
X AMD7930 Lowlevel Driver
@@ -16830,18 +19500,83 @@
X This driver supports the DBRI audio interface found on the SS10,
X SS20, Sparcbook 3, and Voyager systems.
X
-Dummy lowlevel Driver
+Dummy Lowlevel Driver
X CONFIG_SPARCAUDIO_DUMMY
X This is a pseudo-driver used for debugging and testing the
X sparcaudio subsystem. Say N unless you want to work on this
X subsystem.
X
-Sparc hardware (EXPERIMENTAL)
+Sparc hardware
X CONFIG_PARPORT_SUNBPP
X This driver provides support for the bidirectional parallel port
X found on many Sun machines. Note that many of the newer Ultras
X actually have pc style hardware instead.
X
+/proc/hardware support
+CONFIG_PROC_HARDWARE
+ Say Y here to support the /proc/hardware file, which gives you
+ access to information about the machine you're running on,
+ including the model, CPU, MMU, clock speed, BogoMIPS rating,
+ and memory size.
+
+Bluetooth subsystem support
+CONFIG_BLUEZ
+ Bluetooth is low-cost, low-power, short-range wireless technology.
+ It was designed as a replacement for cables and other short-range
+ technologies like IrDA. Bluetooth operates in personal area range
+ that typically extends up to 10 meters. More information about
+ Bluetooth can be found at <http://www.bluetooth.com>.
+
+ Linux Bluetooth subsystem consist of several layers:
+ HCI Core (device and connection manager, scheduler)
+ HCI Device drivers (interface to the hardware)
+ L2CAP Module (L2CAP protocol)
+
+ Say Y here to enable Linux Bluetooth support and to build HCI Core
+ layer.
+
+ To use Linux Bluetooth subsystem, you will need several user-space
+ utilities like hciconfig and hcid. These utilities and updates to
+ Bluetooth kernel modules are provided in the BlueZ package.
+ For more information, see <http://bluez.sf.net>.
+
+ If you want to compile HCI Core as module (hci.o) say M here.
+
+L2CAP protocol support
+CONFIG_BLUEZ_L2CAP
+ L2CAP (Logical Link Control and Adaptation Protocol) provides
+ connection oriented and connection-less data transport. L2CAP
+ support is required for most Bluetooth applications.
+
+ Say Y here to compile L2CAP support into the kernel or say M to
+ compile it as module (l2cap.o).
+
+HCI UART driver
+CONFIG_BLUEZ_HCIUART
+ Bluetooth HCI UART driver.
+ This driver is required if you want to use Bluetooth devices with
+ serial port interface.
+
+ Say Y here to compile support for Bluetooth UART devices into the
+ kernel or say M to compile it as module (hci_uart.o).
+
+HCI USB driver
+CONFIG_BLUEZ_HCIUSB
+ Bluetooth HCI USB driver.
+ This driver is required if you want to use Bluetooth devices with
+ USB interface.
+
+ Say Y here to compile support for Bluetooth USB devices into the


+ kernel or say M to compile it as module (hci_usb.o).
+

+HCI VHCI virtual HCI device driver
+CONFIG_BLUEZ_HCIVHCI
+ Bluetooth Virtual HCI device driver.
+ This driver is required if you want to use HCI Emulation software.
+
+ Say Y here to compile support for virtual HCI devices into the
+ kernel or say M to compile it as module (hci_vhci.o).
+
X # The following options are for Linux when running on the Hitachi
X # SuperH family of RISC microprocessors.
X
@@ -16959,20 +19694,45 @@
X
X #
X # m68k-specific kernel options
-# Documented by Chris Lawrence <qua...@themall.net> et al.
+# Documented by Chris Lawrence <mailto:qua...@themall.net> et al.
X #
X Amiga support
X CONFIG_AMIGA
X This option enables support for the Amiga series of computers. If
X you plan to use this kernel on an Amiga, say Y here and browse the
- material available in Documentation/m68k; otherwise say N.
+ material available in <file:Documentation/m68k>; otherwise say N.
+
+Commodore A2232 serial support
+CONFIG_A2232
+ This option supports the 2232 7-port serial card shipped with the
+ Amiga 2000 and other Zorro-bus machines, dating from 1989. At
+ a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip
+ each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The
+ ports were connected with 8 pin DIN connectors on the card bracket,
+ for which 8 pin to DB25 adapters were supplied. The card also had
+ jumpers internally to toggle various pinning configurations.
+
+ This driver can be built as a module; but then "generic_serial.o"
+ will also be built as a module. This has to be loaded before
+ "ser_a2232.o". If you want to do this, answer M here and read


+ "<file:Documentation/modules.txt>".
+

+A4000T SCSI support
+CONFIG_A4000T_SCSI
+ Support for the NCR53C710 SCSI controller on the Amiga 4000T.
+
+A4091 SCSI support
+CONFIG_A4091_SCSI
+ Support for the NCR53C710 chip on the Amiga 4091 Z3 SCSI2 controller
+ (1993). Very obscure -- the 4091 was part of an Amiga 4000 upgrade
+ plan at the time the Amiga business was sold to DKB.
X
X Atari support
X CONFIG_ATARI
X This option enables support for the 68000-based Atari series of
X computers (including the TT, Falcon and Medusa). If you plan to use
X this kernel on an Atari, say Y here and browse the material
- available in Documentation/m68k; otherwise say N.
+ available in <file:Documentation/m68k>; otherwise say N.
X
X Hades support
X CONFIG_HADES
@@ -16984,7 +19744,7 @@
X This option enables support for the Apple Macintosh series of
X computers (yes, there is experimental support now, at least for part
X of the series).
-
+
X Say N unless you're willing to code the remaining necessary support.
X ;)
X
@@ -16995,14 +19755,51 @@
X If you plan to try to use the kernel on such a machine say Y here.
X Everybody else says N.
X
+Q40/Q60 support
+CONFIG_Q40
+ The Q40 is a Motorola 68040-based successor to the Sinclair QL
+ manufactured in Germany. There is an official Q40 home page at
+ <http://www.q40.de/>. This option enables support for the Q40 and
+ Q60. Select your CPU below. For 68LC060 don't forget to enable FPU
+ emulation.
+
+Sun 3 support
+CONFIG_SUN3
+ This option enables support for the Sun 3 series of workstations.
+ Currently, only the Sun 3/80 is supported within the Sun 3x family.
+ You will also want to enable 68030 support. General Linux
+ information on the Sun 3x series (now discontinued) is at
+ <http://www.angelfire.com/ca2/tech68k/sun3.html>.
+
+ If you don't want to compile a kernel for a Sun 3, say N.
+
X Sun 3X support
X CONFIG_SUN3X
X This option enables support for the Sun 3x series of workstations.
X Be warned that this support is very experimental. You will also want
X to say Y to 68020 support and N to the other processors below.
+ General Linux information on the Sun 3x series (now discontinued)
+ is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
X
X If you don't want to compile a kernel for a Sun 3x, say N.
X
+Sun3x builtin serial support
+CONFIG_SUN3X_ZS
+ ZS refers to a type of asynchronous serial port built in to the Sun3
+ and Sun3x workstations; if you have a Sun 3, you probably have
+ these. Say 'Y' to support ZS ports directly. This option must be
+ enabled in order to support the
+ keyboard and mouse ports.
+
+Sun keyboard support
+CONFIG_SUN_KEYBOARD
+ Say Y here to support the keyboard found on Sun 3 and 3x
+ workstations. It can also be used support Sun Type-5 keyboards
+ through an adaptor. See
+ <http://www.suse.cz/development/input/adapters.html> and
+ <http://sourceforge.net/projects/linuxconsole/> for details on the
+ latter.
+
X 68020 support
X CONFIG_M68020
X If you anticipate running this kernel on a computer with a MC68020
@@ -17028,7 +19825,7 @@
X If you anticipate running this kernel on a computer with a MC68060
X processor, say Y. Otherwise, say N.
X
-Math emulation support (EXPERIMENTAL)
+Math emulation support
X CONFIG_M68KFPU_EMU
X At some point in the future, this will cause floating-point math
X instructions to be emulated by the kernel on machines that lack a
@@ -17060,19 +19857,25 @@
X This gives you access to some advanced options for the CPU. The
X defaults should be fine for most users, but these options may make
X it possible for you to improve performance somewhat if you know what
- you are doing.
+ you are doing.


X
X Note that the answer to this question won't directly affect the
- kernel: saying N will just cause this configure script to skip all
+ kernel: saying N will just cause the configurator to skip all

X the questions about these options.
X
X Most users should say N to this question.
X
+Use one physical chunk of memory only
+CONFIG_SINGLE_MEMORY_CHUNK
+ Ignore all but the first contiguous chunk of physical memory for VM
+ purposes. This will save a few bytes kernel size and may speed up
+ some operations. Say N if not sure.
+
X Use read-modify-write instructions
X CONFIG_RMW_INSNS
X This allows to use certain instructions that work with indivisible
X read-modify-write bus cycles. While this is faster than the
- workaround of disabling interrupts, it can conflict with DMA
+ workaround of disabling interrupts, it can conflict with DMA
X ( = direct memory access) on many Amiga systems, and it is also said
X to destabilize other machines. It is very likely that this will
X cause serious problems on any Amiga or Atari Medusa if set. The only
@@ -17081,7 +19884,7 @@
X really know what you are doing, say N. Try Y only if you're quite
X adventurous.
X
-Zorro support
+Amiga Zorro (AutoConfig) bus support
X CONFIG_ZORRO
X This enables support for the Zorro bus in the Amiga. If you have
X expansion cards in your Amiga that conform to the Amiga
@@ -17103,23 +19906,34 @@
X
X When in doubt, say Y.
X
-Amiga 1200/600 PCMCIA support (EXPERIMENTAL)
+Amiga 1200/600 PCMCIA support
X CONFIG_AMIGA_PCMCIA
X Include support in the kernel for pcmcia on Amiga 1200 and Amiga
X 600. If you intend to use pcmcia cards say Y; otherwise say N.
X
+Hisoft Whippet PCMCIA serial support
+CONFIG_WHIPPET_SERIAL
+ HiSoft has a web page at <http://www.hisoft.co.uk/>, but there
+ is no listing for the Whippet in their Amiga section.
+
X Amiga Zorro II ramdisk support
X CONFIG_AMIGA_Z2RAM
X This enables support for using Chip RAM and Zorro II RAM as a
X ramdisk or as a swap partition. Say Y if you want to include this
- driver in the kernel. This driver is also available as a module
+ driver in the kernel. This driver is also available as a module
X ( = code which can be inserted in and removed from the running
X kernel whenever you want). The module is called z2ram.o. If you want
X to compile it as a module, say M here and read
- Documentation/modules.txt.


+ <file:Documentation/modules.txt>.
X

-Atari ST-RAM swap support
+Support for ST-RAM as swap space
X CONFIG_STRAM_SWAP
+ Some Atari 68k macines (including the 520STF and 1020STE) divide
+ their addressible memory into ST and TT sections. The TT section
+ (up to 512MB) is the main memory; the ST section (up to 4MB) is
+ accessible to the built-in graphics board, runs slower, and is
+ present mainly for backward compatibility with older machines.
+
X This enables support for using (parts of) ST-RAM as swap space,
X instead of as normal system memory. This can first enhance system
X performance if you have lots of alternate RAM (compared to the size
@@ -17130,6 +19944,12 @@
X sound). The probability that such allocations at module load time
X fail is drastically reduced.
X
+ST-RAM statistics in /proc
+CONFIG_STRAM_PROC
+ Say Y here to report ST-RAM usage statistics in /proc/stram. See
+ the help for CONFIG_STRAM_SWAP for discussion of ST-RAM and its
+ uses.
+
X Atari ACSI support
X CONFIG_ATARI_ACSI
X This enables support for the Atari ACSI interface. The driver
@@ -17140,7 +19960,7 @@
X driver is also the basis for certain other drivers for devices
X attached to the ACSI bus: Atari SLM laser printer, BioNet-100
X Ethernet, and PAMsNet Ethernet. If you want to use one of these
- devices, you need ACSI support, too.
+ devices, you need ACSI support, too.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

@@ -17171,7 +19991,7 @@
X also available as a module ( = code which can be inserted in and
X removed from the running kernel whenever you want). The module is
X called wd33c93.o. If you want to compile it as a module, say M here
- and read Documentation/modules.txt.
+ and read <file:Documentation/modules.txt>.
X
X A2091 WD33C93A support
X CONFIG_A2091_SCSI
@@ -17179,7 +19999,7 @@
X say N. This driver is also available as a module ( = code which can


X be inserted in and removed from the running kernel whenever you

X want). The module is called wd33c93.o. If you want to compile it as
- a module, say M here and read Documentation/modules.txt.


+ a module, say M here and read <file:Documentation/modules.txt>.
X

X GVP Series II WD33C93A support
X CONFIG_GVP11_SCSI
@@ -17192,21 +20012,21 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you

X want). The module will be called gvp11.o. If you want to compile it
- as a module, say M here and read Documentation/modules.txt.


+ as a module, say M here and read <file:Documentation/modules.txt>.
X

-Cyberstorm SCSI support
+CyberStorm SCSI support
X CONFIG_CYBERSTORM_SCSI
X If you have an Amiga with an original (MkI) Phase5 Cyberstorm
X accelerator board and the optional Cyberstorm SCSI controller,
X answer Y. Otherwise, say N.
X
-Cyberstorm II SCSI support
+CyberStorm II SCSI support
X CONFIG_CYBERSTORMII_SCSI
X If you have an Amiga with a Phase5 Cyberstorm MkII accelerator board
X and the optional Cyberstorm SCSI controller, say Y. Otherwise,
X answer N.
X
-Blizzard 2060 SCSI support (EXPERIMENTAL)
+Blizzard 2060 SCSI support
X CONFIG_BLZ2060_SCSI
X If you have an Amiga with a Phase5 Blizzard 2060 accelerator board
X and want to use the onboard SCSI controller, say Y. Otherwise,
@@ -17228,18 +20048,25 @@
X If you have the Phase5 Fastlane Z3 SCSI controller, or plan to use
X one in the near future, say Y to this question. Otherwise, say N.
X
+BSC Oktagon SCSI support
+CONFIG_OKTAGON_SCSI
+ If you have the BSC Oktagon SCSI disk controller for the Amiga, say
+ Y to this question. If you're in doubt about whether you have one,
+ see the picture at
+ <http://amiga.multigraph.com/photos/oktagon.html>.
+
X Atari native SCSI support
X CONFIG_ATARI_SCSI
X If you have an Atari with built-in NCR5380 SCSI controller (TT,
X Falcon, ...) say Y to get it supported. Of course also, if you have
- a compatible SCSI controller (e.g. for Medusa). This driver is also
+ a compatible SCSI controller (e.g. for Medusa). This driver is also
X available as a module ( = code which can be inserted in and removed
- from the running kernel whenever you want). The module is called
- atari_scsi.o. If you want to compile it as a module, say M here and
- read Documentation/modules.txt. This driver supports both styles of
- NCR integration into the system: the TT style (separate DMA), and
- the Falcon style (via ST-DMA, replacing ACSI). It does NOT support
- other schemes, like in the Hades (without DMA).
+ from the running kernel whenever you want). The module is called
+ atari_scsi.o. If you want to compile it as a module, say M here and
+ read <file:Documentation/modules.txt>. This driver supports both
+ styles of NCR integration into the system: the TT style (separate
+ DMA), and the Falcon style (via ST-DMA, replacing ACSI). It does
+ NOT support other schemes, like in the Hades (without DMA).
X
X Long delays for Toshiba CD-ROMs
X CONFIG_ATARI_SCSI_TOSHIBA_DELAY
@@ -17248,6 +20075,12 @@
X use a Toshiba CD-ROM drive; otherwise, the option is not needed and
X would impact performance a bit, so say N.
X
+Reset SCSI-devices at boottime
+CONFIG_ATARI_SCSI_RESET_BOOT
+ Reset the devices on your Atari whenever it boots. This makes the
+ boot process fractionally longer but may assist recovery from errors
+ that leave the devices with SCSI operations partway completed.
+
X Hades SCSI DMA emulator
X CONFIG_TT_DMA_EMUL
X This option enables code which emulates the TT SCSI DMA chip on the
@@ -17262,7 +20095,7 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you

X want). The module is called ariadne.o. If you want to compile it as
- a module, say M here and read Documentation/modules.txt.


+ a module, say M here and read <file:Documentation/modules.txt>.
X

X Ariadne II and X-Surf support
X CONFIG_ARIADNE2
@@ -17273,7 +20106,7 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called ariadne2.o. If you want to compile it as
- a module, say M here and read Documentation/modules.txt.


+ a module, say M here and read <file:Documentation/modules.txt>.
X

X A2065 support
X CONFIG_A2065
@@ -17283,7 +20116,7 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you

X want). The module is called a2065.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.


+ module, say M here and read <file:Documentation/modules.txt>.
X

X Hydra support
X CONFIG_HYDRA
@@ -17292,17 +20125,30 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you

X want). The module is called hydra.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.


+ module, say M here and read <file:Documentation/modules.txt>.
X

-Pcmcia NE2000 compatible support
+Sun3 NCR5380 SCSI
+CONFIG_SUN3_SCSI
+ This option will enable support for the OBIO (onboard io) NCR5380
+ SCSI controller found in the Sun 3/50 and 3/60. Note that this
+ driver does not provide support for VME SCSI boards.
+ General Linux information on the Sun 3 series (now discontinued)
+ is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
+
+Sun3x ESP SCSI driver
+CONFIG_SUN3X_ESP
+ The ESP was an on-board SCSI controller used on Sun 3/80
+ machines. Say Y here to compile in support for it.
+
+PCMCIA NE2000 and compatibles support
X CONFIG_APNE
- If you have a pcmcia ne2000 compatible adapter, say Y. Otherwise,
+ If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise,
X say N.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you

X want). The module is called apne.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.


+ module, say M here and read <file:Documentation/modules.txt>.
X

X Atari Lance support
X CONFIG_ATARILANCE
@@ -17324,32 +20170,32 @@
X
X Amiga mouse support
X CONFIG_AMIGAMOUSE
- If you want to be able to use an Amiga mouse in Linux, say Y.
+ If you want to be able to use an Amiga mouse in Linux, say Y.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module is called amigamouse.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.


+ module, say M here and read <file:Documentation/modules.txt>.
X

X Atari mouse support
X CONFIG_ATARIMOUSE
- If you want to be able to use an Atari mouse in Linux, say Y.
+ If you want to be able to use an Atari mouse in Linux, say Y.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module is called atarimouse.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.


+ module, say M here and read <file:Documentation/modules.txt>.
X

X Atari MFP serial support
X CONFIG_ATARI_MFPSER
X If you like to use the MFP serial ports ("Modem1", "Serial1") under
X Linux, say Y. The driver equally supports all kinds of MFP serial
- ports and automatically detects whether Serial1 is available.
+ ports and automatically detects whether Serial1 is available.


X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X If you want to compile it as a module, say M here and read
- Documentation/modules.txt.

+ <file:Documentation/modules.txt>.
X
X Note for Falcon users: You also have an MFP port, it's just not
X wired to the outside... But you could use the port under Linux.
@@ -17365,7 +20211,7 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt.

+ <file:Documentation/modules.txt>.
X
X Atari SCC serial DMA support
X CONFIG_ATARI_SCC_DMA
@@ -17382,9 +20228,9 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you

X want). If you want to compile it as a module, say M here and read
- Documentation/modules.txt.


+ <file:Documentation/modules.txt>.
X

-Atari DSP56k Digital Signal Processor support (EXPERIMENTAL)
+Atari DSP56k Digital Signal Processor support
X CONFIG_ATARI_DSP56K
X If you want to be able to use the DSP56001 in Falcons, say Y. This
X driver is still experimental, and if you don't know what it is, or
@@ -17393,7 +20239,12 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt.

+ <file:Documentation/modules.txt>.
+

+Support for early boot text console
+CONFIG_BOOTX_TEXT
+ Say Y here to see progress messages from the boot firmware in text
+ mode. Requires either BootX or Open Firmware.
X
X Amiga builtin serial support
X CONFIG_AMIGA_BUILTIN_SERIAL
@@ -17403,13 +20254,23 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you

X want). If you want to compile it as a module, say M here and read
- Documentation/modules.txt.
+ <file:Documentation/modules.txt>.
X
X GVP IO-Extender support
X CONFIG_GVPIOEXT
X If you want to use a GVP IO-Extender serial card in Linux, say Y.
X Otherwise, say N.
X
+GVP IO-Extender parallel printer support
+CONFIG_GVPIOEXT_LP
+ Say Y to enable driving a printer from the parallel port on your
+ GVP IO-Extender card, N otherwise.
+
+GVP IO-Extender PLIP support
+CONFIG_GVPIOEXT_PLIP
+ Say Y to enable doing IP over the parallel port on your GVP
+ IO-Extender card, N otherwise.
+
X Multiface Card III serial support
X CONFIG_MULTIFACE_III_TTY
X If you want to use a Multiface III card's serial port in Linux,
@@ -17418,7 +20279,15 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt.

+ <file:Documentation/modules.txt>.
+

+Amiga/Atari/PowerMac DMA sound support
+CONFIG_DMASOUND
+ Support built-in audio chips accessible by DMA on various machines
+ that have them. Note that this symbol does not affect the kernel
+ directly; rather, it controls whether configuration questions
+ enabling DMA sound drivers for various specific machine
+ architectures will be used.
X
X Atari DMA sound support
X CONFIG_DMASOUND_ATARI
@@ -17429,7 +20298,7 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you

X want). If you want to compile it as a module, say M here and read
- Documentation/modules.txt.
+ <file:Documentation/modules.txt>.
X
X PowerMac DMA sound support
X CONFIG_DMASOUND_AWACS
@@ -17440,7 +20309,7 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you

X want). If you want to compile it as a module, say M here and read
- Documentation/modules.txt.
+ <file:Documentation/modules.txt>.
X
X Amiga DMA sound support
X CONFIG_DMASOUND_PAULA
@@ -17451,7 +20320,7 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you

X want). If you want to compile it as a module, say M here and read
- Documentation/modules.txt.
+ <file:Documentation/modules.txt>.
X
X Q40 sound support
X CONFIG_DMASOUND_Q40
@@ -17462,7 +20331,7 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you

X want). If you want to compile it as a module, say M here and read
- Documentation/modules.txt.
+ <file:Documentation/modules.txt>.
X
X HP DCA serial support
X CONFIG_HPDCA
@@ -17480,39 +20349,122 @@
X HP300 machines. If you are using such a system you almost certainly
X want this.
X
+# Choice: ppctype
X Processor Type
X CONFIG_6xx
- There are four types of PowerPC chips supported. The more common
- types (601, 603, 604, 740, 750, 7400), the Motorola embedded versions
- (821, 823, 850, 855, 860, 8260), the IBM embedded versions (403 and
- 405) and the high end 64 bit Power processors (Power 3, Power 4).
- Unless you are building a kernel for one of the embedded processor
- systems, or a 64 bit IBM RS/6000, choose 6xx. Note that the kernel
- runs in 32-bit mode even on 64-bit chips. Also note that because
- the 82xx family has a 603e core, specific support for that chipset
- is asked later on.
+ There are four types of PowerPC chips supported. The more common
+ types (601, 603, 604, 740, 750, 7400), the Motorola embedded
+ versions (821, 823, 850, 855, 860, 8260), the IBM embedded versions
+ (403 and 405) and the high end 64 bit Power processors (Power 3,
+ Power 4). Unless you are building a kernel for one of the embedded
+ processor systems, or a 64 bit IBM RS/6000, choose 6xx. Note that
+ the kernel runs in 32-bit mode even on 64-bit chips. Also note that
+ because the 82xx family has a 603e core, specific support for that
+ chipset is asked later on.
X
X Motorola MPC8260 CPM support
X CONFIG_8260
X The MPC8260 CPM (Communications Processor Module) is a typical
- embedded CPU made by Motorola. Selecting this option means that you
- wish to build a kernel for a machine with specifically an 8260 for
- a CPU.
+ embedded CPU made by Motorola. Selecting this option means that
+ you wish to build a kernel for a machine with specifically an 8260
+ for a CPU.


X
X If in doubt, say N.
X

+# Choice: Machine type
+Oak
+CONFIG_OAK
+ Select Oak if you have an IBM 403GCX "Oak" Evaluation Board.
+
+ Select Walnut if you have an IBM 405GP "Walnut" Evaluation Board.
+
+ More information on these boards is available at:
+ <http://www.chips.ibm.com/products/powerpc/tools/evk_pn.html#GCX>.
+
+Walnut
+CONFIG_WALNUT
+ Select Walnut if you have an IBM 405GP "Walnut" Evaluation Board.
+
X Workarounds for PPC601 bugs
X CONFIG_PPC601_SYNC_FIX
X Some versions of the PPC601 (the first PowerPC chip) have bugs which
- mean that extra synchronization instructions are required near certain
- instructions, typically those that make major changes to the CPU state.
- These extra instructions reduce performance slightly. If you say N
- here, these extra instructions will not be included, resulting in a
- kernel which will run faster but may not run at all on some systems
- with the PPC601 chip.
+ mean that extra synchronization instructions are required near
+ certain instructions, typically those that make major changes to the
+ CPU state. These extra instructions reduce performance slightly.
+ If you say N here, these extra instructions will not be included,
+ resulting in a kernel which will run faster but may not run at all
+ on some systems with the PPC601 chip.
+
+ If in doubt, say Y here.
+
+8xx Cache (Copy-Back or Writethrough)
+CONFIG_8xx_COPYBACK
+ Saying Y here will cause the cache on an MPC8xx processor to be used
+ in Copy-Back mode. If you say N here, it is used in Writethrough
+ mode.
+
+ If in doubt, say Y here.
+
+MPC860 (Pre Rev. C) CPU6 Silicon Errata
+CONFIG_8xx_CPU6
+ MPC860 CPUs, prior to Rev C have some bugs in the silicon, which
+ require workarounds for Linux (and most other OSes to work). If you
+ get a BUG() very early in boot, this might fix the problem. For
+ more details read the document entitled "MPC860 Family Device Errata
+ Reference" on Motorola's website. This option also incurs a
+ performance hit.
+
+ If in doubt, say N here.
+
+MPC8xx IDE support
+CONFIG_BLK_DEV_MPC8xx_IDE
+ This option provides support for IDE on Motorola MPC8xx Systems.
+ Please see 'Type of MPC8xx IDE interface' for details.
+


+ If unsure, say N.

+
+Type of MPC8xx IDE interface
+CONFIG_IDE_8xx_PCCARD
+ Select how the IDE devices are connected to the MPC8xx system:
+
+ 8xx_PCCARD uses the 8xx internal PCMCIA interface in combination
+ with a PC Card (e.g. ARGOSY portable Hard Disk Adapter),
+ ATA PC Card HDDs or ATA PC Flash Cards (example: TQM8xxL
+ systems)
+
+ 8xx_DIRECT is used for directly connected IDE devices using the 8xx
+ internal PCMCIA interface (example: IVMS8 systems)
+
+ EXT_DIRECT is used for IDE devices directly connected to the 8xx
+ bus using some glue logic, but _not_ the 8xx internal
+ PCMCIA interface (example: IDIF860 systems)
+
+Use SMC2 for UART
+CONFIG_SMC2_UART
+ If you would like to use SMC2 as a serial port, say Y here.
X
X If in doubt, say Y here.
X
+Use SMC2 for Console
+CONFIG_CONS_SMC2
+ If you are going to have a serial console on your device and are
+ using SMC2 for your serial port, say Y here, else say N.
+
+Use the alternate SMC2 I/O
+CONFIG_ALTSMC2
+ If you have an MPC823 or MPC850 and would like to use the alternate
+ SMC2 for I/O, say Y here.
+
+ If in doubt, say N here.
+
+Enable SCC2 and SCC3 for UART
+CONFIG_USE_SCC_IO
+ If your MPC8xx board has other SCC ports that you would like to use
+ for for a serial port, say Y here.
+
+ If in doubt, say N here.
+
+# Choice: ppc6xxtype
X Machine Type
X CONFIG_ALL_PPC
X Linux currently supports several different kinds of PowerPC-based
@@ -17522,7 +20474,28 @@
X and some IBM RS/6000 systems), CHRP (Common Hardware Reference
X Platform), and several embedded PowerPC systems containing 4xx, 6xx,
X 7xx, 8xx, 74xx, and 82xx processors. Currently, the default option
- is to build a kernel which works on the first three.
+ is to build a kernel which works on the first three.
+
+ Select PowerMac/PReP/MTX/CHRP if configuring for any of the above.
+
+ Select Gemini if configuring for a Synergy Microsystems' Gemini
+ series Single Board Computer. More information is available at:
+ <http://www.synergymicro.com/PressRel/97_10_15.html>.
+
+ Select APUS if configuring for a PowerUP Amiga. More information is
+ available at: <http://linux-apus.sourceforge.net>.
+
+Synergy-Gemini
+CONFIG_GEMINI
+ Select Gemini if configuring for a Synergy Microsystems' Gemini
+ series Single Board Computer. More information is available at:
+ <http://www.synergymicro.com/PressRel/97_10_15.html>.
+
+Amiga-Apus
+CONFIG_APUS
+ Select APUS if configuring for a PowerUP Amiga.
+ More information is available at:
+ <http://linux-apus.sourceforge.net>.
X
X Embedded 8xx Board Type
X CONFIG_RPXLITE
@@ -17646,7 +20619,7 @@
X altivec registers, and turning on the 'altivec enable' bit so user
X processes can execute altivec instructions.
X
- This option is only usefully if you have a processor that supports
+ This option is only usefully if you have a processor that supports
X altivec (G4, otherwise known as 74xx series), but does not have
X any affect on a non-altivec cpu (it does, however add code to the
X kernel).
@@ -17657,7 +20630,7 @@
X CONFIG_TAU
X G3 and G4 processors have an on-chip temperature sensor called the
X 'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die
- temperature within 2-4 degrees celcius. This option shows the current
+ temperature within 2-4 degrees Celsius. This option shows the current
X on-die temperature in /proc/cpuinfo if the cpu supports it.
X
X Unfortunately, on some chip revisions, this sensor is very inaccurate
@@ -17681,26 +20654,10 @@
X Average high and low temp
X CONFIG_TAU_AVERAGE
X The TAU hardware can compare the temperature to an upper and lower bound.


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

echo 'End of part 016'
echo 'File patch-2.4.15 is continued in part 017'
echo "017" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:02 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part026

#!/bin/sh -x
# this is part 026 of a 115 - part archive


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

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

+ err |= __put_user(regs->cr_iip, &sc->eip);
+ err |= __put_user(regs->r17 & 0xffff, (unsigned int *)&sc->cs);
+ /*
+ * `eflags' is in an ar register for this context
+ */
+ asm volatile ("mov %0=ar.eflag ;;" : "=r"(flag));
+ err |= __put_user((unsigned int)flag, &sc->eflags);
+ err |= __put_user(regs->r12, &sc->esp_at_signal);
+ err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int *)&sc->ss);
X
X #if 0
- tmp = save_i387(fpstate);
- if (tmp < 0)
- err = 1;
- else
- err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);
+ tmp = save_i387(fpstate);
+ if (tmp < 0)
+ err = 1;
+ else
+ err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);
X
- /* non-iBCS2 extensions.. */
+ /* non-iBCS2 extensions.. */
X #endif
- err |= __put_user(mask, &sc->oldmask);
+ err |= __put_user(mask, &sc->oldmask);
X #if 0
- err |= __put_user(current->tss.cr2, &sc->cr2);
+ err |= __put_user(current->tss.cr2, &sc->cr2);
X #endif
-
- return err;
+ return err;
X }
X
X static int
-restore_sigcontext_ia32(struct pt_regs *regs, struct sigcontext_ia32 *sc, int *peax)
+restore_sigcontext_ia32 (struct pt_regs *regs, struct sigcontext_ia32 *sc, int *peax)
X {
- unsigned int err = 0;
+ unsigned int err = 0;
+
+#define COPY(ia64x, ia32x) err |= __get_user(regs->ia64x, &sc->ia32x)
X
-#define COPY(ia64x, ia32x) err |= __get_user(regs->ia64x, &sc->ia32x)
+#define copyseg_gs(tmp) (regs->r16 |= (unsigned long) tmp << 48)
+#define copyseg_fs(tmp) (regs->r16 |= (unsigned long) tmp << 32)
+#define copyseg_cs(tmp) (regs->r17 |= tmp)
+#define copyseg_ss(tmp) (regs->r17 |= (unsigned long) tmp << 16)
+#define copyseg_es(tmp) (regs->r16 |= (unsigned long) tmp << 16)
+#define copyseg_ds(tmp) (regs->r16 |= tmp)
+
+#define COPY_SEG(seg) \
+ { \
+ unsigned short tmp; \
+ err |= __get_user(tmp, &sc->seg); \
+ copyseg_##seg(tmp); \
+ }
+#define COPY_SEG_STRICT(seg) \
+ { \
+ unsigned short tmp; \
+ err |= __get_user(tmp, &sc->seg); \
+ copyseg_##seg(tmp|3); \
+ }
X
-#define copyseg_gs(tmp) (regs->r16 |= (unsigned long) tmp << 48)
-#define copyseg_fs(tmp) (regs->r16 |= (unsigned long) tmp << 32)
-#define copyseg_cs(tmp) (regs->r17 |= tmp)
-#define copyseg_ss(tmp) (regs->r17 |= (unsigned long) tmp << 16)
-#define copyseg_es(tmp) (regs->r16 |= (unsigned long) tmp << 16)
-#define copyseg_ds(tmp) (regs->r16 |= tmp)
-
-#define COPY_SEG(seg) \
- { unsigned short tmp; \
- err |= __get_user(tmp, &sc->seg); \
- copyseg_##seg(tmp); }
-
-#define COPY_SEG_STRICT(seg) \
- { unsigned short tmp; \
- err |= __get_user(tmp, &sc->seg); \
- copyseg_##seg(tmp|3); }
-
- /* To make COPY_SEGs easier, we zero r16, r17 */
- regs->r16 = 0;
- regs->r17 = 0;
-
- COPY_SEG(gs);
- COPY_SEG(fs);
- COPY_SEG(es);
- COPY_SEG(ds);
- COPY(r15, edi);
- COPY(r14, esi);
- COPY(r13, ebp);
- COPY(r12, esp);
- COPY(r11, ebx);
- COPY(r10, edx);
- COPY(r9, ecx);
- COPY(cr_iip, eip);
- COPY_SEG_STRICT(cs);
- COPY_SEG_STRICT(ss);
- {
+ /* To make COPY_SEGs easier, we zero r16, r17 */
+ regs->r16 = 0;
+ regs->r17 = 0;
+
+ COPY_SEG(gs);
+ COPY_SEG(fs);
+ COPY_SEG(es);
+ COPY_SEG(ds);
+ COPY(r15, edi);
+ COPY(r14, esi);
+ COPY(r13, ebp);
+ COPY(r12, esp);
+ COPY(r11, ebx);
+ COPY(r10, edx);
+ COPY(r9, ecx);
+ COPY(cr_iip, eip);
+ COPY_SEG_STRICT(cs);
+ COPY_SEG_STRICT(ss);
+ ia32_load_segment_descriptors(current);
+ {
X unsigned int tmpflags;
X unsigned long flag;
X
X /*
- * IA32 `eflags' is not part of `pt_regs', it's
- * in an ar register which is part of the thread
- * context. Fortunately, we are executing in the
+ * IA32 `eflags' is not part of `pt_regs', it's in an ar register which
+ * is part of the thread context. Fortunately, we are executing in the
X * IA32 process's context.
X */
X err |= __get_user(tmpflags, &sc->eflags);
@@ -210,186 +475,191 @@
X asm volatile ("mov ar.eflag=%0 ;;" :: "r"(flag));
X
X regs->r1 = -1; /* disable syscall checks, r1 is orig_eax */
- }
+ }
X
X #if 0
- {
- struct _fpstate * buf;
- err |= __get_user(buf, &sc->fpstate);
- if (buf) {
- if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
- goto badframe;
- err |= restore_i387(buf);
- }
- }
+ {
+ struct _fpstate * buf;
+ err |= __get_user(buf, &sc->fpstate);
+ if (buf) {
+ if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
+ goto badframe;
+ err |= restore_i387(buf);
+ }
+ }
X #endif
X
- err |= __get_user(*peax, &sc->eax);
- return err;
+ err |= __get_user(*peax, &sc->eax);
+ return err;
X
-#if 0
-badframe:
- return 1;
+#if 0
+ badframe:
+ return 1;
X #endif
-
X }
X
X /*
X * Determine which stack to use..
X */
X static inline void *
-get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
+get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
X {
- unsigned long esp;
- unsigned int xss;
+ unsigned long esp;
X
- /* Default to using normal stack */
- esp = regs->r12;
- xss = regs->r16 >> 16;
-
- /* This is the X/Open sanctioned signal stack switching. */
- if (ka->sa.sa_flags & SA_ONSTACK) {
- if (! on_sig_stack(esp))
- esp = current->sas_ss_sp + current->sas_ss_size;
- }
- /* Legacy stack switching not supported */
-
- return (void *)((esp - frame_size) & -8ul);
+ /* Default to using normal stack (truncate off sign-extension of bit 31: */
+ esp = (unsigned int) regs->r12;
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if (ka->sa.sa_flags & SA_ONSTACK) {
+ if (!on_sig_stack(esp))
+ esp = current->sas_ss_sp + current->sas_ss_size;
+ }
+ /* Legacy stack switching not supported */
+
+ return (void *)((esp - frame_size) & -8ul);
X }
X
X static int
-setup_frame_ia32(int sig, struct k_sigaction *ka, sigset_t *set,
- struct pt_regs * regs)
-{
- struct sigframe_ia32 *frame;
- int err = 0;
-
- frame = get_sigframe(ka, regs, sizeof(*frame));
-
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
-
- err |= __put_user((current->exec_domain
- && current->exec_domain->signal_invmap
- && sig < 32
- ? (int)(current->exec_domain->signal_invmap[sig])
- : sig),
- &frame->sig);
-
- err |= setup_sigcontext_ia32(&frame->sc, &frame->fpstate, regs, set->sig[0]);
-
- if (_IA32_NSIG_WORDS > 1) {
- err |= __copy_to_user(frame->extramask, &set->sig[1],
- sizeof(frame->extramask));
- }
-
- /* Set up to return from userspace. If provided, use a stub
- already in userspace. */
- err |= __put_user((long)frame->retcode, &frame->pretcode);
- /* This is popl %eax ; movl $,%eax ; int $0x80 */
- err |= __put_user(0xb858, (short *)(frame->retcode+0));
-#define __IA32_NR_sigreturn 119
- err |= __put_user(__IA32_NR_sigreturn & 0xffff, (short *)(frame->retcode+2));
- err |= __put_user(__IA32_NR_sigreturn >> 16, (short *)(frame->retcode+4));
- err |= __put_user(0x80cd, (short *)(frame->retcode+6));
-
- if (err)
- goto give_sigsegv;
-
- /* Set up registers for signal handler */
- regs->r12 = (unsigned long) frame;
- regs->cr_iip = (unsigned long) ka->sa.sa_handler;
-
- set_fs(USER_DS);
- regs->r16 = (__USER_DS << 16) | (__USER_DS); /* ES == DS, GS, FS are zero */
- regs->r17 = (__USER_DS << 16) | __USER_CS;
+setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs)
+{
+ struct sigframe_ia32 *frame;
+ int err = 0;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+ err |= __put_user((current->exec_domain
+ && current->exec_domain->signal_invmap
+ && sig < 32
+ ? (int)(current->exec_domain->signal_invmap[sig])
+ : sig),
+ &frame->sig);
+
+ err |= setup_sigcontext_ia32(&frame->sc, &frame->fpstate, regs, set->sig[0]);
+
+ if (_IA32_NSIG_WORDS > 1)
+ err |= __copy_to_user(frame->extramask, (char *) &set->sig + 4,
+ sizeof(frame->extramask));
+
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ unsigned int restorer = IA32_SA_RESTORER(ka);
+ err |= __put_user(restorer, &frame->pretcode);
+ } else {
+ err |= __put_user((long)frame->retcode, &frame->pretcode);
+ /* This is popl %eax ; movl $,%eax ; int $0x80 */
+ err |= __put_user(0xb858, (short *)(frame->retcode+0));
+ err |= __put_user(__IA32_NR_sigreturn & 0xffff, (short *)(frame->retcode+2));
+ err |= __put_user(__IA32_NR_sigreturn >> 16, (short *)(frame->retcode+4));
+ err |= __put_user(0x80cd, (short *)(frame->retcode+6));
+ }
+
+ if (err)
+ goto give_sigsegv;
+
+ /* Set up registers for signal handler */
+ regs->r12 = (unsigned long) frame;
+ regs->cr_iip = IA32_SA_HANDLER(ka);
+
+ set_fs(USER_DS);
+ regs->r16 = (__USER_DS << 16) | (__USER_DS); /* ES == DS, GS, FS are zero */
+ regs->r17 = (__USER_DS << 16) | __USER_CS;
X
X #if 0
- regs->eflags &= ~TF_MASK;
+ regs->eflags &= ~TF_MASK;
X #endif
X
X #if 0
- printk("SIG deliver (%s:%d): sig=%d sp=%p pc=%lx ra=%x\n",
+ printk("SIG deliver (%s:%d): sig=%d sp=%p pc=%lx ra=%x\n",
X current->comm, current->pid, sig, (void *) frame, regs->cr_iip, frame->pretcode);
X #endif
X
- return 1;
+ return 1;
X
-give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
- return 0;
+ give_sigsegv:
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
+ return 0;
X }
X
X static int
-setup_rt_frame_ia32(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs * regs)
+setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs * regs)
X {
- struct rt_sigframe_ia32 *frame;
- int err = 0;
+ struct rt_sigframe_ia32 *frame;
+ int err = 0;
X
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ka, regs, sizeof(*frame));
X
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
-
- err |= __put_user((current->exec_domain
- && current->exec_domain->signal_invmap
- && sig < 32
- ? current->exec_domain->signal_invmap[sig]
- : sig),
- &frame->sig);
- err |= __put_user((long)&frame->info, &frame->pinfo);
- err |= __put_user((long)&frame->uc, &frame->puc);
- err |= copy_siginfo_to_user32(&frame->info, info);
-
- /* Create the ucontext. */
- err |= __put_user(0, &frame->uc.uc_flags);
- err |= __put_user(0, &frame->uc.uc_link);
- err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
- err |= __put_user(sas_ss_flags(regs->r12),
- &frame->uc.uc_stack.ss_flags);
- err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
- err |= setup_sigcontext_ia32(&frame->uc.uc_mcontext, &frame->fpstate,
- regs, set->sig[0]);
- err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
-
- err |= __put_user((long)frame->retcode, &frame->pretcode);
- /* This is movl $,%eax ; int $0x80 */
- err |= __put_user(0xb8, (char *)(frame->retcode+0));
-#define __IA32_NR_rt_sigreturn 173
- err |= __put_user(__IA32_NR_rt_sigreturn, (int *)(frame->retcode+1));
- err |= __put_user(0x80cd, (short *)(frame->retcode+5));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+ err |= __put_user((current->exec_domain
+ && current->exec_domain->signal_invmap
+ && sig < 32
+ ? current->exec_domain->signal_invmap[sig]
+ : sig),
+ &frame->sig);
+ err |= __put_user((long)&frame->info, &frame->pinfo);
+ err |= __put_user((long)&frame->uc, &frame->puc);
+ err |= copy_siginfo_to_user32(&frame->info, info);
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(0, &frame->uc.uc_link);
+ err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->r12), &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= setup_sigcontext_ia32(&frame->uc.uc_mcontext, &frame->fpstate, regs, set->sig[0]);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ if (err)
+ goto give_sigsegv;
+
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ unsigned int restorer = IA32_SA_RESTORER(ka);
+ err |= __put_user(restorer, &frame->pretcode);
+ } else {
+ err |= __put_user((long)frame->retcode, &frame->pretcode);
+ /* This is movl $,%eax ; int $0x80 */
+ err |= __put_user(0xb8, (char *)(frame->retcode+0));
+ err |= __put_user(__IA32_NR_rt_sigreturn, (int *)(frame->retcode+1));
+ err |= __put_user(0x80cd, (short *)(frame->retcode+5));
+ }
X
- if (err)
- goto give_sigsegv;
+ if (err)
+ goto give_sigsegv;
X
- /* Set up registers for signal handler */
- regs->r12 = (unsigned long) frame;
- regs->cr_iip = (unsigned long) ka->sa.sa_handler;
+ /* Set up registers for signal handler */
+ regs->r12 = (unsigned long) frame;
+ regs->cr_iip = IA32_SA_HANDLER(ka);
X
- set_fs(USER_DS);
+ set_fs(USER_DS);
X
- regs->r16 = (__USER_DS << 16) | (__USER_DS); /* ES == DS, GS, FS are zero */
- regs->r17 = (__USER_DS << 16) | __USER_CS;
+ regs->r16 = (__USER_DS << 16) | (__USER_DS); /* ES == DS, GS, FS are zero */
+ regs->r17 = (__USER_DS << 16) | __USER_CS;
X
X #if 0
- regs->eflags &= ~TF_MASK;
+ regs->eflags &= ~TF_MASK;
X #endif
X
X #if 0
- printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%x\n",
+ printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%x\n",
X current->comm, current->pid, (void *) frame, regs->cr_iip, frame->pretcode);
X #endif
X
- return 1;
+ return 1;
X
X give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
- return 0;
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
+ return 0;
X }
X
X int
@@ -398,95 +668,78 @@
X {
X /* Set up the stack frame */
X if (ka->sa.sa_flags & SA_SIGINFO)
- return(setup_rt_frame_ia32(sig, ka, info, set, regs));
+ return setup_rt_frame_ia32(sig, ka, info, set, regs);
X else
- return(setup_frame_ia32(sig, ka, set, regs));
+ return setup_frame_ia32(sig, ka, set, regs);
X }
X
-asmlinkage int
-sys32_sigreturn(
-int arg0,
-int arg1,
-int arg2,
-int arg3,
-int arg4,
-int arg5,
-int arg6,
-int arg7,
-unsigned long stack)
-{
- struct pt_regs *regs = (struct pt_regs *) &stack;
- struct sigframe_ia32 *frame = (struct sigframe_ia32 *)(regs->r12- 8);
- sigset_t set;
- int eax;
-
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
-
- if (__get_user(set.sig[0], &frame->sc.oldmask)
- || (_IA32_NSIG_WORDS > 1
- && __copy_from_user((((char *) &set.sig) + 4),
- &frame->extramask,
- sizeof(frame->extramask))))
- goto badframe;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sigmask_lock);
- current->blocked = (sigset_t) set;
- recalc_sigpending(current);
- spin_unlock_irq(&current->sigmask_lock);
-
- if (restore_sigcontext_ia32(regs, &frame->sc, &eax))
- goto badframe;
- return eax;
-
-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
-
-asmlinkage int
-sys32_rt_sigreturn(
-int arg0,
-int arg1,
-int arg2,
-int arg3,
-int arg4,
-int arg5,
-int arg6,
-int arg7,
-unsigned long stack)
-{
- struct pt_regs *regs = (struct pt_regs *) &stack;
- struct rt_sigframe_ia32 *frame = (struct rt_sigframe_ia32 *)(regs->r12 - 4);
- sigset_t set;
- stack_t st;
- int eax;
-
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
- if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
- goto badframe;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sigmask_lock);
- current->blocked = set;
- recalc_sigpending(current);
- spin_unlock_irq(&current->sigmask_lock);
-
- if (restore_sigcontext_ia32(regs, &frame->uc.uc_mcontext, &eax))
- goto badframe;
-
- if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
- goto badframe;
- /* It is more difficult to avoid calling this function than to
- call it and ignore errors. */
- do_sigaltstack(&st, NULL, regs->r12);
-
- return eax;
-
-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
+asmlinkage long
+sys32_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7,
+ unsigned long stack)
+{
+ struct pt_regs *regs = (struct pt_regs *) &stack;
+ unsigned long esp = (unsigned int) regs->r12;
+ struct sigframe_ia32 *frame = (struct sigframe_ia32 *)(esp - 8);
+ sigset_t set;
+ int eax;
+
+ if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+
+ if (__get_user(set.sig[0], &frame->sc.oldmask)
+ || (_IA32_NSIG_WORDS > 1 && __copy_from_user((char *) &set.sig + 4, &frame->extramask,
+ sizeof(frame->extramask))))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked = (sigset_t) set;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ if (restore_sigcontext_ia32(regs, &frame->sc, &eax))
+ goto badframe;
+ return eax;
+
+ badframe:
+ force_sig(SIGSEGV, current);


+ return 0;
+}
X

+asmlinkage long
+sys32_rt_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7,
+ unsigned long stack)
+{
+ struct pt_regs *regs = (struct pt_regs *) &stack;
+ unsigned long esp = (unsigned int) regs->r12;
+ struct rt_sigframe_ia32 *frame = (struct rt_sigframe_ia32 *)(esp - 4);
+ sigset_t set;
+ stack_t st;
+ int eax;
+
+ if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ if (restore_sigcontext_ia32(regs, &frame->uc.uc_mcontext, &eax))
+ goto badframe;
+
+ if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+ goto badframe;
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, esp);
+
+ return eax;
+
+ badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/ia32/ia32_support.c linux/arch/ia64/ia32/ia32_support.c
--- v2.4.14/linux/arch/ia64/ia32/ia32_support.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/ia32/ia32_support.c Fri Nov 9 14:26:17 2001
@@ -4,15 +4,18 @@
X * Copyright (C) 1999 Arun Sharma <arun....@intel.com>
X * Copyright (C) 2000 Asit K. Mallick <asit.k....@intel.com>
X * Copyright (C) 2001 Hewlett-Packard Co
- * Copyright (C) 2001 David Mosberger-Tang <dav...@hpl.hp.com>
+ * David Mosberger-Tang <dav...@hpl.hp.com>
X *
X * 06/16/00 A. Mallick added csd/ssd/tssd for ia32 thread context
X * 02/19/01 D. Mosberger dropped tssd; it's not needed
+ * 09/14/01 D. Mosberger fixed memory management for gdt/tss page
+ * 09/29/01 D. Mosberger added ia32_load_segment_descriptors()
X */
X
X #include <linux/kernel.h>
X #include <linux/init.h>
X #include <linux/mm.h>
+#include <linux/personality.h>
X #include <linux/sched.h>
X
X #include <asm/page.h>
@@ -21,10 +24,46 @@
X #include <asm/processor.h>
X #include <asm/ia32.h>
X
-extern unsigned long *ia32_gdt_table, *ia32_tss;
-
X extern void die_if_kernel (char *str, struct pt_regs *regs, long err);
X
+struct exec_domain ia32_exec_domain;
+struct page *ia32_shared_page[(2*IA32_PAGE_SIZE + PAGE_SIZE - 1)/PAGE_SIZE];
+unsigned long *ia32_gdt;
+
+static unsigned long
+load_desc (u16 selector)
+{
+ unsigned long *table, limit, index;
+
+ if (!selector)
+ return 0;
+ if (selector & IA32_SEGSEL_TI) {
+ table = (unsigned long *) IA32_LDT_OFFSET;
+ limit = IA32_LDT_ENTRIES;
+ } else {
+ table = ia32_gdt;
+ limit = IA32_PAGE_SIZE / sizeof(ia32_gdt[0]);
+ }
+ index = selector >> IA32_SEGSEL_INDEX_SHIFT;
+ if (index >= limit)
+ return 0;
+ return IA32_SEG_UNSCRAMBLE(table[index]);
+}
+
+void
+ia32_load_segment_descriptors (struct task_struct *task)
+{
+ struct pt_regs *regs = ia64_task_regs(task);
+
+ /* Setup the segment descriptors */
+ regs->r24 = load_desc(regs->r16 >> 16); /* ESD */
+ regs->r27 = load_desc(regs->r16 >> 0); /* DSD */
+ regs->r28 = load_desc(regs->r16 >> 32); /* FSD */
+ regs->r29 = load_desc(regs->r16 >> 48); /* GSD */
+ task->thread.csd = load_desc(regs->r17 >> 0); /* CSD */
+ task->thread.ssd = load_desc(regs->r17 >> 16); /* SSD */
+}
+
X void
X ia32_save_state (struct task_struct *t)
X {
@@ -46,14 +85,17 @@
X t->thread.csd = csd;
X t->thread.ssd = ssd;
X ia64_set_kr(IA64_KR_IO_BASE, t->thread.old_iob);
+ ia64_set_kr(IA64_KR_TSSD, t->thread.old_k1);
X }
X
X void
X ia32_load_state (struct task_struct *t)
X {
- unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd;
+ unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd, tssd;
X struct pt_regs *regs = ia64_task_regs(t);
- int nr;
+ int nr = smp_processor_id(); /* LDT and TSS depend on CPU number: */
+
+ nr = smp_processor_id();
X
X eflag = t->thread.eflag;
X fsr = t->thread.fsr;
@@ -62,6 +104,7 @@
X fdr = t->thread.fdr;
X csd = t->thread.csd;
X ssd = t->thread.ssd;
+ tssd = load_desc(_TSS(nr)); /* TSSD */
X
X asm volatile ("mov ar.eflag=%0;"
X "mov ar.fsr=%1;"
@@ -72,11 +115,12 @@
X "mov ar.ssd=%6;"
X :: "r"(eflag), "r"(fsr), "r"(fcr), "r"(fir), "r"(fdr), "r"(csd), "r"(ssd));
X current->thread.old_iob = ia64_get_kr(IA64_KR_IO_BASE);
+ current->thread.old_k1 = ia64_get_kr(IA64_KR_TSSD);
X ia64_set_kr(IA64_KR_IO_BASE, IA32_IOBASE);
+ ia64_set_kr(IA64_KR_TSSD, tssd);
X
- /* load TSS and LDT while preserving SS and CS: */
- nr = smp_processor_id();
X regs->r17 = (_TSS(nr) << 48) | (_LDT(nr) << 32) | (__u32) regs->r17;
+ regs->r30 = load_desc(_LDT(nr)); /* LDTD */
X }
X
X /*
@@ -85,36 +129,34 @@
X void
X ia32_gdt_init (void)
X {
- unsigned long gdt_and_tss_page, ldt_size;
+ unsigned long *tss;
+ unsigned long ldt_size;
X int nr;
X
- /* allocate two IA-32 pages of memory: */
- gdt_and_tss_page = __get_free_pages(GFP_KERNEL,
- (IA32_PAGE_SHIFT < PAGE_SHIFT)
- ? 0 : (IA32_PAGE_SHIFT + 1) - PAGE_SHIFT);
- ia32_gdt_table = (unsigned long *) gdt_and_tss_page;
- ia32_tss = (unsigned long *) (gdt_and_tss_page + IA32_PAGE_SIZE);
-
- /* Zero the gdt and tss */
- memset((void *) gdt_and_tss_page, 0, 2*IA32_PAGE_SIZE);
+ ia32_shared_page[0] = alloc_page(GFP_KERNEL);
+ ia32_gdt = page_address(ia32_shared_page[0]);
+ tss = ia32_gdt + IA32_PAGE_SIZE/sizeof(ia32_gdt[0]);
+
+ if (IA32_PAGE_SIZE == PAGE_SIZE) {
+ ia32_shared_page[1] = alloc_page(GFP_KERNEL);
+ tss = page_address(ia32_shared_page[1]);
+ }
X
X /* CS descriptor in IA-32 (scrambled) format */
- ia32_gdt_table[__USER_CS >> 3] =
- IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET - 1) >> IA32_PAGE_SHIFT,
- 0xb, 1, 3, 1, 1, 1, 1);
+ ia32_gdt[__USER_CS >> 3] = IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET-1) >> IA32_PAGE_SHIFT,
+ 0xb, 1, 3, 1, 1, 1, 1);
X
X /* DS descriptor in IA-32 (scrambled) format */
- ia32_gdt_table[__USER_DS >> 3] =
- IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET - 1) >> IA32_PAGE_SHIFT,
- 0x3, 1, 3, 1, 1, 1, 1);
+ ia32_gdt[__USER_DS >> 3] = IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET-1) >> IA32_PAGE_SHIFT,
+ 0x3, 1, 3, 1, 1, 1, 1);
X
X /* We never change the TSS and LDT descriptors, so we can share them across all CPUs. */
X ldt_size = PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE);
X for (nr = 0; nr < NR_CPUS; ++nr) {
- ia32_gdt_table[_TSS(nr)] = IA32_SEG_DESCRIPTOR(IA32_TSS_OFFSET, 235,
- 0xb, 0, 3, 1, 1, 1, 0);
- ia32_gdt_table[_LDT(nr)] = IA32_SEG_DESCRIPTOR(IA32_LDT_OFFSET, ldt_size - 1,
- 0x2, 0, 3, 1, 1, 1, 0);
+ ia32_gdt[_TSS(nr)] = IA32_SEG_DESCRIPTOR(IA32_TSS_OFFSET, 235,
+ 0xb, 0, 3, 1, 1, 1, 0);
+ ia32_gdt[_LDT(nr)] = IA32_SEG_DESCRIPTOR(IA32_LDT_OFFSET, ldt_size - 1,
+ 0x2, 0, 3, 1, 1, 1, 0);
X }
X }
X
@@ -133,3 +175,18 @@
X siginfo.si_code = TRAP_BRKPT;
X force_sig_info(SIGTRAP, &siginfo, current);
X }
+
+static int __init
+ia32_init (void)
+{
+ ia32_exec_domain.name = "Linux/x86";
+ ia32_exec_domain.handler = NULL;
+ ia32_exec_domain.pers_low = PER_LINUX32;
+ ia32_exec_domain.pers_high = PER_LINUX32;
+ ia32_exec_domain.signal_map = default_exec_domain.signal_map;
+ ia32_exec_domain.signal_invmap = default_exec_domain.signal_invmap;
+ register_exec_domain(&ia32_exec_domain);


+ return 0;
+}
+

+__initcall(ia32_init);
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/ia32/ia32_traps.c linux/arch/ia64/ia32/ia32_traps.c
--- v2.4.14/linux/arch/ia64/ia32/ia32_traps.c Thu Jan 4 12:50:17 2001
+++ linux/arch/ia64/ia32/ia32_traps.c Fri Nov 9 14:26:17 2001
@@ -1,7 +1,12 @@
X /*
- * IA32 exceptions handler
+ * IA-32 exception handlers
+ *
+ * Copyright (C) 2000 Asit K. Mallick <asit.k....@intel.com>
+ * Copyright (C) 2001 Hewlett-Packard Co
+ * David Mosberger-Tang <dav...@hpl.hp.com>
X *
X * 06/16/00 A. Mallick added siginfo for most cases (close to IA32)
+ * 09/29/00 D. Mosberger added ia32_intercept()
X */
X
X #include <linux/kernel.h>
@@ -9,6 +14,26 @@
X
X #include <asm/ia32.h>
X #include <asm/ptrace.h>
+
+int
+ia32_intercept (struct pt_regs *regs, unsigned long isr)
+{
+ switch ((isr >> 16) & 0xff) {
+ case 0: /* Instruction intercept fault */
+ case 3: /* Locked Data reference fault */
+ case 1: /* Gate intercept trap */
+ return -1;
+
+ case 2: /* System flag trap */
+ if (((isr >> 14) & 0x3) >= 2) {
+ /* MOV SS, POP SS instructions */
+ ia64_psr(regs)->id = 1;
+ return 0;
+ } else
+ return -1;
+ }
+ return -1;
+}
X
X int
X ia32_exception (struct pt_regs *regs, unsigned long isr)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/ia32/sys_ia32.c linux/arch/ia64/ia32/sys_ia32.c
--- v2.4.14/linux/arch/ia64/ia32/sys_ia32.c Mon Aug 27 12:41:39 2001
+++ linux/arch/ia64/ia32/sys_ia32.c Fri Nov 9 14:26:17 2001
@@ -1,14 +1,13 @@
X /*
- * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Based on
- * sys_sparc32
+ * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Derived from sys_sparc32.c.
X *
X * Copyright (C) 2000 VA Linux Co
X * Copyright (C) 2000 Don Dugger <n0...@valinux.com>
X * Copyright (C) 1999 Arun Sharma <arun....@intel.com>
X * Copyright (C) 1997,1998 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
X * Copyright (C) 1997 David S. Miller (da...@caip.rutgers.edu)
- * Copyright (C) 2000 Hewlett-Packard Co.
- * Copyright (C) 2000 David Mosberger-Tang <dav...@hpl.hp.com>
+ * Copyright (C) 2000-2001 Hewlett-Packard Co
+ * David Mosberger-Tang <dav...@hpl.hp.com>
X *
X * These routines maintain argument size conversion between 32bit and 64bit
X * environment.
@@ -53,31 +52,56 @@
X #include <asm/types.h>
X #include <asm/uaccess.h>
X #include <asm/semaphore.h>
-#include <asm/ipc.h>
X
X #include <net/scm.h>
X #include <net/sock.h>
X #include <asm/ia32.h>
X
+#define DEBUG 0
+
+#if DEBUG
+# define DBG(fmt...) printk(KERN_DEBUG fmt)
+#else
+# define DBG(fmt...)
+#endif
+
X #define A(__x) ((unsigned long)(__x))
X #define AA(__x) ((unsigned long)(__x))
X #define ROUND_UP(x,a) ((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))
X #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
X
+#define OFFSET4K(a) ((a) & 0xfff)
+#define PAGE_START(addr) ((addr) & PAGE_MASK)
+#define PAGE_OFF(addr) ((addr) & ~PAGE_MASK)
+
X extern asmlinkage long sys_execve (char *, char **, char **, struct pt_regs *);
X extern asmlinkage long sys_mprotect (unsigned long, size_t, unsigned long);
+extern asmlinkage long sys_munmap (unsigned long, size_t);
+extern unsigned long arch_get_unmapped_area (struct file *, unsigned long, unsigned long,
+ unsigned long, unsigned long);
+
+/* forward declaration: */
+asmlinkage long sys32_mprotect (unsigned int, unsigned int, int);
+
+/*
+ * Anything that modifies or inspects ia32 user virtual memory must hold this semaphore
+ * while doing so.
+ */
+/* XXX make per-mm: */
+static DECLARE_MUTEX(ia32_mmap_sem);
X
X static int
X nargs (unsigned int arg, char **ap)
X {
- int n, err, addr;
+ unsigned int addr;
+ int n, err;
X
X if (!arg)
X return 0;
X
X n = 0;
X do {
- err = get_user(addr, (int *)A(arg));
+ err = get_user(addr, (unsigned int *)A(arg));
X if (err)
X return err;
X if (ap)
@@ -94,7 +118,7 @@
X int stack)
X {
X struct pt_regs *regs = (struct pt_regs *)&stack;
- unsigned long old_map_base, old_task_size;
+ unsigned long old_map_base, old_task_size, tssd;
X char **av, **ae;
X int na, ne, len;
X long r;
@@ -123,15 +147,20 @@
X
X old_map_base = current->thread.map_base;
X old_task_size = current->thread.task_size;
+ tssd = ia64_get_kr(IA64_KR_TSSD);
X
- /* we may be exec'ing a 64-bit process: reset map base & task-size: */
+ /* we may be exec'ing a 64-bit process: reset map base, task-size, and io-base: */
X current->thread.map_base = DEFAULT_MAP_BASE;
X current->thread.task_size = DEFAULT_TASK_SIZE;
+ ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob);
+ ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1);
X
X set_fs(KERNEL_DS);
X r = sys_execve(filename, av, ae, regs);
X if (r < 0) {
- /* oops, execve failed, switch back to old map base & task-size: */
+ /* oops, execve failed, switch back to old values... */
+ ia64_set_kr(IA64_KR_IO_BASE, IA32_IOBASE);
+ ia64_set_kr(IA64_KR_TSSD, tssd);
X current->thread.map_base = old_map_base;
X current->thread.task_size = old_task_size;
X set_fs(USER_DS); /* establish new task-size as the address-limit */
@@ -142,30 +171,33 @@
X }
X
X static inline int
-putstat(struct stat32 *ubuf, struct stat *kbuf)
+putstat (struct stat32 *ubuf, struct stat *kbuf)
X {
X int err;
X
- err = put_user (kbuf->st_dev, &ubuf->st_dev);
- err |= __put_user (kbuf->st_ino, &ubuf->st_ino);
- err |= __put_user (kbuf->st_mode, &ubuf->st_mode);
- err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink);
- err |= __put_user (kbuf->st_uid, &ubuf->st_uid);
- err |= __put_user (kbuf->st_gid, &ubuf->st_gid);
- err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev);
- err |= __put_user (kbuf->st_size, &ubuf->st_size);
- err |= __put_user (kbuf->st_atime, &ubuf->st_atime);
- err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime);
- err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime);
- err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize);
- err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks);
+ if (clear_user(ubuf, sizeof(*ubuf)))
+ return 1;
+
+ err = __put_user(kbuf->st_dev, &ubuf->st_dev);
+ err |= __put_user(kbuf->st_ino, &ubuf->st_ino);
+ err |= __put_user(kbuf->st_mode, &ubuf->st_mode);
+ err |= __put_user(kbuf->st_nlink, &ubuf->st_nlink);
+ err |= __put_user(kbuf->st_uid, &ubuf->st_uid);
+ err |= __put_user(kbuf->st_gid, &ubuf->st_gid);
+ err |= __put_user(kbuf->st_rdev, &ubuf->st_rdev);
+ err |= __put_user(kbuf->st_size, &ubuf->st_size);
+ err |= __put_user(kbuf->st_atime, &ubuf->st_atime);
+ err |= __put_user(kbuf->st_mtime, &ubuf->st_mtime);
+ err |= __put_user(kbuf->st_ctime, &ubuf->st_ctime);
+ err |= __put_user(kbuf->st_blksize, &ubuf->st_blksize);
+ err |= __put_user(kbuf->st_blocks, &ubuf->st_blocks);
X return err;
X }
X
-extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
+extern asmlinkage long sys_newstat (char * filename, struct stat * statbuf);
X
X asmlinkage long
-sys32_newstat(char * filename, struct stat32 *statbuf)
+sys32_newstat (char *filename, struct stat32 *statbuf)
X {
X int ret;
X struct stat s;


@@ -173,8 +205,8 @@
X

X set_fs(KERNEL_DS);
X ret = sys_newstat(filename, &s);
- set_fs (old_fs);
- if (putstat (statbuf, &s))
+ set_fs(old_fs);
+ if (putstat(statbuf, &s))
X return -EFAULT;
X return ret;
X }
@@ -182,16 +214,16 @@
X extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
X
X asmlinkage long
-sys32_newlstat(char * filename, struct stat32 *statbuf)
+sys32_newlstat (char *filename, struct stat32 *statbuf)
X {
- int ret;
- struct stat s;
X mm_segment_t old_fs = get_fs();
+ struct stat s;
+ int ret;
X
- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
X ret = sys_newlstat(filename, &s);
- set_fs (old_fs);
- if (putstat (statbuf, &s))
+ set_fs(old_fs);
+ if (putstat(statbuf, &s))
X return -EFAULT;
X return ret;
X }
@@ -199,112 +231,249 @@
X extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
X
X asmlinkage long
-sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
+sys32_newfstat (unsigned int fd, struct stat32 *statbuf)
X {
- int ret;
- struct stat s;
X mm_segment_t old_fs = get_fs();
+ struct stat s;
+ int ret;
X
- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
X ret = sys_newfstat(fd, &s);
- set_fs (old_fs);
- if (putstat (statbuf, &s))
+ set_fs(old_fs);
+ if (putstat(statbuf, &s))
X return -EFAULT;
X return ret;
X }
X
-#define OFFSET4K(a) ((a) & 0xfff)
+#if PAGE_SHIFT > IA32_PAGE_SHIFT
X
-unsigned long
-do_mmap_fake(struct file *file, unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags, loff_t off)
+
+static int
+get_page_prot (unsigned long addr)
+{
+ struct vm_area_struct *vma = find_vma(current->mm, addr);
+ int prot = 0;
+
+ if (!vma || vma->vm_start > addr)
+ return 0;
+
+ if (vma->vm_flags & VM_READ)
+ prot |= PROT_READ;
+ if (vma->vm_flags & VM_WRITE)
+ prot |= PROT_WRITE;
+ if (vma->vm_flags & VM_EXEC)
+ prot |= PROT_EXEC;
+ return prot;
+}
+
+/*
+ * Map a subpage by creating an anonymous page that contains the union of the old page and
+ * the subpage.
+ */
+static unsigned long
+mmap_subpage (struct file *file, unsigned long start, unsigned long end, int prot, int flags,
+ loff_t off)
X {
+ void *page = (void *) get_zeroed_page(GFP_KERNEL);
X struct inode *inode;
- void *front, *back;
- unsigned long baddr;
- int r;
- char c;
+ unsigned long ret;
+ int old_prot = get_page_prot(start);
X
- if (OFFSET4K(addr) || OFFSET4K(off))
- return -EINVAL;
- prot |= PROT_WRITE;
- front = NULL;
- back = NULL;
- if ((baddr = (addr & PAGE_MASK)) != addr && get_user(c, (char *)baddr) == 0) {
- front = kmalloc(addr - baddr, GFP_KERNEL);
- if (!front)
- return -ENOMEM;
- __copy_user(front, (void *)baddr, addr - baddr);
+ DBG("mmap_subpage(file=%p,start=0x%lx,end=0x%lx,prot=%x,flags=%x,off=0x%llx)\n",
+ file, start, end, prot, flags, off);
+
+ if (!page)
+ return -ENOMEM;
+
+ if (old_prot)
+ copy_from_user(page, (void *) PAGE_START(start), PAGE_SIZE);
+
+ down_write(&current->mm->mmap_sem);
+ {
+ ret = do_mmap(0, PAGE_START(start), PAGE_SIZE, prot | PROT_WRITE,
+ flags | MAP_FIXED | MAP_ANONYMOUS, 0);
X }
- if (addr && ((addr + len) & ~PAGE_MASK) && get_user(c, (char *)(addr + len)) == 0) {
- back = kmalloc(PAGE_SIZE - ((addr + len) & ~PAGE_MASK), GFP_KERNEL);
- if (!back) {
- if (front)
- kfree(front);
- return -ENOMEM;
+ up_write(&current->mm->mmap_sem);
+
+ if (IS_ERR((void *) ret))
+ goto out;
+
+ if (old_prot) {
+ /* copy back the old page contents. */
+ if (PAGE_OFF(start))
+ copy_to_user((void *) PAGE_START(start), page, PAGE_OFF(start));
+ if (PAGE_OFF(end))
+ copy_to_user((void *) end, page + PAGE_OFF(end),
+ PAGE_SIZE - PAGE_OFF(end));
+ }
+ if (!(flags & MAP_ANONYMOUS)) {
+ /* read the file contents */
+ inode = file->f_dentry->d_inode;
+ if (!inode->i_fop || !file->f_op->read
+ || ((*file->f_op->read)(file, (char *) start, end - start, &off) < 0))
+ {
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+ if (!(prot & PROT_WRITE))
+ ret = sys_mprotect(PAGE_START(start), PAGE_SIZE, prot | old_prot);
+ out:
+ free_page((unsigned long) page);
+ return ret;
+}
+
+static unsigned long
+emulate_mmap (struct file *file, unsigned long start, unsigned long len, int prot, int flags,
+ loff_t off)
+{
+ unsigned long tmp, end, pend, pstart, ret, is_congruent, fudge = 0;
+ struct inode *inode;
+ loff_t poff;
+
+ end = start + len;
+ pstart = PAGE_START(start);
+ pend = PAGE_ALIGN(end);
+
+ if (flags & MAP_FIXED) {
+ if (start > pstart) {
+ if (flags & MAP_SHARED)
+ printk(KERN_INFO
+ "%s(%d): emulate_mmap() can't share head (addr=0x%lx)\n",
+ current->comm, current->pid, start);
+ ret = mmap_subpage(file, start, min(PAGE_ALIGN(start), end), prot, flags,
+ off);
+ if (IS_ERR((void *) ret))
+ return ret;
+ pstart += PAGE_SIZE;
+ if (pstart >= pend)
+ return start; /* done */
+ }
+ if (end < pend) {
+ if (flags & MAP_SHARED)
+ printk(KERN_INFO
+ "%s(%d): emulate_mmap() can't share tail (end=0x%lx)\n",
+ current->comm, current->pid, end);
+ ret = mmap_subpage(file, max(start, PAGE_START(end)), end, prot, flags,
+ (off + len) - PAGE_OFF(end));
+ if (IS_ERR((void *) ret))
+ return ret;
+ pend -= PAGE_SIZE;
+ if (pstart >= pend)
+ return start; /* done */
+ }
+ } else {
+ /*
+ * If a start address was specified, use it if the entire rounded out area
+ * is available.
+ */
+ if (start && !pstart)
+ fudge = 1; /* handle case of mapping to range (0,PAGE_SIZE) */
+ tmp = arch_get_unmapped_area(file, pstart - fudge, pend - pstart, 0, flags);
+ if (tmp != pstart) {
+ pstart = tmp;
+ start = pstart + PAGE_OFF(off); /* make start congruent with off */
+ end = start + len;
+ pend = PAGE_ALIGN(end);
X }
- __copy_user(back, (char *)addr + len, PAGE_SIZE - ((addr + len) & ~PAGE_MASK));
X }
+
+ poff = off + (pstart - start); /* note: (pstart - start) may be negative */
+ is_congruent = (flags & MAP_ANONYMOUS) || (PAGE_OFF(poff) == 0);
+
+ if ((flags & MAP_SHARED) && !is_congruent)
+ printk(KERN_INFO "%s(%d): emulate_mmap() can't share contents of incongruent mmap "
+ "(addr=0x%lx,off=0x%llx)\n", current->comm, current->pid, start, off);
+
+ DBG("mmap_body: mapping [0x%lx-0x%lx) %s with poff 0x%llx\n", pstart, pend,
+ is_congruent ? "congruent" : "not congruent", poff);
+
X down_write(&current->mm->mmap_sem);
- r = do_mmap(0, baddr, len + (addr - baddr), prot, flags | MAP_ANONYMOUS, 0);
+ {
+ if (!(flags & MAP_ANONYMOUS) && is_congruent)
+ ret = do_mmap(file, pstart, pend - pstart, prot, flags | MAP_FIXED, poff);
+ else
+ ret = do_mmap(0, pstart, pend - pstart,
+ prot | ((flags & MAP_ANONYMOUS) ? 0 : PROT_WRITE),
+ flags | MAP_FIXED | MAP_ANONYMOUS, 0);
+ }
X up_write(&current->mm->mmap_sem);
- if (r < 0)
- return(r);
- if (addr == 0)
- addr = r;
- if (back) {
- __copy_user((char *)addr + len, back, PAGE_SIZE - ((addr + len) & ~PAGE_MASK));
- kfree(back);
- }
- if (front) {
- __copy_user((void *)baddr, front, addr - baddr);
- kfree(front);
- }
- if (flags & MAP_ANONYMOUS) {
- clear_user((char *)addr, len);
- return(addr);
+
+ if (IS_ERR((void *) ret))
+ return ret;
+
+ if (!is_congruent) {
+ /* read the file contents */
+ inode = file->f_dentry->d_inode;
+ if (!inode->i_fop || !file->f_op->read
+ || ((*file->f_op->read)(file, (char *) pstart, pend - pstart, &poff) < 0))
+ {
+ sys_munmap(pstart, pend - pstart);
+ return -EINVAL;
+ }
+ if (!(prot & PROT_WRITE) && sys_mprotect(pstart, pend - pstart, prot) < 0)
+ return EINVAL;
X }
- if (!file)
- return -EINVAL;
- inode = file->f_dentry->d_inode;
- if (!inode->i_fop)
- return -EINVAL;
- if (!file->f_op->read)
- return -EINVAL;
- r = file->f_op->read(file, (char *)addr, len, &off);
- return (r < 0) ? -EINVAL : addr;
+ return start;
X }
X
-long
-ia32_do_mmap (struct file *file, unsigned int addr, unsigned int len, unsigned int prot,
- unsigned int flags, unsigned int fd, unsigned int offset)
+#endif /* PAGE_SHIFT > IA32_PAGE_SHIFT */
+
+static inline unsigned int
+get_prot32 (unsigned int prot)
X {
- long error = -EFAULT;
- unsigned int poff;
+ if (prot & PROT_WRITE)
+ /* on x86, PROT_WRITE implies PROT_READ which implies PROT_EEC */
+ prot |= PROT_READ | PROT_WRITE | PROT_EXEC;
+ else if (prot & (PROT_READ | PROT_EXEC))
+ /* on x86, there is no distinction between PROT_READ and PROT_EXEC */
+ prot |= (PROT_READ | PROT_EXEC);
X
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- prot |= PROT_EXEC;
+ return prot;
+}
X
- if ((flags & MAP_FIXED) && ((addr & ~PAGE_MASK) || (offset & ~PAGE_MASK)))
- error = do_mmap_fake(file, addr, len, prot, flags, (loff_t)offset);
- else {
- poff = offset & PAGE_MASK;
- len += offset - poff;
+unsigned long
+ia32_do_mmap (struct file *file, unsigned long addr, unsigned long len, int prot, int flags,
+ loff_t offset)
+{
+ DBG("ia32_do_mmap(file=%p,addr=0x%lx,len=0x%lx,prot=%x,flags=%x,offset=0x%llx)\n",
+ file, addr, len, prot, flags, offset);
+
+ if (file && (!file->f_op || !file->f_op->mmap))
+ return -ENODEV;
+
+ len = IA32_PAGE_ALIGN(len);
+ if (len == 0)
+ return addr;
+
+ if (len > IA32_PAGE_OFFSET || addr > IA32_PAGE_OFFSET - len)
+ return -EINVAL;
+
+ if (OFFSET4K(offset))
+ return -EINVAL;
X
- down_write(&current->mm->mmap_sem);
- error = do_mmap_pgoff(file, addr, len, prot, flags, poff >> PAGE_SHIFT);
- up_write(&current->mm->mmap_sem);
+ prot = get_prot32(prot);
X
- if (!IS_ERR((void *) error))
- error += offset - poff;
+#if PAGE_SHIFT > IA32_PAGE_SHIFT
+ down(&ia32_mmap_sem);
+ {
+ addr = emulate_mmap(file, addr, len, prot, flags, offset);
X }
- return error;
+ up(&ia32_mmap_sem);
+#else
+ down_write(&current->mm->mmap_sem);
+ {
+ addr = do_mmap(file, addr, len, prot, flags, offset);
+ }
+ up_write(&current->mm->mmap_sem);
+#endif
+ DBG("ia32_do_mmap: returning 0x%lx\n", addr);
+ return addr;
X }
X
X /*
- * Linux/i386 didn't use to be able to handle more than
- * 4 system call parameters, so these system calls used a memory
- * block for parameter passing..
+ * Linux/i386 didn't use to be able to handle more than 4 system call parameters, so these
+ * system calls used a memory block for parameter passing..
X */
X
X struct mmap_arg_struct {
@@ -317,180 +486,166 @@
X };
X
X asmlinkage long
-sys32_mmap(struct mmap_arg_struct *arg)
+sys32_mmap (struct mmap_arg_struct *arg)
X {
X struct mmap_arg_struct a;
X struct file *file = NULL;
- long retval;
+ unsigned long addr;
+ int flags;
X
X if (copy_from_user(&a, arg, sizeof(a)))
X return -EFAULT;
X
- if (PAGE_ALIGN(a.len) == 0)
- return a.addr;
+ if (OFFSET4K(a.offset))
+ return -EINVAL;
+
+ flags = a.flags;
X
- if (!(a.flags & MAP_ANONYMOUS)) {
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
X file = fget(a.fd);
X if (!file)
X return -EBADF;
X }
-#ifdef CONFIG_IA64_PAGE_SIZE_4KB
- if ((a.offset & ~PAGE_MASK) != 0)
- return -EINVAL;
X
- down_write(&current->mm->mmap_sem);
- retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, a.offset >> PAGE_SHIFT);
- up_write(&current->mm->mmap_sem);
-#else
- retval = ia32_do_mmap(file, a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
-#endif
+ addr = ia32_do_mmap(file, a.addr, a.len, a.prot, flags, a.offset);
+
X if (file)
X fput(file);
- return retval;
+ return addr;
X }
X
X asmlinkage long
-sys32_mprotect(unsigned long start, size_t len, unsigned long prot)
+sys32_mmap2 (unsigned int addr, unsigned int len, unsigned int prot, unsigned int flags,
+ unsigned int fd, unsigned int pgoff)
X {
+ struct file *file = NULL;
+ unsigned long retval;
X
-#ifdef CONFIG_IA64_PAGE_SIZE_4KB
- return(sys_mprotect(start, len, prot));
-#else // CONFIG_IA64_PAGE_SIZE_4KB
- if (prot == 0)
- return(0);
- len += start & ~PAGE_MASK;
- if ((start & ~PAGE_MASK) && (prot & PROT_WRITE))
- prot |= PROT_EXEC;
- return(sys_mprotect(start & PAGE_MASK, len & PAGE_MASK, prot));
-#endif // CONFIG_IA64_PAGE_SIZE_4KB
-}
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
+ file = fget(fd);
+ if (!file)
+ return -EBADF;
+ }
X
-asmlinkage long
-sys32_pipe(int *fd)
-{
- int retval;
- int fds[2];
+ retval = ia32_do_mmap(file, addr, len, prot, flags,
+ (unsigned long) pgoff << IA32_PAGE_SHIFT);
X
- retval = do_pipe(fds);
- if (retval)
- goto out;
- if (copy_to_user(fd, fds, sizeof(fds)))
- retval = -EFAULT;
- out:
+ if (file)
+ fput(file);
X return retval;
X }
X
X asmlinkage long
-sys32_signal (int sig, unsigned int handler)
+sys32_munmap (unsigned int start, unsigned int len)
X {
- struct k_sigaction new_sa, old_sa;
- int ret;
+ unsigned int end = start + len;
+ long ret;
+
+#if PAGE_SHIFT <= IA32_PAGE_SHIFT
+ ret = sys_munmap(start, end - start);
+#else
+ if (start > end)
+ return -EINVAL;
+
+ start = PAGE_ALIGN(start);
+ end = PAGE_START(end);
+
+ if (start >= end)
+ return 0;
+
+ down(&ia32_mmap_sem);
+ {
+ ret = sys_munmap(start, end - start);
+ }
+ up(&ia32_mmap_sem);
+#endif
+ return ret;
+}
X
- new_sa.sa.sa_handler = (__sighandler_t) A(handler);
- new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK;
+#if PAGE_SHIFT > IA32_PAGE_SHIFT
+
+/*
+ * When mprotect()ing a partial page, we set the permission to the union of the old
+ * settings and the new settings. In other words, it's only possible to make access to a
+ * partial page less restrictive.
+ */
+static long
+mprotect_subpage (unsigned long address, int new_prot)
+{
+ int old_prot;
X
- ret = do_sigaction(sig, &new_sa, &old_sa);
+ if (new_prot == PROT_NONE)
+ return 0; /* optimize case where nothing changes... */
X
- return ret ? ret : (unsigned long)old_sa.sa.sa_handler;
+ old_prot = get_page_prot(address);
+ return sys_mprotect(address, PAGE_SIZE, new_prot | old_prot);
X }
X
+#endif /* PAGE_SHIFT > IA32_PAGE_SHIFT */
+
X asmlinkage long
-sys32_rt_sigaction(int sig, struct sigaction32 *act,
- struct sigaction32 *oact, unsigned int sigsetsize)
+sys32_mprotect (unsigned int start, unsigned int len, int prot)
X {
- struct k_sigaction new_ka, old_ka;
- int ret;
- sigset32_t set32;
+ unsigned long end = start + len;
+#if PAGE_SHIFT > IA32_PAGE_SHIFT
+ long retval = 0;
+#endif
+
+ prot = get_prot32(prot);
X
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset32_t))
+#if PAGE_SHIFT <= IA32_PAGE_SHIFT
+ return sys_mprotect(start, end - start, prot);
+#else
+ if (OFFSET4K(start))
X return -EINVAL;
X
- if (act) {
- ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
- ret |= __copy_from_user(&set32, &act->sa_mask,
- sizeof(sigset32_t));
- switch (_NSIG_WORDS) {
- case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]
- | (((long)set32.sig[7]) << 32);
- case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]
- | (((long)set32.sig[5]) << 32);
- case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]
- | (((long)set32.sig[3]) << 32);
- case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]
- | (((long)set32.sig[1]) << 32);
- }
- ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ end = IA32_PAGE_ALIGN(end);
+ if (end < start)
+ return -EINVAL;
X
- if (ret)
- return -EFAULT;
- }
+ down(&ia32_mmap_sem);
+ {
+ if (PAGE_OFF(start)) {
+ /* start address is 4KB aligned but not page aligned. */
+ retval = mprotect_subpage(PAGE_START(start), prot);
+ if (retval < 0)
+ goto out;
X
- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+ start = PAGE_ALIGN(start);
+ if (start >= end)
+ goto out; /* retval is already zero... */
+ }
X
- if (!ret && oact) {
- switch (_NSIG_WORDS) {
- case 4:
- set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);
- set32.sig[6] = old_ka.sa.sa_mask.sig[3];
- case 3:
- set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);
- set32.sig[4] = old_ka.sa.sa_mask.sig[2];
- case 2:
- set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);
- set32.sig[2] = old_ka.sa.sa_mask.sig[1];
- case 1:
- set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
- set32.sig[0] = old_ka.sa.sa_mask.sig[0];
+ if (PAGE_OFF(end)) {
+ /* end address is 4KB aligned but not page aligned. */
+ retval = mprotect_subpage(PAGE_START(end), prot);
+ if (retval < 0)
+ return retval;
+ end = PAGE_START(end);
X }
- ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
- ret |= __copy_to_user(&oact->sa_mask, &set32,
- sizeof(sigset32_t));
- ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ retval = sys_mprotect(start, end - start, prot);
X }
-
- return ret;
+ out:
+ up(&ia32_mmap_sem);
+ return retval;
+#endif
X }
X
-
-extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset,
- size_t sigsetsize);
-
X asmlinkage long
-sys32_rt_sigprocmask(int how, sigset32_t *set, sigset32_t *oset,
- unsigned int sigsetsize)
+sys32_pipe (int *fd)
X {
- sigset_t s;
- sigset32_t s32;
- int ret;
- mm_segment_t old_fs = get_fs();
+ int retval;
+ int fds[2];
X
- if (set) {
- if (copy_from_user (&s32, set, sizeof(sigset32_t)))
- return -EFAULT;
- switch (_NSIG_WORDS) {
- case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
- case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
- case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
- case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
- }
- }
- set_fs (KERNEL_DS);
- ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL,
- sigsetsize);
- set_fs (old_fs);
- if (ret) return ret;
- if (oset) {
- switch (_NSIG_WORDS) {
- case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
- case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
- case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
- case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
- }
- if (copy_to_user (oset, &s32, sizeof(sigset32_t)))
- return -EFAULT;
- }
- return 0;
+ retval = do_pipe(fds);
+ if (retval)
+ goto out;
+ if (copy_to_user(fd, fds, sizeof(fds)))
+ retval = -EFAULT;
+ out:
+ return retval;
X }
X
X static inline int
@@ -498,31 +653,34 @@
X {
X int err;
X
- err = put_user (kbuf->f_type, &ubuf->f_type);
- err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize);
- err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks);
- err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree);
- err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail);
- err |= __put_user (kbuf->f_files, &ubuf->f_files);
- err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree);
- err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen);
- err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
- err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
+ if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
+ return -EFAULT;
+
+ err = __put_user(kbuf->f_type, &ubuf->f_type);
+ err |= __put_user(kbuf->f_bsize, &ubuf->f_bsize);
+ err |= __put_user(kbuf->f_blocks, &ubuf->f_blocks);
+ err |= __put_user(kbuf->f_bfree, &ubuf->f_bfree);
+ err |= __put_user(kbuf->f_bavail, &ubuf->f_bavail);
+ err |= __put_user(kbuf->f_files, &ubuf->f_files);
+ err |= __put_user(kbuf->f_ffree, &ubuf->f_ffree);
+ err |= __put_user(kbuf->f_namelen, &ubuf->f_namelen);
+ err |= __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
+ err |= __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
X return err;
X }
X
X extern asmlinkage long sys_statfs(const char * path, struct statfs * buf);
X
X asmlinkage long
-sys32_statfs(const char * path, struct statfs32 *buf)
+sys32_statfs (const char *path, struct statfs32 *buf)
X {
X int ret;
X struct statfs s;
X mm_segment_t old_fs = get_fs();
X
- set_fs (KERNEL_DS);
- ret = sys_statfs((const char *)path, &s);
- set_fs (old_fs);
+ set_fs(KERNEL_DS);
+ ret = sys_statfs(path, &s);
+ set_fs(old_fs);
X if (put_statfs(buf, &s))
X return -EFAULT;
X return ret;
@@ -531,15 +689,15 @@
X extern asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf);
X
X asmlinkage long
-sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
+sys32_fstatfs (unsigned int fd, struct statfs32 *buf)
X {
X int ret;
X struct statfs s;
X mm_segment_t old_fs = get_fs();
X
- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
X ret = sys_fstatfs(fd, &s);
- set_fs (old_fs);
+ set_fs(old_fs);
X if (put_statfs(buf, &s))
X return -EFAULT;
X return ret;
@@ -557,23 +715,21 @@
X };
X
X static inline long
-get_tv32(struct timeval *o, struct timeval32 *i)
+get_tv32 (struct timeval *o, struct timeval32 *i)
X {
X return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
- (__get_user(o->tv_sec, &i->tv_sec) |
- __get_user(o->tv_usec, &i->tv_usec)));
+ (__get_user(o->tv_sec, &i->tv_sec) | __get_user(o->tv_usec, &i->tv_usec)));
X }
X
X static inline long
-put_tv32(struct timeval32 *o, struct timeval *i)
+put_tv32 (struct timeval32 *o, struct timeval *i)
X {
X return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
- (__put_user(i->tv_sec, &o->tv_sec) |
- __put_user(i->tv_usec, &o->tv_usec)));
+ (__put_user(i->tv_sec, &o->tv_sec) | __put_user(i->tv_usec, &o->tv_usec)));
X }
X
X static inline long
-get_it32(struct itimerval *o, struct itimerval32 *i)
+get_it32 (struct itimerval *o, struct itimerval32 *i)
X {
X return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
X (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
@@ -583,7 +739,7 @@
X }
X
X static inline long
-put_it32(struct itimerval32 *o, struct itimerval *i)
+put_it32 (struct itimerval32 *o, struct itimerval *i)
X {
X return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
X (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
@@ -592,10 +748,10 @@
X __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
X }
X
-extern int do_getitimer(int which, struct itimerval *value);
+extern int do_getitimer (int which, struct itimerval *value);
X
X asmlinkage long
-sys32_getitimer(int which, struct itimerval32 *it)
+sys32_getitimer (int which, struct itimerval32 *it)
X {
X struct itimerval kit;
X int error;
@@ -607,10 +763,10 @@
X return error;
X }
X
-extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
+extern int do_setitimer (int which, struct itimerval *, struct itimerval *);
X
X asmlinkage long
-sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
+sys32_setitimer (int which, struct itimerval32 *in, struct itimerval32 *out)
X {
X struct itimerval kin, kout;
X int error;
@@ -630,8 +786,9 @@


X return 0;
X
X }

+
X asmlinkage unsigned long
-sys32_alarm(unsigned int seconds)
+sys32_alarm (unsigned int seconds)
X {
X struct itimerval it_new, it_old;
X unsigned int oldalarm;
@@ -660,7 +817,7 @@
X extern asmlinkage long sys_gettimeofday (struct timeval *tv, struct timezone *tz);
X
X asmlinkage long
-ia32_utime(char * filename, struct utimbuf_32 *times32)
+sys32_utime (char *filename, struct utimbuf_32 *times32)
X {
X mm_segment_t old_fs = get_fs();
X struct timeval tv[2], *tvp;
@@ -673,20 +830,20 @@
X if (get_user(tv[1].tv_sec, &times32->mtime))
X return -EFAULT;
X tv[1].tv_usec = 0;
- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
X tvp = tv;
X } else
X tvp = NULL;
X ret = sys_utimes(filename, tvp);
- set_fs (old_fs);
+ set_fs(old_fs);
X return ret;
X }
X
X extern struct timezone sys_tz;
-extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
+extern int do_sys_settimeofday (struct timeval *tv, struct timezone *tz);
X
X asmlinkage long
-sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
+sys32_gettimeofday (struct timeval32 *tv, struct timezone *tz)
X {
X if (tv) {
X struct timeval ktv;
@@ -702,7 +859,7 @@
X }
X
X asmlinkage long
-sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
+sys32_settimeofday (struct timeval32 *tv, struct timezone *tz)
X {
X struct timeval ktv;
X struct timezone ktz;
@@ -719,20 +876,6 @@
X return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
X }
X
-struct linux32_dirent {
- u32 d_ino;
- u32 d_off;
- u16 d_reclen;
- char d_name[1];
-};
-
-struct old_linux32_dirent {
- u32 d_ino;
- u32 d_offset;
- u16 d_namlen;
- char d_name[1];
-};
-
X struct getdents32_callback {
X struct linux32_dirent * current_dir;
X struct linux32_dirent * previous;
@@ -775,7 +918,7 @@
X }
X
X asmlinkage long
-sys32_getdents (unsigned int fd, void * dirent, unsigned int count)
+sys32_getdents (unsigned int fd, struct linux32_dirent *dirent, unsigned int count)
X {
X struct file * file;
X struct linux32_dirent * lastdirent;
@@ -787,7 +930,7 @@
X if (!file)
X goto out;
X
- buf.current_dir = (struct linux32_dirent *) dirent;
+ buf.current_dir = dirent;
X buf.previous = NULL;
X buf.count = count;


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

echo 'End of part 026'
echo 'File patch-2.4.15 is continued in part 027'
echo "027" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:04 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part028

#!/bin/sh -x
# this is part 028 of a 115 - part archive


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

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

+static void
+put_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp,
+ int tos)
X {
X struct _fpreg_ia32 *f;
X char buf[32];
@@ -2242,62 +2866,59 @@
X if ((regno += tos) >= 8)
X regno -= 8;
X switch (regno) {
-
- case 0:
+ case 0:
X ia64f2ia32f(f, &ptp->f8);
X break;
- case 1:
+ case 1:
X ia64f2ia32f(f, &ptp->f9);
X break;
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
X ia64f2ia32f(f, &swp->f10 + (regno - 2));
X break;
-
X }
- __copy_to_user(reg, f, sizeof(*reg));
+ copy_to_user(reg, f, sizeof(*reg));
X }
X
-void
-get_fpreg(int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp, int tos)
+static void
+get_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp,
+ int tos)
X {
X
X if ((regno += tos) >= 8)
X regno -= 8;
X switch (regno) {
-
- case 0:
- __copy_from_user(&ptp->f8, reg, sizeof(*reg));
+ case 0:
+ copy_from_user(&ptp->f8, reg, sizeof(*reg));
X break;
- case 1:
- __copy_from_user(&ptp->f9, reg, sizeof(*reg));
+ case 1:
+ copy_from_user(&ptp->f9, reg, sizeof(*reg));
X break;
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- __copy_from_user(&swp->f10 + (regno - 2), reg, sizeof(*reg));
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ copy_from_user(&swp->f10 + (regno - 2), reg, sizeof(*reg));
X break;
-
X }
X return;
X }
X
-int
-save_ia32_fpstate(struct task_struct *tsk, struct _fpstate_ia32 *save)
+static int
+save_ia32_fpstate (struct task_struct *tsk, struct _fpstate_ia32 *save)
X {
X struct switch_stack *swp;
X struct pt_regs *ptp;
X int i, tos;
X
X if (!access_ok(VERIFY_WRITE, save, sizeof(*save)))
- return(-EIO);
+ return -EIO;
X __put_user(tsk->thread.fcr, &save->cw);
X __put_user(tsk->thread.fsr, &save->sw);
X __put_user(tsk->thread.fsr >> 32, &save->tag);
@@ -2313,11 +2934,11 @@
X tos = (tsk->thread.fsr >> 11) & 3;
X for (i = 0; i < 8; i++)
X put_fpreg(i, &save->_st[i], ptp, swp, tos);
- return(0);


+ return 0;
X }
X

-int
-restore_ia32_fpstate(struct task_struct *tsk, struct _fpstate_ia32 *save)
+static int
+restore_ia32_fpstate (struct task_struct *tsk, struct _fpstate_ia32 *save)
X {
X struct switch_stack *swp;
X struct pt_regs *ptp;
@@ -2340,10 +2961,11 @@
X tos = (tsk->thread.fsr >> 11) & 3;
X for (i = 0; i < 8; i++)
X get_fpreg(i, &save->_st[i], ptp, swp, tos);
- return(ret ? -EFAULT : 0);
+ return ret ? -EFAULT : 0;
X }
X
-asmlinkage long sys_ptrace(long, pid_t, unsigned long, unsigned long, long, long, long, long, long);
+extern asmlinkage long sys_ptrace (long, pid_t, unsigned long, unsigned long, long, long, long,
+ long, long);
X
X /*
X * Note that the IA32 version of `ptrace' calls the IA64 routine for
@@ -2358,13 +2980,12 @@


X {
X struct pt_regs *regs = (struct pt_regs *) &stack;

X struct task_struct *child;
+ unsigned int value, tmp;
X long i, ret;
- unsigned int value;
X
X lock_kernel();
X if (request == PTRACE_TRACEME) {
- ret = sys_ptrace(request, pid, addr, data,
- arg4, arg5, arg6, arg7, stack);
+ ret = sys_ptrace(request, pid, addr, data, arg4, arg5, arg6, arg7, stack);
X goto out;
X }
X
@@ -2379,8 +3000,7 @@
X goto out;
X
X if (request == PTRACE_ATTACH) {
- ret = sys_ptrace(request, pid, addr, data,
- arg4, arg5, arg6, arg7, stack);
+ ret = sys_ptrace(request, pid, addr, data, arg4, arg5, arg6, arg7, stack);
X goto out;
X }
X ret = -ESRCH;
@@ -2398,21 +3018,32 @@
X case PTRACE_PEEKDATA: /* read word at location addr */
X ret = ia32_peek(regs, child, addr, &value);
X if (ret == 0)
- ret = put_user(value, (unsigned int *)A(data));
+ ret = put_user(value, (unsigned int *) A(data));
X else
X ret = -EIO;
X goto out;
X
X case PTRACE_POKETEXT:
X case PTRACE_POKEDATA: /* write the word at location addr */
- ret = ia32_poke(regs, child, addr, (unsigned int)data);
+ ret = ia32_poke(regs, child, addr, data);
X goto out;
X
X case PTRACE_PEEKUSR: /* read word at addr in USER area */
- ret = 0;
+ ret = -EIO;
+ if ((addr & 3) || addr > 17*sizeof(int))
+ break;
+
+ tmp = getreg(child, addr);
+ if (!put_user(tmp, (unsigned int *) A(data)))
+ ret = 0;
X break;
X
X case PTRACE_POKEUSR: /* write word at addr in USER area */
+ ret = -EIO;
+ if ((addr & 3) || addr > 17*sizeof(int))
+ break;
+
+ putreg(child, addr, data);
X ret = 0;
X break;
X
@@ -2421,28 +3052,25 @@
X ret = -EIO;
X break;
X }
- for ( i = 0; i < 17*sizeof(int); i += sizeof(int) ) {
- __put_user(getreg(child, i), (unsigned int *) A(data));
+ for (i = 0; i < 17*sizeof(int); i += sizeof(int) ) {
+ put_user(getreg(child, i), (unsigned int *) A(data));
X data += sizeof(int);
X }
X ret = 0;
X break;
X
X case IA32_PTRACE_SETREGS:
- {
- unsigned int tmp;
X if (!access_ok(VERIFY_READ, (int *) A(data), 17*sizeof(int))) {
X ret = -EIO;
X break;
X }
- for ( i = 0; i < 17*sizeof(int); i += sizeof(int) ) {
- __get_user(tmp, (unsigned int *) A(data));
+ for (i = 0; i < 17*sizeof(int); i += sizeof(int) ) {
+ get_user(tmp, (unsigned int *) A(data));
X putreg(child, i, tmp);
X data += sizeof(int);
X }
X ret = 0;
X break;
- }
X
X case IA32_PTRACE_GETFPREGS:
X ret = save_ia32_fpstate(child, (struct _fpstate_ia32 *) A(data));
@@ -2457,10 +3085,8 @@
X case PTRACE_KILL:
X case PTRACE_SINGLESTEP: /* execute chile for one instruction */
X case PTRACE_DETACH: /* detach a process */
- unlock_kernel();
- ret = sys_ptrace(request, pid, addr, data,
- arg4, arg5, arg6, arg7, stack);
- return(ret);
+ ret = sys_ptrace(request, pid, addr, data, arg4, arg5, arg6, arg7, stack);
+ break;
X
X default:
X ret = -EIO;
@@ -2477,7 +3103,10 @@


X {
X int err;
X

- err = get_user(kfl->l_type, &ufl->l_type);
+ if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)))
+ return -EFAULT;
+
+ err = __get_user(kfl->l_type, &ufl->l_type);
X err |= __get_user(kfl->l_whence, &ufl->l_whence);
X err |= __get_user(kfl->l_start, &ufl->l_start);
X err |= __get_user(kfl->l_len, &ufl->l_len);
@@ -2490,6 +3119,9 @@


X {
X int err;
X

+ if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)))
+ return -EFAULT;
+
X err = __put_user(kfl->l_type, &ufl->l_type);
X err |= __put_user(kfl->l_whence, &ufl->l_whence);
X err |= __put_user(kfl->l_start, &ufl->l_start);
@@ -2498,71 +3130,43 @@


X return err;
X }
X

-extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd,
- unsigned long arg);
+extern asmlinkage long sys_fcntl (unsigned int fd, unsigned int cmd, unsigned long arg);
X
X asmlinkage long
-sys32_fcntl(unsigned int fd, unsigned int cmd, int arg)
+sys32_fcntl (unsigned int fd, unsigned int cmd, unsigned int arg)
X {
- struct flock f;
X mm_segment_t old_fs;
+ struct flock f;
X long ret;
X
X switch (cmd) {
- case F_GETLK:
- case F_SETLK:
- case F_SETLKW:
- if(get_flock32(&f, (struct flock32 *)((long)arg)))
+ case F_GETLK:
+ case F_SETLK:
+ case F_SETLKW:
+ if (get_flock32(&f, (struct flock32 *) A(arg)))
X return -EFAULT;
X old_fs = get_fs();
X set_fs(KERNEL_DS);
- ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+ ret = sys_fcntl(fd, cmd, (unsigned long) &f);
X set_fs(old_fs);
- if(cmd == F_GETLK && put_flock32(&f, (struct flock32 *)((long)arg)))
+ if (cmd == F_GETLK && put_flock32(&f, (struct flock32 *) A(arg)))


X return -EFAULT;
X return ret;

- default:
+
+ default:
X /*
X * `sys_fcntl' lies about arg, for the F_SETOWN
X * sub-function arg can have a negative value.
X */
- return sys_fcntl(fd, cmd, (unsigned long)((long)arg));
- }
-}
-
-asmlinkage long
-sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
-{


- struct k_sigaction new_ka, old_ka;
- int ret;
-

- if (act) {
- old_sigset32_t mask;
-


- ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);

- ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
- ret |= __get_user(mask, &act->sa_mask);
- if (ret)
- return ret;
- siginitset(&new_ka.sa.sa_mask, mask);
- }
-


- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);

-


- if (!ret && oact) {

- ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);

- ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
- ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+ return sys_fcntl(fd, cmd, arg);


X }
-
- return ret;

X }
X
X asmlinkage long sys_ni_syscall(void);
X
X asmlinkage long
-sys32_ni_syscall(int dummy0, int dummy1, int dummy2, int dummy3,
- int dummy4, int dummy5, int dummy6, int dummy7, int stack)
+sys32_ni_syscall (int dummy0, int dummy1, int dummy2, int dummy3, int dummy4, int dummy5,
+ int dummy6, int dummy7, int stack)


X {
X struct pt_regs *regs = (struct pt_regs *)&stack;

X
@@ -2577,7 +3181,7 @@
X #define IOLEN ((65536 / 4) * 4096)
X
X asmlinkage long
-sys_iopl (int level)
+sys32_iopl (int level)
X {
X extern unsigned long ia64_iobase;
X int fd;
@@ -2612,9 +3216,8 @@
X up_write(&current->mm->mmap_sem);
X
X if (addr >= 0) {
- ia64_set_kr(IA64_KR_IO_BASE, addr);
X old = (old & ~0x3000) | (level << 12);
- __asm__ __volatile__("mov ar.eflag=%0 ;;" :: "r"(old));
+ asm volatile ("mov ar.eflag=%0;;" :: "r"(old));
X }
X
X fput(file);
@@ -2623,7 +3226,7 @@


X }
X
X asmlinkage long

-sys_ioperm (unsigned int from, unsigned int num, int on)
+sys32_ioperm (unsigned int from, unsigned int num, int on)
X {
X
X /*
@@ -2636,7 +3239,7 @@
X * XXX proper ioperm() support should be emulated by
X * manipulating the page protections...
X */
- return sys_iopl(3);
+ return sys32_iopl(3);
X }
X
X typedef struct {
@@ -2646,10 +3249,8 @@
X } ia32_stack_t;
X
X asmlinkage long
-sys32_sigaltstack (const ia32_stack_t *uss32, ia32_stack_t *uoss32,
-long arg2, long arg3, long arg4,
-long arg5, long arg6, long arg7,
-long stack)
+sys32_sigaltstack (ia32_stack_t *uss32, ia32_stack_t *uoss32,
+ long arg2, long arg3, long arg4, long arg5, long arg6, long arg7, long stack)
X {
X struct pt_regs *pt = (struct pt_regs *) &stack;
X stack_t uss, uoss;
@@ -2658,8 +3259,8 @@


X mm_segment_t old_fs = get_fs();
X

X if (uss32)
- if (copy_from_user(&buf32, (void *)A(uss32), sizeof(ia32_stack_t)))
- return(-EFAULT);
+ if (copy_from_user(&buf32, uss32, sizeof(ia32_stack_t)))
+ return -EFAULT;
X uss.ss_sp = (void *) (long) buf32.ss_sp;
X uss.ss_flags = buf32.ss_flags;
X uss.ss_size = buf32.ss_size;
@@ -2672,34 +3273,34 @@
X buf32.ss_sp = (long) uoss.ss_sp;
X buf32.ss_flags = uoss.ss_flags;
X buf32.ss_size = uoss.ss_size;
- if (copy_to_user((void*)A(uoss32), &buf32, sizeof(ia32_stack_t)))
- return(-EFAULT);
+ if (copy_to_user(uoss32, &buf32, sizeof(ia32_stack_t)))
+ return -EFAULT;
X }
- return(ret);
+ return ret;
X }
X
X asmlinkage int
-sys_pause (void)
+sys32_pause (void)
X {


X current->state = TASK_INTERRUPTIBLE;
X schedule();

X return -ERESTARTNOHAND;
X }
X
-asmlinkage long sys_msync(unsigned long start, size_t len, int flags);
+asmlinkage long sys_msync (unsigned long start, size_t len, int flags);
X
X asmlinkage int
-sys32_msync(unsigned int start, unsigned int len, int flags)
+sys32_msync (unsigned int start, unsigned int len, int flags)
X {
X unsigned int addr;
X
X if (OFFSET4K(start))
X return -EINVAL;
- addr = start & PAGE_MASK;
- return(sys_msync(addr, len + (start - addr), flags));
+ addr = PAGE_START(start);
+ return sys_msync(addr, len + (start - addr), flags);
X }
X
-struct sysctl_ia32 {
+struct sysctl32 {
X unsigned int name;
X int nlen;
X unsigned int oldval;
@@ -2712,16 +3313,16 @@
X extern asmlinkage long sys_sysctl(struct __sysctl_args *args);
X
X asmlinkage long
-sys32_sysctl(struct sysctl_ia32 *args32)
+sys32_sysctl (struct sysctl32 *args)
X {
- struct sysctl_ia32 a32;
+ struct sysctl32 a32;
X mm_segment_t old_fs = get_fs ();
X void *oldvalp, *newvalp;
X size_t oldlen;
X int *namep;
X long ret;
X
- if (copy_from_user(&a32, args32, sizeof (a32)))
+ if (copy_from_user(&a32, args, sizeof(a32)))
X return -EFAULT;
X
X /*
@@ -2754,7 +3355,7 @@


X }
X
X asmlinkage long

-sys32_newuname(struct new_utsname * name)
+sys32_newuname (struct new_utsname *name)
X {
X extern asmlinkage long sys_newuname(struct new_utsname * name);
X int ret = sys_newuname(name);
@@ -2765,10 +3366,10 @@


X return ret;
X }
X

-extern asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
+extern asmlinkage long sys_getresuid (uid_t *ruid, uid_t *euid, uid_t *suid);
X
X asmlinkage long
-sys32_getresuid (u16 *ruid, u16 *euid, u16 *suid)
+sys32_getresuid16 (u16 *ruid, u16 *euid, u16 *suid)
X {
X uid_t a, b, c;
X int ret;
@@ -2786,7 +3387,7 @@
X extern asmlinkage long sys_getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid);
X
X asmlinkage long
-sys32_getresgid(u16 *rgid, u16 *egid, u16 *sgid)
+sys32_getresgid16 (u16 *rgid, u16 *egid, u16 *sgid)
X {
X gid_t a, b, c;
X int ret;
@@ -2796,15 +3397,13 @@
X ret = sys_getresgid(&a, &b, &c);
X set_fs(old_fs);
X
- if (!ret) {
- ret = put_user(a, rgid);
- ret |= put_user(b, egid);
- ret |= put_user(c, sgid);
- }
- return ret;
+ if (ret)
+ return ret;
+
+ return put_user(a, rgid) | put_user(b, egid) | put_user(c, sgid);
X }
X
-int
+asmlinkage long
X sys32_lseek (unsigned int fd, int offset, unsigned int whence)
X {
X extern off_t sys_lseek (unsigned int fd, off_t offset, unsigned int origin);
@@ -2813,36 +3412,272 @@
X return sys_lseek(fd, offset, whence);
X }
X
-#ifdef NOTYET /* UNTESTED FOR IA64 FROM HERE DOWN */
+extern asmlinkage long sys_getgroups (int gidsetsize, gid_t *grouplist);
X
-/* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
- * kernel data space before using them..
- *
- * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
- */
-static inline int
-do_getname32(const char *filename, char *page)
+asmlinkage long
+sys32_getgroups16 (int gidsetsize, short *grouplist)
X {
- int retval;
+ mm_segment_t old_fs = get_fs();
+ gid_t gl[NGROUPS];
+ int ret, i;
X
- /* 32bit pointer will be always far below TASK_SIZE :)) */
- retval = strncpy_from_user((char *)page, (char *)filename, PAGE_SIZE);
- if (retval > 0) {
- if (retval < PAGE_SIZE)
- return 0;
- return -ENAMETOOLONG;
- } else if (!retval)
- retval = -ENOENT;
- return retval;
+ set_fs(KERNEL_DS);
+ ret = sys_getgroups(gidsetsize, gl);
+ set_fs(old_fs);
+
+ if (gidsetsize && ret > 0 && ret <= NGROUPS)
+ for (i = 0; i < ret; i++, grouplist++)
+ if (put_user(gl[i], grouplist))
+ return -EFAULT;
+ return ret;
X }
X
-char *
-getname32(const char *filename)
+extern asmlinkage long sys_setgroups (int gidsetsize, gid_t *grouplist);
+
+asmlinkage long
+sys32_setgroups16 (int gidsetsize, short *grouplist)
X {
- char *tmp, *result;
+ mm_segment_t old_fs = get_fs();
+ gid_t gl[NGROUPS];
+ int ret, i;
X
- result = ERR_PTR(-ENOMEM);
+ if ((unsigned) gidsetsize > NGROUPS)
+ return -EINVAL;
+ for (i = 0; i < gidsetsize; i++, grouplist++)
+ if (get_user(gl[i], grouplist))
+ return -EFAULT;
+ set_fs(KERNEL_DS);
+ ret = sys_setgroups(gidsetsize, gl);
+ set_fs(old_fs);


+ return ret;
+}
+

+/*
+ * Unfortunately, the x86 compiler aligns variables of type "long long" to a 4 byte boundary
+ * only, which means that the x86 version of "struct flock64" doesn't match the ia64 version
+ * of struct flock.
+ */
+
+static inline long
+ia32_put_flock (struct flock *l, unsigned long addr)
+{
+ return (put_user(l->l_type, (short *) addr)
+ | put_user(l->l_whence, (short *) (addr + 2))
+ | put_user(l->l_start, (long *) (addr + 4))
+ | put_user(l->l_len, (long *) (addr + 12))
+ | put_user(l->l_pid, (int *) (addr + 20)));
+}
+
+static inline long
+ia32_get_flock (struct flock *l, unsigned long addr)
+{
+ unsigned int start_lo, start_hi, len_lo, len_hi;
+ int err = (get_user(l->l_type, (short *) addr)
+ | get_user(l->l_whence, (short *) (addr + 2))
+ | get_user(start_lo, (int *) (addr + 4))
+ | get_user(start_hi, (int *) (addr + 8))
+ | get_user(len_lo, (int *) (addr + 12))
+ | get_user(len_hi, (int *) (addr + 16))
+ | get_user(l->l_pid, (int *) (addr + 20)));
+ l->l_start = ((unsigned long) start_hi << 32) | start_lo;
+ l->l_len = ((unsigned long) len_hi << 32) | len_lo;
+ return err;
+}
+
+asmlinkage long
+sys32_fcntl64 (unsigned int fd, unsigned int cmd, unsigned int arg)
+{
+ mm_segment_t old_fs;
+ struct flock f;
+ long ret;
+
+ switch (cmd) {
+ case F_GETLK64:
+ case F_SETLK64:
+ case F_SETLKW64:
+ if (ia32_get_flock(&f, arg))
+ return -EFAULT;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_fcntl(fd, cmd, (unsigned long) &f);
+ set_fs(old_fs);
+ if (cmd == F_GETLK && ia32_put_flock(&f, arg))
+ return -EFAULT;


+ break;
+
+ default:

+ ret = sys32_fcntl(fd, cmd, arg);
+ break;
+ }


+ return ret;
+}
+

+asmlinkage long
+sys32_truncate64 (unsigned int path, unsigned int len_lo, unsigned int len_hi)
+{
+ extern asmlinkage long sys_truncate (const char *path, unsigned long length);
+
+ return sys_truncate((const char *) A(path), ((unsigned long) len_hi << 32) | len_lo);
+}
+
+asmlinkage long
+sys32_ftruncate64 (int fd, unsigned int len_lo, unsigned int len_hi)
+{
+ extern asmlinkage long sys_ftruncate (int fd, unsigned long length);
+
+ return sys_ftruncate(fd, ((unsigned long) len_hi << 32) | len_lo);
+}
+
+static int
+putstat64 (struct stat64 *ubuf, struct stat *kbuf)
+{
+ int err;
+


+ if (clear_user(ubuf, sizeof(*ubuf)))
+ return 1;
+
+ err = __put_user(kbuf->st_dev, &ubuf->st_dev);

+ err |= __put_user(kbuf->st_ino, &ubuf->__st_ino);
+ err |= __put_user(kbuf->st_ino, &ubuf->st_ino_lo);
+ err |= __put_user(kbuf->st_ino >> 32, &ubuf->st_ino_hi);


+ err |= __put_user(kbuf->st_mode, &ubuf->st_mode);
+ err |= __put_user(kbuf->st_nlink, &ubuf->st_nlink);
+ err |= __put_user(kbuf->st_uid, &ubuf->st_uid);
+ err |= __put_user(kbuf->st_gid, &ubuf->st_gid);
+ err |= __put_user(kbuf->st_rdev, &ubuf->st_rdev);

+ err |= __put_user(kbuf->st_size, &ubuf->st_size_lo);
+ err |= __put_user((kbuf->st_size >> 32), &ubuf->st_size_hi);


+ err |= __put_user(kbuf->st_atime, &ubuf->st_atime);
+ err |= __put_user(kbuf->st_mtime, &ubuf->st_mtime);
+ err |= __put_user(kbuf->st_ctime, &ubuf->st_ctime);
+ err |= __put_user(kbuf->st_blksize, &ubuf->st_blksize);
+ err |= __put_user(kbuf->st_blocks, &ubuf->st_blocks);

+ return err;
+}
+
+asmlinkage long
+sys32_stat64 (char *filename, struct stat64 *statbuf)
+{
+ mm_segment_t old_fs = get_fs();
+ struct stat s;
+ long ret;
+
+ set_fs(KERNEL_DS);
+ ret = sys_newstat(filename, &s);
+ set_fs(old_fs);
+ if (putstat64(statbuf, &s))
+ return -EFAULT;


+ return ret;
+}
+

+asmlinkage long
+sys32_lstat64 (char *filename, struct stat64 *statbuf)
+{
+ mm_segment_t old_fs = get_fs();
+ struct stat s;
+ long ret;
+
+ set_fs(KERNEL_DS);
+ ret = sys_newlstat(filename, &s);
+ set_fs(old_fs);
+ if (putstat64(statbuf, &s))
+ return -EFAULT;


+ return ret;
+}
+

+asmlinkage long
+sys32_fstat64 (unsigned int fd, struct stat64 *statbuf)
+{
+ mm_segment_t old_fs = get_fs();
+ struct stat s;
+ long ret;
+
+ set_fs(KERNEL_DS);
+ ret = sys_newfstat(fd, &s);
+ set_fs(old_fs);
+ if (putstat64(statbuf, &s))
+ return -EFAULT;


+ return ret;
+}
+

+asmlinkage long
+sys32_sigpending (unsigned int *set)
+{
+ return do_sigpending(set, sizeof(*set));
+}
+
+struct sysinfo32 {
+ s32 uptime;
+ u32 loads[3];
+ u32 totalram;
+ u32 freeram;
+ u32 sharedram;
+ u32 bufferram;
+ u32 totalswap;
+ u32 freeswap;
+ unsigned short procs;
+ char _f[22];
+};
+
+asmlinkage long
+sys32_sysinfo (struct sysinfo32 *info)
+{
+ extern asmlinkage long sys_sysinfo (struct sysinfo *);
+ mm_segment_t old_fs = get_fs();
+ struct sysinfo s;
+ long ret, err;
+
+ set_fs(KERNEL_DS);
+ ret = sys_sysinfo(&s);
+ set_fs(old_fs);
+
+ if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
+ return -EFAULT;
+
+ err = __put_user(s.uptime, &info->uptime);
+ err |= __put_user(s.loads[0], &info->loads[0]);
+ err |= __put_user(s.loads[1], &info->loads[1]);
+ err |= __put_user(s.loads[2], &info->loads[2]);
+ err |= __put_user(s.totalram, &info->totalram);
+ err |= __put_user(s.freeram, &info->freeram);
+ err |= __put_user(s.sharedram, &info->sharedram);
+ err |= __put_user(s.bufferram, &info->bufferram);
+ err |= __put_user(s.totalswap, &info->totalswap);
+ err |= __put_user(s.freeswap, &info->freeswap);
+ err |= __put_user(s.procs, &info->procs);
+ if (err)
+ return -EFAULT;


+ return ret;
+}
+

+/* In order to reduce some races, while at the same time doing additional
+ * checking and hopefully speeding things up, we copy filenames to the
+ * kernel data space before using them..
+ *
+ * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
+ */
+static inline int
+do_getname32 (const char *filename, char *page)
+{
+ int retval;
+
+ /* 32bit pointer will be always far below TASK_SIZE :)) */
+ retval = strncpy_from_user((char *)page, (char *)filename, PAGE_SIZE);
+ if (retval > 0) {
+ if (retval < PAGE_SIZE)
+ return 0;
+ return -ENAMETOOLONG;
+ } else if (!retval)
+ retval = -ENOENT;


+ return retval;
+}
+

+static char *
+getname32 (const char *filename)
+{
+ char *tmp, *result;
+
+ result = ERR_PTR(-ENOMEM);
X tmp = (char *)__get_free_page(GFP_KERNEL);
X if (tmp) {
X int retval = do_getname32(filename, tmp);
@@ -2856,178 +3691,132 @@
X return result;
X }
X
-/* 32-bit timeval and related flotsam. */
-
-extern asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
-
-asmlinkage long
-sys32_ioperm(u32 from, u32 num, int on)
-{
- return sys_ioperm((unsigned long)from, (unsigned long)num, on);
-}
-
X struct dqblk32 {
- __u32 dqb_bhardlimit;
- __u32 dqb_bsoftlimit;
- __u32 dqb_curblocks;
- __u32 dqb_ihardlimit;
- __u32 dqb_isoftlimit;
- __u32 dqb_curinodes;
- __kernel_time_t32 dqb_btime;
- __kernel_time_t32 dqb_itime;
+ __u32 dqb_bhardlimit;
+ __u32 dqb_bsoftlimit;
+ __u32 dqb_curblocks;
+ __u32 dqb_ihardlimit;
+ __u32 dqb_isoftlimit;
+ __u32 dqb_curinodes;
+ __kernel_time_t32 dqb_btime;
+ __kernel_time_t32 dqb_itime;
X };
X
-extern asmlinkage long sys_quotactl(int cmd, const char *special, int id,
- caddr_t addr);
-
X asmlinkage long
-sys32_quotactl(int cmd, const char *special, int id, unsigned long addr)
+sys32_quotactl (int cmd, unsigned int special, int id, struct dqblk32 *addr)
X {
+ extern asmlinkage long sys_quotactl (int, const char *, int, caddr_t);
X int cmds = cmd >> SUBCMDSHIFT;
- int err;
- struct dqblk d;
X mm_segment_t old_fs;
+ struct dqblk d;
X char *spec;
+ long err;
X
X switch (cmds) {
- case Q_GETQUOTA:
+ case Q_GETQUOTA:
X break;
- case Q_SETQUOTA:
- case Q_SETUSE:
- case Q_SETQLIM:
- if (copy_from_user (&d, (struct dqblk32 *)addr,
- sizeof (struct dqblk32)))
+ case Q_SETQUOTA:
+ case Q_SETUSE:
+ case Q_SETQLIM:
+ if (copy_from_user (&d, addr, sizeof(struct dqblk32)))
X return -EFAULT;
X d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime;
X d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime;
X break;
- default:
- return sys_quotactl(cmd, special,
- id, (caddr_t)addr);
+ default:
+ return sys_quotactl(cmd, (void *) A(special), id, (caddr_t) addr);
X }
- spec = getname32 (special);
+ spec = getname32((void *) A(special));
X err = PTR_ERR(spec);
- if (IS_ERR(spec)) return err;
+ if (IS_ERR(spec))
+ return err;
X old_fs = get_fs ();


- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);

X err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
- set_fs (old_fs);
- putname (spec);
+ set_fs(old_fs);
+ putname(spec);
X if (cmds == Q_GETQUOTA) {
X __kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
X ((struct dqblk32 *)&d)->dqb_itime = i;
X ((struct dqblk32 *)&d)->dqb_btime = b;
- if (copy_to_user ((struct dqblk32 *)addr, &d,
- sizeof (struct dqblk32)))
+ if (copy_to_user(addr, &d, sizeof(struct dqblk32)))
X return -EFAULT;
X }


X return err;
X }
X

-extern asmlinkage long sys_utime(char * filename, struct utimbuf * times);
-
-struct utimbuf32 {
- __kernel_time_t32 actime, modtime;
-};
-
X asmlinkage long
-sys32_utime(char * filename, struct utimbuf32 *times)
+sys32_sched_rr_get_interval (pid_t pid, struct timespec32 *interval)
X {
- struct utimbuf t;
- mm_segment_t old_fs;
- int ret;
- char *filenam;
+ extern asmlinkage long sys_sched_rr_get_interval (pid_t, struct timespec *);
+ mm_segment_t old_fs = get_fs();
+ struct timespec t;
+ long ret;
X
- if (!times)
- return sys_utime(filename, NULL);
- if (get_user (t.actime, &times->actime) ||
- __get_user (t.modtime, &times->modtime))
- return -EFAULT;
- filenam = getname32 (filename);
- ret = PTR_ERR(filenam);
- if (!IS_ERR(filenam)) {
- old_fs = get_fs();
- set_fs (KERNEL_DS);
- ret = sys_utime(filenam, &t);
- set_fs (old_fs);
- putname (filenam);
- }
+ set_fs(KERNEL_DS);
+ ret = sys_sched_rr_get_interval(pid, &t);
+ set_fs(old_fs);
+ if (put_user (t.tv_sec, &interval->tv_sec) || put_user (t.tv_nsec, &interval->tv_nsec))
+ return -EFAULT;


X return ret;
X }
X

-/*
- * Ooo, nasty. We need here to frob 32-bit unsigned longs to
- * 64-bit unsigned longs.
- */
-
-static inline int
-get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
+asmlinkage long
+sys32_pread (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
X {
- if (ufdset) {
- unsigned long odd;
-
- if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
- return -EFAULT;
+ extern asmlinkage long sys_pread (unsigned int, char *, size_t, loff_t);
+ return sys_pread(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
+}
X
- odd = n & 1UL;
- n &= ~1UL;
- while (n) {
- unsigned long h, l;
- __get_user(l, ufdset);
- __get_user(h, ufdset+1);
- ufdset += 2;
- *fdset++ = h << 32 | l;
- n -= 2;
- }
- if (odd)
- __get_user(*fdset, ufdset);
- } else {
- /* Tricky, must clear full unsigned long in the
- * kernel fdset at the end, this makes sure that
- * actually happens.
- */
- memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
- }
- return 0;
+asmlinkage long
+sys32_pwrite (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
+{
+ extern asmlinkage long sys_pwrite (unsigned int, const char *, size_t, loff_t);
+ return sys_pwrite(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
X }
X
-static inline void
-set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
+asmlinkage long
+sys32_sendfile (int out_fd, int in_fd, int *offset, unsigned int count)
X {
- unsigned long odd;
+ extern asmlinkage long sys_sendfile (int, int, off_t *, size_t);
+ mm_segment_t old_fs = get_fs();
+ long ret;
+ off_t of;
X
- if (!ufdset)
- return;
+ if (offset && get_user(of, offset))
+ return -EFAULT;
X
- odd = n & 1UL;
- n &= ~1UL;
- while (n) {
- unsigned long h, l;
- l = *fdset++;
- h = l >> 32;
- __put_user(l, ufdset);
- __put_user(h, ufdset+1);
- ufdset += 2;
- n -= 2;
- }
- if (odd)
- __put_user(*fdset, ufdset);
-}
+ set_fs(KERNEL_DS);
+ ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
+ set_fs(old_fs);
+
+ if (!ret && offset && put_user(of, offset))
+ return -EFAULT;
X
-extern asmlinkage long sys_sysfs(int option, unsigned long arg1,
- unsigned long arg2);


+ return ret;
+}
X

X asmlinkage long
-sys32_sysfs(int option, u32 arg1, u32 arg2)
+sys32_personality (unsigned int personality)
X {
- return sys_sysfs(option, arg1, arg2);
+ extern asmlinkage long sys_personality (unsigned long);
+ long ret;
+
+ if (current->personality == PER_LINUX32 && personality == PER_LINUX)
+ personality = PER_LINUX32;
+ ret = sys_personality(personality);
+ if (ret == PER_LINUX32)
+ ret = PER_LINUX;
+ return ret;
X }
X
+#ifdef NOTYET /* UNTESTED FOR IA64 FROM HERE DOWN */
+
X struct ncp_mount_data32 {
X int version;
X unsigned int ncp_fd;
X __kernel_uid_t32 mounted_uid;
- __kernel_pid_t32 wdog_pid;
+ int wdog_pid;
X unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
X unsigned int time_out;
X unsigned int retry_count;
@@ -3061,1485 +3850,169 @@
X __kernel_uid_t32 uid;
X __kernel_gid_t32 gid;
X __kernel_mode_t32 file_mode;
- __kernel_mode_t32 dir_mode;
-};
-
-static void *
-do_smb_super_data_conv(void *raw_data)
-{
- struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
- struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
-
- s->version = s32->version;
- s->mounted_uid = s32->mounted_uid;
- s->uid = s32->uid;
- s->gid = s32->gid;
- s->file_mode = s32->file_mode;
- s->dir_mode = s32->dir_mode;
- return raw_data;
-}
-
-static int
-copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
-{
- int i;
- unsigned long page;
- struct vm_area_struct *vma;
-
- *kernel = 0;
- if(!user)
- return 0;
- vma = find_vma(current->mm, (unsigned long)user);
- if(!vma || (unsigned long)user < vma->vm_start)
- return -EFAULT;
- if(!(vma->vm_flags & VM_READ))
- return -EFAULT;
- i = vma->vm_end - (unsigned long) user;
- if(PAGE_SIZE <= (unsigned long) i)
- i = PAGE_SIZE - 1;
- if(!(page = __get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- if(copy_from_user((void *) page, user, i)) {
- free_page(page);
- return -EFAULT;
- }
- *kernel = page;


- return 0;
-}
-

-extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
- unsigned long new_flags, void *data);
-
-#define SMBFS_NAME "smbfs"
-#define NCPFS_NAME "ncpfs"
-
-asmlinkage long
-sys32_mount(char *dev_name, char *dir_name, char *type,
- unsigned long new_flags, u32 data)
-{
- unsigned long type_page;
- int err, is_smb, is_ncp;
-
- if(!capable(CAP_SYS_ADMIN))
- return -EPERM;
- is_smb = is_ncp = 0;
- err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
- if(err)
- return err;
- if(type_page) {
- is_smb = !strcmp((char *)type_page, SMBFS_NAME);
- is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
- }
- if(!is_smb && !is_ncp) {
- if(type_page)
- free_page(type_page);
- return sys_mount(dev_name, dir_name, type, new_flags,
- (void *)AA(data));
- } else {
- unsigned long dev_page, dir_page, data_page;
-
- err = copy_mount_stuff_to_kernel((const void *)dev_name,
- &dev_page);
- if(err)
- goto out;
- err = copy_mount_stuff_to_kernel((const void *)dir_name,
- &dir_page);
- if(err)
- goto dev_out;
- err = copy_mount_stuff_to_kernel((const void *)AA(data),
- &data_page);
- if(err)
- goto dir_out;
- if(is_ncp)
- do_ncp_super_data_conv((void *)data_page);
- else if(is_smb)
- do_smb_super_data_conv((void *)data_page);
- else
- panic("The problem is here...");
- err = do_mount((char *)dev_page, (char *)dir_page,
- (char *)type_page, new_flags,
- (void *)data_page);
- if(data_page)
- free_page(data_page);
- dir_out:
- if(dir_page)
- free_page(dir_page);
- dev_out:
- if(dev_page)
- free_page(dev_page);
- out:
- if(type_page)
- free_page(type_page);
- return err;
- }
-}
-
-struct sysinfo32 {
- s32 uptime;
- u32 loads[3];
- u32 totalram;
- u32 freeram;
- u32 sharedram;
- u32 bufferram;
- u32 totalswap;
- u32 freeswap;
- unsigned short procs;
- char _f[22];
-};
-
-extern asmlinkage long sys_sysinfo(struct sysinfo *info);
-
-asmlinkage long
-sys32_sysinfo(struct sysinfo32 *info)
-{
- struct sysinfo s;
- int ret, err;
- mm_segment_t old_fs = get_fs ();
-
- set_fs (KERNEL_DS);
- ret = sys_sysinfo(&s);
- set_fs (old_fs);
- err = put_user (s.uptime, &info->uptime);
- err |= __put_user (s.loads[0], &info->loads[0]);
- err |= __put_user (s.loads[1], &info->loads[1]);
- err |= __put_user (s.loads[2], &info->loads[2]);
- err |= __put_user (s.totalram, &info->totalram);
- err |= __put_user (s.freeram, &info->freeram);
- err |= __put_user (s.sharedram, &info->sharedram);
- err |= __put_user (s.bufferram, &info->bufferram);
- err |= __put_user (s.totalswap, &info->totalswap);
- err |= __put_user (s.freeswap, &info->freeswap);
- err |= __put_user (s.procs, &info->procs);
- if (err)
- return -EFAULT;
- return ret;
-}
-
-extern asmlinkage long sys_sched_rr_get_interval(pid_t pid,
- struct timespec *interval);
-
-asmlinkage long
-sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval)
-{
- struct timespec t;


- int ret;
- mm_segment_t old_fs = get_fs ();

-
- set_fs (KERNEL_DS);
- ret = sys_sched_rr_get_interval(pid, &t);
- set_fs (old_fs);
- if (put_user (t.tv_sec, &interval->tv_sec) ||
- __put_user (t.tv_nsec, &interval->tv_nsec))
- return -EFAULT;
- return ret;
-}
-
-extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set,
- old_sigset_t *oset);
-
-asmlinkage long
-sys32_sigprocmask(int how, old_sigset_t32 *set, old_sigset_t32 *oset)
-{
- old_sigset_t s;


- int ret;
- mm_segment_t old_fs = get_fs();

-
- if (set && get_user (s, set)) return -EFAULT;
- set_fs (KERNEL_DS);
- ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);


- set_fs (old_fs);
- if (ret) return ret;

- if (oset && put_user (s, oset)) return -EFAULT;


- return 0;
-}
-

-extern asmlinkage long sys_sigpending(old_sigset_t *set);
-
-asmlinkage long
-sys32_sigpending(old_sigset_t32 *set)
-{
- old_sigset_t s;


- int ret;
- mm_segment_t old_fs = get_fs();

-
- set_fs (KERNEL_DS);
- ret = sys_sigpending(&s);
- set_fs (old_fs);
- if (put_user (s, set)) return -EFAULT;
- return ret;
-}
-
-extern asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
-
-asmlinkage long
-sys32_rt_sigpending(sigset_t32 *set, __kernel_size_t32 sigsetsize)
-{
- sigset_t s;
- sigset_t32 s32;


- int ret;
- mm_segment_t old_fs = get_fs();

-
- set_fs (KERNEL_DS);
- ret = sys_rt_sigpending(&s, sigsetsize);
- set_fs (old_fs);
- if (!ret) {


- switch (_NSIG_WORDS) {
- case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
- case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
- case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
- case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
- }

- if (copy_to_user (set, &s32, sizeof(sigset_t32)))
- return -EFAULT;
- }
- return ret;
-}
-
-siginfo_t32 *
-siginfo64to32(siginfo_t32 *d, siginfo_t *s)
-{
- memset(d, 0, sizeof(siginfo_t32));
- d->si_signo = s->si_signo;
- d->si_errno = s->si_errno;
- d->si_code = s->si_code;
- if (s->si_signo >= SIGRTMIN) {
- d->si_pid = s->si_pid;
- d->si_uid = s->si_uid;
- /* XXX: Ouch, how to find this out??? */
- d->si_int = s->si_int;
- } else switch (s->si_signo) {
- /* XXX: What about POSIX1.b timers */
- case SIGCHLD:
- d->si_pid = s->si_pid;
- d->si_status = s->si_status;
- d->si_utime = s->si_utime;
- d->si_stime = s->si_stime;
- break;
- case SIGSEGV:
- case SIGBUS:
- case SIGFPE:
- case SIGILL:
- d->si_addr = (long)(s->si_addr);
- /* XXX: Do we need to translate this from ia64 to ia32 traps? */
- d->si_trapno = s->si_trapno;
- break;
- case SIGPOLL:
- d->si_band = s->si_band;
- d->si_fd = s->si_fd;
- break;
- default:
- d->si_pid = s->si_pid;
- d->si_uid = s->si_uid;
- break;
- }
- return d;
-}
-
-siginfo_t *
-siginfo32to64(siginfo_t *d, siginfo_t32 *s)
-{
- d->si_signo = s->si_signo;
- d->si_errno = s->si_errno;
- d->si_code = s->si_code;
- if (s->si_signo >= SIGRTMIN) {
- d->si_pid = s->si_pid;
- d->si_uid = s->si_uid;
- /* XXX: Ouch, how to find this out??? */
- d->si_int = s->si_int;
- } else switch (s->si_signo) {
- /* XXX: What about POSIX1.b timers */
- case SIGCHLD:
- d->si_pid = s->si_pid;
- d->si_status = s->si_status;
- d->si_utime = s->si_utime;
- d->si_stime = s->si_stime;
- break;
- case SIGSEGV:
- case SIGBUS:
- case SIGFPE:
- case SIGILL:
- d->si_addr = (void *)A(s->si_addr);
- /* XXX: Do we need to translate this from ia32 to ia64 traps? */
- d->si_trapno = s->si_trapno;
- break;
- case SIGPOLL:
- d->si_band = s->si_band;
- d->si_fd = s->si_fd;
- break;
- default:
- d->si_pid = s->si_pid;
- d->si_uid = s->si_uid;
- break;
- }
- return d;
-}
-
-extern asmlinkage long
-sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo,
- const struct timespec *uts, size_t sigsetsize);
-
-asmlinkage long
-sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
- struct timespec32 *uts, __kernel_size_t32 sigsetsize)
-{
- sigset_t s;
- sigset_t32 s32;
- struct timespec t;


- int ret;
- mm_segment_t old_fs = get_fs();

- siginfo_t info;
- siginfo_t32 info32;
-
- if (copy_from_user (&s32, uthese, sizeof(sigset_t32)))


- return -EFAULT;
- switch (_NSIG_WORDS) {
- case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
- case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
- case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
- case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
- }

- if (uts) {
- ret = get_user (t.tv_sec, &uts->tv_sec);
- ret |= __get_user (t.tv_nsec, &uts->tv_nsec);


- if (ret)
- return -EFAULT;
- }

- set_fs (KERNEL_DS);
- ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
- set_fs (old_fs);
- if (ret >= 0 && uinfo) {
- if (copy_to_user (uinfo, siginfo64to32(&info32, &info),
- sizeof(siginfo_t32)))
- return -EFAULT;
- }
- return ret;
-}
-
-extern asmlinkage long
-sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
-
-asmlinkage long
-sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
-{
- siginfo_t info;
- siginfo_t32 info32;


- int ret;
- mm_segment_t old_fs = get_fs();

-
- if (copy_from_user (&info32, uinfo, sizeof(siginfo_t32)))
- return -EFAULT;
- /* XXX: Is this correct? */
- siginfo32to64(&info, &info32);
- set_fs (KERNEL_DS);
- ret = sys_rt_sigqueueinfo(pid, sig, &info);
- set_fs (old_fs);
- return ret;
-}
-
-extern asmlinkage long sys_setreuid(uid_t ruid, uid_t euid);
-
-asmlinkage long sys32_setreuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid)
-{
- uid_t sruid, seuid;
-
- sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
- seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
- return sys_setreuid(sruid, seuid);
-}
-
-extern asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
-
-asmlinkage long
-sys32_setresuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid,
- __kernel_uid_t32 suid)
-{
- uid_t sruid, seuid, ssuid;
-
- sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
- seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
- ssuid = (suid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)suid);
- return sys_setresuid(sruid, seuid, ssuid);
-}
-
-extern asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
-
-asmlinkage long
-sys32_getresuid(__kernel_uid_t32 *ruid, __kernel_uid_t32 *euid,
- __kernel_uid_t32 *suid)
-{
- uid_t a, b, c;


- int ret;
- mm_segment_t old_fs = get_fs();

-
- set_fs (KERNEL_DS);
- ret = sys_getresuid(&a, &b, &c);
- set_fs (old_fs);
- if (put_user (a, ruid) || put_user (b, euid) || put_user (c, suid))
- return -EFAULT;
- return ret;
-}
-
-extern asmlinkage long sys_setregid(gid_t rgid, gid_t egid);
-
-asmlinkage long
-sys32_setregid(__kernel_gid_t32 rgid, __kernel_gid_t32 egid)
-{
- gid_t srgid, segid;
-
- srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid);
- segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid);
- return sys_setregid(srgid, segid);
-}
-
-extern asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);
-
-asmlinkage long
-sys32_setresgid(__kernel_gid_t32 rgid, __kernel_gid_t32 egid,
- __kernel_gid_t32 sgid)
-{
- gid_t srgid, segid, ssgid;
-
- srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid);
- segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid);
- ssgid = (sgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)sgid);
- return sys_setresgid(srgid, segid, ssgid);
-}
-
-extern asmlinkage long sys_getgroups(int gidsetsize, gid_t *grouplist);
-
-asmlinkage long
-sys32_getgroups(int gidsetsize, __kernel_gid_t32 *grouplist)
-{
- gid_t gl[NGROUPS];
- int ret, i;
- mm_segment_t old_fs = get_fs ();
-
- set_fs (KERNEL_DS);
- ret = sys_getgroups(gidsetsize, gl);
- set_fs (old_fs);
- if (gidsetsize && ret > 0 && ret <= NGROUPS)
- for (i = 0; i < ret; i++, grouplist++)
- if (__put_user (gl[i], grouplist))
- return -EFAULT;
- return ret;
-}
-
-extern asmlinkage long sys_setgroups(int gidsetsize, gid_t *grouplist);
-
-asmlinkage long
-sys32_setgroups(int gidsetsize, __kernel_gid_t32 *grouplist)
-{
- gid_t gl[NGROUPS];
- int ret, i;
- mm_segment_t old_fs = get_fs ();
-
- if ((unsigned) gidsetsize > NGROUPS)
- return -EINVAL;
- for (i = 0; i < gidsetsize; i++, grouplist++)
- if (__get_user (gl[i], grouplist))
- return -EFAULT;
- set_fs (KERNEL_DS);
- ret = sys_setgroups(gidsetsize, gl);
- set_fs (old_fs);
- return ret;
-}
-
-
-/* XXX These as well... */
-extern __inline__ struct socket *
-socki_lookup(struct inode *inode)
-{
- return &inode->u.socket_i;
-}
-
-extern __inline__ struct socket *
-sockfd_lookup(int fd, int *err)
-{
- struct file *file;
- struct inode *inode;
-
- if (!(file = fget(fd)))
- {
- *err = -EBADF;
- return NULL;
- }
-


- inode = file->f_dentry->d_inode;

- if (!inode->i_sock || !socki_lookup(inode))
- {
- *err = -ENOTSOCK;
- fput(file);
- return NULL;
- }
-
- return socki_lookup(inode);
-}
-
-struct msghdr32 {
- u32 msg_name;
- int msg_namelen;
- u32 msg_iov;
- __kernel_size_t32 msg_iovlen;
- u32 msg_control;
- __kernel_size_t32 msg_controllen;
- unsigned msg_flags;
-};
-
-struct cmsghdr32 {
- __kernel_size_t32 cmsg_len;
- int cmsg_level;
- int cmsg_type;
-};
-
-/* Bleech... */
-#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) \
- __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) \
- cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
-
-#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-
-#define CMSG32_DATA(cmsg) \
- ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
-#define CMSG32_SPACE(len) \
- (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
-#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
-
-#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
- (struct cmsghdr32 *)(ctl) : \
- (struct cmsghdr32 *)NULL)
-#define CMSG32_FIRSTHDR(msg) \
- __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-__inline__ struct cmsghdr32 *
-__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
- struct cmsghdr32 *__cmsg, int __cmsg_len)
-{
- struct cmsghdr32 * __ptr;
-
- __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
- CMSG32_ALIGN(__cmsg_len));
- if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
- return NULL;
-
- return __ptr;
-}
-
-__inline__ struct cmsghdr32 *
-cmsg32_nxthdr (struct msghdr *__msg, struct cmsghdr32 *__cmsg, int __cmsg_len)
-{
- return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
- __cmsg, __cmsg_len);
-}
-
-static inline int
-iov_from_user32_to_kern(struct iovec *kiov, struct iovec32 *uiov32, int niov)
-{
- int tot_len = 0;
-
- while(niov > 0) {
- u32 len, buf;
-
- if(get_user(len, &uiov32->iov_len) ||
- get_user(buf, &uiov32->iov_base)) {
- tot_len = -EFAULT;
- break;
- }
- tot_len += len;
- kiov->iov_base = (void *)A(buf);
- kiov->iov_len = (__kernel_size_t) len;
- uiov32++;
- kiov++;
- niov--;
- }
- return tot_len;
-}
-
-static inline int
-msghdr_from_user32_to_kern(struct msghdr *kmsg, struct msghdr32 *umsg)
-{
- u32 tmp1, tmp2, tmp3;
- int err;
-
- err = get_user(tmp1, &umsg->msg_name);
- err |= __get_user(tmp2, &umsg->msg_iov);
- err |= __get_user(tmp3, &umsg->msg_control);
- if (err)
- return -EFAULT;
-
- kmsg->msg_name = (void *)A(tmp1);
- kmsg->msg_iov = (struct iovec *)A(tmp2);
- kmsg->msg_control = (void *)A(tmp3);
-
- err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
- err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
- err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
- err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
-
- return err;
-}
-
-/* I've named the args so it is easy to tell whose space the pointers are in. */
-static int
-verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
- char *kern_address, int mode)
-{
- int tot_len;
-
- if(kern_msg->msg_namelen) {
- if(mode==VERIFY_READ) {
- int err = move_addr_to_kernel(kern_msg->msg_name,
- kern_msg->msg_namelen,
- kern_address);
- if(err < 0)
- return err;
- }
- kern_msg->msg_name = kern_address;
- } else
- kern_msg->msg_name = NULL;
-
- if(kern_msg->msg_iovlen > UIO_FASTIOV) {
- kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
- GFP_KERNEL);
- if(!kern_iov)
- return -ENOMEM;
- }
-
- tot_len = iov_from_user32_to_kern(kern_iov,
- (struct iovec32 *)kern_msg->msg_iov,
- kern_msg->msg_iovlen);
- if(tot_len >= 0)
- kern_msg->msg_iov = kern_iov;
- else if(kern_msg->msg_iovlen > UIO_FASTIOV)
- kfree(kern_iov);
-
- return tot_len;
-}
-
-/* There is a lot of hair here because the alignment rules (and
- * thus placement) of cmsg headers and length are different for
- * 32-bit apps. -DaveM
- */
-static int
-cmsghdr_from_user32_to_kern(struct msghdr *kmsg, unsigned char *stackbuf,
- int stackbuf_size)
-{
- struct cmsghdr32 *ucmsg;
- struct cmsghdr *kcmsg, *kcmsg_base;
- __kernel_size_t32 ucmlen;
- __kernel_size_t kcmlen, tmp;
-
- kcmlen = 0;
- kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
- ucmsg = CMSG32_FIRSTHDR(kmsg);
- while(ucmsg != NULL) {
- if(get_user(ucmlen, &ucmsg->cmsg_len))
- return -EFAULT;
-
- /* Catch bogons. */
- if(CMSG32_ALIGN(ucmlen) <
- CMSG32_ALIGN(sizeof(struct cmsghdr32)))
- return -EINVAL;
- if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
- + ucmlen) > kmsg->msg_controllen)
- return -EINVAL;
-
- tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
- CMSG_ALIGN(sizeof(struct cmsghdr)));
- kcmlen += tmp;
- ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
- }
- if(kcmlen == 0)
- return -EINVAL;
-
- /* The kcmlen holds the 64-bit version of the control length.
- * It may not be modified as we do not stick it into the kmsg
- * until we have successfully copied over all of the data
- * from the user.
- */
- if(kcmlen > stackbuf_size)
- kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
- if(kcmsg == NULL)
- return -ENOBUFS;
-
- /* Now copy them over neatly. */
- memset(kcmsg, 0, kcmlen);
- ucmsg = CMSG32_FIRSTHDR(kmsg);
- while(ucmsg != NULL) {
- __get_user(ucmlen, &ucmsg->cmsg_len);
- tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
- CMSG_ALIGN(sizeof(struct cmsghdr)));
- kcmsg->cmsg_len = tmp;
- __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
- __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
- /* Copy over the data. */
- if(copy_from_user(CMSG_DATA(kcmsg),
- CMSG32_DATA(ucmsg),
- (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
- goto out_free_efault;
-
- /* Advance. */
- kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
- ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
- }
-
- /* Ok, looks like we made it. Hook it up and return success. */
- kmsg->msg_control = kcmsg_base;
- kmsg->msg_controllen = kcmlen;
- return 0;
-
-out_free_efault:
- if(kcmsg_base != (struct cmsghdr *)stackbuf)
- kfree(kcmsg_base);


- return -EFAULT;
-}
-

-static void
-put_cmsg32(struct msghdr *kmsg, int level, int type, int len, void *data)
-{
- struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
- struct cmsghdr32 cmhdr;
- int cmlen = CMSG32_LEN(len);
-
- if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
- kmsg->msg_flags |= MSG_CTRUNC;
- return;
- }
-
- if(kmsg->msg_controllen < cmlen) {
- kmsg->msg_flags |= MSG_CTRUNC;
- cmlen = kmsg->msg_controllen;
- }
- cmhdr.cmsg_level = level;
- cmhdr.cmsg_type = type;
- cmhdr.cmsg_len = cmlen;
-
- if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
- return;
- if(copy_to_user(CMSG32_DATA(cm), data,
- cmlen - sizeof(struct cmsghdr32)))
- return;
- cmlen = CMSG32_SPACE(len);
- kmsg->msg_control += cmlen;
- kmsg->msg_controllen -= cmlen;
-}
-
-static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
-{
- struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
- int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32))
- / sizeof(int);
- int fdnum = scm->fp->count;
- struct file **fp = scm->fp->fp;
- int *cmfptr;
- int err = 0, i;
-
- if (fdnum < fdmax)
- fdmax = fdnum;
-
- for (i = 0, cmfptr = (int *) CMSG32_DATA(cm);
- i < fdmax;
- i++, cmfptr++) {
- int new_fd;
- err = get_unused_fd();
- if (err < 0)
- break;
- new_fd = err;
- err = put_user(new_fd, cmfptr);
- if (err) {
- put_unused_fd(new_fd);
- break;
- }
- /* Bump the usage count and install the file. */
- fp[i]->f_count++;
- current->files->fd[new_fd] = fp[i];
- }
-
- if (i > 0) {
- int cmlen = CMSG32_LEN(i * sizeof(int));
- if (!err)
- err = put_user(SOL_SOCKET, &cm->cmsg_level);
- if (!err)
- err = put_user(SCM_RIGHTS, &cm->cmsg_type);
- if (!err)
- err = put_user(cmlen, &cm->cmsg_len);
- if (!err) {
- cmlen = CMSG32_SPACE(i * sizeof(int));
- kmsg->msg_control += cmlen;
- kmsg->msg_controllen -= cmlen;
- }
- }
- if (i < fdnum)
- kmsg->msg_flags |= MSG_CTRUNC;
-
- /*
- * All of the files that fit in the message have had their
- * usage counts incremented, so we just free the list.
- */
- __scm_destroy(scm);
-}
-
-/* In these cases we (currently) can just copy to data over verbatim
- * because all CMSGs created by the kernel have well defined types which
- * have the same layout in both the 32-bit and 64-bit API. One must add
- * some special cased conversions here if we start sending control messages
- * with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
- * we do our work. The remaining cases are:
- *
- * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean
- * IP_TTL int 32-bit clean
- * IP_TOS __u8 32-bit clean
- * IP_RECVOPTS variable length 32-bit clean
- * IP_RETOPTS variable length 32-bit clean
- * (these last two are clean because the types are defined
- * by the IPv4 protocol)
- * IP_RECVERR struct sock_extended_err +
- * struct sockaddr_in 32-bit clean
- * SOL_IPV6 IPV6_RECVERR struct sock_extended_err +
- * struct sockaddr_in6 32-bit clean
- * IPV6_PKTINFO struct in6_pktinfo 32-bit clean
- * IPV6_HOPLIMIT int 32-bit clean
- * IPV6_FLOWINFO u32 32-bit clean
- * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean
- * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean
- * IPV6_RTHDR ipv6 routing exthdr 32-bit clean
- * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean
- */
-static void
-cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
- unsigned char *workbuf, *wp;
- unsigned long bufsz, space_avail;
- struct cmsghdr *ucmsg;
-
- bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
- space_avail = kmsg->msg_controllen + bufsz;
- wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
- if(workbuf == NULL)
- goto fail;
-
- /* To make this more sane we assume the kernel sends back properly
- * formatted control messages. Because of how the kernel will truncate
- * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
- */
- ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
- while(((unsigned long)ucmsg) < ((unsigned long)kmsg->msg_control)) {
- struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
- int clen64, clen32;
-
- /* UCMSG is the 64-bit format CMSG entry in user-space.
- * KCMSG32 is within the kernel space temporary buffer
- * we use to convert into a 32-bit style CMSG.
- */
- __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
- __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
- __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
-
- clen64 = kcmsg32->cmsg_len;
- copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
- clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
- clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
- CMSG32_ALIGN(sizeof(struct cmsghdr32)));
- kcmsg32->cmsg_len = clen32;
-
- ucmsg = (struct cmsghdr *) (((char *)ucmsg) +
- CMSG_ALIGN(clen64));
- wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
- }
-
- /* Copy back fixed up data, and adjust pointers. */
- bufsz = (wp - workbuf);
- copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
-
- kmsg->msg_control = (struct cmsghdr *)
- (((char *)orig_cmsg_uptr) + bufsz);
- kmsg->msg_controllen = space_avail - bufsz;
-
- kfree(workbuf);
- return;
-
-fail:
- /* If we leave the 64-bit format CMSG chunks in there,
- * the application could get confused and crash. So to
- * ensure greater recovery, we report no CMSGs.
- */
- kmsg->msg_controllen += bufsz;
- kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-asmlinkage long
-sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
-{
- struct socket *sock;
- char address[MAX_SOCK_ADDR];
- struct iovec iov[UIO_FASTIOV];
- unsigned char ctl[sizeof(struct cmsghdr) + 20];
- unsigned char *ctl_buf = ctl;
- struct msghdr kern_msg;
- int err, total_len;
-
- if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
- return -EFAULT;
- if(kern_msg.msg_iovlen > UIO_MAXIOV)
- return -EINVAL;
- err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
- if (err < 0)
- goto out;
- total_len = err;
-
- if(kern_msg.msg_controllen) {
- err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
- if(err)
- goto out_freeiov;
- ctl_buf = kern_msg.msg_control;
- }
- kern_msg.msg_flags = user_flags;
-
- sock = sockfd_lookup(fd, &err);
- if (sock != NULL) {
- if (sock->file->f_flags & O_NONBLOCK)
- kern_msg.msg_flags |= MSG_DONTWAIT;
- err = sock_sendmsg(sock, &kern_msg, total_len);
- sockfd_put(sock);
- }
-
- /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
- if(ctl_buf != ctl)
- kfree(ctl_buf);
-out_freeiov:
- if(kern_msg.msg_iov != iov)
- kfree(kern_msg.msg_iov);
-out:
- return err;
-}
-
-asmlinkage long
-sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
-{
- struct iovec iovstack[UIO_FASTIOV];
- struct msghdr kern_msg;
- char addr[MAX_SOCK_ADDR];
- struct socket *sock;
- struct iovec *iov = iovstack;
- struct sockaddr *uaddr;
- int *uaddr_len;
- unsigned long cmsg_ptr;
- int err, total_len, len = 0;
-
- if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
- return -EFAULT;
- if(kern_msg.msg_iovlen > UIO_MAXIOV)
- return -EINVAL;
-
- uaddr = kern_msg.msg_name;
- uaddr_len = &user_msg->msg_namelen;
- err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
- if (err < 0)
- goto out;
- total_len = err;
-
- cmsg_ptr = (unsigned long) kern_msg.msg_control;
- kern_msg.msg_flags = 0;
-
- sock = sockfd_lookup(fd, &err);
- if (sock != NULL) {
- struct scm_cookie scm;
-
- if (sock->file->f_flags & O_NONBLOCK)
- user_flags |= MSG_DONTWAIT;
- memset(&scm, 0, sizeof(scm));
- lock_kernel();
- err = sock->ops->recvmsg(sock, &kern_msg, total_len,
- user_flags, &scm);
- if(err >= 0) {
- len = err;
- if(!kern_msg.msg_control) {
- if(sock->passcred || scm.fp)
- kern_msg.msg_flags |= MSG_CTRUNC;
- if(scm.fp)
- __scm_destroy(&scm);
- } else {
- /* If recvmsg processing itself placed some
- * control messages into user space, it's is
- * using 64-bit CMSG processing, so we need
- * to fix it up before we tack on more stuff.
- */
- if((unsigned long) kern_msg.msg_control
- != cmsg_ptr)
- cmsg32_recvmsg_fixup(&kern_msg,
- cmsg_ptr);
-
- /* Wheee... */
- if(sock->passcred)
- put_cmsg32(&kern_msg,
- SOL_SOCKET, SCM_CREDENTIALS,
- sizeof(scm.creds),
- &scm.creds);
- if(scm.fp != NULL)
- scm_detach_fds32(&kern_msg, &scm);
- }
- }
- unlock_kernel();
- sockfd_put(sock);
- }
-
- if(uaddr != NULL && err >= 0)
- err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr,
- uaddr_len);
- if(cmsg_ptr != 0 && err >= 0) {
- unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
- __kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr
- - cmsg_ptr);
- err |= __put_user(uclen, &user_msg->msg_controllen);
- }
- if(err >= 0)
- err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
- if(kern_msg.msg_iov != iov)
- kfree(kern_msg.msg_iov);
-out:
- if(err < 0)
- return err;
- return len;
-}
-
-extern void check_pending(int signum);
-
-#ifdef CONFIG_MODULES
-
-extern asmlinkage unsigned long sys_create_module(const char *name_user,
- size_t size);
-
-asmlinkage unsigned long
-sys32_create_module(const char *name_user, __kernel_size_t32 size)
-{
- return sys_create_module(name_user, (size_t)size);
-}
-
-extern asmlinkage long sys_init_module(const char *name_user,
- struct module *mod_user);
-
-/* Hey, when you're trying to init module, take time and prepare us a nice 64bit
- * module structure, even if from 32bit modutils... Why to pollute kernel... :))
- */
-asmlinkage long
-sys32_init_module(const char *name_user, struct module *mod_user)
-{
- return sys_init_module(name_user, mod_user);
-}
-
-extern asmlinkage long sys_delete_module(const char *name_user);
-
-asmlinkage long
-sys32_delete_module(const char *name_user)
-{
- return sys_delete_module(name_user);
-}
-
-struct module_info32 {
- u32 addr;
- u32 size;
- u32 flags;
- s32 usecount;
-};
-
-/* Query various bits about modules. */
-
-static inline long
-get_mod_name(const char *user_name, char **buf)
-{
- unsigned long page;
- long retval;
-
- if ((unsigned long)user_name >= TASK_SIZE
- && !segment_eq(get_fs (), KERNEL_DS))
- return -EFAULT;
-
- page = __get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
- retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
- if (retval > 0) {
- if (retval < PAGE_SIZE) {
- *buf = (char *)page;
- return retval;
- }
- retval = -ENAMETOOLONG;
- } else if (!retval)
- retval = -EINVAL;
-
- free_page(page);


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

echo 'End of part 028'
echo 'File patch-2.4.15 is continued in part 029'
echo "029" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:03 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part027

#!/bin/sh -x
# this is part 027 of a 115 - part archive


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

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

X buf.error = 0;
@@ -831,7 +974,7 @@


X }
X
X asmlinkage long

-sys32_readdir (unsigned int fd, void * dirent, unsigned int count)
+sys32_readdir (unsigned int fd, void *dirent, unsigned int count)
X {
X int error;


X struct file * file;

@@ -866,7 +1009,7 @@
X #define ROUND_UP_TIME(x,y) (((x)+(y)-1)/(y))
X
X asmlinkage long
-sys32_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval32 *tvp32)
+sys32_select (int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval32 *tvp32)
X {
X fd_set_bits fds;
X char *bits;
@@ -878,8 +1021,7 @@
X time_t sec, usec;
X
X ret = -EFAULT;
- if (get_user(sec, &tvp32->tv_sec)
- || get_user(usec, &tvp32->tv_usec))
+ if (get_user(sec, &tvp32->tv_sec) || get_user(usec, &tvp32->tv_usec))
X goto out_nofds;
X
X ret = -EINVAL;
@@ -933,9 +1075,7 @@
X usec = timeout % HZ;
X usec *= (1000000/HZ);
X }
- if (put_user(sec, (int *)&tvp32->tv_sec)
- || put_user(usec, (int *)&tvp32->tv_usec))
- {
+ if (put_user(sec, &tvp32->tv_sec) || put_user(usec, &tvp32->tv_usec)) {
X ret = -EFAULT;
X goto out;
X }
@@ -969,50 +1109,43 @@


X };
X
X asmlinkage long

-old_select(struct sel_arg_struct *arg)
+sys32_old_select (struct sel_arg_struct *arg)
X {
X struct sel_arg_struct a;


X
X if (copy_from_user(&a, arg, sizeof(a)))
X return -EFAULT;

- return sys32_select(a.n, (fd_set *)A(a.inp), (fd_set *)A(a.outp), (fd_set *)A(a.exp),
- (struct timeval32 *)A(a.tvp));
+ return sys32_select(a.n, (fd_set *) A(a.inp), (fd_set *) A(a.outp), (fd_set *) A(a.exp),
+ (struct timeval32 *) A(a.tvp));
X }
X
-struct timespec32 {
- int tv_sec;
- int tv_nsec;
-};
-
-extern asmlinkage long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
+extern asmlinkage long sys_nanosleep (struct timespec *rqtp, struct timespec *rmtp);
X
X asmlinkage long
-sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
+sys32_nanosleep (struct timespec32 *rqtp, struct timespec32 *rmtp)
X {
X struct timespec t;
X int ret;


- mm_segment_t old_fs = get_fs ();

+ mm_segment_t old_fs = get_fs();
X
- if (get_user (t.tv_sec, &rqtp->tv_sec) ||
- __get_user (t.tv_nsec, &rqtp->tv_nsec))
+ if (get_user (t.tv_sec, &rqtp->tv_sec) || get_user (t.tv_nsec, &rqtp->tv_nsec))
X return -EFAULT;


- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);

X ret = sys_nanosleep(&t, rmtp ? &t : NULL);


- set_fs (old_fs);
+ set_fs(old_fs);

X if (rmtp && ret == -EINTR) {
- if (__put_user (t.tv_sec, &rmtp->tv_sec) ||
- __put_user (t.tv_nsec, &rmtp->tv_nsec))
+ if (put_user(t.tv_sec, &rmtp->tv_sec) || put_user(t.tv_nsec, &rmtp->tv_nsec))
X return -EFAULT;
X }


X return ret;
X }
X

X struct iovec32 { unsigned int iov_base; int iov_len; };
-asmlinkage ssize_t sys_readv(unsigned long,const struct iovec *,unsigned long);
-asmlinkage ssize_t sys_writev(unsigned long,const struct iovec *,unsigned long);
+asmlinkage ssize_t sys_readv (unsigned long,const struct iovec *,unsigned long);
+asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long);
X
X static struct iovec *
-get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type)
+get_iovec32 (struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type)
X {
X int i;
X u32 buf, len;
@@ -1022,24 +1155,23 @@
X
X if (!count)
X return 0;
- if(verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count))
- return(struct iovec *)0;
+ if (verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count))
+ return NULL;
X if (count > UIO_MAXIOV)
- return(struct iovec *)0;
+ return NULL;
X if (count > UIO_FASTIOV) {
X iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
X if (!iov)
- return((struct iovec *)0);
+ return NULL;
X } else
X iov = iov_buf;
X
X ivp = iov;
X for (i = 0; i < count; i++) {
- if (__get_user(len, &iov32->iov_len) ||
- __get_user(buf, &iov32->iov_base)) {
+ if (__get_user(len, &iov32->iov_len) || __get_user(buf, &iov32->iov_base)) {
X if (iov != iov_buf)
X kfree(iov);
- return((struct iovec *)0);
+ return NULL;
X }
X if (verify_area(type, (void *)A(buf), len)) {
X if (iov != iov_buf)
@@ -1047,22 +1179,23 @@
X return((struct iovec *)0);
X }
X ivp->iov_base = (void *)A(buf);
- ivp->iov_len = (__kernel_size_t)len;
+ ivp->iov_len = (__kernel_size_t) len;
X iov32++;
X ivp++;
X }
- return(iov);
+ return iov;


X }
X
X asmlinkage long

-sys32_readv(int fd, struct iovec32 *vector, u32 count)
+sys32_readv (int fd, struct iovec32 *vector, u32 count)
X {
X struct iovec iovstack[UIO_FASTIOV];
X struct iovec *iov;
- int ret;
+ long ret;


X mm_segment_t old_fs = get_fs();
X

- if ((iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE)) == (struct iovec *)0)
+ iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE);
+ if (!iov)
X return -EFAULT;
X set_fs(KERNEL_DS);
X ret = sys_readv(fd, iov, count);
@@ -1073,14 +1206,15 @@


X }
X
X asmlinkage long

-sys32_writev(int fd, struct iovec32 *vector, u32 count)
+sys32_writev (int fd, struct iovec32 *vector, u32 count)
X {
X struct iovec iovstack[UIO_FASTIOV];
X struct iovec *iov;
- int ret;
+ long ret;


X mm_segment_t old_fs = get_fs();
X

- if ((iov = get_iovec32(vector, iovstack, count, VERIFY_READ)) == (struct iovec *)0)
+ iov = get_iovec32(vector, iovstack, count, VERIFY_READ);
+ if (!iov)
X return -EFAULT;
X set_fs(KERNEL_DS);
X ret = sys_writev(fd, iov, count);
@@ -1098,45 +1232,66 @@
X int rlim_max;
X };
X
-extern asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim);
+extern asmlinkage long sys_getrlimit (unsigned int resource, struct rlimit *rlim);
X
X asmlinkage long
-sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim)
+sys32_old_getrlimit (unsigned int resource, struct rlimit32 *rlim)
X {
+ mm_segment_t old_fs = get_fs();
+ struct rlimit r;
+ int ret;
+
+ set_fs(KERNEL_DS);
+ ret = sys_getrlimit(resource, &r);
+ set_fs(old_fs);
+ if (!ret) {
+ ret = put_user(RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
+ ret |= put_user(RESOURCE32(r.rlim_max), &rlim->rlim_max);
+ }


+ return ret;
+}
+

+asmlinkage long
+sys32_getrlimit (unsigned int resource, struct rlimit32 *rlim)
+{
+ mm_segment_t old_fs = get_fs();
X struct rlimit r;
X int ret;


- mm_segment_t old_fs = get_fs ();

X
- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);

X ret = sys_getrlimit(resource, &r);


- set_fs (old_fs);
+ set_fs(old_fs);

X if (!ret) {
- ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
- ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max);
+ if (r.rlim_cur >= 0xffffffff)
+ r.rlim_cur = 0xffffffff;
+ if (r.rlim_max >= 0xffffffff)
+ r.rlim_max = 0xffffffff;
+ ret = put_user(r.rlim_cur, &rlim->rlim_cur);
+ ret |= put_user(r.rlim_max, &rlim->rlim_max);
X }


X return ret;
X }
X

-extern asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim);
+extern asmlinkage long sys_setrlimit (unsigned int resource, struct rlimit *rlim);
X
X asmlinkage long
-sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
+sys32_setrlimit (unsigned int resource, struct rlimit32 *rlim)
X {
X struct rlimit r;
X int ret;


- mm_segment_t old_fs = get_fs ();

+ mm_segment_t old_fs = get_fs();
X
- if (resource >= RLIM_NLIMITS) return -EINVAL;
- if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
- __get_user (r.rlim_max, &rlim->rlim_max))
+ if (resource >= RLIM_NLIMITS)
+ return -EINVAL;
+ if (get_user(r.rlim_cur, &rlim->rlim_cur) || get_user(r.rlim_max, &rlim->rlim_max))
X return -EFAULT;
X if (r.rlim_cur == RLIM_INFINITY32)
X r.rlim_cur = RLIM_INFINITY;
X if (r.rlim_max == RLIM_INFINITY32)
X r.rlim_max = RLIM_INFINITY;


- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);

X ret = sys_setrlimit(resource, &r);


- set_fs (old_fs);
+ set_fs(old_fs);
X return ret;
X }
X

@@ -1154,25 +1309,141 @@
X unsigned msg_flags;
X };
X
-static inline int
-shape_msg(struct msghdr *mp, struct msghdr32 *mp32)
-{
- int ret;
- unsigned int i;
+struct cmsghdr32 {
+ __kernel_size_t32 cmsg_len;
+ int cmsg_level;
+ int cmsg_type;
+};
X
- if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32)))
- return(-EFAULT);
- ret = __get_user(i, &mp32->msg_name);
- mp->msg_name = (void *)A(i);
- ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen);
- ret |= __get_user(i, &mp32->msg_iov);
+/* Bleech... */
+#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
+#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
+#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
+#define CMSG32_DATA(cmsg) \
+ ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
+#define CMSG32_SPACE(len) \
+ (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
+#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
+#define __CMSG32_FIRSTHDR(ctl,len) \
+ ((len) >= sizeof(struct cmsghdr32) ? (struct cmsghdr32 *)(ctl) : (struct cmsghdr32 *)NULL)
+#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+
+static inline struct cmsghdr32 *
+__cmsg32_nxthdr (void *ctl, __kernel_size_t size, struct cmsghdr32 *cmsg, int cmsg_len)
+{
+ struct cmsghdr32 * ptr;
+
+ ptr = (struct cmsghdr32 *)(((unsigned char *) cmsg) + CMSG32_ALIGN(cmsg_len));
+ if ((unsigned long)((char*)(ptr+1) - (char *) ctl) > size)
+ return NULL;
+ return ptr;
+}
+
+static inline struct cmsghdr32 *
+cmsg32_nxthdr (struct msghdr *msg, struct cmsghdr32 *cmsg, int cmsg_len)
+{
+ return __cmsg32_nxthdr(msg->msg_control, msg->msg_controllen, cmsg, cmsg_len);
+}
+
+static inline int
+get_msghdr32 (struct msghdr *mp, struct msghdr32 *mp32)
+{
+ int ret;
+ unsigned int i;
+
+ if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32)))
+ return -EFAULT;
+ ret = __get_user(i, &mp32->msg_name);
+ mp->msg_name = (void *)A(i);
+ ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen);
+ ret |= __get_user(i, &mp32->msg_iov);
X mp->msg_iov = (struct iovec *)A(i);
X ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen);
X ret |= __get_user(i, &mp32->msg_control);
X mp->msg_control = (void *)A(i);
X ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen);
X ret |= __get_user(mp->msg_flags, &mp32->msg_flags);


- return(ret ? -EFAULT : 0);
+ return ret ? -EFAULT : 0;

+}
+
+/*
+ * There is a lot of hair here because the alignment rules (and thus placement) of cmsg
+ * headers and length are different for 32-bit apps. -DaveM
+ */
+static int
+get_cmsghdr32 (struct msghdr *kmsg, unsigned char *stackbuf, struct sock *sk, size_t *bufsize)
+{
+ struct cmsghdr *kcmsg, *kcmsg_base;
+ __kernel_size_t kcmlen, tmp;
+ __kernel_size_t32 ucmlen;
+ struct cmsghdr32 *ucmsg;
+ long err;
+
+ kcmlen = 0;
+ kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
+ ucmsg = CMSG32_FIRSTHDR(kmsg);
+ while (ucmsg != NULL) {
+ if (get_user(ucmlen, &ucmsg->cmsg_len))
+ return -EFAULT;
+
+ /* Catch bogons. */
+ if (CMSG32_ALIGN(ucmlen) < CMSG32_ALIGN(sizeof(struct cmsghdr32)))
+ return -EINVAL;
+ if ((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) + ucmlen)
+ > kmsg->msg_controllen)
+ return -EINVAL;
+
+ tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+ CMSG_ALIGN(sizeof(struct cmsghdr)));
+ kcmlen += tmp;
+ ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+ }
+ if (kcmlen == 0)
+ return -EINVAL;
+
+ /*
+ * The kcmlen holds the 64-bit version of the control length. It may not be
+ * modified as we do not stick it into the kmsg until we have successfully copied
+ * over all of the data from the user.
+ */
+ if (kcmlen > *bufsize) {
+ *bufsize = kcmlen;
+ kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL);
+ }
+ if (kcmsg == NULL)
+ return -ENOBUFS;
+
+ /* Now copy them over neatly. */
+ memset(kcmsg, 0, kcmlen);
+ ucmsg = CMSG32_FIRSTHDR(kmsg);
+ while (ucmsg != NULL) {
+ err = get_user(ucmlen, &ucmsg->cmsg_len);
+ tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+ CMSG_ALIGN(sizeof(struct cmsghdr)));
+ kcmsg->cmsg_len = tmp;
+ err |= get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
+ err |= get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
+
+ /* Copy over the data. */
+ err |= copy_from_user(CMSG_DATA(kcmsg), CMSG32_DATA(ucmsg),
+ (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))));
+ if (err)
+ goto out_free_efault;
+
+ /* Advance. */
+ kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
+ ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+ }
+
+ /* Ok, looks like we made it. Hook it up and return success. */
+ kmsg->msg_control = kcmsg_base;
+ kmsg->msg_controllen = kcmlen;
+ return 0;
+
+out_free_efault:
+ if (kcmsg_base != (struct cmsghdr *)stackbuf)
+ sock_kfree_s(sk, kcmsg_base, kcmlen);
+ return -EFAULT;
X }
X
X /*
@@ -1187,20 +1458,17 @@
X */


X
X static inline int

-verify_iovec32(struct msghdr *m, struct iovec *iov, char *address, int mode)
+verify_iovec32 (struct msghdr *m, struct iovec *iov, char *address, int mode)
X {
X int size, err, ct;
X struct iovec32 *iov32;
X
- if(m->msg_namelen)
- {
- if(mode==VERIFY_READ)
- {
- err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
- if(err<0)
+ if (m->msg_namelen) {
+ if (mode == VERIFY_READ) {
+ err = move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
+ if (err < 0)


X goto out;
X }
-

X m->msg_name = address;
X } else
X m->msg_name = NULL;
@@ -1209,7 +1477,7 @@
X size = m->msg_iovlen * sizeof(struct iovec32);
X if (copy_from_user(iov, m->msg_iov, size))
X goto out;
- m->msg_iov=iov;
+ m->msg_iov = iov;
X
X err = 0;
X iov32 = (struct iovec32 *)iov;
@@ -1222,8 +1490,188 @@


X return err;
X }
X

-extern __inline__ void
-sockfd_put(struct socket *sock)
+static void
+put_cmsg32(struct msghdr *kmsg, int level, int type, int len, void *data)
+{
+ struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
+ struct cmsghdr32 cmhdr;
+ int cmlen = CMSG32_LEN(len);
+
+ if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
+ kmsg->msg_flags |= MSG_CTRUNC;
+ return;
+ }
+
+ if(kmsg->msg_controllen < cmlen) {
+ kmsg->msg_flags |= MSG_CTRUNC;
+ cmlen = kmsg->msg_controllen;
+ }
+ cmhdr.cmsg_level = level;
+ cmhdr.cmsg_type = type;
+ cmhdr.cmsg_len = cmlen;
+
+ if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
+ return;
+ if(copy_to_user(CMSG32_DATA(cm), data,
+ cmlen - sizeof(struct cmsghdr32)))
+ return;
+ cmlen = CMSG32_SPACE(len);
+ kmsg->msg_control += cmlen;
+ kmsg->msg_controllen -= cmlen;
+}
+
+static void
+scm_detach_fds32 (struct msghdr *kmsg, struct scm_cookie *scm)
+{
+ struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
+ int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32))
+ / sizeof(int);
+ int fdnum = scm->fp->count;
+ struct file **fp = scm->fp->fp;
+ int *cmfptr;
+ int err = 0, i;
+
+ if (fdnum < fdmax)
+ fdmax = fdnum;
+
+ for (i = 0, cmfptr = (int *) CMSG32_DATA(cm);
+ i < fdmax;
+ i++, cmfptr++) {
+ int new_fd;
+ err = get_unused_fd();
+ if (err < 0)
+ break;
+ new_fd = err;
+ err = put_user(new_fd, cmfptr);
+ if (err) {
+ put_unused_fd(new_fd);
+ break;
+ }
+ /* Bump the usage count and install the file. */
+ get_file(fp[i]);
+ current->files->fd[new_fd] = fp[i];
+ }
+
+ if (i > 0) {
+ int cmlen = CMSG32_LEN(i * sizeof(int));
+ if (!err)
+ err = put_user(SOL_SOCKET, &cm->cmsg_level);
+ if (!err)
+ err = put_user(SCM_RIGHTS, &cm->cmsg_type);
+ if (!err)
+ err = put_user(cmlen, &cm->cmsg_len);
+ if (!err) {
+ cmlen = CMSG32_SPACE(i * sizeof(int));
+ kmsg->msg_control += cmlen;
+ kmsg->msg_controllen -= cmlen;
+ }
+ }
+ if (i < fdnum)
+ kmsg->msg_flags |= MSG_CTRUNC;
+
+ /*
+ * All of the files that fit in the message have had their
+ * usage counts incremented, so we just free the list.
+ */
+ __scm_destroy(scm);
+}
+
+/*
+ * In these cases we (currently) can just copy to data over verbatim because all CMSGs
+ * created by the kernel have well defined types which have the same layout in both the
+ * 32-bit and 64-bit API. One must add some special cased conversions here if we start
+ * sending control messages with incompatible types.
+ *
+ * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
+ * we do our work. The remaining cases are:
+ *
+ * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean
+ * IP_TTL int 32-bit clean
+ * IP_TOS __u8 32-bit clean
+ * IP_RECVOPTS variable length 32-bit clean
+ * IP_RETOPTS variable length 32-bit clean
+ * (these last two are clean because the types are defined
+ * by the IPv4 protocol)
+ * IP_RECVERR struct sock_extended_err +
+ * struct sockaddr_in 32-bit clean
+ * SOL_IPV6 IPV6_RECVERR struct sock_extended_err +
+ * struct sockaddr_in6 32-bit clean
+ * IPV6_PKTINFO struct in6_pktinfo 32-bit clean
+ * IPV6_HOPLIMIT int 32-bit clean
+ * IPV6_FLOWINFO u32 32-bit clean
+ * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean
+ * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean
+ * IPV6_RTHDR ipv6 routing exthdr 32-bit clean
+ * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean
+ */
+static void
+cmsg32_recvmsg_fixup (struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
+{
+ unsigned char *workbuf, *wp;
+ unsigned long bufsz, space_avail;
+ struct cmsghdr *ucmsg;
+ long err;
+
+ bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
+ space_avail = kmsg->msg_controllen + bufsz;
+ wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
+ if (workbuf == NULL)
+ goto fail;
+
+ /* To make this more sane we assume the kernel sends back properly
+ * formatted control messages. Because of how the kernel will truncate
+ * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
+ */
+ ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
+ while (((unsigned long)ucmsg) < ((unsigned long)kmsg->msg_control)) {
+ struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
+ int clen64, clen32;
+
+ /*
+ * UCMSG is the 64-bit format CMSG entry in user-space. KCMSG32 is within
+ * the kernel space temporary buffer we use to convert into a 32-bit style
+ * CMSG.
+ */
+ err = get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
+ err |= get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
+ err |= get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
+ if (err)
+ goto fail2;
+
+ clen64 = kcmsg32->cmsg_len;
+ copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
+ clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
+ clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
+ CMSG32_ALIGN(sizeof(struct cmsghdr32)));
+ kcmsg32->cmsg_len = clen32;
+
+ ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
+ wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
+ }
+
+ /* Copy back fixed up data, and adjust pointers. */
+ bufsz = (wp - workbuf);
+ if (copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz))
+ goto fail2;
+
+ kmsg->msg_control = (struct cmsghdr *) (((char *)orig_cmsg_uptr) + bufsz);
+ kmsg->msg_controllen = space_avail - bufsz;
+ kfree(workbuf);
+ return;
+
+ fail2:
+ kfree(workbuf);
+ fail:
+ /*
+ * If we leave the 64-bit format CMSG chunks in there, the application could get
+ * confused and crash. So to ensure greater recovery, we report no CMSGs.
+ */
+ kmsg->msg_controllen += bufsz;
+ kmsg->msg_control = (void *) orig_cmsg_uptr;
+}
+
+static inline void
+sockfd_put (struct socket *sock)
X {
X fput(sock->file);
X }
@@ -1234,13 +1682,14 @@
X 24 for IPv6,
X about 80 for AX.25 */
X
-extern struct socket *sockfd_lookup(int fd, int *err);
+extern struct socket *sockfd_lookup (int fd, int *err);
X
X /*
X * BSD sendmsg interface
X */
X
-int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags)
+int
+sys32_sendmsg (int fd, struct msghdr32 *msg, unsigned flags)
X {
X struct socket *sock;
X char address[MAX_SOCK_ADDR];
@@ -1248,10 +1697,11 @@
X unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */
X unsigned char *ctl_buf = ctl;
X struct msghdr msg_sys;
- int err, ctl_len, iov_size, total_len;
+ int err, iov_size, total_len;
+ size_t ctl_len;
X
X err = -EFAULT;
- if (shape_msg(&msg_sys, msg))
+ if (get_msghdr32(&msg_sys, msg))
X goto out;
X
X sock = sockfd_lookup(fd, &err);
@@ -1282,20 +1732,12 @@
X
X if (msg_sys.msg_controllen > INT_MAX)
X goto out_freeiov;
- ctl_len = msg_sys.msg_controllen;
- if (ctl_len)
- {
- if (ctl_len > sizeof(ctl))
- {
- err = -ENOBUFS;
- ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
- if (ctl_buf == NULL)
- goto out_freeiov;
- }
- err = -EFAULT;
- if (copy_from_user(ctl_buf, msg_sys.msg_control, ctl_len))
- goto out_freectl;
- msg_sys.msg_control = ctl_buf;
+ if (msg_sys.msg_controllen) {
+ ctl_len = sizeof(ctl);
+ err = get_cmsghdr32(&msg_sys, ctl_buf, sock->sk, &ctl_len);
+ if (err)
+ goto out_freeiov;
+ ctl_buf = msg_sys.msg_control;
X }
X msg_sys.msg_flags = flags;
X
@@ -1303,7 +1745,6 @@
X msg_sys.msg_flags |= MSG_DONTWAIT;
X err = sock_sendmsg(sock, &msg_sys, total_len);
X
-out_freectl:
X if (ctl_buf != ctl)
X sock_kfree_s(sock->sk, ctl_buf, ctl_len);
X out_freeiov:
@@ -1328,6 +1769,7 @@
X struct msghdr msg_sys;
X unsigned long cmsg_ptr;
X int err, iov_size, total_len, len;
+ struct scm_cookie scm;
X
X /* kernel mode address */
X char addr[MAX_SOCK_ADDR];
@@ -1336,8 +1778,8 @@
X struct sockaddr *uaddr;
X int *uaddr_len;
X
- err=-EFAULT;
- if (shape_msg(&msg_sys, msg))
+ err = -EFAULT;
+ if (get_msghdr32(&msg_sys, msg))
X goto out;
X
X sock = sockfd_lookup(fd, &err);
@@ -1374,13 +1816,42 @@
X
X if (sock->file->f_flags & O_NONBLOCK)
X flags |= MSG_DONTWAIT;
- err = sock_recvmsg(sock, &msg_sys, total_len, flags);
- if (err < 0)
- goto out_freeiov;
- len = err;
X
- if (uaddr != NULL) {
- err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
+ memset(&scm, 0, sizeof(scm));
+
+ lock_kernel();
+ {
+ err = sock->ops->recvmsg(sock, &msg_sys, total_len, flags, &scm);
+ if (err < 0)
+ goto out_unlock_freeiov;
+
+ len = err;
+ if (!msg_sys.msg_control) {
+ if (sock->passcred || scm.fp)
+ msg_sys.msg_flags |= MSG_CTRUNC;
+ if (scm.fp)
+ __scm_destroy(&scm);
+ } else {
+ /*
+ * If recvmsg processing itself placed some control messages into
+ * user space, it's is using 64-bit CMSG processing, so we need to
+ * fix it up before we tack on more stuff.
+ */
+ if ((unsigned long) msg_sys.msg_control != cmsg_ptr)
+ cmsg32_recvmsg_fixup(&msg_sys, cmsg_ptr);
+
+ /* Wheee... */
+ if (sock->passcred)
+ put_cmsg32(&msg_sys, SOL_SOCKET, SCM_CREDENTIALS,
+ sizeof(scm.creds), &scm.creds);
+ if (scm.fp != NULL)
+ scm_detach_fds32(&msg_sys, &scm);
+ }
+ }
+ unlock_kernel();
+
+ if (uaddr != NULL) {
+ err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
X if (err < 0)
X goto out_freeiov;
X }
@@ -1393,20 +1864,23 @@
X goto out_freeiov;
X err = len;
X
-out_freeiov:
+ out_freeiov:
X if (iov != iovstack)
X sock_kfree_s(sock->sk, iov, iov_size);
-out_put:
+ out_put:
X sockfd_put(sock);
-out:
+ out:
X return err;
+
+ out_unlock_freeiov:
+ goto out_freeiov;
X }
X
X /* Argument list sizes for sys_socketcall */
X #define AL(x) ((x) * sizeof(u32))
-static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
- AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
- AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
+static const unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
+ AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
+ AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
X #undef AL
X
X extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
@@ -1435,7 +1909,8 @@
X extern asmlinkage long sys_shutdown(int fd, int how);
X extern asmlinkage long sys_listen(int fd, int backlog);
X
-asmlinkage long sys32_socketcall(int call, u32 *args)
+asmlinkage long
+sys32_socketcall (int call, u32 *args)
X {
X int ret;
X u32 a[6];
@@ -1463,16 +1938,13 @@
X ret = sys_listen(a0, a1);
X break;
X case SYS_ACCEPT:
- ret = sys_accept(a0, (struct sockaddr *)A(a1),
- (int *)A(a[2]));
+ ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
X break;
X case SYS_GETSOCKNAME:
- ret = sys_getsockname(a0, (struct sockaddr *)A(a1),
- (int *)A(a[2]));
+ ret = sys_getsockname(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
X break;
X case SYS_GETPEERNAME:
- ret = sys_getpeername(a0, (struct sockaddr *)A(a1),
- (int *)A(a[2]));
+ ret = sys_getpeername(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
X break;
X case SYS_SOCKETPAIR:
X ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
@@ -1500,12 +1972,10 @@
X ret = sys_getsockopt(a0, a1, a[2], a[3], a[4]);
X break;
X case SYS_SENDMSG:
- ret = sys32_sendmsg(a0, (struct msghdr32 *)A(a1),
- a[2]);
+ ret = sys32_sendmsg(a0, (struct msghdr32 *) A(a1), a[2]);
X break;
X case SYS_RECVMSG:
- ret = sys32_recvmsg(a0, (struct msghdr32 *)A(a1),
- a[2]);
+ ret = sys32_recvmsg(a0, (struct msghdr32 *) A(a1), a[2]);
X break;
X default:
X ret = EINVAL;
@@ -1522,15 +1992,28 @@
X
X struct msgbuf32 { s32 mtype; char mtext[1]; };
X
-struct ipc_perm32
-{
- key_t key;
- __kernel_uid_t32 uid;
- __kernel_gid_t32 gid;
- __kernel_uid_t32 cuid;
- __kernel_gid_t32 cgid;
+struct ipc_perm32 {
+ key_t key;
+ __kernel_uid_t32 uid;
+ __kernel_gid_t32 gid;
+ __kernel_uid_t32 cuid;
+ __kernel_gid_t32 cgid;
+ __kernel_mode_t32 mode;
+ unsigned short seq;
+};
+
+struct ipc64_perm32 {
+ key_t key;
+ __kernel_uid32_t32 uid;
+ __kernel_gid32_t32 gid;
+ __kernel_uid32_t32 cuid;
+ __kernel_gid32_t32 cgid;
X __kernel_mode_t32 mode;
- unsigned short seq;
+ unsigned short __pad1;
+ unsigned short seq;
+ unsigned short __pad2;
+ unsigned int unused1;
+ unsigned int unused2;
X };
X
X struct semid_ds32 {
@@ -1544,8 +2027,18 @@
X unsigned short sem_nsems; /* no. of semaphores in array */
X };
X
-struct msqid_ds32
-{
+struct semid64_ds32 {
+ struct ipc64_perm32 sem_perm;
+ __kernel_time_t32 sem_otime;
+ unsigned int __unused1;
+ __kernel_time_t32 sem_ctime;
+ unsigned int __unused2;
+ unsigned int sem_nsems;
+ unsigned int __unused3;
+ unsigned int __unused4;
+};
+
+struct msqid_ds32 {
X struct ipc_perm32 msg_perm;
X u32 msg_first;
X u32 msg_last;
@@ -1561,110 +2054,206 @@
X __kernel_ipc_pid_t32 msg_lrpid;
X };
X
+struct msqid64_ds32 {
+ struct ipc64_perm32 msg_perm;
+ __kernel_time_t32 msg_stime;
+ unsigned int __unused1;
+ __kernel_time_t32 msg_rtime;
+ unsigned int __unused2;
+ __kernel_time_t32 msg_ctime;
+ unsigned int __unused3;
+ unsigned int msg_cbytes;
+ unsigned int msg_qnum;
+ unsigned int msg_qbytes;
+ __kernel_pid_t32 msg_lspid;
+ __kernel_pid_t32 msg_lrpid;
+ unsigned int __unused4;
+ unsigned int __unused5;
+};
+
X struct shmid_ds32 {
- struct ipc_perm32 shm_perm;
- int shm_segsz;
- __kernel_time_t32 shm_atime;
- __kernel_time_t32 shm_dtime;
- __kernel_time_t32 shm_ctime;
- __kernel_ipc_pid_t32 shm_cpid;
- __kernel_ipc_pid_t32 shm_lpid;
- unsigned short shm_nattch;
+ struct ipc_perm32 shm_perm;
+ int shm_segsz;
+ __kernel_time_t32 shm_atime;
+ __kernel_time_t32 shm_dtime;
+ __kernel_time_t32 shm_ctime;
+ __kernel_ipc_pid_t32 shm_cpid;
+ __kernel_ipc_pid_t32 shm_lpid;
+ unsigned short shm_nattch;
+};
+
+struct shmid64_ds32 {
+ struct ipc64_perm shm_perm;
+ __kernel_size_t32 shm_segsz;
+ __kernel_time_t32 shm_atime;
+ unsigned int __unused1;
+ __kernel_time_t32 shm_dtime;
+ unsigned int __unused2;
+ __kernel_time_t32 shm_ctime;
+ unsigned int __unused3;
+ __kernel_pid_t32 shm_cpid;
+ __kernel_pid_t32 shm_lpid;
+ unsigned int shm_nattch;
+ unsigned int __unused4;
+ unsigned int __unused5;
+};
+
+struct shminfo64_32 {
+ unsigned int shmmax;
+ unsigned int shmmin;
+ unsigned int shmmni;
+ unsigned int shmseg;
+ unsigned int shmall;
+ unsigned int __unused1;
+ unsigned int __unused2;
+ unsigned int __unused3;
+ unsigned int __unused4;
X };
X
+struct shm_info32 {
+ int used_ids;
+ u32 shm_tot, shm_rss, shm_swp;
+ u32 swap_attempts, swap_successes;
+};
+
+struct ipc_kludge {
+ struct msgbuf *msgp;
+ long msgtyp;
+};
+
+#define SEMOP 1
+#define SEMGET 2
+#define SEMCTL 3
+#define MSGSND 11
+#define MSGRCV 12
+#define MSGGET 13
+#define MSGCTL 14
+#define SHMAT 21
+#define SHMDT 22
+#define SHMGET 23
+#define SHMCTL 24
+
X #define IPCOP_MASK(__x) (1UL << (__x))
X
X static int
-do_sys32_semctl(int first, int second, int third, void *uptr)
+ipc_parse_version32 (int *cmd)
+{
+ if (*cmd & IPC_64) {
+ *cmd ^= IPC_64;
+ return IPC_64;
+ } else {
+ return IPC_OLD;
+ }
+}
+
+static int
+semctl32 (int first, int second, int third, void *uptr)
X {
X union semun fourth;
X u32 pad;
X int err = 0, err2;
X struct semid64_ds s;
- struct semid_ds32 *usp;
X mm_segment_t old_fs;
+ int version = ipc_parse_version32(&third);
X
X if (!uptr)
X return -EINVAL;
X if (get_user(pad, (u32 *)uptr))
X return -EFAULT;
- if(third == SETVAL)
+ if (third == SETVAL)
X fourth.val = (int)pad;
X else
X fourth.__pad = (void *)A(pad);
X switch (third) {
-
- case IPC_INFO:
- case IPC_RMID:
- case IPC_SET:
- case SEM_INFO:
- case GETVAL:
- case GETPID:
- case GETNCNT:
- case GETZCNT:
- case GETALL:
- case SETVAL:
- case SETALL:
- err = sys_semctl (first, second, third, fourth);
+ case IPC_INFO:
+ case IPC_RMID:
+ case IPC_SET:
+ case SEM_INFO:
+ case GETVAL:
+ case GETPID:
+ case GETNCNT:
+ case GETZCNT:
+ case GETALL:
+ case SETVAL:
+ case SETALL:
+ err = sys_semctl(first, second, third, fourth);
X break;
X
- case IPC_STAT:
- case SEM_STAT:
- usp = (struct semid_ds32 *)A(pad);
+ case IPC_STAT:
+ case SEM_STAT:
X fourth.__pad = &s;
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_semctl (first, second, third, fourth);
- set_fs (old_fs);
- err2 = put_user(s.sem_perm.key, &usp->sem_perm.key);
- err2 |= __put_user(s.sem_perm.uid, &usp->sem_perm.uid);
- err2 |= __put_user(s.sem_perm.gid, &usp->sem_perm.gid);
- err2 |= __put_user(s.sem_perm.cuid,
- &usp->sem_perm.cuid);
- err2 |= __put_user (s.sem_perm.cgid,
- &usp->sem_perm.cgid);
- err2 |= __put_user (s.sem_perm.mode,
- &usp->sem_perm.mode);
- err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
- err2 |= __put_user (s.sem_otime, &usp->sem_otime);
- err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
- err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);


+ old_fs = get_fs();
+ set_fs(KERNEL_DS);

+ err = sys_semctl(first, second, third, fourth);
+ set_fs(old_fs);
+
+ if (version == IPC_64) {
+ struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad);
+
+ if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key);
+ err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid);
+ err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid);
+ err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid);
+ err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid);
+ err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode);
+ err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq);
+ err2 |= __put_user(s.sem_otime, &usp64->sem_otime);
+ err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime);
+ err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems);
+ } else {
+ struct semid_ds32 *usp32 = (struct semid_ds32 *) A(pad);
+
+ if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key);
+ err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid);
+ err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid);
+ err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid);
+ err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid);
+ err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode);
+ err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq);
+ err2 |= __put_user(s.sem_otime, &usp32->sem_otime);
+ err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime);
+ err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems);
+ }
X if (err2)
- err = -EFAULT;
+ err = -EFAULT;


X break;
-
X }
-

X return err;
X }
X

X static int
X do_sys32_msgsnd (int first, int second, int third, void *uptr)
X {
- struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf)
- + 4, GFP_USER);
+ struct msgbuf *p = kmalloc(second + sizeof(struct msgbuf) + 4, GFP_USER);
X struct msgbuf32 *up = (struct msgbuf32 *)uptr;
X mm_segment_t old_fs;
X int err;
X
X if (!p)
X return -ENOMEM;
- err = get_user (p->mtype, &up->mtype);
- err |= __copy_from_user (p->mtext, &up->mtext, second);
+ err = get_user(p->mtype, &up->mtype);
+ err |= copy_from_user(p->mtext, &up->mtext, second);
X if (err)
X goto out;
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_msgsnd (first, p, second, third);
- set_fs (old_fs);
-out:
- kfree (p);


+ old_fs = get_fs();
+ set_fs(KERNEL_DS);

+ err = sys_msgsnd(first, p, second, third);
+ set_fs(old_fs);
+ out:
+ kfree(p);


X return err;
X }
X

X static int
-do_sys32_msgrcv (int first, int second, int msgtyp, int third,
- int version, void *uptr)
+do_sys32_msgrcv (int first, int second, int msgtyp, int third, int version, void *uptr)
X {
X struct msgbuf32 *up;
X struct msgbuf *p;
@@ -1679,185 +2268,281 @@
X if (!uptr)
X goto out;
X err = -EFAULT;
- if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge)))
+ if (copy_from_user(&ipck, uipck, sizeof(struct ipc_kludge)))
X goto out;
X uptr = (void *)A(ipck.msgp);
X msgtyp = ipck.msgtyp;
X }
X err = -ENOMEM;
- p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
+ p = kmalloc(second + sizeof(struct msgbuf) + 4, GFP_USER);
X if (!p)
X goto out;
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_msgrcv (first, p, second + 4, msgtyp, third);
- set_fs (old_fs);


+ old_fs = get_fs();
+ set_fs(KERNEL_DS);

+ err = sys_msgrcv(first, p, second + 4, msgtyp, third);
+ set_fs(old_fs);
X if (err < 0)
X goto free_then_out;
X up = (struct msgbuf32 *)uptr;
- if (put_user (p->mtype, &up->mtype) ||
- __copy_to_user (&up->mtext, p->mtext, err))
+ if (put_user(p->mtype, &up->mtype) || copy_to_user(&up->mtext, p->mtext, err))
X err = -EFAULT;
X free_then_out:
- kfree (p);
+ kfree(p);
X out:


X return err;
X }
X

X static int
-do_sys32_msgctl (int first, int second, void *uptr)
+msgctl32 (int first, int second, void *uptr)
X {
X int err = -EINVAL, err2;
X struct msqid_ds m;
X struct msqid64_ds m64;
- struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
+ struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr;
+ struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr;
X mm_segment_t old_fs;
+ int version = ipc_parse_version32(&second);
X
X switch (second) {
-
- case IPC_INFO:
- case IPC_RMID:
- case MSG_INFO:
- err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
- break;
-
- case IPC_SET:
- err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
- err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
- err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
- err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
+ case IPC_INFO:
+ case IPC_RMID:
+ case MSG_INFO:
+ err = sys_msgctl(first, second, (struct msqid_ds *)uptr);
+ break;
+
+ case IPC_SET:
+ if (version == IPC_64) {
+ err = get_user(m.msg_perm.uid, &up64->msg_perm.uid);
+ err |= get_user(m.msg_perm.gid, &up64->msg_perm.gid);
+ err |= get_user(m.msg_perm.mode, &up64->msg_perm.mode);
+ err |= get_user(m.msg_qbytes, &up64->msg_qbytes);
+ } else {
+ err = get_user(m.msg_perm.uid, &up32->msg_perm.uid);
+ err |= get_user(m.msg_perm.gid, &up32->msg_perm.gid);
+ err |= get_user(m.msg_perm.mode, &up32->msg_perm.mode);
+ err |= get_user(m.msg_qbytes, &up32->msg_qbytes);
+ }
X if (err)
X break;
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_msgctl (first, second, &m);
- set_fs (old_fs);


+ old_fs = get_fs();
+ set_fs(KERNEL_DS);

+ err = sys_msgctl(first, second, &m);
+ set_fs(old_fs);
X break;
X
- case IPC_STAT:
- case MSG_STAT:
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_msgctl (first, second, (void *) &m64);
- set_fs (old_fs);
- err2 = put_user (m64.msg_perm.key, &up->msg_perm.key);
- err2 |= __put_user(m64.msg_perm.uid, &up->msg_perm.uid);
- err2 |= __put_user(m64.msg_perm.gid, &up->msg_perm.gid);
- err2 |= __put_user(m64.msg_perm.cuid, &up->msg_perm.cuid);
- err2 |= __put_user(m64.msg_perm.cgid, &up->msg_perm.cgid);
- err2 |= __put_user(m64.msg_perm.mode, &up->msg_perm.mode);
- err2 |= __put_user(m64.msg_perm.seq, &up->msg_perm.seq);
- err2 |= __put_user(m64.msg_stime, &up->msg_stime);
- err2 |= __put_user(m64.msg_rtime, &up->msg_rtime);
- err2 |= __put_user(m64.msg_ctime, &up->msg_ctime);
- err2 |= __put_user(m64.msg_cbytes, &up->msg_cbytes);
- err2 |= __put_user(m64.msg_qnum, &up->msg_qnum);
- err2 |= __put_user(m64.msg_qbytes, &up->msg_qbytes);
- err2 |= __put_user(m64.msg_lspid, &up->msg_lspid);
- err2 |= __put_user(m64.msg_lrpid, &up->msg_lrpid);
- if (err2)
- err = -EFAULT;
- break;
+ case IPC_STAT:
+ case MSG_STAT:


+ old_fs = get_fs();
+ set_fs(KERNEL_DS);

+ err = sys_msgctl(first, second, (void *) &m64);
+ set_fs(old_fs);
X
+ if (version == IPC_64) {
+ if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(m64.msg_perm.key, &up64->msg_perm.key);
+ err2 |= __put_user(m64.msg_perm.uid, &up64->msg_perm.uid);
+ err2 |= __put_user(m64.msg_perm.gid, &up64->msg_perm.gid);
+ err2 |= __put_user(m64.msg_perm.cuid, &up64->msg_perm.cuid);
+ err2 |= __put_user(m64.msg_perm.cgid, &up64->msg_perm.cgid);
+ err2 |= __put_user(m64.msg_perm.mode, &up64->msg_perm.mode);
+ err2 |= __put_user(m64.msg_perm.seq, &up64->msg_perm.seq);
+ err2 |= __put_user(m64.msg_stime, &up64->msg_stime);
+ err2 |= __put_user(m64.msg_rtime, &up64->msg_rtime);
+ err2 |= __put_user(m64.msg_ctime, &up64->msg_ctime);
+ err2 |= __put_user(m64.msg_cbytes, &up64->msg_cbytes);
+ err2 |= __put_user(m64.msg_qnum, &up64->msg_qnum);
+ err2 |= __put_user(m64.msg_qbytes, &up64->msg_qbytes);
+ err2 |= __put_user(m64.msg_lspid, &up64->msg_lspid);
+ err2 |= __put_user(m64.msg_lrpid, &up64->msg_lrpid);
+ if (err2)
+ err = -EFAULT;
+ } else {
+ if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(m64.msg_perm.key, &up32->msg_perm.key);
+ err2 |= __put_user(m64.msg_perm.uid, &up32->msg_perm.uid);
+ err2 |= __put_user(m64.msg_perm.gid, &up32->msg_perm.gid);
+ err2 |= __put_user(m64.msg_perm.cuid, &up32->msg_perm.cuid);
+ err2 |= __put_user(m64.msg_perm.cgid, &up32->msg_perm.cgid);
+ err2 |= __put_user(m64.msg_perm.mode, &up32->msg_perm.mode);
+ err2 |= __put_user(m64.msg_perm.seq, &up32->msg_perm.seq);
+ err2 |= __put_user(m64.msg_stime, &up32->msg_stime);
+ err2 |= __put_user(m64.msg_rtime, &up32->msg_rtime);
+ err2 |= __put_user(m64.msg_ctime, &up32->msg_ctime);
+ err2 |= __put_user(m64.msg_cbytes, &up32->msg_cbytes);
+ err2 |= __put_user(m64.msg_qnum, &up32->msg_qnum);
+ err2 |= __put_user(m64.msg_qbytes, &up32->msg_qbytes);
+ err2 |= __put_user(m64.msg_lspid, &up32->msg_lspid);
+ err2 |= __put_user(m64.msg_lrpid, &up32->msg_lrpid);
+ if (err2)
+ err = -EFAULT;
+ }
+ break;
X }
-


X return err;
X }
X

X static int
-do_sys32_shmat (int first, int second, int third, int version, void *uptr)
+shmat32 (int first, int second, int third, int version, void *uptr)
X {
X unsigned long raddr;
X u32 *uaddr = (u32 *)A((u32)third);
X int err;
X
X if (version == 1)
- return -EINVAL;
- err = sys_shmat (first, uptr, second, &raddr);
+ return -EINVAL; /* iBCS2 emulator entry point: unsupported */
+ err = sys_shmat(first, uptr, second, &raddr);


X if (err)
X return err;

X return put_user(raddr, uaddr);


X }
X
X static int

-do_sys32_shmctl (int first, int second, void *uptr)
+shmctl32 (int first, int second, void *uptr)
X {
X int err = -EFAULT, err2;
X struct shmid_ds s;
X struct shmid64_ds s64;
- struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
+ struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr;
+ struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr;
X mm_segment_t old_fs;
- struct shm_info32 {
- int used_ids;
- u32 shm_tot, shm_rss, shm_swp;
- u32 swap_attempts, swap_successes;
- } *uip = (struct shm_info32 *)uptr;
+ struct shm_info32 *uip = (struct shm_info32 *)uptr;
X struct shm_info si;
+ int version = ipc_parse_version32(&second);
+ struct shminfo64 smi;
+ struct shminfo *usi32 = (struct shminfo *) uptr;
+ struct shminfo64_32 *usi64 = (struct shminfo64_32 *) uptr;
X
X switch (second) {
+ case IPC_INFO:


+ old_fs = get_fs();
+ set_fs(KERNEL_DS);

+ err = sys_shmctl(first, second, (struct shmid_ds *)&smi);
+ set_fs(old_fs);
+
+ if (version == IPC_64) {
+ if (!access_ok(VERIFY_WRITE, usi64, sizeof(*usi64))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(smi.shmmax, &usi64->shmmax);
+ err2 |= __put_user(smi.shmmin, &usi64->shmmin);
+ err2 |= __put_user(smi.shmmni, &usi64->shmmni);
+ err2 |= __put_user(smi.shmseg, &usi64->shmseg);
+ err2 |= __put_user(smi.shmall, &usi64->shmall);
+ } else {
+ if (!access_ok(VERIFY_WRITE, usi32, sizeof(*usi32))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(smi.shmmax, &usi32->shmmax);
+ err2 |= __put_user(smi.shmmin, &usi32->shmmin);
+ err2 |= __put_user(smi.shmmni, &usi32->shmmni);
+ err2 |= __put_user(smi.shmseg, &usi32->shmseg);
+ err2 |= __put_user(smi.shmall, &usi32->shmall);
+ }
+ if (err2)
+ err = -EFAULT;
+ break;
X
- case IPC_INFO:
- case IPC_RMID:
- case SHM_LOCK:
- case SHM_UNLOCK:
- err = sys_shmctl (first, second, (struct shmid_ds *)uptr);
+ case IPC_RMID:
+ case SHM_LOCK:
+ case SHM_UNLOCK:
+ err = sys_shmctl(first, second, (struct shmid_ds *)uptr);
X break;
- case IPC_SET:
- err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
- err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
- err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
+
+ case IPC_SET:
+ if (version == IPC_64) {
+ err = get_user(s.shm_perm.uid, &up64->shm_perm.uid);
+ err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid);
+ err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode);
+ } else {
+ err = get_user(s.shm_perm.uid, &up32->shm_perm.uid);
+ err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid);
+ err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode);
+ }
X if (err)
X break;
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_shmctl (first, second, &s);
- set_fs (old_fs);


+ old_fs = get_fs();
+ set_fs(KERNEL_DS);

+ err = sys_shmctl(first, second, &s);
+ set_fs(old_fs);
X break;
X
- case IPC_STAT:
- case SHM_STAT:
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_shmctl (first, second, (void *) &s64);
- set_fs (old_fs);
+ case IPC_STAT:
+ case SHM_STAT:


+ old_fs = get_fs();
+ set_fs(KERNEL_DS);

+ err = sys_shmctl(first, second, (void *) &s64);
+ set_fs(old_fs);
X if (err < 0)
X break;
- err2 = put_user (s64.shm_perm.key, &up->shm_perm.key);
- err2 |= __put_user (s64.shm_perm.uid, &up->shm_perm.uid);
- err2 |= __put_user (s64.shm_perm.gid, &up->shm_perm.gid);
- err2 |= __put_user (s64.shm_perm.cuid,
- &up->shm_perm.cuid);
- err2 |= __put_user (s64.shm_perm.cgid,
- &up->shm_perm.cgid);
- err2 |= __put_user (s64.shm_perm.mode,
- &up->shm_perm.mode);
- err2 |= __put_user (s64.shm_perm.seq, &up->shm_perm.seq);
- err2 |= __put_user (s64.shm_atime, &up->shm_atime);
- err2 |= __put_user (s64.shm_dtime, &up->shm_dtime);
- err2 |= __put_user (s64.shm_ctime, &up->shm_ctime);
- err2 |= __put_user (s64.shm_segsz, &up->shm_segsz);
- err2 |= __put_user (s64.shm_nattch, &up->shm_nattch);
- err2 |= __put_user (s64.shm_cpid, &up->shm_cpid);
- err2 |= __put_user (s64.shm_lpid, &up->shm_lpid);
+ if (version == IPC_64) {
+ if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key);
+ err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid);
+ err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid);
+ err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid);
+ err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid);
+ err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode);
+ err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq);
+ err2 |= __put_user(s64.shm_atime, &up64->shm_atime);
+ err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime);
+ err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime);
+ err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz);
+ err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch);
+ err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid);
+ err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid);
+ } else {
+ if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key);
+ err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid);
+ err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid);
+ err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid);
+ err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid);
+ err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode);
+ err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq);
+ err2 |= __put_user(s64.shm_atime, &up32->shm_atime);
+ err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime);
+ err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime);
+ err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz);
+ err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch);
+ err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid);
+ err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid);
+ }
X if (err2)
X err = -EFAULT;
X break;
X
- case SHM_INFO:
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_shmctl (first, second, (void *)&si);
- set_fs (old_fs);
+ case SHM_INFO:


+ old_fs = get_fs();
+ set_fs(KERNEL_DS);

+ err = sys_shmctl(first, second, (void *)&si);
+ set_fs(old_fs);
X if (err < 0)
X break;
- err2 = put_user (si.used_ids, &uip->used_ids);
- err2 |= __put_user (si.shm_tot, &uip->shm_tot);
- err2 |= __put_user (si.shm_rss, &uip->shm_rss);
- err2 |= __put_user (si.shm_swp, &uip->shm_swp);
- err2 |= __put_user (si.swap_attempts,
- &uip->swap_attempts);
- err2 |= __put_user (si.swap_successes,
- &uip->swap_successes);
+
+ if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(si.used_ids, &uip->used_ids);
+ err2 |= __put_user(si.shm_tot, &uip->shm_tot);
+ err2 |= __put_user(si.shm_rss, &uip->shm_rss);
+ err2 |= __put_user(si.shm_swp, &uip->shm_swp);
+ err2 |= __put_user(si.swap_attempts, &uip->swap_attempts);
+ err2 |= __put_user(si.swap_successes, &uip->swap_successes);
X if (err2)
X err = -EFAULT;
X break;
@@ -1869,59 +2554,42 @@
X asmlinkage long
X sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
X {
- int version, err;
+ int version;
X
X version = call >> 16; /* hack for backward compatibility */
X call &= 0xffff;
X
X switch (call) {
-
- case SEMOP:
+ case SEMOP:
X /* struct sembuf is the same on 32 and 64bit :)) */
- err = sys_semop (first, (struct sembuf *)AA(ptr),
- second);
- break;
- case SEMGET:
- err = sys_semget (first, second, third);
- break;
- case SEMCTL:
- err = do_sys32_semctl (first, second, third,
- (void *)AA(ptr));
- break;
-
- case MSGSND:
- err = do_sys32_msgsnd (first, second, third,
- (void *)AA(ptr));
- break;
- case MSGRCV:
- err = do_sys32_msgrcv (first, second, fifth, third,
- version, (void *)AA(ptr));
- break;
- case MSGGET:
- err = sys_msgget ((key_t) first, second);
- break;
- case MSGCTL:
- err = do_sys32_msgctl (first, second, (void *)AA(ptr));
- break;
+ return sys_semop(first, (struct sembuf *)AA(ptr), second);
+ case SEMGET:
+ return sys_semget(first, second, third);
+ case SEMCTL:
+ return semctl32(first, second, third, (void *)AA(ptr));
+
+ case MSGSND:
+ return do_sys32_msgsnd(first, second, third, (void *)AA(ptr));
+ case MSGRCV:
+ return do_sys32_msgrcv(first, second, fifth, third, version, (void *)AA(ptr));
+ case MSGGET:
+ return sys_msgget((key_t) first, second);
+ case MSGCTL:
+ return msgctl32(first, second, (void *)AA(ptr));
+
+ case SHMAT:
+ return shmat32(first, second, third, version, (void *)AA(ptr));
+ break;
+ case SHMDT:
+ return sys_shmdt((char *)AA(ptr));
+ case SHMGET:
+ return sys_shmget(first, second, third);
+ case SHMCTL:
+ return shmctl32(first, second, (void *)AA(ptr));
X
- case SHMAT:
- err = do_sys32_shmat (first, second, third, version, (void *)AA(ptr));
- break;
- case SHMDT:
- err = sys_shmdt ((char *)AA(ptr));
- break;
- case SHMGET:
- err = sys_shmget (first, second, third);
- break;
- case SHMCTL:
- err = do_sys32_shmctl (first, second, (void *)AA(ptr));
- break;
- default:
- err = -EINVAL;
- break;
+ default:


+ return -EINVAL;
X }
-

- return err;
X }
X
X /*
@@ -1929,7 +2597,8 @@
X * sys_gettimeofday(). IA64 did this but i386 Linux did not
X * so we have to implement this system call here.
X */
-asmlinkage long sys32_time(int * tloc)
+asmlinkage long
+sys32_time (int *tloc)


X {
X int i;
X

@@ -1937,7 +2606,7 @@
X stuff it to user space. No side effects */
X i = CURRENT_TIME;
X if (tloc) {
- if (put_user(i,tloc))
+ if (put_user(i, tloc))
X i = -EFAULT;
X }
X return i;
@@ -1967,7 +2636,10 @@


X {
X int err;
X

- err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
+ if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)))
+ return -EFAULT;
+
+ err = __put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
X err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
X err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
X err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
@@ -1989,8 +2661,7 @@


X }
X
X asmlinkage long

-sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options,
- struct rusage32 *ru)
+sys32_wait4 (int pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
X {
X if (!ru)
X return sys_wait4(pid, stat_addr, options, NULL);
@@ -2000,37 +2671,38 @@
X unsigned int status;


X mm_segment_t old_fs = get_fs();
X
- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);

X ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
- set_fs (old_fs);
- if (put_rusage (ru, &r)) return -EFAULT;
- if (stat_addr && put_user (status, stat_addr))
+ set_fs(old_fs);
+ if (put_rusage(ru, &r))
+ return -EFAULT;
+ if (stat_addr && put_user(status, stat_addr))


X return -EFAULT;
X return ret;
X }
X }

X
X asmlinkage long
-sys32_waitpid(__kernel_pid_t32 pid, unsigned int *stat_addr, int options)
+sys32_waitpid (int pid, unsigned int *stat_addr, int options)
X {
X return sys32_wait4(pid, stat_addr, options, NULL);
X }


X
X
-extern asmlinkage long

-sys_getrusage(int who, struct rusage *ru);
+extern asmlinkage long sys_getrusage (int who, struct rusage *ru);
X
X asmlinkage long
-sys32_getrusage(int who, struct rusage32 *ru)
+sys32_getrusage (int who, struct rusage32 *ru)
X {
X struct rusage r;
X int ret;


X mm_segment_t old_fs = get_fs();
X
- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);

X ret = sys_getrusage(who, &r);
- set_fs (old_fs);
- if (put_rusage (ru, &r)) return -EFAULT;
+ set_fs(old_fs);
+ if (put_rusage (ru, &r))
+ return -EFAULT;


X return ret;
X }
X

@@ -2041,41 +2713,41 @@
X __kernel_clock_t32 tms_cstime;
X };
X
-extern asmlinkage long sys_times(struct tms * tbuf);
+extern asmlinkage long sys_times (struct tms * tbuf);
X
X asmlinkage long
-sys32_times(struct tms32 *tbuf)
+sys32_times (struct tms32 *tbuf)
X {
+ mm_segment_t old_fs = get_fs();
X struct tms t;
X long ret;


- mm_segment_t old_fs = get_fs ();

X int err;
X

- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);

X ret = sys_times(tbuf ? &t : NULL);


- set_fs (old_fs);
+ set_fs(old_fs);

X if (tbuf) {
X err = put_user (IA32_TICK(t.tms_utime), &tbuf->tms_utime);
- err |= __put_user (IA32_TICK(t.tms_stime), &tbuf->tms_stime);
- err |= __put_user (IA32_TICK(t.tms_cutime), &tbuf->tms_cutime);
- err |= __put_user (IA32_TICK(t.tms_cstime), &tbuf->tms_cstime);
+ err |= put_user (IA32_TICK(t.tms_stime), &tbuf->tms_stime);
+ err |= put_user (IA32_TICK(t.tms_cutime), &tbuf->tms_cutime);
+ err |= put_user (IA32_TICK(t.tms_cstime), &tbuf->tms_cstime);
X if (err)
X ret = -EFAULT;
X }
X return IA32_TICK(ret);
X }
X
-unsigned int
+static unsigned int
X ia32_peek (struct pt_regs *regs, struct task_struct *child, unsigned long addr, unsigned int *val)
X {
X size_t copied;
X unsigned int ret;
X
X copied = access_process_vm(child, addr, val, sizeof(*val), 0);
- return(copied != sizeof(ret) ? -EIO : 0);
+ return (copied != sizeof(ret)) ? -EIO : 0;
X }
X
-unsigned int
+static unsigned int
X ia32_poke (struct pt_regs *regs, struct task_struct *child, unsigned long addr, unsigned int val)
X {
X
@@ -2105,135 +2777,87 @@
X #define PT_UESP 15
X #define PT_SS 16
X
-unsigned int
-getreg(struct task_struct *child, int regno)
+static unsigned int
+getreg (struct task_struct *child, int regno)
X {
X struct pt_regs *child_regs;
X
X child_regs = ia64_task_regs(child);
X switch (regno / sizeof(int)) {
-
- case PT_EBX:
- return(child_regs->r11);
- case PT_ECX:
- return(child_regs->r9);
- case PT_EDX:
- return(child_regs->r10);
- case PT_ESI:
- return(child_regs->r14);
- case PT_EDI:
- return(child_regs->r15);
- case PT_EBP:
- return(child_regs->r13);
- case PT_EAX:
- case PT_ORIG_EAX:
- return(child_regs->r8);
- case PT_EIP:
- return(child_regs->cr_iip);
- case PT_UESP:
- return(child_regs->r12);
- case PT_EFL:
- return(child->thread.eflag);
- case PT_DS:
- case PT_ES:
- case PT_FS:
- case PT_GS:
- case PT_SS:
- return((unsigned int)__USER_DS);
- case PT_CS:
- return((unsigned int)__USER_CS);
- default:
- printk(KERN_ERR "getregs:unknown register %d\n", regno);
+ case PT_EBX: return child_regs->r11;
+ case PT_ECX: return child_regs->r9;
+ case PT_EDX: return child_regs->r10;
+ case PT_ESI: return child_regs->r14;
+ case PT_EDI: return child_regs->r15;
+ case PT_EBP: return child_regs->r13;
+ case PT_EAX: return child_regs->r8;
+ case PT_ORIG_EAX: return child_regs->r1; /* see dispatch_to_ia32_handler() */
+ case PT_EIP: return child_regs->cr_iip;
+ case PT_UESP: return child_regs->r12;
+ case PT_EFL: return child->thread.eflag;
+ case PT_DS: case PT_ES: case PT_FS: case PT_GS: case PT_SS:
+ return __USER_DS;
+ case PT_CS: return __USER_CS;
+ default:
+ printk(KERN_ERR "ia32.getreg(): unknown register %d\n", regno);
X break;
-
X }
- return(0);


+ return 0;
X }
X

-void
-putreg(struct task_struct *child, int regno, unsigned int value)
+static void
+putreg (struct task_struct *child, int regno, unsigned int value)
X {
X struct pt_regs *child_regs;
X
X child_regs = ia64_task_regs(child);
X switch (regno / sizeof(int)) {
-
- case PT_EBX:
- child_regs->r11 = value;
- break;
- case PT_ECX:
- child_regs->r9 = value;
- break;
- case PT_EDX:
- child_regs->r10 = value;
- break;
- case PT_ESI:
- child_regs->r14 = value;
- break;
- case PT_EDI:
- child_regs->r15 = value;
- break;
- case PT_EBP:
- child_regs->r13 = value;
- break;
- case PT_EAX:
- case PT_ORIG_EAX:
- child_regs->r8 = value;
- break;
- case PT_EIP:
- child_regs->cr_iip = value;
- break;
- case PT_UESP:
- child_regs->r12 = value;
- break;
- case PT_EFL:
- child->thread.eflag = value;
- break;
- case PT_DS:
- case PT_ES:
- case PT_FS:
- case PT_GS:
- case PT_SS:
+ case PT_EBX: child_regs->r11 = value; break;
+ case PT_ECX: child_regs->r9 = value; break;
+ case PT_EDX: child_regs->r10 = value; break;
+ case PT_ESI: child_regs->r14 = value; break;
+ case PT_EDI: child_regs->r15 = value; break;
+ case PT_EBP: child_regs->r13 = value; break;
+ case PT_EAX: child_regs->r8 = value; break;
+ case PT_ORIG_EAX: child_regs->r1 = value; break;
+ case PT_EIP: child_regs->cr_iip = value; break;
+ case PT_UESP: child_regs->r12 = value; break;
+ case PT_EFL: child->thread.eflag = value; break;
+ case PT_DS: case PT_ES: case PT_FS: case PT_GS: case PT_SS:
X if (value != __USER_DS)
- printk(KERN_ERR "setregs:try to set invalid segment register %d = %x\n",
+ printk(KERN_ERR
+ "ia32.putreg: attempt to set invalid segment register %d = %x\n",
X regno, value);
X break;
- case PT_CS:
+ case PT_CS:
X if (value != __USER_CS)
- printk(KERN_ERR "setregs:try to set invalid segment register %d = %x\n",
+ printk(KERN_ERR
+ "ia32.putreg: attempt to to set invalid segment register %d = %x\n",
X regno, value);
X break;
- default:
- printk(KERN_ERR "getregs:unknown register %d\n", regno);
+ default:
+ printk(KERN_ERR "ia32.putreg: unknown register %d\n", regno);
X break;
-
X }
X }
X
X static inline void
-ia32f2ia64f(void *dst, void *src)
+ia32f2ia64f (void *dst, void *src)
X {
-
- __asm__ ("ldfe f6=[%1] ;;\n\t"
- "stf.spill [%0]=f6"
- :
- : "r"(dst), "r"(src));
+ asm volatile ("ldfe f6=[%1];; stf.spill [%0]=f6" :: "r"(dst), "r"(src) : "memory");
X return;
X }
X
X static inline void
-ia64f2ia32f(void *dst, void *src)
+ia64f2ia32f (void *dst, void *src)
X {
-
- __asm__ ("ldf.fill f6=[%1] ;;\n\t"
- "stfe [%0]=f6"
- :
- : "r"(dst), "r"(src));
+ asm volatile ("ldf.fill f6=[%1];; stfe [%0]=f6" :: "r"(dst), "r"(src) : "memory");
X return;
X }
X
-void
-put_fpreg(int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp, int tos)


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

echo 'End of part 027'
echo 'File patch-2.4.15 is continued in part 028'
echo "028" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:58:54 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part018

#!/bin/sh -x
# this is part 018 of a 115 - part archive


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

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

+ is available at five speeds ranging from 100 MHz to 233 MHz.


+ More information is available at

+ <http://developer.intel.com/design/strong/sa110.htm>.
+
+ Say Y if you want support for the SA-110 processor.
+ Otherwise, say N.
X
X Math emulation
X CONFIG_FPE_NWFPE
@@ -18483,24 +21991,26 @@
X You may say N here if you are going to load the Acorn FPEmulator
X early in the bootup.
X
+FastFPE math emulation
X CONFIG_FPE_FASTFPE
X Say Y here to include the FAST floating point emulator in the kernel.
X This is an experimental much faster emulator which has only 32 bit
- precision for the mantissa. It does not support any exceptions. This
- makes it very simple, it is approximately 4-8 times faster than NWFPE.
-
- It should be sufficient for most programs. It is definitely not
- suitable if you do scientific calculations that need double precision
- for iteration formulas that sum up lots of very small numbers. If you
- do not feel you need a faster FP emulation you should better choose
+ precision for the mantissa. It does not support any exceptions.
+ This makes it very simple, it is approximately 4-8 times faster than
X NWFPE.
X
+ It should be sufficient for most programs. It is definitely not
+ suitable if you do scientific calculations that need double
+ precision for iteration formulas that sum up lots of very small
+ numbers. If you do not feel you need a faster FP emulation you
+ should better choose NWFPE.
+
X It is also possible to say M to build the emulator as a module
- (fastfpe.o). But keep in mind that you should only load the FP emulator
- early in the bootup. You should never change from NWFPE to FASTFPE or
- vice versa in an active system!
+ (fastfpe.o). But keep in mind that you should only load the FP
+ emulator early in the bootup. You should never change from NWFPE to
+ FASTFPE or vice versa in an active system!
X
-DS1620 Thermometer support
+DS1620 thermometer support
X CONFIG_DS1620
X Say Y here to include support for the thermal management hardware
X found in the NetWinder. This driver allows the user to control the
@@ -18531,7 +22041,7 @@
X information that is reported is severely limited. Most people
X should say N here.
X
-User fault debugging
+Verbose user fault messages
X CONFIG_DEBUG_USER
X When a user program crashes due to an exception, the kernel can
X print a brief message explaining what the problem was. This is
@@ -18555,22 +22065,18 @@
X
X Kernel low-level debugging messages via footbridge serial port
X CONFIG_DEBUG_DC21285_PORT
- Say Y here if you want the low-level print routines to direct their
- output to the serial port in the DC21285 (Footbridge).
+ Say Y here if you want the debug print routines to direct their
+ output to the serial port in the DC21285 (Footbridge). Saying N
+ will cause the debug messages to appear on the first 16550
+ serial port.
+
+Kernel low-level debugging messages via UART2
+CONFIG_DEBUG_CLPS711X_UART2
+ Say Y here if you want the debug print routines to direct their
+ output to the second serial port on these devices. Saying N will
+ cause the debug messages to appear on the first serial port.
X
-Split initialisation functions into discardable section
-CONFIG_TEXT_SECTIONS
- If you say Y here, kernel code that is only used during
- initialisation is collected into a special area of the kernel so
- that it can be discarded and the memory reclaimed when
- initialisation is complete. In addition, if the kernel you wish to
- build is able to run on multiple architectures, it allows the unused
- code to be discarded. Some versions of binutils, however, have a bug
- that causes the kernel to crash during startup when this option is
- enabled. Say Y unless you experience problems that you suspect may
- be caused by this.
-
-Disable pgtable cache (EXPERIMENTAL)
+Disable pgtable cache
X CONFIG_NO_PGT_CACHE
X Normally the kernel maintains a `quicklist' of preallocated
X pagetable structures in order to increase performance. On machines
@@ -18580,7 +22086,7 @@
X RISC OS personality
X CONFIG_ARTHUR
X Say Y here to include the kernel code necessary if you want to run
- Acorn RISC OS/Arthur binaries under Linux. This code is still very
+ Acorn RISC OS/Arthur binaries under Linux. This code is still very
X experimental; if this sounds frightening, say N and sleep in peace.
X You can also say M here to compile this support as a module (which
X will be called arthur.o).
@@ -18591,9 +22097,9 @@
X for the boot loader to pass arguments to the kernel. For these
X architectures, you should supply some command-line options at build
X time by entering them here. As a minimum, you should specify the
- memory size and the root device (e.g., mem=64M root=/dev/nfs)
+ memory size and the root device (e.g., mem=64M root=/dev/nfs).
X
-Hardware alignment trap (EXPERIMENTAL)
+Kernel-mode alignment trap handler
X CONFIG_ALIGNMENT_TRAP
X ARM processors can not fetch/store information which is not
X naturally aligned on the bus, i.e., a 4 byte fetch must start at an
@@ -18603,57 +22109,82 @@
X correct operation of some network protocols. With an IP-only
X configuration it is safe to say N, otherwise say Y.
X
-21285 serial port support
+DC21285 serial port support
X CONFIG_SERIAL_21285
X If you have a machine based on a 21285 (Footbridge) StrongARM(R)/
X PCI bridge you can enable its onboard serial port by enabling this
X option. The device has major ID 4, minor 64.
X
-Console on 21285 serial port
+Console on DC21285 serial port
X CONFIG_SERIAL_21285_CONSOLE
X If you have enabled the serial port on the 21285 footbridge you can
X make it the console by answering Y to this option.
X
X SA1100 serial port support
X CONFIG_SERIAL_SA1100
+ * Orphaned entry retained 20 April 2001 by Russell King *


+ * If you read this note from the configurator, please contact *
+ * the Configure.help maintainers. *

X If you have a machine based on a SA1100/SA1110 StrongARM CPU you can
X enable its onboard serial port by enabling this option.
- Please read Documentation/arm/SA1100/serial_UART for further info.
+ Please read <file:Documentation/arm/SA1100/serial_UART> for further
+ info.
X
X Console on SA1100 serial port
X CONFIG_SERIAL_SA1100_CONSOLE
+ * Orphaned entry retained 20 April 2001 by Russell King *


+ * If you read this note from the configurator, please contact *
+ * the Configure.help maintainers. *

X If you have enabled the serial port on the SA1100/SA1110 StrongARM
X CPU you can make it the console by answering Y to this option.
X
X L7200 serial port support
X CONFIG_SERIAL_L7200
+ * Orphaned entry retained 20 April 2001 by Russell King *


+ * If you read this note from the configurator, please contact *
+ * the Configure.help maintainers. *

X If you have a LinkUp Systems L7200 board you can enable its two
X onboard serial ports by enabling this option. The device numbers
X are major ID 4 with minor 64 and 65 respectively.
X
X Console on L7200 serial port
X CONFIG_SERIAL_L7200_CONSOLE
+ * Orphaned entry retained 20 April 2001 by Russell King *


+ * If you read this note from the configurator, please contact *
+ * the Configure.help maintainers. *

X If you have enabled the serial ports on the L7200 development board
X you can make the first serial port the console by answering Y to
X this option.
X
X L7200 SDB keyboard support
X CONFIG_KEYBOARD_L7200
+ * Orphaned entry retained 20 April 2001 by Russell King *


+ * If you read this note from the configurator, please contact *
+ * the Configure.help maintainers. *

X Enable this option if you would like to be able to use a keyboard
X on a LinkUp Systems L7200 board.
X
X L7200 SDB Fujitsu keyboard support
X CONFIG_KEYBOARD_L7200_NORM
+ * Orphaned entry retained 20 April 2001 by Russell King *


+ * If you read this note from the configurator, please contact *
+ * the Configure.help maintainers. *

X Select the Fujitsu keyboard if you want a normal QWERTY style
X keyboard on the LinkUp SDB.
X
X L7200 SDB Prototype keyboard support
X CONFIG_KEYBOARD_L7200_DEMO
+ * Orphaned entry retained 20 April 2001 by Russell King *


+ * If you read this note from the configurator, please contact *
+ * the Configure.help maintainers. *

X Select the prototype keyboard if you want to play with the
X LCD/keyboard combination on the LinkUp SDB.
X
X Footbridge Mode
X CONFIG_HOST_FOOTBRIDGE
+ * Orphaned entry retained 20 April 2001 by Russell King *


+ * If you read this note from the configurator, please contact *
+ * the Configure.help maintainers. *

X The 21285 Footbridge chip can operate in either `host mode' or
X `add-in' mode. Say Y if your 21285 is in host mode, and therefore
X is the configuration master, otherwise say N. This must not be
@@ -18691,7 +22222,7 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called nwflash.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
X
X If you're not sure, say N.
X
@@ -18704,22 +22235,22 @@
X
X This driver is also available as a module and will be called
X srm_env.o if you build it as a module.
-
+
X Footbridge internal watchdog
X CONFIG_21285_WATCHDOG
- The Intel Footbridge chip contains a builtin watchdog circuit. Say Y
+ The Intel Footbridge chip contains a builtin watchdog circuit. Say Y
X here if you wish to use this. Alternatively say M to compile the
X driver as a module, which will be called wdt285.o.
X
- This driver does not work on all machines. In particular, early CATS
- boards have hardware problems that will cause the machine to simply
+ This driver does not work on all machines. In particular, early CATS
+ boards have hardware problems that will cause the machine to simply
X lock up if the watchdog fires.
X
X "If in doubt, leave it out" - say N.
X
-NetWinder WB977 watchdog
+NetWinder WB83C977 watchdog
X CONFIG_977_WATCHDOG
- Say Y here to include support for the WB977 watchdog included in
+ Say Y here to include support for the WB977 watchdog included in
X NetWinder machines. Alternatively say M to compile the driver as
X a module, which will be called wdt977.o.
X
@@ -18732,27 +22263,41 @@
X infrared communication and is supported by most laptops and PDA's.
X
X To use Linux support for the IrDA (tm) protocols, you will also need
- some user-space utilities like irattach. For more information, see the file
- Documentation/networking/irda.txt. You also want to read the
- IR-HOWTO, available at http://www.linuxdoc.org/docs.html#howto .
+ some user-space utilities like irattach. For more information, see
+ the file <file:Documentation/networking/irda.txt>. You also want to
+ read the IR-HOWTO, available at
+ <http://www.linuxdoc.org/docs.html#howto>.
+
+ If you want to exchange bits of data (vCal, vCard) with a PDA, you
+ will need to install some OBEX application, such as OpenObex :
+ <http://sourceforge.net/projects/openobex/>
X
- This support is also available as a module called irda.o. If you
+ This support is also available as a module called irda.o. If you
X want to compile it as a module, say M here and read


- Documentation/modules.txt.
+ <file:Documentation/modules.txt>.
+

+Ultra (connectionless) protocol
+CONFIG_IRDA_ULTRA
+ Say Y here to support the connectionless Ultra IRDA protocol.
+ Ultra allows to exchange data over IrDA with really simple devices
+ (watch, beacon) without the overhead of the IrDA protocol (no handshaking,
+ no management frames, simple fixed header).
+ Ultra is available as a special socket : socket(AF_IRDA, SOCK_DGRAM, 1);
X
X IrDA protocol options
X CONFIG_IRDA_OPTIONS
- Say Y here if you want to configure any of the following IrDA options.
+ Say Y here if you want to configure any of the following IrDA
+ options.
X
-IrDA Cache last LSAP
+IrDA cache last LSAP
X CONFIG_IRDA_CACHE_LAST_LSAP
- Say Y here if you want IrLMP to cache the last LSAP used. This makes
- sense since most frames will be sent/received on the same
- connection. Enabling this option will save a hash-lookup per frame.
+ Say Y here if you want IrLMP to cache the last LSAP used. This
+ makes sense since most frames will be sent/received on the same
+ connection. Enabling this option will save a hash-lookup per frame.
X
X If unsure, say Y.
X
-IrDA Fast RR's
+IrDA Fast RRs
X CONFIG_IRDA_FAST_RR
X Say Y here is you want IrLAP to send fast RR (Receive Ready) frames
X when acting as a primary station. This will make IrLAP send out a RR
@@ -18768,129 +22313,165 @@
X
X If unsure, say N.
X
-IrDA Debug
+IrDA debugging information
X CONFIG_IRDA_DEBUG
X Say Y here if you want the IrDA subsystem to write debug information
X to your syslog. You can change the debug level in
- /proc/sys/net/irda/debug
+ /proc/sys/net/irda/debug .
X
X If unsure, say Y (since it makes it easier to find the bugs).
X
-IrLAP Compression support
+IrLAP compression support
X CONFIG_IRDA_COMPRESSION
X Compression is _not_ part of the IrDA(tm) protocol specification,
X but it's working great! Linux is the first to try out compression
X support at the IrLAP layer. This means that you will only benefit
X from compression if you are running a Linux <-> Linux configuration.
-
+
X If you say Y here, you also need to say Y or M to a compression
X protocol below.
X
-IrLAP Deflate Compression Protocol (EXPERIMENTAL)
+IrLAP Deflate compression
X CONFIG_IRDA_DEFLATE
X Say Y here if you want to build support for the Deflate compression
X protocol. The deflate compression (GZIP) is exactly
- the same as the one used by the PPP protocol.
+ the same as the one used by the PPP protocol.
X
X If you want to compile this compression support as a module, say M
- here and read Documentation/modules.txt. The module will be called
- irda_deflate.o.
+ here and read <file:Documentation/modules.txt>. The module will be
+ called irda_deflate.o.
X
-IrLAN Protocol
+IrLAN protocol
X CONFIG_IRLAN
- Say Y here if you want to build support for the IrLAN protocol. If
+ Say Y here if you want to build support for the IrLAN protocol. If
X you want to compile it as a module (irlan.o), say M here and read
- Documentation/modules.txt. IrLAN emulates an Ethernet and makes it
- possible to put up a wireless LAN using infrared beams.
+ <file:Documentation/modules.txt>. IrLAN emulates an Ethernet and
+ makes it possible to put up a wireless LAN using infrared beams.
X
- The IrLAN protocol can be used to talk with infrared access points
- like the HP NetbeamIR, or the ESI JetEye NET. You can also connect
- to another Linux machine running the IrLAN protocol for ad-hoc
+ The IrLAN protocol can be used to talk with infrared access points
+ like the HP NetbeamIR, or the ESI JetEye NET. You can also connect
+ to another Linux machine running the IrLAN protocol for ad-hoc
X networking!
X
-IrNET Protocol
+IrNET protocol
X CONFIG_IRNET
- Say Y here if you want to build support for the IrNET protocol. If
+ Say Y here if you want to build support for the IrNET protocol. If
X you want to compile it as a module (irnet.o), say M here and read
- Documentation/modules.txt. IrNET is a PPP driver, so you will also
- need a working PPP subsystem (driver, daemon and config)...
+ <file:Documentation/modules.txt>. IrNET is a PPP driver, so you
+ will also need a working PPP subsystem (driver, daemon and
+ config)...
X
- IrNET is an alternate way to tranfer TCP/IP traffic over IrDA. It
- uses synchronous PPP over a set of point to point IrDA sockets. You
+ IrNET is an alternate way to tranfer TCP/IP traffic over IrDA. It
+ uses synchronous PPP over a set of point to point IrDA sockets. You
X can use it between Linux machine or with W2k.
X
-IrCOMM Protocol
+IrCOMM protocol
X CONFIG_IRCOMM
- Say Y here if you want to build support for the IrCOMM protocol. If
+ Say Y here if you want to build support for the IrCOMM protocol. If
X you want to compile it as a module (you will get ircomm.o and
- ircomm-tty.o), say M here and read Documentation/modules.txt. IrCOMM
- implements serial port emulation, and makes it possible to use all
- existing applications that understands TTY's with an infrared link.
- Thus you should be able to use application like PPP, minicom and
- others. Enabling this option will create two modules called ircomm
- and ircomm_tty.
+ ircomm-tty.o), say M here and read <file:Documentation/modules.txt>.
+ IrCOMM implements serial port emulation, and makes it possible to
+ use all existing applications that understands TTY's with an
+ infrared link. Thus you should be able to use application like PPP,
+ minicom and others. Enabling this option will create two modules
+ called ircomm and ircomm_tty.
X
X IrTTY IrDA Device Driver
X CONFIG_IRTTY_SIR
X Say Y here if you want to build support for the IrTTY line
- discipline. If you want to compile it as a module (irtty.o), say M
- here and read Documentation/modules.txt. IrTTY makes it possible to
- use Linux's own serial driver for all IrDA ports that are 16550
- compatible. Most IrDA chips are 16550 compatible so you should
- probably say Y to this option. Using IrTTY will however limit the
- speed of the connection to 115200 bps (IrDA SIR mode)
+ discipline. If you want to compile it as a module (irtty.o), say M
+ here and read <file:Documentation/modules.txt>. IrTTY makes it
+ possible to use Linux's own serial driver for all IrDA ports that
+ are 16550 compatible. Most IrDA chips are 16550 compatible so you
+ should probably say Y to this option. Using IrTTY will however
+ limit the speed of the connection to 115200 bps (IrDA SIR mode).
X
X If unsure, say Y.
X
-IrPORT IrDA Device Driver
+IrPORT IrDA serial driver
X CONFIG_IRPORT_SIR
X Say Y here if you want to build support for the IrPORT IrDA device
X driver. If you want to compile it as a module (irport.o), say M here
- and read Documentation/modules.txt. IrPORT can be used instead of
- IrTTY and sometimes this can be better. One example is if your IrDA
- port does not have echo-canceling, which will work OK with IrPORT
- since this driver is working in half-duplex mode only. You don't
- need to use irattach with IrPORT, but you just insert it the same
- way as FIR drivers (insmod irport io=0x3e8 irq=11). Notice that
- IrPORT is a SIR device driver which means that speed is limited to
- 115200 bps.
+ and read <file:Documentation/modules.txt>. IrPORT can be used
+ instead of IrTTY and sometimes this can be better. One example is
+ if your IrDA port does not have echo-canceling, which will work OK
+ with IrPORT since this driver is working in half-duplex mode only.
+ You don't need to use irattach with IrPORT, but you just insert it
+ the same way as FIR drivers (insmod irport io=0x3e8 irq=11). Notice
+ that IrPORT is a SIR device driver which means that speed is limited
+ to 115200 bps.
X
X If unsure, say Y.
X
+USB IrDA FIR dongle Device Driver
+CONFIG_USB_IRDA
+ Say Y here if you want to build support for the USB IrDA FIR Dongle
+ device driver. If you want to compile it as a module (irda-usb.o),
+ say M here and read <file:Documentation/modules.txt>. IrDA-USB
+ support the various IrDA USB dongles available and most of their
+ pecularities. Those dongles plug in the USB port of your computer,
+ are plug and play, and support SIR and FIR (4Mbps) speeds. On the
+ other hand, those dongles tend to be less efficient than a FIR
+ chipset.
+
+ Please note that the driver is still experimental. And of course,
+ you will need both USB and IrDA support in your kernel...
+
X Winbond W83977AF IrDA Device Driver
X CONFIG_WINBOND_FIR
X Say Y here if you want to build IrDA support for the Winbond
- W83977AF super-io chipset. This driver should be used for the IrDA
- chipset in the Corel NetWinder. The driver supports SIR, MIR and FIR
- (4Mbps) speeds.
+ W83977AF super-io chipset. This driver should be used for the IrDA
+ chipset in the Corel NetWinder. The driver supports SIR, MIR and
+ FIR (4Mbps) speeds.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. The module will be called w83977af_ir.o.
+ <file:Documentation/modules.txt>. The module will be called
+ w83977af_ir.o.
X
-NSC PC87108 IrDA Device Driver
+NSC PC87108/PC87338 IrDA Device Driver
X CONFIG_NSC_FIR
X Say Y here if you want to build support for the NSC PC87108 and
- PC87338 IrDA chipsets. This driver supports SIR,
- MIR and FIR (4Mbps) speeds.
+ PC87338 IrDA chipsets. This driver supports SIR,
+ MIR and FIR (4Mbps) speeds.
X
X If you want to compile it as a module, say M here and read
- Documentation/modules.txt. The module will be called nsc-ircc.o.
+ <file:Documentation/modules.txt>. The module will be called
+ nsc-ircc.o.
X
-Toshiba Type-O IR Port Device Driver
+National Semiconductor DP83820 series driver
+CONFIG_NS83820
+ This is a driver for the National Semiconductor DP83820 series
+ of gigabit ethernet MACs. Cards using this chipset include
+ the D-Link DGE-500T, PureData's PDP8023Z-TG, SMC's SMC9462TX,
+ SOHO-GA2000T, SOHO-GA2500T. The driver supports the use of
+ zero copy.
+
+Toshiba Type-O IR Port device driver
X CONFIG_TOSHIBA_FIR
X Say Y here if you want to build support for the Toshiba Type-O IR
- chipset. This chipset is used by the Toshiba Libretto 100CT, and
- many more laptops. If you want to compile it as a module, say M here
- and read Documentation/modules.txt. The module will be called
- toshoboe.o.
+ chipset. This chipset is used by the Toshiba Libretto 100CT, and
+ many more laptops. If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>. The module will be
+ called toshoboe.o.
X
-SMC IrCC (Experimental)
+SMC IrCC
X CONFIG_SMC_IRCC_FIR
X Say Y here if you want to build support for the SMC Infrared
- Communications Controller. It is used in the Fujitsu Lifebook 635t
- and Sony PCG-505TX. If you want to compile it as a module, say M
- here and read Documentation/modules.txt. The module will be called
- smc-ircc.o.
+ Communications Controller. It is used in the Fujitsu Lifebook 635t
+ and Sony PCG-505TX. If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>. The module will be
+ called smc-ircc.o.
+
+ALi M5123 FIR Controller Driver
+CONFIG_ALI_FIR
+ Say Y here if you want to build support for the ALi M5123 FIR
+ Controller. The ALi M5123 FIR Controller is embedded in ALi M1543C,
+ M1535, M1535D, M1535+, M1535D Sourth Bridge. This driver supports
+ SIR, MIR and FIR (4Mbps) speeds.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ ali-ircc.o.
X
X VLSI 82C147 PCI-IrDA Controller Driver
X CONFIG_VLSI_FIR
@@ -18909,69 +22490,76 @@
X or M to the driver for your particular dongle below.
X

X Note that the answer to this question won't directly affect the
- kernel: saying N will just cause this configure script to skip all
+ kernel: saying N will just cause the configurator to skip all

X the questions about serial dongles.
X
-ESI JetEye PC Dongle
+ESI JetEye PC dongle
X CONFIG_ESI_DONGLE
X Say Y here if you want to build support for the Extended Systems
- JetEye PC dongle. If you want to compile it as a module, say M here
- and read Documentation/modules.txt. The ESI dongle attaches to the
- normal 9-pin serial port connector, and can currently only be used
- by IrTTY. To activate support for ESI dongles you will have to
+ JetEye PC dongle. If you want to compile it as a module, say M here
+ and read <file:Documentation/modules.txt>. The ESI dongle attaches
+ to the normal 9-pin serial port connector, and can currently only be
+ used by IrTTY. To activate support for ESI dongles you will have to
X start irattach like this: "irattach -d esi".
X
X ACTiSYS IR-220L and IR220L+ dongle
X CONFIG_ACTISYS_DONGLE
- Say Y here if you want to build support for the ACTiSYS
- IR-220L and IR220L+ dongles. If you want to compile it as a module,
- say M here and read Documentation/modules.txt. The ACTiSYS dongles
+ Say Y here if you want to build support for the ACTiSYS IR-220L and
+ IR220L+ dongles. If you want to compile it as a module, say M here
+ and read <file:Documentation/modules.txt>. The ACTiSYS dongles
X attaches to the normal 9-pin serial port connector, and can
- currently only be used by IrTTY. To activate support for ACTiSYS
- dongles you will have to start irattach like this:
+ currently only be used by IrTTY. To activate support for ACTiSYS
+ dongles you will have to start irattach like this:
X "irattach -d actisys" or "irattach -d actisys+".
X
X Tekram IrMate 210B dongle
X CONFIG_TEKRAM_DONGLE
- Say Y here if you want to build support for the Tekram IrMate 210B
- dongle. If you want to compile it as a module, say M here
- and read Documentation/modules.txt. The Tekram dongle attaches to
- the normal 9-pin serial port connector, and can currently only be
- used by IrTTY. To activate support for Tekram dongles you will have
- to start irattach like this: "irattach -d tekram".
+ Say Y here if you want to build support for the Tekram IrMate 210B
+ dongle. If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The Tekram dongle attaches to the
+ normal 9-pin serial port connector, and can currently only be used
+ by IrTTY. To activate support for Tekram dongles you will have to
+ start irattach like this: "irattach -d tekram".
X
X Greenwich GIrBIL dongle
X CONFIG_GIRBIL_DONGLE
X Say Y here if you want to build support for the Greenwich GIrBIL
- dongle. If you want to compile it as a module, say M here and read
- Documentation/modules.txt. The Greenwich dongle attaches to the
- normal 9-pin serial port connector, and can currently only be used
- by IrTTY. To activate support for Greenwich dongles you will have to
- insert "irattach -d girbil" in the /etc/irda/drivers script.
+ dongle. If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The Greenwich dongle attaches to
+ the normal 9-pin serial port connector, and can currently only be
+ used by IrTTY. To activate support for Greenwich dongles you will
+ have to insert "irattach -d girbil" in the /etc/irda/drivers script.
X
-Parallax Litelink dongle
+Parallax LiteLink dongle
X CONFIG_LITELINK_DONGLE
X Say Y here if you want to build support for the Parallax Litelink
- dongle. If you want to compile it as a module, say M here and read
- Documentation/modules.txt. The Parallax dongle attaches to the
- normal 9-pin serial port connector, and can currently only be used
- by IrTTY. To activate support for Parallax dongles you will have to
- start irattach like this "irattach -d litelink".
+ dongle. If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The Parallax dongle attaches to
+ the normal 9-pin serial port connector, and can currently only be
+ used by IrTTY. To activate support for Parallax dongles you will
+ have to start irattach like this "irattach -d litelink".
X
X Old Belkin dongle
X CONFIG_OLD_BELKIN_DONGLE
X Say Y here if you want to build support for the Adaptec Airport 1000
- and 2000 dongles. If you want to compile it as a module, say M here
- and read Documentation/modules.txt. The module will be called
- old_belkin.o. Some information is contained in the comments at the
- top of drivers/net/irda/old_belkin.c.
+ and 2000 dongles. If you want to compile it as a module, say M here
+ and read <file:Documentation/modules.txt>. The module will be
+ called old_belkin.o. Some information is contained in the comments
+ at the top of <file:drivers/net/irda/old_belkin.c>.
X
X VME (Motorola and BVM) support
X CONFIG_VME
X Say Y here if you want to build a kernel for a 680x0 based VME
- board. Boards currently supported include Motorola boards MVME162,
- MVME166, MVME167, MVME172, and MVME177. BVME4000 and BVME6000
- boards from BVM Ltd are also supported.
+ board. Boards currently supported include Motorola boards MVME147,
+ MVME162, MVME166, MVME167, MVME172, and MVME177. BVME4000 and
+ BVME6000 boards from BVM Ltd are also supported.
+
+MVME147 support
+CONFIG_MVME147
+ Say Y to include support for early Motorola VME boards. This will
+ build a kernel which can run on MVME147 single-board computers. If
+ you select this option you will have to select the appropriate
+ drivers for SCSI, Ethernet and serial ports later on.
X
X MVME162, 166 and 167 support
X CONFIG_MVME16x
@@ -19001,6 +22589,16 @@
X is hardwired on. The 53c710 SCSI driver is known to suffer from
X this problem.
X
+WD33C93 SCSI driver for MVME147
+CONFIG_MVME147_SCSI
+ Support for the on-board SCSI controller on the Motorola MVME147
+ single-board computer.
+
+SCC support for MVME147 serial ports
+CONFIG_MVME147_SCC
+ This is the driver for the serial ports on the Motorola MVME147
+ boards. Everyone using one of these boards should say Y here.
+
X NCR53C710 SCSI driver for MVME16x
X CONFIG_MVME16x_SCSI
X The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710
@@ -19013,19 +22611,26 @@
X SCSI controller chip. Almost everyone using one of these boards
X will want to say Y to this question.
X
+MVME147 (Lance) Ethernet support
+CONFIG_MVME147_NET
+ Support for the on-board Ethernet interface on the Motorola MVME147
+ single-board computer. Say Y here to include the
+ driver for this chip in your kernel. If you want to compile it as


+ a module, say M here and read <file:Documentation/modules.txt>.
+

X MVME16x Ethernet support
X CONFIG_MVME16x_NET
X This is the driver for the Ethernet interface on the Motorola
X MVME162, 166, 167, 172 and 177 boards. Say Y here to include the
X driver for this chip in your kernel. If you want to compile it as
- a module, say M here and read Documentation/modules.txt.
+ a module, say M here and read <file:Documentation/modules.txt>.
X
X BVME6000 Ethernet support
X CONFIG_BVME6000_NET
X This is the driver for the Ethernet interface on BVME4000 and
X BVME6000 VME boards. Say Y here to include the driver for this chip
X in your kernel. If you want to compile it as a module, say M here
- and read Documentation/modules.txt.
+ and read <file:Documentation/modules.txt>.
X
X CD2401 support for MVME166/7 serial ports
X CONFIG_SERIAL167
@@ -19052,11 +22657,707 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called display7seg.o. If you want to compile it
- as a module, say M here and read Documentation/modules.txt.
+ as a module, say M here and read <file:Documentation/modules.txt>.
X
X If you do not have a CompactPCI model CP1400 or CP1500, or
X another UltraSPARC-IIi-cEngine boardset with a 7-segment display,
- you should say N to this option.
+ you should say N to this option.
+
+# Choice: cristype
+Etrax-100-LX-v1
+CONFIG_ETRAX100LX
+ Support version 1 of the Etrax 100LX.
+
+Etrax-100-LX-v2
+CONFIG_ETRAX100LX_V2
+ Support version 2 of the Etrax 100LX.
+
+Etrax-100-LX-for-xsim-simulator
+CONFIG_SVINTO_SIM
+ Support the xsim ETRAX Simulator.
+
+DRAM size (dec, in MB)
+CONFIG_ETRAX_DRAM_SIZE
+ Size of DRAM (decimal in MB) typically 2, 8 or 16.
+
+ETRAX Flash Memory configuration
+CONFIG_ETRAX_FLASH_BUSWIDTH
+ Width in bytes of the Flash bus (1, 2 or 4). Is usually 2.
+
+LED configuration on PA
+CONFIG_ETRAX_PA_LEDS
+ The Etrax network driver is responsible for flashing LED's when
+ packets arrive and are sent. It uses macros defined in
+ <file:include/asm-cris/io.h>, and those macros are defined after what
+ YOU choose in this option. The actual bits used are configured
+ separately. Select this if the LEDs are on port PA. Some products
+ put the leds on PB or a memory-mapped latch (CSP0) instead.
+
+LED configuration on PB
+CONFIG_ETRAX_PB_LEDS
+ The Etrax network driver is responsible for flashing LED's when
+ packets arrive and are sent. It uses macros defined in
+ <file:include/asm-cris/io.h>, and those macros are defined after what
+ YOU choose in this option. The actual bits used are configured
+ separately. Select this if the LEDs are on port PB. Some products
+ put the leds on PA or a memory-mapped latch (CSP0) instead.
+
+LED configuration on CSP0
+CONFIG_ETRAX_CSP0_LEDS
+ The Etrax network driver is responsible for flashing LED's when
+ packets arrive and are sent. It uses macros defined in
+ <file:include/asm-cris/io.h>, and those macros are defined after what
+ YOU choose in this option. The actual bits used are configured
+ separately. Select this if the LEDs are on a memory-mapped latch
+ using chip select CSP0, this is mapped at 0x90000000.
+ Some products put the leds on PA or PB instead.
+
+No LED at all
+CONFIG_ETRAX_NO_LEDS
+ Select this option if you don't have any LED at all.
+
+First green LED bit
+CONFIG_ETRAX_LED1G
+ Bit to use for the first green LED.
+ Most Axis products use bit 2 here.
+
+First red LED bit
+CONFIG_ETRAX_LED1R
+ Bit to use for the first red LED.
+ Most Axis products use bit 3 here.
+ For products with only one controllable LED,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Second green LED bit
+CONFIG_ETRAX_LED2G
+ Bit to use for the second green LED. The "Active" LED.
+ Most Axis products use bit 4 here.
+ For products with only one controllable LED,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Second red LED bit
+CONFIG_ETRAX_LED2R
+ Bit to use for the second red LED.
+ Most Axis products use bit 5 here.
+ For products with only one controllable LED,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Third green LED bit
+CONFIG_ETRAX_LED3G
+ Bit to use for the third green LED. The "Drive" LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Third red LED bit
+CONFIG_ETRAX_LED3R
+ Bit to use for the third red LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Fourth green LED bit
+CONFIG_ETRAX_LED4G
+ Bit to use for the fourth green LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Fourth red LED bit
+CONFIG_ETRAX_LED4R
+ Bit to use for the fourth red LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Fifth green LED bit
+CONFIG_ETRAX_LED5G
+ Bit to use for the fifth green LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Fifth red LED bit
+CONFIG_ETRAX_LED5R
+ Bit to use for the fifth red LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Sixth green LED bit
+CONFIG_ETRAX_LED6G
+ Bit to use for the sixth green LED. The "Drive" LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Sixth red LED bit
+CONFIG_ETRAX_LED6R
+ Bit to use for the sixth red LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Seventh green LED bit
+CONFIG_ETRAX_LED7G
+ Bit to use for the seventh green LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Seventh red LED bit
+CONFIG_ETRAX_LED7R
+ Bit to use for the seventh red LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Eighth yellow LED bit
+CONFIG_ETRAX_LED8Y
+ Bit to use for the eighth yellow LED. The "Drive" LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Ninth yellow LED bit
+CONFIG_ETRAX_LED9Y
+ Bit to use for the ninth yellow LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Tenth yellow LED bit
+CONFIG_ETRAX_LED10Y
+ Bit to use for the tenth yellow LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Eleventh yellow LED bit
+CONFIG_ETRAX_LED11Y
+ Bit to use for the eleventh yellow LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Twelfth red LED bit
+CONFIG_ETRAX_LED12R
+ Bit to use for the twelfth red LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+Flash LED off during activity
+CONFIG_ETRAX_LED_OFF_DURING_ACTIVITY
+ This option allows you to decide whether the network LED (and
+ Bluetooth LED in case you use Bluetooth) will be on or off when
+ the network is connected, and whether it should flash off or on
+ when there is activity. If you say y to this option the network
+ LED will be lit when there is a connection, and will flash off
+ when there is activity.
+
+PA button configuration
+CONFIG_ETRAX_PA_BUTTON_BITMASK
+ This is a bitmask with information about what bits on PA that
+ are used for buttons.
+ Most products has a so called TEST button on PA1, if that's true
+ use 02 here.
+ Use 00 if there are no buttons on PA.
+ If the bitmask is <> 00 a button driver will be included in the gpio
+ driver. Etrax general I/O support must be enabled.
+
+PA changeable direction bits
+CONFIG_ETRAX_PA_CHANGEABLE_DIR
+ This is a bitmask with information of what bits in PA that a user
+ can change direction on using ioctl's.
+ Bit set = changeable.
+ You probably want 00 here.
+
+PA changeable data bits
+CONFIG_ETRAX_PA_CHANGEABLE_BITS
+ This is a bitmask with information of what bits in PA that a user
+ can change change the value on using ioctl's.
+ Bit set = changeable.
+ You probably want 00 here.
+
+PA changeable direction bits
+CONFIG_ETRAX_PB_CHANGEABLE_DIR
+ This is a bitmask with information of what bits in PB that a user
+ can change direction on using ioctl's.
+ Bit set = changeable.
+ You probably want 00 here.
+
+PB changeable data bits
+CONFIG_ETRAX_PB_CHANGEABLE_BITS
+ This is a bitmask with information of what bits in PB that a user
+ can change the value on using ioctl's.
+ Bit set = changeable.
+ You probably want 00 here.
+
+Kernel debugger (kgdb)
+CONFIG_ETRAX_KGDB
+ The CRIS version of gdb can be used to remotely debug a running
+ Linux kernel via the serial debug port. Provided you have gdb-cris
+ installed, run gdb-cris vmlinux, then type
+
+ (gdb) set remotebaud 115200 <- kgdb uses 115200 as default
+ (gdb) target remote /dev/ttyS0 <- maybe you use another port
+
+ This should connect you to your booted kernel (or boot it now if you
+ didn't before). The kernel halts when it boots, waiting for gdb if
+ this option is turned on!
+
+Etrax bus waitstates
+CONFIG_ETRAX_DEF_R_WAITSTATES
+ Waitstates for SRAM, Flash and peripherials (not DRAM). 95f8 is a
+ good choice for most Axis products...
+
+Etrax bus configuration
+CONFIG_ETRAX_DEF_R_BUS_CONFIG
+ Assorted bits controlling write mode, DMA burst length etc. 104 is
+ a good choice for most Axis products...
+
+Etrax SDRAM configuration
+CONFIG_ETRAX_SDRAM
+ Enable this if you use SDRAM chips and configure
+ R_SDRAM_CONFIG and R_SDRAM_TIMING as well.
+
+DRAM size (dec, in MB)
+CONFIG_ETRAX_DEF_R_DRAM_CONFIG
+ The R_DRAM_CONFIG register specifies everything on how the DRAM
+ chips in the system are connected to the Etrax CPU. This is
+ different depending on the manufacturer, chip type and number of
+ chips. So this value often needs to be different for each Axis
+ product.
+
+Etrax DRAM timing
+CONFIG_ETRAX_DEF_R_DRAM_TIMING
+ Different DRAM chips have different speeds. Current Axis products
+ use 50ns DRAM chips which can use the timing: 5611.
+
+Etrax SDRAM configuration
+CONFIG_ETRAX_DEF_R_SDRAM_CONFIG
+ The R_SDRAM_CONFIG register specifies everything on how the SDRAM
+ chips in the system are connected to the Etrax CPU. This is
+ different depending on the manufacturer, chip type and number of
+ chips. So this value often needs to be different for each Axis
+ product.
+
+Etrax SDRAM timing
+CONFIG_ETRAX_DEF_R_SDRAM_TIMING
+ Different SDRAM chips have different timing.
+
+Etrax General port A direction
+CONFIG_ETRAX_DEF_R_PORT_PA_DIR
+ Configures the direction of general port A bits. 1 is out, 0 is in.
+ This is often totally different depending on the product used.
+ There are some guidelines though - if you know that only LED's are
+ connected to port PA, then they are usually connected to bits 2-4
+ and you can therefore use 1c. On other boards which don't have the
+ LED's at the general ports, these bits are used for all kinds of
+ stuff. If you don't know what to use, it is always safe to put all
+ as inputs, although floating inputs isn't good.
+
+Etrax General port A data
+CONFIG_ETRAX_DEF_R_PORT_PA_DATA
+ Configures the initial data for the general port A bits. Most
+ products should use 00 here.
+
+Etrax General port B config
+CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG
+ Configures the type of the general port B bits. 1 is chip select,
+ 0 is port. Most products should use 00 here.
+
+Etrax General port B direction
+CONFIG_ETRAX_DEF_R_PORT_PB_DIR
+ Configures the direction of general port B bits. 1 is out, 0 is in.
+ This is often totally different depending on the product used. Bits
+ 0 and 1 on port PB are usually used for I2C communication, but the
+ kernel I2C driver sets the appropriate directions itself so you
+ don't need to take that into consideration when setting this option.
+ If you don't know what to use, it is always safe to put all as
+ inputs.
+
+Etrax General port B data
+CONFIG_ETRAX_DEF_R_PORT_PB_DATA
+ Configures the initial data for the general port A bits. Most
+ products should use FF here.
+
+Etrax General port device
+CONFIG_ETRAX_GPIO
+ Enables the Etrax general port device (major 120, minors 0 and 1).
+ You can use this driver to access the general port bits. It supports
+ these ioctl's:
+ #include <linux/etraxgpio.h>
+ fd = open("/dev/gpioa", O_RDWR); // or /dev/gpiob
+ ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS), bits_to_set);
+ ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS), bits_to_clear);
+ val = ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_READBITS), NULL);
+ Remember that you need to setup the port directions appropriately in
+ the General configuration.
+
+Etrax parallel data support
+CONFIG_ETRAX_PARDATA
+ Adds support for writing data to the parallel port par0 of the ETRAX
+ 100. If you create a character special file with major number 126,
+ you can write to the data bits of par0.
+ Note: you need to disable Etrax100 parallel port support.
+
+Etrax parallel LCD (HD44780) Driver
+CONFIG_ETRAX_LCD_HD44780
+ Adds support for a HD44780 controlled LCD connected to the parallel
+ port par0 of the Etrax.
+
+Etrax Serial port ser0 support
+CONFIG_ETRAX_SERIAL
+ Enables the ETRAX 100 serial driver for ser0 (ttyS0)
+ You probably want this enabled.
+
+/proc/serial entry
+CONFIG_ETRAX_SERIAL_PROC_ENTRY
+ Enables /proc/serial entry where errors and statistics can be
+ viewed. CONFIG_PROC_FS must also be set for this to work.
+
+Etrax Serial port fast flush of DMA using fast timer API
+CONFIG_ETRAX_SERIAL_FAST_TIMER
+ Select this to have the serial DMAs flushed at a higher rate than
+ normally, possible by using the fast timer API, the timeout is
+ approx. 4 character times.


+ If unsure, say N.
+

+Etrax Serial port fast flush of DMA
+CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
+ Select this to have the serial DMAs flushed at a higher rate than
+ normally possible through a fast timer interrupt (currently at
+ 15360 Hz).


+ If unsure, say N.
+

+Etrax Serial port receive flush timeout
+CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS
+ Number of timer ticks between flush of receive fifo (1 tick = 10ms).
+ Try 0-3 for low latency applications. Approx 5 for high load
+ applications (e.g. PPP). Maybe this should be more adaptive some
+ day...
+
+Etrax Serial port ser0 DTR, RI, DSR and CD support on PB
+CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB
+ Enables the status and control signals DTR, RI, DSR and CD on PB for
+ ser0.
+
+Serial port 1 enabled
+CONFIG_ETRAX_SERIAL_PORT1
+ Enables the ETRAX 100 serial driver for ser1 (ttyS1).
+
+Etrax Serial port ser1 DTR, RI, DSR and CD support on PB
+CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_PB
+ Enables the status and control signals DTR, RI, DSR and CD on PB for
+ ser1.
+
+Serial port 2 enabled
+CONFIG_ETRAX_SERIAL_PORT2
+ Enables the ETRAX 100 serial driver for ser2 (ttyS2).
+
+Etrax Serial port ser2 DTR, RI, DSR and CD support on PA
+CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_PA
+ Enables the status and control signals DTR, RI, DSR and CD on PA for
+ ser2.
+
+Serial port 3 enabled
+CONFIG_ETRAX_SERIAL_PORT3
+ Enables the ETRAX 100 serial driver for ser3 (ttyS3).
+
+Etrax100 RS-485 support
+CONFIG_ETRAX_RS485
+ Enables support for RS-485 serial communication. For a primer on
+ RS-485, see <http://www.hw.cz/english/docs/rs485/rs485.html>.
+
+Etrax100 RS-485 mode on PA
+CONFIG_ETRAX_RS485_ON_PA
+ Control Driver Output Enable on RS485 tranceiver using a pin on PA
+ port:
+ Axis 2400/2401 uses PA 3.
+
+Etrax100 RS-485 mode on PA bit
+CONFIG_ETRAX_RS485_ON_PA_BIT
+ Control Driver Output Enable on RS485 tranceiver using a this bit
+ on PA port.
+
+Ser0 DTR on PB bit
+CONFIG_ETRAX_SER0_DTR_ON_PB_BIT
+ Specify the pin of the PB port to carry the DTR signal for serial
+ port 0.
+
+Ser0 RI on PB bit
+CONFIG_ETRAX_SER0_RI_ON_PB_BIT
+ Specify the pin of the PB port to carry the RI signal for serial
+ port 0.
+
+Ser0 DSR on PB bit
+CONFIG_ETRAX_SER0_DSR_ON_PB_BIT
+ Specify the pin of the PB port to carry the DSR signal for serial
+ port 0.
+
+Ser0 CD on PB bit
+CONFIG_ETRAX_SER0_CD_ON_PB_BIT
+ Specify the pin of the PB port to carry the CD signal for serial
+ port 0.
+
+Ser1 DTR on PB bit
+CONFIG_ETRAX_SER1_DTR_ON_PB_BIT
+ Specify the pin of the PB port to carry the DTR signal for serial
+ port 1.
+
+Ser1 RI on PB bit
+CONFIG_ETRAX_SER1_RI_ON_PB_BIT
+ Specify the pin of the PB port to carry the RI signal for serial
+ port 1.
+
+Ser1 DSR on PB bit
+CONFIG_ETRAX_SER1_DSR_ON_PB_BIT
+ Specify the pin of the PB port to carry the DSR signal for serial
+ port 1.
+
+Ser1 CD on PB bit
+CONFIG_ETRAX_SER1_CD_ON_PB_BIT
+ Specify the pin of the PB port to carry the CD signal for serial
+ port 1.
+
+Ser2 DTR on PA bit
+CONFIG_ETRAX_SER2_DTR_ON_PA_BIT
+ Specify the pin of the PA port to carry the DTR signal for serial
+ port 2.
+
+Ser2 RI on PA bit
+CONFIG_ETRAX_SER2_RI_ON_PA_BIT
+ Specify the pin of the PA port to carry the RI signal for serial
+ port 2.
+
+Ser2 DSR on PA bit
+CONFIG_ETRAX_SER2_DSR_ON_PA_BIT
+ Specify the pin of the PA port to carry the DTR signal for serial
+ port 2.
+
+Ser2 CD on PA bit
+CONFIG_ETRAX_SER2_CD_ON_PA_BIT
+ Specify the pin of the PA port to carry the CD signal for serial
+ port 2.
+
+Etrax100 RS-485 disable receiver
+CONFIG_ETRAX_RS485_DISABLE_RECEIVER
+ It's necessary to disable the serial receiver to avoid serial
+ loopback. Not all products are able to do this in software only.
+ Axis 2400/2401 must disable receiver.
+
+Etrax100 I2C Support
+CONFIG_ETRAX_I2C
+ Enables an I2C driver on PB0 and PB1 on ETRAX100.
+ EXAMPLE usage:
+ i2c_arg = I2C_WRITEARG(STA013_WRITE_ADDR, reg, val);
+ ioctl(fd, _IO(ETRAXI2C_IOCTYPE, I2C_WRITEREG), i2c_arg);
+ i2c_arg = I2C_READARG(STA013_READ_ADDR, reg);
+ val = ioctl(fd, _IO(ETRAXI2C_IOCTYPE, I2C_READREG), i2c_arg);
+
+Etrax100 I2C configuration
+CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C
+ Select whether to use the special I2C mode in the PB I/O register or
+ not. This option needs to be selected in order to use some drivers
+ that access the I2C I/O pins directly instead of going through the
+ I2C driver, like the DS1302 realtime-clock driver. If you are
+ uncertain, choose Y here.
+
+Etrax100 I2C EEPROM (NVRAM) support
+CONFIG_ETRAX_I2C_EEPROM
+ Enables I2C EEPROM (non-volatile RAM) on PB0 and PB1 using the I2C
+ driver. Select size option: Probed, 2k, 8k, 16k.
+ (Probing works for 2k and 8k but not that well for 16k)
+
+Etrax100 I2C EEPROM (NVRAM) size/16kB
+CONFIG_ETRAX_I2C_EEPROM_16KB
+ Use a 16kB EEPROM.
+
+Etrax100 I2C EEPROM (NVRAM) size/2kB
+CONFIG_ETRAX_I2C_EEPROM_2KB
+ Use a 2kB EEPROM.
+
+Etrax100 I2C EEPROM (NVRAM) size/8kB
+CONFIG_ETRAX_I2C_EEPROM_8KB
+ Use a 8kB EEPROM.
+
+Etrax100 I2C EEPROM (NVRAM) size/probe
+CONFIG_ETRAX_I2C_EEPROM_PROBE
+ Specifies size or auto probe of the EEPROM size.
+ Options: Probed, 2k, 8k, 16k.
+ (Probing works for 2k and 8k but not that well for 16k)
+
+Etrax DS1302 Real-Time Clock driver
+CONFIG_ETRAX_DS1302
+ Enables the driver for the DS1302 Real-Time Clock battery-backed
+ chip on some products. The kernel reads the time when booting, and
+ the date can be set using ioctl(fd, RTC_SET_TIME, &rt) with rt a
+ rtc_time struct (see <file:include/asm-cris/rtc.h>) on the /dev/rtc
+ device, major 121. You can check the time with cat /proc/rtc, but
+ normal time reading should be done using libc function time and
+ friends.
+
+Etrax DS1302 RST on the Generic Port
+CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
+ If your product has the RST signal line for the DS1302 RTC on the
+ Generic Port then say Y here, otherwise leave it as N in which
+ case the RST signal line is assumed to be connected to Port PB
+ (just like the SCL and SDA lines).
+
+Etrax DS1302 RST bit number
+CONFIG_ETRAX_DS1302_RSTBIT
+ This is the bit number for the RST signal line of the DS1302 RTC on
+ the selected port. If you have selected the generic port then it
+ should be bit 27, otherwise your best bet is bit 5.
+
+Etrax DS1302 SCL bit number
+CONFIG_ETRAX_DS1302_SCLBIT
+ This is the bit number for the SCL signal line of the DS1302 RTC on
+ Port PB. This is probably best left at 3.
+
+Etrax DS1302 SDA bit number
+CONFIG_ETRAX_DS1302_SDABIT
+ This is the bit number for the SDA signal line of the DS1302 RTC on
+ Port PB. This is probably best left at 2.
+
+Etrax 100 IDE Reset
+CONFIG_ETRAX_IDE_CSP0_8_RESET
+ Configures the pin used to reset the IDE bus.
+
+Etrax 100 IDE Reset
+CONFIG_ETRAX_IDE_CSPE1_16_RESET
+ Configures the pin used to reset the IDE bus.
+
+Etrax 100 ATA/IDE support
+CONFIG_ETRAX_IDE_DELAY
+ Sets the time to wait for disks to regain consciousness after reset.
+
+Etrax 100 IDE Reset
+CONFIG_ETRAX_IDE_G27_RESET
+ Configures the pin used to reset the IDE bus.
+
+IDE reset on PB Bit 7
+CONFIG_ETRAX_IDE_PB7_RESET
+ Configures the pin used to reset the IDE bus.
+
+USB 1.1 host
+CONFIG_ETRAX_USB_HOST
+ This option enables the host functionality of the ETRAX 100LX
+ built-in USB controller. In host mode the controller is designed
+ for CTRL and BULK traffic only, INTR traffic may work as well
+ however (depending on the requirements of timeliness).
+
+USB 1.1 host port 1 enabled
+CONFIG_ETRAX_USB_HOST_PORT1
+ This option enables port 1 of the ETRAX 100LX USB root hub (RH).
+
+USB 1.1 host port 2 enabled
+CONFIG_ETRAX_USB_HOST_PORT2
+ This option enables port 2 of the ETRAX 100LX USB root hub (RH).
+
+ETRAX 100LX 10/100Mbit Ethernet controller
+CONFIG_ETRAX_ETHERNET
+ This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet
+ controller.
+
+ETRAX 100LX Synchronous serial ports
+CONFIG_ETRAX_SYNCHRONOUS_SERIAL
+ This option enables support for the ETRAX 100LX built-in
+ synchronous serial ports. These ports are used for continuous
+ streamed data like audio. The default setting is compatible
+ with the STA 013 MP3 decoder, but can easily be tuned to fit
+ any other audio encoder/decoder and SPI.
+
+ETRAX 100LX Synchronous serial port 0 enabled
+CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0
+ Enables the ETRAX 100LX synchronous serial port 0 (syncser0).
+
+ETRAX 100LX Synchronous serial port 0 uses DMA
+CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA
+ Makes synchronous serial port 0 use DMA.
+
+ETRAX 100LX Synchronous serial port 1 enabled
+CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1
+ Enables the ETRAX 100LX synchronous serial port 1 (syncser1).
+
+ETRAX 100LX Synchronous serial port 1 uses DMA
+CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA
+ Makes synchronous serial port 1 use DMA.
+
+Delay for drives to regain consciousness
+CONFIG_IDE_DELAY
+ Number of seconds to wait for IDE drives to spin up after an IDE
+ reset.
+
+ARTPEC-1 support
+CONFIG_JULIETTE
+ The ARTPEC-1 is a video-compression chip used in the AXIS 2100
+ network camera, which is built around an ETRAX-100 board. With this
+ option selected, the ETRAX kernel configures a DMA channel at boot
+ time to talk to the chip.
+
+Axis flash-map support
+CONFIG_ETRAX_AXISFLASHMAP
+ This option enables MTD mapping of flash devices. Needed to use
+ flash memories. If unsure, say Y.
+
+Byte-offset of partition table sector
+CONFIG_ETRAX_PTABLE_SECTOR
+ Byte-offset of the partition table in the first flash chip.
+ The default value is 64kB and should not be changed unless
+ you know exactly what you are doing. The only valid reason
+ for changing this is when the flash block size is bigger
+ than 64kB (e.g. when using two parallel 16 bit flashes).
+
+Enable Etrax100 watchdog
+CONFIG_ETRAX_WATCHDOG
+ Enable the built-in watchdog timer support on Etrax100 embedded
+ network computers.
+
+# Choice: crisdebug
+Serial-0
+CONFIG_ETRAX_DEBUG_PORT0
+ Choose a serial port for the ETRAX debug console. Default to
+ port 0.
+
+Etrax debug port on ser1
+CONFIG_ETRAX_DEBUG_PORT1
+ Use serial port 1 for the console.
+
+Etrax debug port on ser2
+CONFIG_ETRAX_DEBUG_PORT2
+ Use serial port 2 for the console.
+
+Etrax debug port on ser3
+CONFIG_ETRAX_DEBUG_PORT3
+ Use serial port 3 for the console.
+
+No Etrax debug port
+CONFIG_ETRAX_DEBUG_PORT_NULL
+ Disable serial-port debugging.
+
+Parallel port support
+CONFIG_ETRAX_PARPORT
+ Say Y here to enable the ETRAX on-board parallel ports.
+
+Parallel port 0 enabled
+CONFIG_ETRAX_PARALLEL_PORT0
+ Say Y here to enable parallel port 0.
+
+Parallel port 1 enabled
+CONFIG_ETRAX_PARALLEL_PORT1
+ Say Y here to enable parallel port 1.
+
+# Choice: crisrescue
+Select a product rescue port
+CONFIG_ETRAX_RESCUE_SER0
+ Select one of the four serial ports as a rescue port. The default
+ is port 0.
+
+Serial-1
+CONFIG_ETRAX_RESCUE_SER1
+ Use serial port 1 as the rescue port.
+
+Serial-2
+CONFIG_ETRAX_RESCUE_SER2
+ Use serial port 2 as the rescue port.
+
+Serial-3
+CONFIG_ETRAX_RESCUE_SER3
+ Use serial port 3 as the rescue port.
+
+RIO Hardware Watchdog support
+CONFIG_WATCHDOG_RIO
+ Say Y here to support the hardware watchdog capability on Sun RIO
+ machines. The watchdog timeout period is normally one minute but
+ can be changed with a boot-time parameter.
X
X CP1XXX Hardware Watchdog support
X CONFIG_WATCHDOG_CP1XXX
@@ -19066,12 +23367,22 @@


X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).

X The module will be called cpwatchdog.o. If you want to compile it
- as a module, say M here and read Documentation/modules.txt.
+ as a module, say M here and read <file:Documentation/modules.txt>.
X
X If you do not have a CompactPCI model CP1400 or CP1500, or
X another UltraSPARC-IIi-cEngine boardset with hardware watchdog,
- you should say N to this option.
+ you should say N to this option.
+
+# Choice: ia64type
+Itanium
+CONFIG_ITANIUM
+ Select your IA64 processor type. The default is Intel Itanium.
+
+McKinley
+CONFIG_MCKINLEY
+ Select this to configure for a McKinley processor.
X
+# Choice: ia64system
X IA-64 system type
X CONFIG_IA64_GENERIC
X This selects the system type of your hardware. A "generic" kernel
@@ -19079,19 +23390,21 @@
X a kernel for your specific system, it will be faster and smaller.
X
X To find out what type of IA-64 system you have, you may want to
- check the IA-64 Linux web site at http://www.linux-ia64.org/.
+ check the IA-64 Linux web site at <http://www.linux-ia64.org/>.
X As of the time of this writing, most hardware is DIG compliant,
X so the "DIG-compliant" option is usually the right choice.
X
- HP-simulator For the HP simulator (http://software.hp.com/ia64linux/).
+ HP-simulator For the HP simulator
+ (<http://software.hp.com/ia64linux/>).
X SN1-simulator For the SGI SN1 simulator.
- DIG-compliant For DIG ("Developer's Interface Guide") compliant system.
+ DIG-compliant For DIG ("Developer's Interface Guide") compliant
+ system.


X
X If you don't know what to do, choose "generic".
X

+# Choice: pagesize
X Kernel page size
X CONFIG_IA64_PAGE_SIZE_4KB
-
X This lets you select the page size of the kernel. For best IA-64
X performance, a page size of 8KB or 16KB is recommended. For best
X IA-32 compatibility, a page size of 4KB should be selected (the vast


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

echo 'End of part 018'
echo 'File patch-2.4.15 is continued in part 019'
echo "019" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:01 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part025

#!/bin/sh -x
# this is part 025 of a 115 - part archive


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

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

+# CONFIG_INPUT_TURBOGRAFX is not set
X # CONFIG_QIC02_TAPE is not set
X
X #
X # Watchdog Cards
X #
X # CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
X # CONFIG_NVRAM is not set
X # CONFIG_RTC is not set
X CONFIG_EFI_RTC=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
X # CONFIG_DTLK is not set
X # CONFIG_R3964 is not set
X # CONFIG_APPLICOM is not set
@@ -210,69 +515,366 @@
X # Ftape, the floppy tape device driver
X #
X # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
-# CONFIG_AGP is not set
+CONFIG_AGP=y
+# CONFIG_AGP_INTEL is not set
+CONFIG_AGP_I460=y
+# CONFIG_AGP_I810 is not set
+# CONFIG_AGP_VIA is not set
+# CONFIG_AGP_AMD is not set
+# CONFIG_AGP_SIS is not set
+# CONFIG_AGP_ALI is not set
+# CONFIG_AGP_SWORKS is not set
+CONFIG_DRM=y
+# CONFIG_DRM_NEW is not set
+CONFIG_DRM_OLD=y
+CONFIG_DRM40_TDFX=y
+# CONFIG_DRM40_GAMMA is not set
+# CONFIG_DRM40_R128 is not set
+# CONFIG_DRM40_RADEON is not set
+# CONFIG_DRM40_I810 is not set
+# CONFIG_DRM40_MGA is not set
X
X #
-# USB support
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+
+#
+# Video For Linux
X #
-# CONFIG_USB is not set
+CONFIG_VIDEO_PROC_FS=y
+# CONFIG_I2C_PARPORT is not set
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZR36120 is not set
+# CONFIG_VIDEO_MEYE is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+# CONFIG_RADIO_MIROPCM20_RDS is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
X
X #
X # File systems
X #


X # CONFIG_QUOTA is not set

-# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS_FS=y


X # CONFIG_AUTOFS4_FS is not set

+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
X # CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
X # CONFIG_AFFS_FS is not set
X # CONFIG_HFS_FS is not set
X # CONFIG_BFS_FS is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y


X # CONFIG_UMSDOS_FS is not set

-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=y


X # CONFIG_EFS_FS is not set

+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
X # CONFIG_CRAMFS is not set
-# CONFIG_ISO9660_FS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_RAMFS is not set
+CONFIG_ISO9660_FS=y


X # CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
X # CONFIG_MINIX_FS is not set

+# CONFIG_VXFS_FS is not set
X # CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
X # CONFIG_HPFS_FS is not set
-# CONFIG_PROC_FS is not set
+CONFIG_PROC_FS=y
X # CONFIG_DEVFS_FS is not set
X # CONFIG_DEVFS_MOUNT is not set
X # CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS is not set
+CONFIG_DEVPTS_FS=y
X # CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
X # CONFIG_ROMFS_FS is not set
-# CONFIG_EXT2_FS is not set
+CONFIG_EXT2_FS=y
X # CONFIG_SYSV_FS is not set
X # CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
X # CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_ROOT_NFS is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set


+# CONFIG_ZISOFS_FS is not set

+# CONFIG_ZLIB_FS_INFLATE is not set
X
X #
X # Partition Types
X #
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
X CONFIG_MSDOS_PARTITION=y
-# CONFIG_NLS is not set
-# CONFIG_NLS is not set
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_DEVFS_GUID is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set


+# CONFIG_SMB_NLS is not set

+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set


+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set

+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set


+# CONFIG_NLS_ISO8859_13 is not set

+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_VGA_CONSOLE=y
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
X
X #
X # Sound
X #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_MIDI_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+CONFIG_SOUND_CS4281=y
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_MIDI_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_LONG_TIMEOUT is not set
+
+#
+# USB Controllers
+#
+CONFIG_USB_UHCI=m


+# CONFIG_USB_UHCI_ALT is not set

+# CONFIG_USB_OHCI is not set
+
+#


+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_ACM is not set

+# CONFIG_USB_PRINTER is not set
+
+#


+# USB Human Interface Devices (HID)
+#

+CONFIG_USB_HID=m
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+# CONFIG_USB_WACOM is not set
+
+#


+# USB Imaging devices
+#
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set

+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_DABUSB is not set
+
+#


+# USB Network adaptors
+#
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_CDCETHER is not set

+# CONFIG_USB_USBNET is not set
+
+#


+# USB port drivers
+#

+# CONFIG_USB_USS720 is not set
+
+#


+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set

+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set

+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#


+# USB Miscellaneous drivers
+#

+# CONFIG_USB_RIO500 is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
X
X #
X # Kernel hacking
X #
-# CONFIG_IA32_SUPPORT is not set
-# CONFIG_MATHEMU is not set
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_IA64_EARLY_PRINTK is not set
+# CONFIG_IA64_GRANULE_16MB is not set
+CONFIG_IA64_GRANULE_64MB=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_IA64_PRINT_HAZARDS=y
+# CONFIG_DISABLE_VHPT is not set
+CONFIG_MAGIC_SYSRQ=y


+# CONFIG_DEBUG_SLAB is not set

+# CONFIG_DEBUG_SPINLOCK is not set
X # CONFIG_IA64_DEBUG_CMPXCHG is not set
X # CONFIG_IA64_DEBUG_IRQ is not set
-# CONFIG_IA64_PRINT_HAZARDS is not set
-# CONFIG_KDB is not set
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/ia32/binfmt_elf32.c linux/arch/ia64/ia32/binfmt_elf32.c
--- v2.4.14/linux/arch/ia64/ia32/binfmt_elf32.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/ia32/binfmt_elf32.c Fri Nov 9 14:26:17 2001
@@ -3,10 +3,11 @@
X *


X * Copyright (C) 1999 Arun Sharma <arun....@intel.com>

X * Copyright (C) 2001 Hewlett-Packard Co
- * Copyright (C) 2001 David Mosberger-Tang <dav...@hpl.hp.com>
+ * David Mosberger-Tang <dav...@hpl.hp.com>
X *

X * 06/16/00 A. Mallick initialize csd/ssd/tssd/cflg for ia32_load_state
X * 04/13/01 D. Mosberger dropped saving tssd in ar.k1---it's not needed


+ * 09/14/01 D. Mosberger fixed memory management for gdt/tss page

X */
X #include <linux/config.h>
X
@@ -41,65 +42,59 @@
X extern void ia64_elf32_init (struct pt_regs *regs);
X extern void put_dirty_page (struct task_struct * tsk, struct page *page, unsigned long address);
X
+static void elf32_set_personality (void);
+
X #define ELF_PLAT_INIT(_r) ia64_elf32_init(_r)
X #define setup_arg_pages(bprm) ia32_setup_arg_pages(bprm)
-#define elf_map elf_map32
+#define elf_map elf32_map
+#define SET_PERSONALITY(ex, ibcs2) elf32_set_personality()
X
X /* Ugly but avoids duplication */
X #include "../../../fs/binfmt_elf.c"
X
-/* Global descriptor table */
-unsigned long *ia32_gdt_table, *ia32_tss;
+extern struct page *ia32_shared_page[];
+extern unsigned long *ia32_gdt;
X
X struct page *
-put_shared_page (struct task_struct * tsk, struct page *page, unsigned long address)
+ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int no_share)
X {
- pgd_t * pgd;
- pmd_t * pmd;
- pte_t * pte;
-
- if (page_count(page) != 1)
- printk("mem_map disagrees with %p at %08lx\n", (void *) page, address);
+ struct page *pg = ia32_shared_page[(address - vma->vm_start)/PAGE_SIZE];
X
- pgd = pgd_offset(tsk->mm, address);
-
- spin_lock(&tsk->mm->page_table_lock);
- {
- pmd = pmd_alloc(tsk->mm, pgd, address);
- if (!pmd)
- goto out;
- pte = pte_alloc(tsk->mm, pmd, address);
- if (!pte)
- goto out;
- if (!pte_none(*pte))
- goto out;
- flush_page_to_ram(page);
- set_pte(pte, pte_mkwrite(mk_pte(page, PAGE_SHARED)));
- }
- spin_unlock(&tsk->mm->page_table_lock);
- /* no need for flush_tlb */
- return page;
-
- out:
- spin_unlock(&tsk->mm->page_table_lock);
- __free_page(page);
- return 0;
+ get_page(pg);
+ return pg;
X }
X
+static struct vm_operations_struct ia32_shared_page_vm_ops = {
+ nopage: ia32_install_shared_page
+};
+
X void
X ia64_elf32_init (struct pt_regs *regs)
X {
X struct vm_area_struct *vma;
- int nr;
X
X /*
X * Map GDT and TSS below 4GB, where the processor can find them. We need to map
X * it with privilege level 3 because the IVE uses non-privileged accesses to these
X * tables. IA-32 segmentation is used to protect against IA-32 accesses to them.
X */
- put_shared_page(current, virt_to_page(ia32_gdt_table), IA32_GDT_OFFSET);
- if (PAGE_SHIFT <= IA32_PAGE_SHIFT)
- put_shared_page(current, virt_to_page(ia32_tss), IA32_TSS_OFFSET);
+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ if (vma) {
+ vma->vm_mm = current->mm;
+ vma->vm_start = IA32_GDT_OFFSET;
+ vma->vm_end = vma->vm_start + max(PAGE_SIZE, 2*IA32_PAGE_SIZE);
+ vma->vm_page_prot = PAGE_SHARED;
+ vma->vm_flags = VM_READ|VM_MAYREAD;
+ vma->vm_ops = &ia32_shared_page_vm_ops;
+ vma->vm_pgoff = 0;
+ vma->vm_file = NULL;
+ vma->vm_private_data = NULL;


+ down_write(&current->mm->mmap_sem);
+ {

+ insert_vm_struct(current->mm, vma);


+ }
+ up_write(&current->mm->mmap_sem);

+ }
X
X /*
X * Install LDT as anonymous memory. This gives us all-zero segment descriptors
@@ -116,34 +111,13 @@
X vma->vm_pgoff = 0;
X vma->vm_file = NULL;
X vma->vm_private_data = NULL;
- insert_vm_struct(current->mm, vma);


+ down_write(&current->mm->mmap_sem);
+ {

+ insert_vm_struct(current->mm, vma);
+ }
+ up_write(&current->mm->mmap_sem);
X }
X
- nr = smp_processor_id();
-
- current->thread.map_base = IA32_PAGE_OFFSET/3;
- current->thread.task_size = IA32_PAGE_OFFSET; /* use what Linux/x86 uses... */
- set_fs(USER_DS); /* set addr limit for new TASK_SIZE */
-
- /* Setup the segment selectors */
- regs->r16 = (__USER_DS << 16) | __USER_DS; /* ES == DS, GS, FS are zero */
- regs->r17 = (__USER_DS << 16) | __USER_CS; /* SS, CS; ia32_load_state() sets TSS and LDT */
-
- /* Setup the segment descriptors */
- regs->r24 = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[__USER_DS >> 3]); /* ESD */
- regs->r27 = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[__USER_DS >> 3]); /* DSD */
- regs->r28 = 0; /* FSD (null) */
- regs->r29 = 0; /* GSD (null) */
- regs->r30 = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[_LDT(nr)]); /* LDTD */
-
- /*
- * Setup GDTD. Note: GDTD is the descrambled version of the pseudo-descriptor
- * format defined by Figure 3-11 "Pseudo-Descriptor Format" in the IA-32
- * architecture manual.
- */
- regs->r31 = IA32_SEG_UNSCRAMBLE(IA32_SEG_DESCRIPTOR(IA32_GDT_OFFSET, IA32_PAGE_SIZE - 1, 0,
- 0, 0, 0, 0, 0, 0));
-
X ia64_psr(regs)->ac = 0; /* turn off alignment checking */
X regs->loadrs = 0;
X /*
@@ -164,10 +138,19 @@
X current->thread.fcr = IA32_FCR_DEFAULT;
X current->thread.fir = 0;
X current->thread.fdr = 0;
- current->thread.csd = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[__USER_CS >> 3]);
- current->thread.ssd = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[__USER_DS >> 3]);
- current->thread.tssd = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[_TSS(nr)]);
X
+ /*
+ * Setup GDTD. Note: GDTD is the descrambled version of the pseudo-descriptor
+ * format defined by Figure 3-11 "Pseudo-Descriptor Format" in the IA-32
+ * architecture manual.
+ */
+ regs->r31 = IA32_SEG_UNSCRAMBLE(IA32_SEG_DESCRIPTOR(IA32_GDT_OFFSET, IA32_PAGE_SIZE - 1, 0,
+ 0, 0, 0, 0, 0, 0));
+ /* Setup the segment selectors */
+ regs->r16 = (__USER_DS << 16) | __USER_DS; /* ES == DS, GS, FS are zero */
+ regs->r17 = (__USER_DS << 16) | __USER_CS; /* SS, CS; ia32_load_state() sets TSS and LDT */
+
+ ia32_load_segment_descriptors(current);
X ia32_load_state(current);
X }
X
@@ -189,6 +172,7 @@
X if (!mpnt)
X return -ENOMEM;
X
+ down_write(&current->mm->mmap_sem);
X {
X mpnt->vm_mm = current->mm;
X mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
@@ -204,54 +188,32 @@
X }
X
X for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
- if (bprm->page[i]) {
- put_dirty_page(current,bprm->page[i],stack_base);
+ struct page *page = bprm->page[i];
+ if (page) {
+ bprm->page[i] = NULL;
+ put_dirty_page(current, page, stack_base);
X }
X stack_base += PAGE_SIZE;
X }
+ up_write(&current->mm->mmap_sem);


X
X return 0;
X }

X
-static unsigned long
-ia32_mm_addr (unsigned long addr)
+static void
+elf32_set_personality (void)
X {


- struct vm_area_struct *vma;
-

- if ((vma = find_vma(current->mm, addr)) == NULL)
- return ELF_PAGESTART(addr);
- if (vma->vm_start > addr)
- return ELF_PAGESTART(addr);
- return ELF_PAGEALIGN(addr);
+ set_personality(PER_LINUX32);
+ current->thread.map_base = IA32_PAGE_OFFSET/3;
+ current->thread.task_size = IA32_PAGE_OFFSET; /* use what Linux/x86 uses... */
+ set_fs(USER_DS); /* set addr limit for new TASK_SIZE */
X }
X
-/*
- * Normally we would do an `mmap' to map in the process's text section.
- * This doesn't work with IA32 processes as the ELF file might specify
- * a non page size aligned address. Instead we will just allocate
- * memory and read the data in from the file. Slightly less efficient
- * but it works.
- */
-extern long ia32_do_mmap (struct file *filep, unsigned int len, unsigned int prot,
- unsigned int flags, unsigned int fd, unsigned int offset);
-
X static unsigned long
-elf_map32 (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
+elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
X {
- unsigned long retval;
+ unsigned long pgoff = (eppnt->p_vaddr) & ~IA32_PAGE_MASK;
X
- if (eppnt->p_memsz >= (1UL<<32) || addr > (1UL<<32) - eppnt->p_memsz)


- return -EINVAL;
-
- /*

- * Make sure the elf interpreter doesn't get loaded at location 0
- * so that NULL pointers correctly cause segfaults.
- */


- if (addr == 0)

- addr += PAGE_SIZE;
- set_brk(ia32_mm_addr(addr), addr + eppnt->p_memsz);
- memset((char *) addr + eppnt->p_filesz, 0, eppnt->p_memsz - eppnt->p_filesz);
- kernel_read(filep, eppnt->p_offset, (char *) addr, eppnt->p_filesz);
- retval = (unsigned long) addr;
- return retval;
+ return ia32_do_mmap(filep, (addr & IA32_PAGE_MASK), eppnt->p_filesz + pgoff, prot, type,
+ eppnt->p_offset - pgoff);
X }
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/ia32/ia32_entry.S linux/arch/ia64/ia32/ia32_entry.S
--- v2.4.14/linux/arch/ia64/ia32/ia32_entry.S Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/ia32/ia32_entry.S Fri Nov 9 14:26:17 2001
@@ -2,7 +2,7 @@
X #include <asm/offsets.h>
X #include <asm/signal.h>
X
-#include "../kernel/entry.h"
+#include "../kernel/minstate.h"
X
X /*
X * execve() is special because in case of success, we need to
@@ -14,13 +14,13 @@
X alloc loc1=ar.pfs,3,2,4,0
X mov loc0=rp
X .body
- mov out0=in0 // filename
+ zxt4 out0=in0 // filename
X ;; // stop bit between alloc and call
- mov out1=in1 // argv
- mov out2=in2 // envp
+ zxt4 out1=in1 // argv
+ zxt4 out2=in2 // envp
X add out3=16,sp // regs
X br.call.sptk.few rp=sys32_execve
-1: cmp4.ge p6,p0=r8,r0
+1: cmp.ge p6,p0=r8,r0
X mov ar.pfs=loc1 // restore ar.pfs
X ;;
X (p6) mov ar.pfs=r0 // clear ar.pfs in case of success
@@ -29,31 +29,80 @@
X br.ret.sptk.few rp
X END(ia32_execve)
X
- //
- // Get possibly unaligned sigmask argument into an aligned
- // kernel buffer
-GLOBAL_ENTRY(ia32_rt_sigsuspend)
- // We'll cheat and not do an alloc here since we are ultimately
- // going to do a simple branch to the IA64 sys_rt_sigsuspend.
- // r32 is still the first argument which is the signal mask.
- // We copy this 4-byte aligned value to an 8-byte aligned buffer
- // in the task structure and then jump to the IA64 code.
+ENTRY(ia32_clone)
+ .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
+ alloc r16=ar.pfs,2,2,4,0
+ DO_SAVE_SWITCH_STACK
+ mov loc0=rp
+ mov loc1=r16 // save ar.pfs across do_fork
+ .body
+ zxt4 out1=in1 // newsp
+ mov out3=0 // stacksize
+ adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs
+ zxt4 out0=in0 // out0 = clone_flags
+ br.call.sptk.many rp=do_fork
+.ret0: .restore sp
+ adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack
+ mov ar.pfs=loc1
+ mov rp=loc0
+ br.ret.sptk.many rp
+END(ia32_clone)
X
- EX(.Lfail, ld4 r2=[r32],4) // load low part of sigmask
- ;;
- EX(.Lfail, ld4 r3=[r32]) // load high part of sigmask
- adds r32=IA64_TASK_THREAD_SIGMASK_OFFSET,r13
- ;;
- st8 [r32]=r2
- adds r10=IA64_TASK_THREAD_SIGMASK_OFFSET+4,r13
+ENTRY(sys32_rt_sigsuspend)
+ .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
+ alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs
+ mov loc0=rp
+ mov out0=in0 // mask
+ mov out1=in1 // sigsetsize
+ mov out2=sp // out2 = &sigscratch
+ .fframe 16
+ adds sp=-16,sp // allocate dummy "sigscratch"
X ;;
+ .body
+ br.call.sptk.many rp=ia32_rt_sigsuspend
+1: .restore sp
+ adds sp=16,sp
+ mov rp=loc0
+ mov ar.pfs=loc1
+ br.ret.sptk.many rp
+END(sys32_rt_sigsuspend)
X
- st4 [r10]=r3
- br.cond.sptk.many sys_rt_sigsuspend
-
-.Lfail: br.ret.sptk.many rp // failed to read sigmask
-END(ia32_rt_sigsuspend)
+ENTRY(sys32_sigsuspend)
+ .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
+ alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs
+ mov loc0=rp
+ mov out0=in2 // mask (first two args are ignored)
+ ;;
+ mov out1=sp // out1 = &sigscratch
+ .fframe 16
+ adds sp=-16,sp // allocate dummy "sigscratch"
+ .body
+ br.call.sptk.many rp=ia32_sigsuspend
+1: .restore sp
+ adds sp=16,sp
+ mov rp=loc0
+ mov ar.pfs=loc1
+ br.ret.sptk.many rp
+END(sys32_sigsuspend)
X
+GLOBAL_ENTRY(ia32_ret_from_clone)
+ PT_REGS_UNWIND_INFO(0)
+ /*
+ * We need to call schedule_tail() to complete the scheduling process.
+ * Called by ia64_switch_to after do_fork()->copy_thread(). r8 contains the
+ * address of the previously executing task.
+ */
+ br.call.sptk.many rp=ia64_invoke_schedule_tail
+.ret1: adds r2=IA64_TASK_PTRACE_OFFSET,r13
+ ;;
+ ld8 r2=[r2]
+ ;;
+ mov r8=0
+ tbit.nz p6,p0=r2,PT_TRACESYS_BIT
+(p6) br.cond.spnt .ia32_strace_check_retval
+ ;; // prevent RAW on r8
+END(ia32_ret_from_clone)
+ // fall thrugh
X GLOBAL_ENTRY(ia32_ret_from_syscall)
X PT_REGS_UNWIND_INFO(0)
X
@@ -72,20 +121,25 @@
X // manipulate ar.pfs.
X //
X // Input:
- // r15 = syscall number
- // b6 = syscall entry point
+ // r8 = syscall number
+ // b6 = syscall entry point
X //
X GLOBAL_ENTRY(ia32_trace_syscall)
X PT_REGS_UNWIND_INFO(0)
+ mov r3=-38
+ adds r2=IA64_PT_REGS_R8_OFFSET+16,sp
+ ;;
+ st8 [r2]=r3 // initialize return code to -ENOSYS
X br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch syscall args
-.ret0: br.call.sptk.few rp=b6 // do the syscall
-.ret1: cmp.lt p6,p0=r8,r0 // syscall failed?
+.ret2: br.call.sptk.few rp=b6 // do the syscall
+.ia32_strace_check_retval:
+ cmp.lt p6,p0=r8,r0 // syscall failed?
X adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8
X ;;
X st8.spill [r2]=r8 // store return value in slot for r8
X br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch return value
-.ret2: alloc r2=ar.pfs,0,0,0,0 // drop the syscall argument frame
- br.cond.sptk.many ia64_leave_kernel // rp MUST be != ia64_leave_kernel!
+.ret4: alloc r2=ar.pfs,0,0,0,0 // drop the syscall argument frame
+ br.cond.sptk.many ia64_leave_kernel
X END(ia32_trace_syscall)
X
X GLOBAL_ENTRY(sys32_vfork)
@@ -110,7 +164,7 @@
X mov out3=0
X adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs
X br.call.sptk.few rp=do_fork
-.ret3: mov ar.pfs=loc1
+.ret5: mov ar.pfs=loc1
X .restore sp
X adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack
X mov rp=loc0
@@ -137,21 +191,21 @@
X data8 sys32_time
X data8 sys_mknod
X data8 sys_chmod /* 15 */
- data8 sys_lchown
+ data8 sys_lchown /* 16-bit version */
X data8 sys32_ni_syscall /* old break syscall holder */
X data8 sys32_ni_syscall
X data8 sys32_lseek
X data8 sys_getpid /* 20 */
X data8 sys_mount
X data8 sys_oldumount
- data8 sys_setuid
- data8 sys_getuid
+ data8 sys_setuid /* 16-bit version */
+ data8 sys_getuid /* 16-bit version */
X data8 sys32_ni_syscall /* sys_stime is not supported on IA64 */ /* 25 */
X data8 sys32_ptrace
X data8 sys32_alarm
X data8 sys32_ni_syscall
- data8 sys_pause
- data8 ia32_utime /* 30 */
+ data8 sys32_pause
+ data8 sys32_utime /* 30 */
X data8 sys32_ni_syscall /* old stty syscall holder */
X data8 sys32_ni_syscall /* old gtty syscall holder */
X data8 sys_access
@@ -167,15 +221,15 @@
X data8 sys32_times
X data8 sys32_ni_syscall /* old prof syscall holder */
X data8 sys_brk /* 45 */
- data8 sys_setgid
- data8 sys_getgid
+ data8 sys_setgid /* 16-bit version */
+ data8 sys_getgid /* 16-bit version */
X data8 sys32_signal
- data8 sys_geteuid
- data8 sys_getegid /* 50 */
+ data8 sys_geteuid /* 16-bit version */
+ data8 sys_getegid /* 16-bit version */ /* 50 */
X data8 sys_acct
X data8 sys_umount /* recycled never used phys( */
X data8 sys32_ni_syscall /* old lock syscall holder */
- data8 ia32_ioctl
+ data8 sys32_ioctl
X data8 sys32_fcntl /* 55 */
X data8 sys32_ni_syscall /* old mpx syscall holder */
X data8 sys_setpgid
@@ -191,19 +245,19 @@
X data8 sys32_sigaction
X data8 sys32_ni_syscall
X data8 sys32_ni_syscall
- data8 sys_setreuid /* 70 */
- data8 sys_setregid
- data8 sys32_ni_syscall
- data8 sys_sigpending
+ data8 sys_setreuid /* 16-bit version */ /* 70 */
+ data8 sys_setregid /* 16-bit version */
+ data8 sys32_sigsuspend
+ data8 sys32_sigpending
X data8 sys_sethostname
X data8 sys32_setrlimit /* 75 */
- data8 sys32_getrlimit
+ data8 sys32_old_getrlimit
X data8 sys32_getrusage
X data8 sys32_gettimeofday
X data8 sys32_settimeofday
- data8 sys_getgroups /* 80 */
- data8 sys_setgroups
- data8 old_select
+ data8 sys32_getgroups16 /* 80 */
+ data8 sys32_setgroups16
+ data8 sys32_old_select
X data8 sys_symlink
X data8 sys32_ni_syscall
X data8 sys_readlink /* 85 */
@@ -212,17 +266,17 @@
X data8 sys_reboot
X data8 sys32_readdir
X data8 sys32_mmap /* 90 */
- data8 sys_munmap
+ data8 sys32_munmap
X data8 sys_truncate
X data8 sys_ftruncate
X data8 sys_fchmod
- data8 sys_fchown /* 95 */
+ data8 sys_fchown /* 16-bit version */ /* 95 */
X data8 sys_getpriority
X data8 sys_setpriority
X data8 sys32_ni_syscall /* old profil syscall holder */
X data8 sys32_statfs
X data8 sys32_fstatfs /* 100 */
- data8 sys_ioperm
+ data8 sys32_ioperm
X data8 sys32_socketcall
X data8 sys_syslog
X data8 sys32_setitimer
@@ -231,36 +285,36 @@
X data8 sys32_newlstat
X data8 sys32_newfstat
X data8 sys32_ni_syscall
- data8 sys_iopl /* 110 */
+ data8 sys32_iopl /* 110 */
X data8 sys_vhangup
X data8 sys32_ni_syscall /* used to be sys_idle */
X data8 sys32_ni_syscall
X data8 sys32_wait4
X data8 sys_swapoff /* 115 */
- data8 sys_sysinfo
+ data8 sys32_sysinfo
X data8 sys32_ipc
X data8 sys_fsync
X data8 sys32_sigreturn
- data8 sys_clone /* 120 */
+ data8 ia32_clone /* 120 */
X data8 sys_setdomainname
X data8 sys32_newuname
X data8 sys32_modify_ldt
- data8 sys_adjtimex
+ data8 sys32_ni_syscall /* adjtimex */
X data8 sys32_mprotect /* 125 */
- data8 sys_sigprocmask
- data8 sys_create_module
- data8 sys_init_module
- data8 sys_delete_module
- data8 sys_get_kernel_syms /* 130 */
- data8 sys_quotactl
+ data8 sys32_sigprocmask
+ data8 sys32_ni_syscall /* create_module */
+ data8 sys32_ni_syscall /* init_module */
+ data8 sys32_ni_syscall /* delete_module */
+ data8 sys32_ni_syscall /* get_kernel_syms */ /* 130 */
+ data8 sys32_quotactl
X data8 sys_getpgid
X data8 sys_fchdir
- data8 sys_bdflush
- data8 sys_sysfs /* 135 */
- data8 sys_personality
+ data8 sys32_ni_syscall /* sys_bdflush */
+ data8 sys_sysfs /* 135 */
+ data8 sys32_personality
X data8 sys32_ni_syscall /* for afs_syscall */
- data8 sys_setfsuid
- data8 sys_setfsgid
+ data8 sys_setfsuid /* 16-bit version */
+ data8 sys_setfsgid /* 16-bit version */
X data8 sys_llseek /* 140 */
X data8 sys32_getdents
X data8 sys32_select
@@ -282,66 +336,73 @@
X data8 sys_sched_yield
X data8 sys_sched_get_priority_max
X data8 sys_sched_get_priority_min /* 160 */
- data8 sys_sched_rr_get_interval
+ data8 sys32_sched_rr_get_interval
X data8 sys32_nanosleep
X data8 sys_mremap
- data8 sys_setresuid
- data8 sys32_getresuid /* 165 */
- data8 sys_vm86
- data8 sys_query_module
+ data8 sys_setresuid /* 16-bit version */
+ data8 sys32_getresuid16 /* 16-bit version */ /* 165 */
+ data8 sys32_ni_syscall /* vm86 */
+ data8 sys32_ni_syscall /* sys_query_module */
X data8 sys_poll
- data8 sys_nfsservctl
+ data8 sys32_ni_syscall /* nfsservctl */
X data8 sys_setresgid /* 170 */
- data8 sys32_getresgid
+ data8 sys32_getresgid16
X data8 sys_prctl
X data8 sys32_rt_sigreturn
X data8 sys32_rt_sigaction
X data8 sys32_rt_sigprocmask /* 175 */
X data8 sys_rt_sigpending
- data8 sys_rt_sigtimedwait
- data8 sys_rt_sigqueueinfo
- data8 ia32_rt_sigsuspend
- data8 sys_pread /* 180 */
- data8 sys_pwrite
- data8 sys_chown
+ data8 sys32_rt_sigtimedwait
+ data8 sys32_rt_sigqueueinfo
+ data8 sys32_rt_sigsuspend
+ data8 sys32_pread /* 180 */
+ data8 sys32_pwrite
+ data8 sys_chown /* 16-bit version */
X data8 sys_getcwd
X data8 sys_capget
X data8 sys_capset /* 185 */
X data8 sys32_sigaltstack
- data8 sys_sendfile
+ data8 sys32_sendfile
X data8 sys32_ni_syscall /* streams1 */
X data8 sys32_ni_syscall /* streams2 */
X data8 sys32_vfork /* 190 */
+ data8 sys32_getrlimit
+ data8 sys32_mmap2
+ data8 sys32_truncate64
+ data8 sys32_ftruncate64
+ data8 sys32_stat64 /* 195 */
+ data8 sys32_lstat64
+ data8 sys32_fstat64
+ data8 sys_lchown
+ data8 sys_getuid
+ data8 sys_getgid /* 200 */
+ data8 sys_geteuid
+ data8 sys_getegid
+ data8 sys_setreuid
+ data8 sys_setregid
+ data8 sys_getgroups /* 205 */
+ data8 sys_setgroups
+ data8 sys_fchown
+ data8 sys_setresuid
+ data8 sys_getresuid
+ data8 sys_setresgid /* 210 */
+ data8 sys_getresgid
+ data8 sys_chown
+ data8 sys_setuid
+ data8 sys_setgid
+ data8 sys_setfsuid /* 215 */
+ data8 sys_setfsgid
+ data8 sys_pivot_root
+ data8 sys_mincore
+ data8 sys_madvise
+ data8 sys_getdents64 /* 220 */
+ data8 sys32_fcntl64
+ data8 sys_ni_syscall /* reserved for TUX */
+ data8 sys_ni_syscall /* reserved for Security */
+ data8 sys_gettid
+ data8 sys_readahead /* 225 */
X data8 sys_ni_syscall
X data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall /* 195 */
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall /* 200 */
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall /* 205 */
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall /* 210 */
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall /* 215 */
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall
- data8 sys_ni_syscall /* 220 */
X data8 sys_ni_syscall
X data8 sys_ni_syscall
X /*
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/ia32/ia32_ioctl.c linux/arch/ia64/ia32/ia32_ioctl.c
--- v2.4.14/linux/arch/ia64/ia32/ia32_ioctl.c Thu Jan 4 12:50:17 2001
+++ linux/arch/ia64/ia32/ia32_ioctl.c Fri Nov 9 14:26:17 2001
@@ -3,6 +3,8 @@
X *


X * Copyright (C) 2000 VA Linux Co
X * Copyright (C) 2000 Don Dugger <n0...@valinux.com>

+ * Copyright (C) 2001 Hewlett-Packard Co
+ * David Mosberger-Tang <dav...@hpl.hp.com>

X */
X
X #include <linux/types.h>
@@ -22,8 +24,12 @@
X #include <linux/if_ppp.h>
X #include <linux/ixjuser.h>
X #include <linux/i2o-dev.h>
+
+#include <asm/ia32.h>
+
X #include <../drivers/char/drm/drm.h>
X
+
X #define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
X
X #define DO_IOCTL(fd, cmd, arg) ({ \
@@ -36,179 +42,200 @@
X _ret; \
X })
X
-#define P(i) ((void *)(long)(i))
-
+#define P(i) ((void *)(unsigned long)(i))
X
X asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
X
-asmlinkage long ia32_ioctl(unsigned int fd, unsigned int cmd, unsigned int arg)
+static long
+put_dirent32 (struct dirent *d, struct linux32_dirent *d32)
+{
+ size_t namelen = strlen(d->d_name);
+
+ return (put_user(d->d_ino, &d32->d_ino)
+ || put_user(d->d_off, &d32->d_off)
+ || put_user(d->d_reclen, &d32->d_reclen)
+ || copy_to_user(d32->d_name, d->d_name, namelen + 1));
+}
+
+asmlinkage long
+sys32_ioctl (unsigned int fd, unsigned int cmd, unsigned int arg)
X {
X long ret;
X
X switch (IOCTL_NR(cmd)) {
-
- case IOCTL_NR(DRM_IOCTL_VERSION):
- {
- drm_version_t ver;
- struct {
- int version_major;
- int version_minor;
- int version_patchlevel;
- unsigned int name_len;
- unsigned int name; /* pointer */
- unsigned int date_len;
- unsigned int date; /* pointer */
- unsigned int desc_len;
- unsigned int desc; /* pointer */
- } ver32;
-
- if (copy_from_user(&ver32, P(arg), sizeof(ver32)))
- return -EFAULT;
- ver.name_len = ver32.name_len;
- ver.name = P(ver32.name);
- ver.date_len = ver32.date_len;
- ver.date = P(ver32.date);
- ver.desc_len = ver32.desc_len;
- ver.desc = P(ver32.desc);
- ret = DO_IOCTL(fd, cmd, &ver);
- if (ret >= 0) {
- ver32.version_major = ver.version_major;
- ver32.version_minor = ver.version_minor;
- ver32.version_patchlevel = ver.version_patchlevel;
- ver32.name_len = ver.name_len;
- ver32.date_len = ver.date_len;
- ver32.desc_len = ver.desc_len;
- if (copy_to_user(P(arg), &ver32, sizeof(ver32)))
- return -EFAULT;
- }
- return(ret);
- }
-
- case IOCTL_NR(DRM_IOCTL_GET_UNIQUE):
- {
- drm_unique_t un;
- struct {
- unsigned int unique_len;
- unsigned int unique;
- } un32;
-
- if (copy_from_user(&un32, P(arg), sizeof(un32)))
- return -EFAULT;
- un.unique_len = un32.unique_len;
- un.unique = P(un32.unique);
- ret = DO_IOCTL(fd, cmd, &un);
- if (ret >= 0) {
- un32.unique_len = un.unique_len;
- if (copy_to_user(P(arg), &un32, sizeof(un32)))
- return -EFAULT;
- }
- return(ret);
- }
- case IOCTL_NR(DRM_IOCTL_SET_UNIQUE):
- case IOCTL_NR(DRM_IOCTL_ADD_MAP):
- case IOCTL_NR(DRM_IOCTL_ADD_BUFS):
- case IOCTL_NR(DRM_IOCTL_MARK_BUFS):
- case IOCTL_NR(DRM_IOCTL_INFO_BUFS):
- case IOCTL_NR(DRM_IOCTL_MAP_BUFS):
- case IOCTL_NR(DRM_IOCTL_FREE_BUFS):
- case IOCTL_NR(DRM_IOCTL_ADD_CTX):
- case IOCTL_NR(DRM_IOCTL_RM_CTX):
- case IOCTL_NR(DRM_IOCTL_MOD_CTX):
- case IOCTL_NR(DRM_IOCTL_GET_CTX):
- case IOCTL_NR(DRM_IOCTL_SWITCH_CTX):
- case IOCTL_NR(DRM_IOCTL_NEW_CTX):
- case IOCTL_NR(DRM_IOCTL_RES_CTX):
-
- case IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE):
- case IOCTL_NR(DRM_IOCTL_AGP_RELEASE):
- case IOCTL_NR(DRM_IOCTL_AGP_ENABLE):
- case IOCTL_NR(DRM_IOCTL_AGP_INFO):
- case IOCTL_NR(DRM_IOCTL_AGP_ALLOC):
- case IOCTL_NR(DRM_IOCTL_AGP_FREE):
- case IOCTL_NR(DRM_IOCTL_AGP_BIND):
- case IOCTL_NR(DRM_IOCTL_AGP_UNBIND):
-
- /* Mga specific ioctls */
-
- case IOCTL_NR(DRM_IOCTL_MGA_INIT):
-
- /* I810 specific ioctls */
-
- case IOCTL_NR(DRM_IOCTL_I810_GETBUF):
- case IOCTL_NR(DRM_IOCTL_I810_COPY):
-
- /* Rage 128 specific ioctls */
-
- case IOCTL_NR(DRM_IOCTL_R128_PACKET):
-
- case IOCTL_NR(VFAT_IOCTL_READDIR_BOTH):
- case IOCTL_NR(VFAT_IOCTL_READDIR_SHORT):
- case IOCTL_NR(MTIOCGET):
- case IOCTL_NR(MTIOCPOS):
- case IOCTL_NR(MTIOCGETCONFIG):
- case IOCTL_NR(MTIOCSETCONFIG):
- case IOCTL_NR(PPPIOCSCOMPRESS):
- case IOCTL_NR(PPPIOCGIDLE):
- case IOCTL_NR(NCP_IOC_GET_FS_INFO_V2):
- case IOCTL_NR(NCP_IOC_GETOBJECTNAME):
- case IOCTL_NR(NCP_IOC_SETOBJECTNAME):
- case IOCTL_NR(NCP_IOC_GETPRIVATEDATA):
- case IOCTL_NR(NCP_IOC_SETPRIVATEDATA):
- case IOCTL_NR(NCP_IOC_GETMOUNTUID2):
- case IOCTL_NR(CAPI_MANUFACTURER_CMD):
- case IOCTL_NR(VIDIOCGTUNER):
- case IOCTL_NR(VIDIOCSTUNER):
- case IOCTL_NR(VIDIOCGWIN):
- case IOCTL_NR(VIDIOCSWIN):
- case IOCTL_NR(VIDIOCGFBUF):
- case IOCTL_NR(VIDIOCSFBUF):
- case IOCTL_NR(MGSL_IOCSPARAMS):
- case IOCTL_NR(MGSL_IOCGPARAMS):
- case IOCTL_NR(ATM_GETNAMES):
- case IOCTL_NR(ATM_GETLINKRATE):
- case IOCTL_NR(ATM_GETTYPE):
- case IOCTL_NR(ATM_GETESI):
- case IOCTL_NR(ATM_GETADDR):
- case IOCTL_NR(ATM_RSTADDR):
- case IOCTL_NR(ATM_ADDADDR):
- case IOCTL_NR(ATM_DELADDR):
- case IOCTL_NR(ATM_GETCIRANGE):
- case IOCTL_NR(ATM_SETCIRANGE):
- case IOCTL_NR(ATM_SETESI):
- case IOCTL_NR(ATM_SETESIF):
- case IOCTL_NR(ATM_GETSTAT):
- case IOCTL_NR(ATM_GETSTATZ):
- case IOCTL_NR(ATM_GETLOOP):
- case IOCTL_NR(ATM_SETLOOP):
- case IOCTL_NR(ATM_QUERYLOOP):
- case IOCTL_NR(ENI_SETMULT):
- case IOCTL_NR(NS_GETPSTAT):
- /* case IOCTL_NR(NS_SETBUFLEV): This is a duplicate case with ZATM_GETPOOLZ */
- case IOCTL_NR(ZATM_GETPOOLZ):
- case IOCTL_NR(ZATM_GETPOOL):
- case IOCTL_NR(ZATM_SETPOOL):
- case IOCTL_NR(ZATM_GETTHIST):
- case IOCTL_NR(IDT77105_GETSTAT):
- case IOCTL_NR(IDT77105_GETSTATZ):
- case IOCTL_NR(IXJCTL_TONE_CADENCE):
- case IOCTL_NR(IXJCTL_FRAMES_READ):
- case IOCTL_NR(IXJCTL_FRAMES_WRITTEN):
- case IOCTL_NR(IXJCTL_READ_WAIT):
- case IOCTL_NR(IXJCTL_WRITE_WAIT):
- case IOCTL_NR(IXJCTL_DRYBUFFER_READ):
- case IOCTL_NR(I2OHRTGET):
- case IOCTL_NR(I2OLCTGET):
- case IOCTL_NR(I2OPARMSET):
- case IOCTL_NR(I2OPARMGET):
- case IOCTL_NR(I2OSWDL):
- case IOCTL_NR(I2OSWUL):
- case IOCTL_NR(I2OSWDEL):
- case IOCTL_NR(I2OHTML):
+ case IOCTL_NR(VFAT_IOCTL_READDIR_SHORT):
+ case IOCTL_NR(VFAT_IOCTL_READDIR_BOTH): {
+ struct linux32_dirent *d32 = P(arg);
+ struct dirent d[2];
+
+ ret = DO_IOCTL(fd, _IOR('r', _IOC_NR(cmd),
+ struct dirent [2]),
+ (unsigned long) d);
+ if (ret < 0)
+ return ret;
+
+ if (put_dirent32(d, d32) || put_dirent32(d + 1, d32 + 1))
+ return -EFAULT;
+
+ return ret;
+ }
+
+ case IOCTL_NR(DRM_IOCTL_VERSION):
+ {
+ drm_version_t ver;
+ struct {
+ int version_major;
+ int version_minor;
+ int version_patchlevel;
+ unsigned int name_len;
+ unsigned int name; /* pointer */
+ unsigned int date_len;
+ unsigned int date; /* pointer */
+ unsigned int desc_len;
+ unsigned int desc; /* pointer */
+ } ver32;
+
+ if (copy_from_user(&ver32, P(arg), sizeof(ver32)))
+ return -EFAULT;
+ ver.name_len = ver32.name_len;
+ ver.name = P(ver32.name);
+ ver.date_len = ver32.date_len;
+ ver.date = P(ver32.date);
+ ver.desc_len = ver32.desc_len;
+ ver.desc = P(ver32.desc);
+ ret = DO_IOCTL(fd, DRM_IOCTL_VERSION, &ver);
+ if (ret >= 0) {
+ ver32.version_major = ver.version_major;
+ ver32.version_minor = ver.version_minor;
+ ver32.version_patchlevel = ver.version_patchlevel;
+ ver32.name_len = ver.name_len;
+ ver32.date_len = ver.date_len;
+ ver32.desc_len = ver.desc_len;
+ if (copy_to_user(P(arg), &ver32, sizeof(ver32)))
+ return -EFAULT;
+ }
+ return ret;
+ }
+
+ case IOCTL_NR(DRM_IOCTL_GET_UNIQUE):
+ {
+ drm_unique_t un;
+ struct {
+ unsigned int unique_len;
+ unsigned int unique;
+ } un32;
+
+ if (copy_from_user(&un32, P(arg), sizeof(un32)))
+ return -EFAULT;
+ un.unique_len = un32.unique_len;
+ un.unique = P(un32.unique);
+ ret = DO_IOCTL(fd, DRM_IOCTL_GET_UNIQUE, &un);
+ if (ret >= 0) {
+ un32.unique_len = un.unique_len;
+ if (copy_to_user(P(arg), &un32, sizeof(un32)))
+ return -EFAULT;
+ }
+ return ret;
+ }
+ case IOCTL_NR(DRM_IOCTL_SET_UNIQUE):
+ case IOCTL_NR(DRM_IOCTL_ADD_MAP):
+ case IOCTL_NR(DRM_IOCTL_ADD_BUFS):
+ case IOCTL_NR(DRM_IOCTL_MARK_BUFS):
+ case IOCTL_NR(DRM_IOCTL_INFO_BUFS):
+ case IOCTL_NR(DRM_IOCTL_MAP_BUFS):
+ case IOCTL_NR(DRM_IOCTL_FREE_BUFS):
+ case IOCTL_NR(DRM_IOCTL_ADD_CTX):
+ case IOCTL_NR(DRM_IOCTL_RM_CTX):
+ case IOCTL_NR(DRM_IOCTL_MOD_CTX):
+ case IOCTL_NR(DRM_IOCTL_GET_CTX):
+ case IOCTL_NR(DRM_IOCTL_SWITCH_CTX):
+ case IOCTL_NR(DRM_IOCTL_NEW_CTX):
+ case IOCTL_NR(DRM_IOCTL_RES_CTX):
+
+ case IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE):
+ case IOCTL_NR(DRM_IOCTL_AGP_RELEASE):
+ case IOCTL_NR(DRM_IOCTL_AGP_ENABLE):
+ case IOCTL_NR(DRM_IOCTL_AGP_INFO):
+ case IOCTL_NR(DRM_IOCTL_AGP_ALLOC):
+ case IOCTL_NR(DRM_IOCTL_AGP_FREE):
+ case IOCTL_NR(DRM_IOCTL_AGP_BIND):
+ case IOCTL_NR(DRM_IOCTL_AGP_UNBIND):
+
+ /* Mga specific ioctls */
+
+ case IOCTL_NR(DRM_IOCTL_MGA_INIT):
+
+ /* I810 specific ioctls */
+
+ case IOCTL_NR(DRM_IOCTL_I810_GETBUF):
+ case IOCTL_NR(DRM_IOCTL_I810_COPY):
+
+ case IOCTL_NR(MTIOCGET):
+ case IOCTL_NR(MTIOCPOS):
+ case IOCTL_NR(MTIOCGETCONFIG):
+ case IOCTL_NR(MTIOCSETCONFIG):
+ case IOCTL_NR(PPPIOCSCOMPRESS):
+ case IOCTL_NR(PPPIOCGIDLE):
+ case IOCTL_NR(NCP_IOC_GET_FS_INFO_V2):
+ case IOCTL_NR(NCP_IOC_GETOBJECTNAME):
+ case IOCTL_NR(NCP_IOC_SETOBJECTNAME):
+ case IOCTL_NR(NCP_IOC_GETPRIVATEDATA):
+ case IOCTL_NR(NCP_IOC_SETPRIVATEDATA):
+ case IOCTL_NR(NCP_IOC_GETMOUNTUID2):
+ case IOCTL_NR(CAPI_MANUFACTURER_CMD):
+ case IOCTL_NR(VIDIOCGTUNER):
+ case IOCTL_NR(VIDIOCSTUNER):
+ case IOCTL_NR(VIDIOCGWIN):
+ case IOCTL_NR(VIDIOCSWIN):
+ case IOCTL_NR(VIDIOCGFBUF):
+ case IOCTL_NR(VIDIOCSFBUF):
+ case IOCTL_NR(MGSL_IOCSPARAMS):
+ case IOCTL_NR(MGSL_IOCGPARAMS):
+ case IOCTL_NR(ATM_GETNAMES):
+ case IOCTL_NR(ATM_GETLINKRATE):
+ case IOCTL_NR(ATM_GETTYPE):
+ case IOCTL_NR(ATM_GETESI):
+ case IOCTL_NR(ATM_GETADDR):
+ case IOCTL_NR(ATM_RSTADDR):
+ case IOCTL_NR(ATM_ADDADDR):
+ case IOCTL_NR(ATM_DELADDR):
+ case IOCTL_NR(ATM_GETCIRANGE):
+ case IOCTL_NR(ATM_SETCIRANGE):
+ case IOCTL_NR(ATM_SETESI):
+ case IOCTL_NR(ATM_SETESIF):
+ case IOCTL_NR(ATM_GETSTAT):
+ case IOCTL_NR(ATM_GETSTATZ):
+ case IOCTL_NR(ATM_GETLOOP):
+ case IOCTL_NR(ATM_SETLOOP):
+ case IOCTL_NR(ATM_QUERYLOOP):
+ case IOCTL_NR(ENI_SETMULT):
+ case IOCTL_NR(NS_GETPSTAT):
+ /* case IOCTL_NR(NS_SETBUFLEV): This is a duplicate case with ZATM_GETPOOLZ */
+ case IOCTL_NR(ZATM_GETPOOLZ):
+ case IOCTL_NR(ZATM_GETPOOL):
+ case IOCTL_NR(ZATM_SETPOOL):
+ case IOCTL_NR(ZATM_GETTHIST):
+ case IOCTL_NR(IDT77105_GETSTAT):
+ case IOCTL_NR(IDT77105_GETSTATZ):
+ case IOCTL_NR(IXJCTL_TONE_CADENCE):
+ case IOCTL_NR(IXJCTL_FRAMES_READ):
+ case IOCTL_NR(IXJCTL_FRAMES_WRITTEN):
+ case IOCTL_NR(IXJCTL_READ_WAIT):
+ case IOCTL_NR(IXJCTL_WRITE_WAIT):
+ case IOCTL_NR(IXJCTL_DRYBUFFER_READ):
+ case IOCTL_NR(I2OHRTGET):
+ case IOCTL_NR(I2OLCTGET):
+ case IOCTL_NR(I2OPARMSET):
+ case IOCTL_NR(I2OPARMGET):
+ case IOCTL_NR(I2OSWDL):
+ case IOCTL_NR(I2OSWUL):
+ case IOCTL_NR(I2OSWDEL):
+ case IOCTL_NR(I2OHTML):
X break;
- default:
- return(sys_ioctl(fd, cmd, (unsigned long)arg));
+ default:
+ return sys_ioctl(fd, cmd, (unsigned long)arg);
X
X }
X printk("%x:unimplemented IA32 ioctl system call\n", cmd);
- return(-EINVAL);
+ return -EINVAL;
X }
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/ia32/ia32_ldt.c linux/arch/ia64/ia32/ia32_ldt.c
--- v2.4.14/linux/arch/ia64/ia32/ia32_ldt.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/ia32/ia32_ldt.c Fri Nov 9 14:26:17 2001
@@ -1,6 +1,6 @@
X /*


X * Copyright (C) 2001 Hewlett-Packard Co
- * Copyright (C) 2001 David Mosberger-Tang <dav...@hpl.hp.com>
+ * David Mosberger-Tang <dav...@hpl.hp.com>
X *

X * Adapted from arch/i386/kernel/ldt.c
X */
@@ -16,6 +16,8 @@
X #include <asm/uaccess.h>
X #include <asm/ia32.h>
X
+#define P(p) ((void *) (unsigned long) (p))
+
X /*
X * read_ldt() is not really atomic - this is not a problem since synchronization of reads
X * and writes done to the LDT has to be assured by user-space anyway. Writes are atomic,
@@ -58,10 +60,30 @@
X }
X
X static int
+read_default_ldt (void * ptr, unsigned long bytecount)
+{
+ unsigned long size;
+ int err;
+
+ /* XXX fix me: should return equivalent of default_ldt[0] */
+ err = 0;
+ size = 8;
+ if (size > bytecount)
+ size = bytecount;
+
+ err = size;
+ if (clear_user(ptr, size))


+ err = -EFAULT;
+

+ return err;
+}
+
+static int
X write_ldt (void * ptr, unsigned long bytecount, int oldmode)
X {
X struct ia32_modify_ldt_ldt_s ldt_info;
X __u64 entry;
+ int ret;
X
X if (bytecount != sizeof(ldt_info))
X return -EINVAL;
@@ -97,23 +119,28 @@
X * memory, but we still need to guard against out-of-memory, hence we must use
X * put_user().
X */
- return __put_user(entry, (__u64 *) IA32_LDT_OFFSET + ldt_info.entry_number);
+ ret = __put_user(entry, (__u64 *) IA32_LDT_OFFSET + ldt_info.entry_number);
+ ia32_load_segment_descriptors(current);
+ return ret;
X }
X
X asmlinkage int
-sys32_modify_ldt (int func, void *ptr, unsigned int bytecount)
+sys32_modify_ldt (int func, unsigned int ptr, unsigned int bytecount)
X {
X int ret = -ENOSYS;
X
X switch (func) {
X case 0:
- ret = read_ldt(ptr, bytecount);
+ ret = read_ldt(P(ptr), bytecount);
X break;
X case 1:
- ret = write_ldt(ptr, bytecount, 1);
+ ret = write_ldt(P(ptr), bytecount, 1);
+ break;
+ case 2:
+ ret = read_default_ldt(P(ptr), bytecount);
X break;
X case 0x11:
- ret = write_ldt(ptr, bytecount, 0);
+ ret = write_ldt(P(ptr), bytecount, 0);
X break;
X }
X return ret;
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/ia32/ia32_signal.c linux/arch/ia64/ia32/ia32_signal.c
--- v2.4.14/linux/arch/ia64/ia32/ia32_signal.c Mon Oct 9 17:54:53 2000
+++ linux/arch/ia64/ia32/ia32_signal.c Fri Nov 9 14:26:17 2001
@@ -1,8 +1,8 @@
X /*
X * IA32 Architecture-specific signal handling support.
X *
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <dav...@hpl.hp.com>
+ * Copyright (C) 1999, 2001 Hewlett-Packard Co


+ * David Mosberger-Tang <dav...@hpl.hp.com>

X * Copyright (C) 1999 Arun Sharma <arun....@intel.com>

X * Copyright (C) 2000 VA Linux Co
X * Copyright (C) 2000 Don Dugger <n0...@valinux.com>

@@ -13,6 +13,7 @@
X #include <linux/errno.h>
X #include <linux/kernel.h>


X #include <linux/mm.h>
+#include <linux/personality.h>

X #include <linux/ptrace.h>
X #include <linux/sched.h>
X #include <linux/signal.h>
@@ -28,9 +29,15 @@
X #include <asm/segment.h>
X #include <asm/ia32.h>
X
+#include "../kernel/sigframe.h"
+
+#define A(__x) ((unsigned long)(__x))
+
X #define DEBUG_SIG 0
X #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
X
+#define __IA32_NR_sigreturn 119
+#define __IA32_NR_rt_sigreturn 173
X
X struct sigframe_ia32
X {
@@ -54,12 +61,51 @@
X char retcode[8];
X };
X
-static int
+int
+copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from)
+{
+ unsigned long tmp;
+ int err;
+
+ if (!access_ok(VERIFY_READ, from, sizeof(siginfo_t32)))
+ return -EFAULT;
+
+ err = __get_user(to->si_signo, &from->si_signo);
+ err |= __get_user(to->si_errno, &from->si_errno);
+ err |= __get_user(to->si_code, &from->si_code);
+
+ if (from->si_code < 0)
+ err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
+ else {
+ switch (from->si_code >> 16) {
+ case __SI_CHLD >> 16:
+ err |= __get_user(to->si_utime, &from->si_utime);
+ err |= __get_user(to->si_stime, &from->si_stime);
+ err |= __get_user(to->si_status, &from->si_status);
+ default:
+ err |= __get_user(to->si_pid, &from->si_pid);
+ err |= __get_user(to->si_uid, &from->si_uid);
+ break;
+ case __SI_FAULT >> 16:
+ err |= __get_user(tmp, &from->si_addr);
+ to->si_addr = (void *) tmp;
+ break;
+ case __SI_POLL >> 16:
+ err |= __get_user(to->si_band, &from->si_band);
+ err |= __get_user(to->si_fd, &from->si_fd);
+ break;
+ /* case __SI_RT: This is not generated by the kernel as of now. */
+ }
+ }


+ return err;
+}
+

+int
X copy_siginfo_to_user32 (siginfo_t32 *to, siginfo_t *from)


X {
X int err;
X

- if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))
+ if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t32)))
X return -EFAULT;
X
X /* If you change siginfo_t structure, please be sure
@@ -97,110 +143,329 @@


X return err;
X }
X

+static inline void
+sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int restorer)
+{
+ if (handler + 1 <= 2)
+ /* SIG_DFL, SIG_IGN, or SIG_ERR: must sign-extend to 64-bits */
+ sa->sa.sa_handler = (__sighandler_t) A((int) handler);
+ else
+ sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler);
+}
X
+asmlinkage long
+ia32_rt_sigsuspend (sigset32_t *uset, unsigned int sigsetsize, struct sigscratch *scr)
+{
+ extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall);
+ sigset_t oldset, set;
X
-static int
-setup_sigcontext_ia32(struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate,
- struct pt_regs *regs, unsigned long mask)
+ scr->scratch_unat = 0; /* avoid leaking kernel bits to user level */
+ memset(&set, 0, sizeof(&set));
+
+ if (sigsetsize > sizeof(sigset_t))
+ return -EINVAL;
+
+ if (copy_from_user(&set.sig, &uset->sig, sigsetsize))
+ return -EFAULT;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+
+ spin_lock_irq(&current->sigmask_lock);
+ {
+ oldset = current->blocked;


+ current->blocked = set;
+ recalc_sigpending(current);
+ }

+ spin_unlock_irq(&current->sigmask_lock);
+
+ /*
+ * The return below usually returns to the signal handler. We need to pre-set the
+ * correct error code here to ensure that the right values get saved in sigcontext
+ * by ia64_do_signal.
+ */
+ scr->pt.r8 = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (ia64_do_signal(&oldset, scr, 1))
+ return -EINTR;
+ }
+}
+
+asmlinkage long
+ia32_sigsuspend (unsigned int mask, struct sigscratch *scr)
+{
+ return ia32_rt_sigsuspend((sigset32_t *)&mask, sizeof(mask), scr);
+}
+
+asmlinkage long
+sys32_signal (int sig, unsigned int handler)
+{
+ struct k_sigaction new_sa, old_sa;
+ int ret;
+
+ sigact_set_handler(&new_sa, handler, 0);
+ new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK;
+
+ ret = do_sigaction(sig, &new_sa, &old_sa);
+
+ return ret ? ret : IA32_SA_HANDLER(&old_sa);
+}
+
+asmlinkage long
+sys32_rt_sigaction (int sig, struct sigaction32 *act,
+ struct sigaction32 *oact, unsigned int sigsetsize)
+{
+ struct k_sigaction new_ka, old_ka;
+ unsigned int handler, restorer;
+ int ret;
+
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset32_t))
+ return -EINVAL;
+
+ if (act) {
+ ret = get_user(handler, &act->sa_handler);
+ ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ ret |= get_user(restorer, &act->sa_restorer);
+ ret |= copy_from_user(&new_ka.sa.sa_mask, &act->sa_mask, sizeof(sigset32_t));
+ if (ret)
+ return -EFAULT;
+
+ sigact_set_handler(&new_ka, handler, restorer);
+ }
+
+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+ if (!ret && oact) {
+ ret = put_user(IA32_SA_HANDLER(&old_ka), &oact->sa_handler);
+ ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ ret |= put_user(IA32_SA_RESTORER(&old_ka), &oact->sa_restorer);
+ ret |= copy_to_user(&oact->sa_mask, &old_ka.sa.sa_mask, sizeof(sigset32_t));


+ }
+ return ret;
+}
+
+

+extern asmlinkage long sys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset,
+ size_t sigsetsize);
+
+asmlinkage long
+sys32_rt_sigprocmask (int how, sigset32_t *set, sigset32_t *oset, unsigned int sigsetsize)


+{
+ mm_segment_t old_fs = get_fs();

+ sigset_t s;
+ long ret;
+
+ if (sigsetsize > sizeof(s))
+ return -EINVAL;
+
+ if (set) {
+ memset(&s, 0, sizeof(s));
+ if (copy_from_user(&s.sig, set, sigsetsize))
+ return -EFAULT;
+ }
+ set_fs(KERNEL_DS);
+ ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sizeof(s));
+ set_fs(old_fs);


+ if (ret)
+ return ret;

+ if (oset) {
+ if (copy_to_user(oset, &s.sig, sigsetsize))
+ return -EFAULT;
+ }


+ return 0;
+}
+

+asmlinkage long
+sys32_sigprocmask (int how, unsigned int *set, unsigned int *oset)
X {


- int err = 0;

- unsigned long flag;
+ return sys32_rt_sigprocmask(how, (sigset32_t *) set, (sigset32_t *) oset, sizeof(*set));
+}
X
- err |= __put_user((regs->r16 >> 32) & 0xffff , (unsigned int *)&sc->fs);
- err |= __put_user((regs->r16 >> 48) & 0xffff , (unsigned int *)&sc->gs);
+asmlinkage long
+sys32_rt_sigtimedwait (sigset32_t *uthese, siginfo_t32 *uinfo, struct timespec32 *uts,
+ unsigned int sigsetsize)
+{
+ extern asmlinkage long sys_rt_sigtimedwait (const sigset_t *, siginfo_t *,
+ const struct timespec *, size_t);
+ extern int copy_siginfo_to_user32 (siginfo_t32 *, siginfo_t *);


+ mm_segment_t old_fs = get_fs();

+ struct timespec t;
+ siginfo_t info;
+ sigset_t s;
+ int ret;
X
- err |= __put_user((regs->r16 >> 56) & 0xffff, (unsigned int *)&sc->es);
- err |= __put_user(regs->r16 & 0xffff, (unsigned int *)&sc->ds);
- err |= __put_user(regs->r15, &sc->edi);
- err |= __put_user(regs->r14, &sc->esi);
- err |= __put_user(regs->r13, &sc->ebp);
- err |= __put_user(regs->r12, &sc->esp);
- err |= __put_user(regs->r11, &sc->ebx);
- err |= __put_user(regs->r10, &sc->edx);
- err |= __put_user(regs->r9, &sc->ecx);
- err |= __put_user(regs->r8, &sc->eax);
+ if (copy_from_user(&s.sig, uthese, sizeof(sigset32_t)))
+ return -EFAULT;
+ if (uts) {
+ ret = get_user(t.tv_sec, &uts->tv_sec);
+ ret |= get_user(t.tv_nsec, &uts->tv_nsec);
+ if (ret)
+ return -EFAULT;
+ }
+ set_fs(KERNEL_DS);
+ ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
+ set_fs(old_fs);
+ if (ret >= 0 && uinfo) {
+ if (copy_siginfo_to_user32(uinfo, &info))
+ return -EFAULT;
+ }


+ return ret;
+}
+
+asmlinkage long

+sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 *uinfo)
+{
+ extern asmlinkage long sys_rt_sigqueueinfo (int, int, siginfo_t *);
+ extern int copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from);


+ mm_segment_t old_fs = get_fs();

+ siginfo_t info;
+ int ret;
+
+ if (copy_siginfo_from_user32(&info, uinfo))
+ return -EFAULT;
+ set_fs(KERNEL_DS);
+ ret = sys_rt_sigqueueinfo(pid, sig, &info);
+ set_fs(old_fs);


+ return ret;
+}
+
+asmlinkage long

+sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
+{
+ struct k_sigaction new_ka, old_ka;
+ unsigned int handler, restorer;
+ int ret;
+
+ if (act) {
+ old_sigset32_t mask;
+
+ ret = get_user(handler, &act->sa_handler);
+ ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ ret |= get_user(restorer, &act->sa_restorer);
+ ret |= get_user(mask, &act->sa_mask);
+ if (ret)
+ return ret;
+
+ sigact_set_handler(&new_ka, handler, restorer);
+ siginitset(&new_ka.sa.sa_mask, mask);
+ }
+
+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+ if (!ret && oact) {
+ ret = put_user(IA32_SA_HANDLER(&old_ka), &oact->sa_handler);
+ ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ ret |= put_user(IA32_SA_RESTORER(&old_ka), &oact->sa_restorer);
+ ret |= put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+ }


+
+ return ret;
+}
+

+static int
+setup_sigcontext_ia32 (struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate,
+ struct pt_regs *regs, unsigned long mask)
+{


+ int err = 0;

+ unsigned long flag;
+
+ err |= __put_user((regs->r16 >> 32) & 0xffff, (unsigned int *)&sc->fs);
+ err |= __put_user((regs->r16 >> 48) & 0xffff, (unsigned int *)&sc->gs);
+ err |= __put_user((regs->r16 >> 16) & 0xffff, (unsigned int *)&sc->es);
+ err |= __put_user(regs->r16 & 0xffff, (unsigned int *)&sc->ds);
+ err |= __put_user(regs->r15, &sc->edi);
+ err |= __put_user(regs->r14, &sc->esi);
+ err |= __put_user(regs->r13, &sc->ebp);
+ err |= __put_user(regs->r12, &sc->esp);
+ err |= __put_user(regs->r11, &sc->ebx);
+ err |= __put_user(regs->r10, &sc->edx);
+ err |= __put_user(regs->r9, &sc->ecx);
+ err |= __put_user(regs->r8, &sc->eax);
X #if 0
- err |= __put_user(current->tss.trap_no, &sc->trapno);
- err |= __put_user(current->tss.error_code, &sc->err);
+ err |= __put_user(current->tss.trap_no, &sc->trapno);
+ err |= __put_user(current->tss.error_code, &sc->err);
X #endif
- err |= __put_user(regs->cr_iip, &sc->eip);
- err |= __put_user(regs->r17 & 0xffff, (unsigned int *)&sc->cs);
- /*
- * `eflags' is in an ar register for this context
- */
- asm volatile ("mov %0=ar.eflag ;;" : "=r"(flag));
- err |= __put_user((unsigned int)flag, &sc->eflags);
-
- err |= __put_user(regs->r12, &sc->esp_at_signal);
- err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int *)&sc->ss);


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

echo 'End of part 025'
echo 'File patch-2.4.15 is continued in part 026'
echo "026" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:05 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part029

#!/bin/sh -x
# this is part 029 of a 115 - part archive


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

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

- return retval;
-}
-

-static inline void
-put_mod_name(char *buf)
-{
- free_page((unsigned long)buf);
-}
-
-static __inline__ struct module *
-find_module(const char *name)
-{
- struct module *mod;
-
- for (mod = module_list; mod ; mod = mod->next) {
- if (mod->flags & MOD_DELETED)
- continue;
- if (!strcmp(mod->name, name))
- break;
- }
-
- return mod;
-}
-
-static int
-qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret)
-{
- struct module *mod;
- size_t nmod, space, len;
-
- nmod = space = 0;
-
- for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) {
- len = strlen(mod->name)+1;
- if (len > bufsize)
- goto calc_space_needed;
- if (copy_to_user(buf, mod->name, len))
- return -EFAULT;
- buf += len;
- bufsize -= len;
- space += len;
- }
-
- if (put_user(nmod, ret))
- return -EFAULT;
- else
- return 0;
-
-calc_space_needed:
- space += len;
- while ((mod = mod->next)->next != NULL)
- space += strlen(mod->name)+1;
-
- if (put_user(space, ret))
- return -EFAULT;
- else
- return -ENOSPC;
-}
-
-static int
-qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
-{
- size_t i, space, len;
-
- if (mod->next == NULL)
- return -EINVAL;
- if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
- if (put_user(0, ret))
- return -EFAULT;
- else
- return 0;
-
- space = 0;
- for (i = 0; i < mod->ndeps; ++i) {
- const char *dep_name = mod->deps[i].dep->name;
-
- len = strlen(dep_name)+1;
- if (len > bufsize)
- goto calc_space_needed;
- if (copy_to_user(buf, dep_name, len))
- return -EFAULT;
- buf += len;
- bufsize -= len;
- space += len;
- }
-
- if (put_user(i, ret))
- return -EFAULT;
- else
- return 0;
-
-calc_space_needed:
- space += len;
- while (++i < mod->ndeps)
- space += strlen(mod->deps[i].dep->name)+1;
-
- if (put_user(space, ret))
- return -EFAULT;
- else
- return -ENOSPC;
-}
-
-static int
-qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
-{
- size_t nrefs, space, len;
- struct module_ref *ref;
-
- if (mod->next == NULL)
- return -EINVAL;
- if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
- if (put_user(0, ret))
- return -EFAULT;
- else
- return 0;
-
- space = 0;
- for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
- const char *ref_name = ref->ref->name;
-
- len = strlen(ref_name)+1;
- if (len > bufsize)
- goto calc_space_needed;
- if (copy_to_user(buf, ref_name, len))
- return -EFAULT;
- buf += len;
- bufsize -= len;
- space += len;
- }
-
- if (put_user(nrefs, ret))
- return -EFAULT;
- else
- return 0;
-
-calc_space_needed:
- space += len;
- while ((ref = ref->next_ref) != NULL)
- space += strlen(ref->ref->name)+1;
-
- if (put_user(space, ret))
- return -EFAULT;
- else
- return -ENOSPC;


-}
-
-static inline int

-qm_symbols(struct module *mod, char *buf, size_t bufsize,
- __kernel_size_t32 *ret)
-{
- size_t i, space, len;
- struct module_symbol *s;
- char *strings;
- unsigned *vals;
-
- if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
- if (put_user(0, ret))
- return -EFAULT;
- else
- return 0;
-
- space = mod->nsyms * 2*sizeof(u32);
-
- i = len = 0;
- s = mod->syms;
-
- if (space > bufsize)
- goto calc_space_needed;
-
- if (!access_ok(VERIFY_WRITE, buf, space))
- return -EFAULT;
-
- bufsize -= space;
- vals = (unsigned *)buf;
- strings = buf+space;
-
- for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
- len = strlen(s->name)+1;
- if (len > bufsize)
- goto calc_space_needed;
-
- if (copy_to_user(strings, s->name, len)
- || __put_user(s->value, vals+0)
- || __put_user(space, vals+1))
- return -EFAULT;
-
- strings += len;
- bufsize -= len;
- space += len;
- }
-
- if (put_user(i, ret))
- return -EFAULT;
- else
- return 0;
+ __kernel_mode_t32 dir_mode;
+};
X
-calc_space_needed:
- for (; i < mod->nsyms; ++i, ++s)
- space += strlen(s->name)+1;
+static void *
+do_smb_super_data_conv(void *raw_data)
+{
+ struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
+ struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
X
- if (put_user(space, ret))
- return -EFAULT;
- else
- return -ENOSPC;
+ s->version = s32->version;
+ s->mounted_uid = s32->mounted_uid;
+ s->uid = s32->uid;
+ s->gid = s32->gid;
+ s->file_mode = s32->file_mode;
+ s->dir_mode = s32->dir_mode;
+ return raw_data;


X }
X
-static inline int

-qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+static int
+copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
X {
- int error = 0;
-
- if (mod->next == NULL)
- return -EINVAL;
-
- if (sizeof(struct module_info32) <= bufsize) {
- struct module_info32 info;
- info.addr = (unsigned long)mod;
- info.size = mod->size;
- info.flags = mod->flags;
- info.usecount =
- ((mod_member_present(mod, can_unload)
- && mod->can_unload)
- ? -1 : atomic_read(&mod->uc.usecount));
-
- if (copy_to_user(buf, &info, sizeof(struct module_info32)))
- return -EFAULT;
- } else
- error = -ENOSPC;
+ int i;
+ unsigned long page;
+ struct vm_area_struct *vma;
X
- if (put_user(sizeof(struct module_info32), ret))
+ *kernel = 0;
+ if(!user)
+ return 0;
+ vma = find_vma(current->mm, (unsigned long)user);
+ if(!vma || (unsigned long)user < vma->vm_start)
X return -EFAULT;
-
- return error;
+ if(!(vma->vm_flags & VM_READ))
+ return -EFAULT;
+ i = vma->vm_end - (unsigned long) user;
+ if(PAGE_SIZE <= (unsigned long) i)
+ i = PAGE_SIZE - 1;
+ if(!(page = __get_free_page(GFP_KERNEL)))
+ return -ENOMEM;
+ if(copy_from_user((void *) page, user, i)) {
+ free_page(page);
+ return -EFAULT;
+ }
+ *kernel = page;


+ return 0;
X }
X

+extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
+ unsigned long new_flags, void *data);
+
+#define SMBFS_NAME "smbfs"
+#define NCPFS_NAME "ncpfs"
+
X asmlinkage long
-sys32_query_module(char *name_user, int which, char *buf,
- __kernel_size_t32 bufsize, u32 ret)
+sys32_mount(char *dev_name, char *dir_name, char *type,
+ unsigned long new_flags, u32 data)
X {
- struct module *mod;
- int err;
+ unsigned long type_page;
+ int err, is_smb, is_ncp;
X
- lock_kernel();
- if (name_user == 0) {
- /* This finds "kernel_module" which is not exported. */
- for(mod = module_list; mod->next != NULL; mod = mod->next)
- ;
+ if(!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ is_smb = is_ncp = 0;
+ err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
+ if(err)
+ return err;
+ if(type_page) {
+ is_smb = !strcmp((char *)type_page, SMBFS_NAME);
+ is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
+ }
+ if(!is_smb && !is_ncp) {
+ if(type_page)
+ free_page(type_page);
+ return sys_mount(dev_name, dir_name, type, new_flags,
+ (void *)AA(data));
X } else {
- long namelen;
- char *name;
+ unsigned long dev_page, dir_page, data_page;
X
- if ((namelen = get_mod_name(name_user, &name)) < 0) {
- err = namelen;
- goto out;
- }
- err = -ENOENT;
- if (namelen == 0) {
- /* This finds "kernel_module" which is not exported. */
- for(mod = module_list;
- mod->next != NULL;
- mod = mod->next) ;
- } else if ((mod = find_module(name)) == NULL) {
- put_mod_name(name);
+ err = copy_mount_stuff_to_kernel((const void *)dev_name,
+ &dev_page);
+ if(err)
X goto out;
- }
- put_mod_name(name);
- }
-
- switch (which)
- {
- case 0:
- err = 0;
- break;
- case QM_MODULES:
- err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret));
- break;
- case QM_DEPS:
- err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
- break;
- case QM_REFS:
- err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
- break;
- case QM_SYMBOLS:
- err = qm_symbols(mod, buf, bufsize,
- (__kernel_size_t32 *)AA(ret));
- break;
- case QM_INFO:
- err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
- break;
- default:


- err = -EINVAL;
- break;

+ err = copy_mount_stuff_to_kernel((const void *)dir_name,
+ &dir_page);
+ if(err)
+ goto dev_out;
+ err = copy_mount_stuff_to_kernel((const void *)AA(data),
+ &data_page);
+ if(err)
+ goto dir_out;
+ if(is_ncp)
+ do_ncp_super_data_conv((void *)data_page);
+ else if(is_smb)
+ do_smb_super_data_conv((void *)data_page);
+ else
+ panic("The problem is here...");
+ err = do_mount((char *)dev_page, (char *)dir_page,
+ (char *)type_page, new_flags,
+ (void *)data_page);
+ if(data_page)
+ free_page(data_page);
+ dir_out:
+ if(dir_page)
+ free_page(dir_page);
+ dev_out:
+ if(dev_page)
+ free_page(dev_page);
+ out:
+ if(type_page)
+ free_page(type_page);
+ return err;
X }
-out:
- unlock_kernel();


- return err;
X }
X

-struct kernel_sym32 {
- u32 value;
- char name[60];
-};
-
-extern asmlinkage long sys_get_kernel_syms(struct kernel_sym *table);
+extern asmlinkage long sys_setreuid(uid_t ruid, uid_t euid);
X
-asmlinkage long
-sys32_get_kernel_syms(struct kernel_sym32 *table)
+asmlinkage long sys32_setreuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid)
X {
- int len, i;
- struct kernel_sym *tbl;
- mm_segment_t old_fs;
+ uid_t sruid, seuid;
X
- len = sys_get_kernel_syms(NULL);
- if (!table) return len;
- tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
- if (!tbl) return -ENOMEM;


- old_fs = get_fs();
- set_fs (KERNEL_DS);

- sys_get_kernel_syms(tbl);
- set_fs (old_fs);
- for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) {
- if (put_user (tbl[i].value, &table->value) ||
- copy_to_user (table->name, tbl[i].name, 60))
- break;
- }
- kfree (tbl);
- return i;
+ sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
+ seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
+ return sys_setreuid(sruid, seuid);
X }
X
-#else /* CONFIG_MODULES */
-
-asmlinkage unsigned long
-sys32_create_module(const char *name_user, size_t size)
-{
- return -ENOSYS;
-}
+extern asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
X
X asmlinkage long


-sys32_init_module(const char *name_user, struct module *mod_user)

+sys32_setresuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid,
+ __kernel_uid_t32 suid)
X {
- return -ENOSYS;
-}
+ uid_t sruid, seuid, ssuid;
X

-asmlinkage long
-sys32_delete_module(const char *name_user)
-{

- return -ENOSYS;
+ sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
+ seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
+ ssuid = (suid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)suid);
+ return sys_setresuid(sruid, seuid, ssuid);
X }
X
+extern asmlinkage long sys_setregid(gid_t rgid, gid_t egid);
+
X asmlinkage long
-sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize,
- size_t *ret)
+sys32_setregid(__kernel_gid_t32 rgid, __kernel_gid_t32 egid)
X {
- /* Let the program know about the new interface. Not that
- it'll do them much good. */
- if (which == 0)
- return 0;
+ gid_t srgid, segid;
X
- return -ENOSYS;
+ srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid);
+ segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid);
+ return sys_setregid(srgid, segid);
X }
X
+extern asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);
+
X asmlinkage long
-sys32_get_kernel_syms(struct kernel_sym *table)
+sys32_setresgid(__kernel_gid_t32 rgid, __kernel_gid_t32 egid,
+ __kernel_gid_t32 sgid)
X {
- return -ENOSYS;
-}
+ gid_t srgid, segid, ssgid;
X
-#endif /* CONFIG_MODULES */
+ srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid);
+ segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid);
+ ssgid = (sgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)sgid);
+ return sys_setresgid(srgid, segid, ssgid);
+}
X
X /* Stuff for NFS server syscalls... */
X struct nfsctl_svc32 {
@@ -4820,154 +4293,6 @@


X return err;
X }
X

-asmlinkage long sys_utimes(char *, struct timeval *);
-
-asmlinkage long
-sys32_utimes(char *filename, struct timeval32 *tvs)
-{
- char *kfilename;
- struct timeval ktvs[2];


- mm_segment_t old_fs;
- int ret;
-

- kfilename = getname32(filename);
- ret = PTR_ERR(kfilename);
- if (!IS_ERR(kfilename)) {
- if (tvs) {
- if (get_tv32(&ktvs[0], tvs) ||
- get_tv32(&ktvs[1], 1+tvs))


- return -EFAULT;
- }
-

- old_fs = get_fs();
- set_fs(KERNEL_DS);

- ret = sys_utimes(kfilename, &ktvs[0]);
- set_fs(old_fs);
-
- putname(kfilename);


- }
- return ret;
-}
-

-/* These are here just in case some old ia32 binary calls it. */
-asmlinkage long
-sys32_pause(void)
-{
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- return -ERESTARTNOHAND;
-}
-
-/* PCI config space poking. */
-extern asmlinkage long sys_pciconfig_read(unsigned long bus,
- unsigned long dfn,
- unsigned long off,
- unsigned long len,
- unsigned char *buf);
-
-extern asmlinkage long sys_pciconfig_write(unsigned long bus,
- unsigned long dfn,
- unsigned long off,
- unsigned long len,
- unsigned char *buf);
-
-asmlinkage long
-sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
-{
- return sys_pciconfig_read((unsigned long) bus,
- (unsigned long) dfn,
- (unsigned long) off,
- (unsigned long) len,
- (unsigned char *)AA(ubuf));
-}
-
-asmlinkage long
-sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
-{
- return sys_pciconfig_write((unsigned long) bus,
- (unsigned long) dfn,
- (unsigned long) off,
- (unsigned long) len,
- (unsigned char *)AA(ubuf));
-}
-
-extern asmlinkage long sys_prctl(int option, unsigned long arg2,
- unsigned long arg3, unsigned long arg4,
- unsigned long arg5);
-
-asmlinkage long
-sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
-{
- return sys_prctl(option,
- (unsigned long) arg2,
- (unsigned long) arg3,
- (unsigned long) arg4,
- (unsigned long) arg5);
-}
-
-
-extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
- size_t count, loff_t pos);
-
-extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
- size_t count, loff_t pos);
-
-typedef __kernel_ssize_t32 ssize_t32;
-
-asmlinkage ssize_t32
-sys32_pread(unsigned int fd, char *ubuf, __kernel_size_t32 count,
- u32 poshi, u32 poslo)
-{
- return sys_pread(fd, ubuf, count,
- ((loff_t)AA(poshi) << 32) | AA(poslo));
-}
-
-asmlinkage ssize_t32
-sys32_pwrite(unsigned int fd, char *ubuf, __kernel_size_t32 count,
- u32 poshi, u32 poslo)
-{
- return sys_pwrite(fd, ubuf, count,
- ((loff_t)AA(poshi) << 32) | AA(poslo));
-}
-
-
-extern asmlinkage long sys_personality(unsigned long);
-
-asmlinkage long
-sys32_personality(unsigned long personality)
-{
- int ret;
- if (current->personality == PER_LINUX32 && personality == PER_LINUX)
- personality = PER_LINUX32;
- ret = sys_personality(personality);
- if (ret == PER_LINUX32)
- ret = PER_LINUX;


- return ret;
-}
-

-extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset,
- size_t count);
-
-asmlinkage long
-sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
-{


- mm_segment_t old_fs = get_fs();

- int ret;
- off_t of;
-
- if (offset && get_user(of, offset))
- return -EFAULT;
-
- set_fs(KERNEL_DS);
- ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
- set_fs(old_fs);
-
- if (!ret && offset && put_user(of, offset))


- return -EFAULT;
-
- return ret;
-}
-

X /* Handle adjtimex compatability. */
X
X struct timex32 {
@@ -5041,4 +4366,4 @@


X
X return ret;
X }

-#endif // NOTYET
+#endif /* NOTYET */
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/Makefile linux/arch/ia64/kernel/Makefile
--- v2.4.14/linux/arch/ia64/kernel/Makefile Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/Makefile Fri Nov 9 14:26:17 2001
@@ -16,7 +16,7 @@
X obj-y := acpi.o entry.o gate.o efi.o efi_stub.o ia64_ksyms.o irq.o irq_ia64.o irq_lsapic.o ivt.o \
X machvec.o pal.o process.o perfmon.o ptrace.o sal.o semaphore.o setup.o \
X signal.o sys_ia64.o traps.o time.o unaligned.o unwind.o
-obj-$(CONFIG_IA64_GENERIC) += machvec.o iosapic.o
+obj-$(CONFIG_IA64_GENERIC) += iosapic.o
X obj-$(CONFIG_IA64_DIG) += iosapic.o
X obj-$(CONFIG_IA64_PALINFO) += palinfo.o
X obj-$(CONFIG_EFI_VARS) += efivars.o
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/acpi.c linux/arch/ia64/kernel/acpi.c
--- v2.4.14/linux/arch/ia64/kernel/acpi.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/acpi.c Fri Nov 9 14:26:17 2001
@@ -9,7 +9,7 @@
X * Copyright (C) 2000 Hewlett-Packard Co.
X * Copyright (C) 2000 David Mosberger-Tang <dav...@hpl.hp.com>
X * Copyright (C) 2000 Intel Corp.
- * Copyright (C) 2000 J.I. Lee <jung-...@intel.com>
+ * Copyright (C) 2000,2001 J.I. Lee <jung-...@intel.com>
X * ACPI based kernel configuration manager.
X * ACPI 2.0 & IA64 ext 0.71
X */
@@ -23,6 +23,9 @@
X #include <linux/string.h>
X #include <linux/types.h>
X #include <linux/irq.h>
+#ifdef CONFIG_SERIAL_ACPI
+#include <linux/acpi_serial.h>
+#endif
X
X #include <asm/acpi-ext.h>
X #include <asm/acpikcfg.h>
@@ -34,6 +37,9 @@
X
X #undef ACPI_DEBUG /* Guess what this does? */
X
+/* global array to record platform interrupt vectors for generic int routing */
+int platform_irq_list[ACPI_MAX_PLATFORM_IRQS];
+
X /* These are ugly but will be reclaimed by the kernel */
X int __initdata available_cpus;
X int __initdata total_cpus;
@@ -41,8 +47,11 @@
X void (*pm_idle) (void);
X void (*pm_power_off) (void);
X
+asm (".weak iosapic_register_irq");
X asm (".weak iosapic_register_legacy_irq");
+asm (".weak iosapic_register_platform_irq");
X asm (".weak iosapic_init");
+asm (".weak iosapic_version");
X
X const char *
X acpi_get_sysname (void)
@@ -55,6 +64,8 @@
X return "hpsim";
X # elif defined (CONFIG_IA64_SGI_SN1)
X return "sn1";
+# elif defined (CONFIG_IA64_SGI_SN2)
+ return "sn2";
X # elif defined (CONFIG_IA64_DIG)
X return "dig";
X # else
@@ -65,6 +76,25 @@
X }
X
X /*
+ * Interrupt routing API for device drivers.
+ * Provides the interrupt vector for a generic platform event
+ * (currently only CPEI implemented)
+ */
+int
+acpi_request_vector(u32 int_type)
+{
+ int vector = -1;
+
+ if (int_type < ACPI_MAX_PLATFORM_IRQS) {
+ /* correctable platform error interrupt */
+ vector = platform_irq_list[int_type];
+ } else
+ printk("acpi_request_vector(): invalid interrupt type\n");
+
+ return vector;
+}
+
+/*
X * Configure legacy IRQ information.
X */
X static void __init
@@ -139,15 +169,93 @@
X }
X
X /*
- * Info on platform interrupt sources: NMI. PMI, INIT, etc.
+ * Extract iosapic info from madt (again) to determine which iosapic
+ * this platform interrupt resides in
+ */
+static int __init
+acpi20_which_iosapic (int global_vector, acpi_madt_t *madt, u32 *irq_base, char **iosapic_address)
+{
+ acpi_entry_iosapic_t *iosapic;
+ char *p, *end;
+ int ver, max_pin;
+
+ p = (char *) (madt + 1);
+ end = p + (madt->header.length - sizeof(acpi_madt_t));
+
+ while (p < end) {
+ switch (*p) {
+ case ACPI20_ENTRY_IO_SAPIC:
+ /* collect IOSAPIC info for platform int use later */
+ iosapic = (acpi_entry_iosapic_t *)p;
+ *irq_base = iosapic->irq_base;
+ *iosapic_address = ioremap(iosapic->address, 0);
+ /* is this the iosapic we're looking for? */
+ ver = iosapic_version(*iosapic_address);
+ max_pin = (ver >> 16) & 0xff;
+ if ((global_vector - *irq_base) <= max_pin)
+ return 0; /* found it! */
+ break;
+ default:
+ break;
+ }
+ p += p[1];
+ }


+ return 1;
+}
+

+/*
+ * Info on platform interrupt sources: NMI, PMI, INIT, etc.
X */
X static void __init
-acpi20_platform (char *p)
+acpi20_platform (char *p, acpi_madt_t *madt)
X {
+ int vector;
+ u32 irq_base;
+ char *iosapic_address;
+ unsigned long polarity = 0, trigger = 0;
X acpi20_entry_platform_src_t *plat = (acpi20_entry_platform_src_t *) p;
X
X printk("PLATFORM: IOSAPIC %x -> Vector %x on CPU %.04u:%.04u\n",
X plat->iosapic_vector, plat->global_vector, plat->eid, plat->id);
+
+ /* record platform interrupt vectors for generic int routing code */
+
+ if (!iosapic_register_platform_irq) {
+ printk("acpi20_platform(): no ACPI platform IRQ support\n");
+ return;
+ }
+
+ /* extract polarity and trigger info from flags */
+ switch (plat->flags) {
+ case 0x5: polarity = 1; trigger = 1; break;
+ case 0x7: polarity = 0; trigger = 1; break;
+ case 0xd: polarity = 1; trigger = 0; break;
+ case 0xf: polarity = 0; trigger = 0; break;
+ default:
+ printk("acpi20_platform(): unknown flags 0x%x\n", plat->flags);
+ break;
+ }
+
+ /* which iosapic does this IRQ belong to? */
+ if (acpi20_which_iosapic(plat->global_vector, madt, &irq_base, &iosapic_address)) {
+ printk("acpi20_platform(): I/O SAPIC not found!\n");
+ return;
+ }
+
+ /*
+ * get vector assignment for this IRQ, set attributes, and program the IOSAPIC
+ * routing table
+ */
+ vector = iosapic_register_platform_irq(plat->int_type,
+ plat->global_vector,
+ plat->iosapic_vector,
+ plat->eid,
+ plat->id,
+ polarity,
+ trigger,
+ irq_base,
+ iosapic_address);
+ platform_irq_list[plat->int_type] = vector;
X }
X
X /*
@@ -173,8 +281,10 @@
X static void __init
X acpi20_parse_madt (acpi_madt_t *madt)
X {
- acpi_entry_iosapic_t *iosapic;
+ acpi_entry_iosapic_t *iosapic = NULL;
+ acpi20_entry_lsapic_t *lsapic = NULL;
X char *p, *end;
+ int i;
X
X /* Base address of IPI Message Block */
X if (madt->lapic_address) {
@@ -186,23 +296,27 @@
X p = (char *) (madt + 1);
X end = p + (madt->header.length - sizeof(acpi_madt_t));
X
+ /* Initialize platform interrupt vector array */
+ for (i = 0; i < ACPI_MAX_PLATFORM_IRQS; i++)
+ platform_irq_list[i] = -1;
+
X /*
- * Splitted entry parsing to ensure ordering.
+ * Split-up entry parsing to ensure ordering.
X */
-
X while (p < end) {
X switch (*p) {
- case ACPI20_ENTRY_LOCAL_APIC_ADDR_OVERRIDE:
+ case ACPI20_ENTRY_LOCAL_APIC_ADDR_OVERRIDE:
X printk("ACPI 2.0 MADT: LOCAL APIC Override\n");
X acpi20_lapic_addr_override(p);
X break;
X
- case ACPI20_ENTRY_LOCAL_SAPIC:
+ case ACPI20_ENTRY_LOCAL_SAPIC:
X printk("ACPI 2.0 MADT: LOCAL SAPIC\n");
+ lsapic = (acpi20_entry_lsapic_t *) p;
X acpi20_lsapic(p);
X break;
X
- case ACPI20_ENTRY_IO_SAPIC:
+ case ACPI20_ENTRY_IO_SAPIC:
X iosapic = (acpi_entry_iosapic_t *) p;
X if (iosapic_init)
X /*
@@ -218,26 +332,25 @@
X );
X break;
X
- case ACPI20_ENTRY_PLATFORM_INT_SOURCE:
+ case ACPI20_ENTRY_PLATFORM_INT_SOURCE:
X printk("ACPI 2.0 MADT: PLATFORM INT SOURCE\n");
- acpi20_platform(p);
+ acpi20_platform(p, madt);
X break;
X
- case ACPI20_ENTRY_LOCAL_APIC:
+ case ACPI20_ENTRY_LOCAL_APIC:
X printk("ACPI 2.0 MADT: LOCAL APIC entry\n"); break;
- case ACPI20_ENTRY_IO_APIC:
+ case ACPI20_ENTRY_IO_APIC:
X printk("ACPI 2.0 MADT: IO APIC entry\n"); break;
- case ACPI20_ENTRY_NMI_SOURCE:
+ case ACPI20_ENTRY_NMI_SOURCE:
X printk("ACPI 2.0 MADT: NMI SOURCE entry\n"); break;
- case ACPI20_ENTRY_LOCAL_APIC_NMI:
+ case ACPI20_ENTRY_LOCAL_APIC_NMI:
X printk("ACPI 2.0 MADT: LOCAL APIC NMI entry\n"); break;
- case ACPI20_ENTRY_INT_SRC_OVERRIDE:
+ case ACPI20_ENTRY_INT_SRC_OVERRIDE:
X break;
- default:
+ default:
X printk("ACPI 2.0 MADT: unknown entry skip\n"); break;
X break;
X }
-
X p += p[1];
X }
X
@@ -245,16 +358,35 @@
X end = p + (madt->header.length - sizeof(acpi_madt_t));
X
X while (p < end) {
+ switch (*p) {
+ case ACPI20_ENTRY_LOCAL_APIC:
+ if (lsapic) break;
+ printk("ACPI 2.0 MADT: LOCAL APIC entry\n");
+ /* parse local apic if there's no local Sapic */
+ break;
+ case ACPI20_ENTRY_IO_APIC:
+ if (iosapic) break;
+ printk("ACPI 2.0 MADT: IO APIC entry\n");
+ /* parse ioapic if there's no ioSapic */
+ break;
+ default:
+ break;
+ }
+ p += p[1];
+ }
X
+ p = (char *) (madt + 1);
+ end = p + (madt->header.length - sizeof(acpi_madt_t));
+
+ while (p < end) {
X switch (*p) {
- case ACPI20_ENTRY_INT_SRC_OVERRIDE:
+ case ACPI20_ENTRY_INT_SRC_OVERRIDE:
X printk("ACPI 2.0 MADT: INT SOURCE Override\n");
X acpi_legacy_irq(p);
X break;
- default:
+ default:
X break;
X }
-
X p += p[1];
X }
X
@@ -269,6 +401,7 @@
X # ifdef CONFIG_ACPI
X acpi_xsdt_t *xsdt;
X acpi_desc_table_hdr_t *hdrp;
+ acpi_madt_t *madt;
X int tables, i;
X
X if (strncmp(rsdp20->signature, ACPI_RSDP_SIG, ACPI_RSDP_SIG_LEN)) {
@@ -310,9 +443,76 @@
X ACPI_MADT_SIG, ACPI_MADT_SIG_LEN) != 0)
X continue;
X
- acpi20_parse_madt((acpi_madt_t *) hdrp);
+ /* Save MADT pointer for later */
+ madt = (acpi_madt_t *) hdrp;
+ acpi20_parse_madt(madt);
X }
X
+#ifdef CONFIG_SERIAL_ACPI
+ /*
+ * Now we're interested in other tables. We want the iosapics already
+ * initialized, so we do it in a separate loop.
+ */
+ for (i = 0; i < tables; i++) {
+ hdrp = (acpi_desc_table_hdr_t *) __va(readl_unaligned(&xsdt->entry_ptrs[i]));
+ /*
+ * search for SPCR and DBGP table entries so we can enable
+ * non-pci interrupts to IO-SAPICs.
+ */
+ if (!strncmp(hdrp->signature, ACPI_SPCRT_SIG, ACPI_SPCRT_SIG_LEN) ||
+ !strncmp(hdrp->signature, ACPI_DBGPT_SIG, ACPI_DBGPT_SIG_LEN))
+ {
+ acpi_ser_t *spcr = (void *)hdrp;
+ unsigned long global_int;
+
+ setup_serial_acpi(hdrp);
+
+ /*
+ * ACPI is able to describe serial ports that live at non-standard
+ * memory space addresses and use SAPIC interrupts. If not also
+ * PCI devices, there would be no interrupt vector information for
+ * them. This checks for and fixes that situation.
+ */
+ if (spcr->length < sizeof(acpi_ser_t))
+ /* table is not long enough for full info, thus no int */
+ break;
+
+ /*
+ * If the device is not in PCI space, but uses a SAPIC interrupt,
+ * we need to program the SAPIC so that serial can autoprobe for
+ * the IA64 interrupt vector later on. If the device is in PCI
+ * space, it should already be setup via the PCI vectors
+ */
+ if (spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE &&
+ spcr->int_type == ACPI_SERIAL_INT_SAPIC)
+ {
+ u32 irq_base;
+ char *iosapic_address;
+ int vector;
+
+ /* We have a UART in memory space with a SAPIC interrupt */
+ global_int = ( (spcr->global_int[3] << 24)
+ | (spcr->global_int[2] << 16)
+ | (spcr->global_int[1] << 8)
+ | spcr->global_int[0]);
+
+ if (!iosapic_register_irq)
+ continue;
+
+ /* which iosapic does this IRQ belong to? */
+ if (acpi20_which_iosapic(global_int, madt, &irq_base,
+ &iosapic_address) == 0)
+ {
+ vector = iosapic_register_irq(global_int,
+ 1, /* active high polarity */
+ 1, /* edge triggered */
+ irq_base,
+ iosapic_address);
+ }
+ }
+ }
+ }
+#endif
X acpi_cf_terminate();
X
X # ifdef CONFIG_SMP
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/efi.c linux/arch/ia64/kernel/efi.c
--- v2.4.14/linux/arch/ia64/kernel/efi.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/efi.c Fri Nov 9 14:26:17 2001
@@ -6,8 +6,8 @@
X * Copyright (C) 1999 VA Linux Systems
X * Copyright (C) 1999 Walt Drummond <drum...@valinux.com>
X * Copyright (C) 1999-2001 Hewlett-Packard Co.


- * Copyright (C) 1999 David Mosberger-Tang <dav...@hpl.hp.com>

- * Copyright (C) 1999-2001 Stephane Eranian <era...@hpl.hp.com>


+ * David Mosberger-Tang <dav...@hpl.hp.com>

+ * Stephane Eranian <era...@hpl.hp.com>
X *
X * All EFI Runtime Services are not implemented yet as EFI only
X * supports physical mode addressing on SoftSDV. This is to be fixed
@@ -234,7 +234,7 @@
X * The only ITLB entry in region 7 that is used is the one installed by
X * __start(). That entry covers a 64MB range.
X */
- mask = ~((1 << KERNEL_PG_SHIFT) - 1);
+ mask = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1);
X vaddr = PAGE_OFFSET + md->phys_addr;
X
X /*
@@ -242,29 +242,32 @@
X * mapping.
X *
X * PAL code is guaranteed to be aligned on a power of 2 between 4k and
- * 256KB. Also from the documentation, it seems like there is an implicit
- * guarantee that you will need only ONE ITR to map it. This implies that
- * the PAL code is always aligned on its size, i.e., the closest matching
- * page size supported by the TLB. Therefore PAL code is guaranteed never
- * to cross a 64MB unless it is bigger than 64MB (very unlikely!). So for
+ * 256KB and that only one ITR is needed to map it. This implies that the
+ * PAL code is always aligned on its size, i.e., the closest matching page
+ * size supported by the TLB. Therefore PAL code is guaranteed never to
+ * cross a 64MB unless it is bigger than 64MB (very unlikely!). So for
X * now the following test is enough to determine whether or not we need a
X * dedicated ITR for the PAL code.
X */
X if ((vaddr & mask) == (KERNEL_START & mask)) {
- printk(__FUNCTION__ " : no need to install ITR for PAL code\n");
+ printk(__FUNCTION__ ": no need to install ITR for PAL code\n");
X continue;
X }
X
+ if (md->num_pages << 12 > IA64_GRANULE_SIZE)
+ panic("Woah! PAL code size bigger than a granule!");
+
+ mask = ~((1 << IA64_GRANULE_SHIFT) - 1);
X printk("CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n",
X smp_processor_id(), md->phys_addr, md->phys_addr + (md->num_pages << 12),
- vaddr & mask, (vaddr & mask) + KERNEL_PG_SIZE);
+ vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE);
X
X /*
X * Cannot write to CRx with PSR.ic=1
X */
X ia64_clear_ic(flags);
X ia64_itr(0x1, IA64_TR_PALCODE, vaddr & mask,
- pte_val(mk_pte_phys(md->phys_addr, PAGE_KERNEL)), KERNEL_PG_SHIFT);
+ pte_val(mk_pte_phys(md->phys_addr, PAGE_KERNEL)), IA64_GRANULE_SHIFT);
X local_irq_restore(flags);
X ia64_srlz_i();
X }
@@ -482,5 +485,7 @@
X static void __exit
X efivars_exit(void)
X {
+#ifdef CONFIG_PROC_FS
X remove_proc_entry(efi_dir->name, NULL);
+#endif
X }
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/efi_stub.S linux/arch/ia64/kernel/efi_stub.S
--- v2.4.14/linux/arch/ia64/kernel/efi_stub.S Thu Apr 5 12:51:47 2001
+++ linux/arch/ia64/kernel/efi_stub.S Fri Nov 9 14:26:17 2001


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

X * EFI call stub.
X *
- * Copyright (C) 1999-2000 Hewlett-Packard Co
- * Copyright (C) 1999-2000 David Mosberger <dav...@hpl.hp.com>
+ * Copyright (C) 1999-2001 Hewlett-Packard Co
+ * David Mosberger <dav...@hpl.hp.com>
X *
X * This stub allows us to make EFI calls in physical mode with interrupts
X * turned off. We need this because we can't call SetVirtualMap() until
@@ -68,17 +68,17 @@
X ;;
X andcm r16=loc3,r16 // get psr with IT, DT, and RT bits cleared
X mov out3=in4
- br.call.sptk.few rp=ia64_switch_mode
+ br.call.sptk.many rp=ia64_switch_mode
X .ret0: mov out4=in5
X mov out5=in6
X mov out6=in7
- br.call.sptk.few rp=b6 // call the EFI function
+ br.call.sptk.many rp=b6 // call the EFI function
X .ret1: mov ar.rsc=0 // put RSE in enforced lazy, LE mode
X mov r16=loc3
- br.call.sptk.few rp=ia64_switch_mode // return to virtual mode
+ br.call.sptk.many rp=ia64_switch_mode // return to virtual mode
X .ret2: mov ar.rsc=loc4 // restore RSE configuration
X mov ar.pfs=loc1
X mov rp=loc0
X mov gp=loc2
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
X END(efi_call_phys)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/efivars.c linux/arch/ia64/kernel/efivars.c
--- v2.4.14/linux/arch/ia64/kernel/efivars.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/efivars.c Fri Nov 9 14:26:17 2001
@@ -65,6 +65,7 @@
X
X MODULE_AUTHOR("Matt Domsch <Matt_...@Dell.com>");
X MODULE_DESCRIPTION("/proc interface to EFI Variables");
+MODULE_LICENSE("GPL");
X
X #define EFIVARS_VERSION "0.03 2001-Apr-20"
X
@@ -276,21 +277,20 @@
X if (!capable(CAP_SYS_ADMIN))
X return -EACCES;
X
- spin_lock(&efivars_lock);
X MOD_INC_USE_COUNT;
X
X var_data = kmalloc(size, GFP_KERNEL);
X if (!var_data) {
X MOD_DEC_USE_COUNT;
- spin_unlock(&efivars_lock);
X return -ENOMEM;
X }
X if (copy_from_user(var_data, buffer, size)) {
X MOD_DEC_USE_COUNT;
- spin_unlock(&efivars_lock);
+ kfree(var_data);


X return -EFAULT;
X }
X

+ spin_lock(&efivars_lock);
X
X /* Since the data ptr we've currently got is probably for
X a different variable find the right variable.
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/entry.S linux/arch/ia64/kernel/entry.S
--- v2.4.14/linux/arch/ia64/kernel/entry.S Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/entry.S Fri Nov 9 14:26:17 2001
@@ -4,7 +4,7 @@
X * Kernel entry points.
X *
X * Copyright (C) 1998-2001 Hewlett-Packard Co
- * Copyright (C) 1998-2001 David Mosberger-Tang <dav...@hpl.hp.com>


+ * David Mosberger-Tang <dav...@hpl.hp.com>

X * Copyright (C) 1999 VA Linux Systems
X * Copyright (C) 1999 Walt Drummond <drum...@valinux.com>
X * Copyright (C) 1999 Asit Mallick <Asit.K....@intel.com>
@@ -15,7 +15,7 @@
X * kernel stack. This allows us to handle interrupts without changing
X * to physical mode.
X *
- * Jonathan Nickin <nic...@missioncriticallinux.com>
+ * Jonathan Nicklin <nic...@missioncriticallinux.com>
X * Patrick O'Rourke <oro...@missioncriticallinux.com>
X * 11/07/2000
X /
@@ -55,7 +55,7 @@
X mov out1=in1 // argv
X mov out2=in2 // envp


X add out3=16,sp // regs

- br.call.sptk.few rp=sys_execve
+ br.call.sptk.many rp=sys_execve
X .ret0: cmp4.ge p6,p7=r8,r0


X mov ar.pfs=loc1 // restore ar.pfs

X sxt4 r8=r8 // return 64-bit result
@@ -64,7 +64,7 @@
X (p6) cmp.ne pKern,pUser=r0,r0 // a successful execve() lands us in user-mode...
X mov rp=loc0
X (p6) mov ar.pfs=r0 // clear ar.pfs on success
-(p7) br.ret.sptk.few rp
+(p7) br.ret.sptk.many rp
X
X /*
X * In theory, we'd have to zap this state only to prevent leaking of
@@ -85,7 +85,7 @@
X ldf.fill f26=[sp]; ldf.fill f27=[sp]; mov f28=f0
X ldf.fill f29=[sp]; ldf.fill f30=[sp]; mov f31=f0
X mov ar.lc=0
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
X END(ia64_execve)
X
X GLOBAL_ENTRY(sys_clone2)
@@ -99,7 +99,7 @@
X mov out3=in2


X adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs

X mov out0=in0 // out0 = clone_flags
- br.call.sptk.few rp=do_fork
+ br.call.sptk.many rp=do_fork
X .ret1: .restore sp


X adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack

X mov ar.pfs=loc1
@@ -118,7 +118,7 @@


X mov out3=0
X adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs

X mov out0=in0 // out0 = clone_flags
- br.call.sptk.few rp=do_fork
+ br.call.sptk.many rp=do_fork
X .ret2: .restore sp


X adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack

X mov ar.pfs=loc1
@@ -140,23 +140,23 @@
X dep r20=0,in0,61,3 // physical address of "current"
X ;;
X st8 [r22]=sp // save kernel stack pointer of old task
- shr.u r26=r20,KERNEL_PG_SHIFT
- mov r16=KERNEL_PG_NUM
+ shr.u r26=r20,IA64_GRANULE_SHIFT
+ shr.u r17=r20,KERNEL_TR_PAGE_SHIFT
X ;;
- cmp.ne p6,p7=r26,r16 // check >= 64M && < 128M
+ cmp.ne p6,p7=KERNEL_TR_PAGE_NUM,r17
X adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0
X ;;
X /*
- * If we've already mapped this task's page, we can skip doing it
- * again.
+ * If we've already mapped this task's page, we can skip doing it again.
X */
X (p6) cmp.eq p7,p6=r26,r27
-(p6) br.cond.dpnt.few .map
+(p6) br.cond.dpnt .map
X ;;
-.done: ld8 sp=[r21] // load kernel stack pointer of new task
+.done:
X (p6) ssm psr.ic // if we we had to map, renable the psr.ic bit FIRST!!!
X ;;
X (p6) srlz.d
+ ld8 sp=[r21] // load kernel stack pointer of new task
X mov IA64_KR(CURRENT)=r20 // update "current" application register
X mov r8=r13 // return pointer to previously running task
X mov r13=in0 // set "current" pointer
@@ -167,7 +167,7 @@
X #ifdef CONFIG_SMP
X sync.i // ensure "fc"s done by this CPU are visible on other CPUs
X #endif
- br.ret.sptk.few rp // boogie on out in new context
+ br.ret.sptk.many rp // boogie on out in new context
X
X .map:
X rsm psr.i | psr.ic
@@ -175,7 +175,7 @@
X ;;
X srlz.d
X or r23=r25,r20 // construct PA | page properties
- mov r25=KERNEL_PG_SHIFT<<2
+ mov r25=IA64_GRANULE_SHIFT<<2
X ;;
X mov cr.itir=r25
X mov cr.ifa=in0 // VA of next task...
@@ -184,7 +184,7 @@
X mov IA64_KR(CURRENT_STACK)=r26 // remember last page we mapped...
X ;;
X itr.d dtr[r25]=r23 // wire in new mapping...
- br.cond.sptk.many .done
+ br.cond.sptk .done
X END(ia64_switch_to)
X
X /*
@@ -212,24 +212,18 @@
X .save @priunat,r17
X mov r17=ar.unat // preserve caller's
X .body
-#if !(defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC))
X adds r3=80,sp
X ;;
X lfetch.fault.excl.nt1 [r3],128
-#endif
X mov ar.rsc=0 // put RSE in mode: enforced lazy, little endian, pl 0
-#if !(defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC))
X adds r2=16+128,sp
X ;;
X lfetch.fault.excl.nt1 [r2],128
X lfetch.fault.excl.nt1 [r3],128
-#endif
X adds r14=SW(R4)+16,sp
-#if !(defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC))
X ;;
X lfetch.fault.excl [r2]
X lfetch.fault.excl [r3]
-#endif
X adds r15=SW(R5)+16,sp
X ;;
X mov r18=ar.fpsr // preserve fpsr
@@ -309,7 +303,7 @@
X st8 [r2]=r20 // save ar.bspstore
X st8 [r3]=r21 // save predicate registers
X mov ar.rsc=3 // put RSE back into eager mode, pl 0
- br.cond.sptk.few b7
+ br.cond.sptk.many b7
X END(save_switch_stack)
X
X /*
@@ -321,11 +315,9 @@
X ENTRY(load_switch_stack)
X .prologue
X .altrp b7
- .body
-#if !(defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC))
X
+ .body
X lfetch.fault.nt1 [sp]
-#endif
X adds r2=SW(AR_BSPSTORE)+16,sp
X adds r3=SW(AR_UNAT)+16,sp
X mov ar.rsc=0 // put RSE into enforced lazy mode
@@ -426,7 +418,7 @@
X ;;
X (p6) st4 [r2]=r8
X (p6) mov r8=-1
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
X END(__ia64_syscall)
X
X /*
@@ -441,11 +433,11 @@
X .body
X mov loc2=b6
X ;;
- br.call.sptk.few rp=syscall_trace
+ br.call.sptk.many rp=syscall_trace
X .ret3: mov rp=loc0
X mov ar.pfs=loc1
X mov b6=loc2
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
X END(invoke_syscall_trace)
X
X /*
@@ -462,21 +454,21 @@
X
X GLOBAL_ENTRY(ia64_trace_syscall)
X PT_REGS_UNWIND_INFO(0)
- br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch syscall args
-.ret6: br.call.sptk.few rp=b6 // do the syscall
+ br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch syscall args
+.ret6: br.call.sptk.many rp=b6 // do the syscall
X strace_check_retval:
X cmp.lt p6,p0=r8,r0 // syscall failed?
X adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8
X adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10
X mov r10=0
-(p6) br.cond.sptk.few strace_error // syscall failed ->
+(p6) br.cond.sptk strace_error // syscall failed ->
X ;; // avoid RAW on r10
X strace_save_retval:
X .mem.offset 0,0; st8.spill [r2]=r8 // store return value in slot for r8
X .mem.offset 8,0; st8.spill [r3]=r10 // clear error indication in slot for r10
X ia64_strace_leave_kernel:
- br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch return value
-.rety: br.cond.sptk.many ia64_leave_kernel
+ br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch return value
+.rety: br.cond.sptk ia64_leave_kernel
X
X strace_error:
X ld8 r3=[r2] // load pt_regs.r8
@@ -487,7 +479,7 @@
X ;;
X (p6) mov r10=-1
X (p6) mov r8=r9
- br.cond.sptk.few strace_save_retval
+ br.cond.sptk strace_save_retval
X END(ia64_trace_syscall)
X
X GLOBAL_ENTRY(ia64_ret_from_clone)
@@ -497,7 +489,7 @@
X * Called by ia64_switch_to after do_fork()->copy_thread(). r8 contains the
X * address of the previously executing task.
X */
- br.call.sptk.few rp=invoke_schedule_tail
+ br.call.sptk.many rp=ia64_invoke_schedule_tail
X .ret8:
X adds r2=IA64_TASK_PTRACE_OFFSET,r13
X ;;
@@ -505,7 +497,7 @@
X ;;
X mov r8=0
X tbit.nz p6,p0=r2,PT_TRACESYS_BIT
-(p6) br strace_check_retval
+(p6) br.cond.spnt strace_check_retval
X ;; // added stop bits to prevent r8 dependency
X END(ia64_ret_from_clone)
X // fall through
@@ -519,7 +511,7 @@
X (p6) st8.spill [r2]=r8 // store return value in slot for r8 and set unat bit
X .mem.offset 8,0
X (p6) st8.spill [r3]=r0 // clear error indication in slot for r10 and set unat bit
-(p7) br.cond.spnt.few handle_syscall_error // handle potential syscall failure
+(p7) br.cond.spnt handle_syscall_error // handle potential syscall failure
X END(ia64_ret_from_syscall)
X // fall through
X GLOBAL_ENTRY(ia64_leave_kernel)
@@ -527,22 +519,22 @@
X lfetch.fault [sp]
X movl r14=.restart
X ;;
- MOVBR(.ret.sptk,rp,r14,.restart)
+ mov.ret.sptk rp=r14,.restart
X .restart:
X adds r17=IA64_TASK_NEED_RESCHED_OFFSET,r13
X adds r18=IA64_TASK_SIGPENDING_OFFSET,r13
X #ifdef CONFIG_PERFMON
- adds r19=IA64_TASK_PFM_NOTIFY_OFFSET,r13
+ adds r19=IA64_TASK_PFM_MUST_BLOCK_OFFSET,r13
X #endif
X ;;
X #ifdef CONFIG_PERFMON
- ld8 r19=[r19] // load current->task.pfm_notify
+(pUser) ld8 r19=[r19] // load current->thread.pfm_must_block
X #endif
- ld8 r17=[r17] // load current->need_resched
- ld4 r18=[r18] // load current->sigpending
+(pUser) ld8 r17=[r17] // load current->need_resched
+(pUser) ld4 r18=[r18] // load current->sigpending
X ;;
X #ifdef CONFIG_PERFMON
- cmp.ne p9,p0=r19,r0 // current->task.pfm_notify != 0?
+(pUser) cmp.ne.unc p9,p0=r19,r0 // current->thread.pfm_must_block != 0?
X #endif
X (pUser) cmp.ne.unc p7,p0=r17,r0 // current->need_resched != 0?
X (pUser) cmp.ne.unc p8,p0=r18,r0 // current->sigpending != 0?
@@ -550,7 +542,7 @@
X adds r2=PT(R8)+16,r12
X adds r3=PT(R9)+16,r12
X #ifdef CONFIG_PERFMON
-(p9) br.call.spnt.many b7=pfm_overflow_notify
+(p9) br.call.spnt.many b7=pfm_block_on_overflow
X #endif
X #if __GNUC__ < 3
X (p7) br.call.spnt.many b7=invoke_schedule
@@ -650,13 +642,13 @@
X movl r17=PERCPU_ADDR+IA64_CPU_PHYS_STACKED_SIZE_P8_OFFSET
X ;;
X ld4 r17=[r17] // r17 = cpu_data->phys_stacked_size_p8
-(pKern) br.cond.dpnt.few skip_rbs_switch
+(pKern) br.cond.dpnt skip_rbs_switch
X /*
X * Restore user backing store.
X *
X * NOTE: alloc, loadrs, and cover can't be predicated.
X */
-(pNonSys) br.cond.dpnt.few dont_preserve_current_frame
+(pNonSys) br.cond.dpnt dont_preserve_current_frame
X cover // add current frame into dirty partition
X ;;
X mov r19=ar.bsp // get new backing store pointer
@@ -687,7 +679,7 @@
X shladd in0=loc1,3,r17
X mov in1=0
X ;;
- .align 32
+// .align 32 // gas-2.11.90 is unable to generate a stop bit after .align
X rse_clear_invalid:
X // cycle 0
X { .mii
@@ -706,7 +698,7 @@
X }{ .mib
X mov loc3=0
X mov loc4=0
-(pRecurse) br.call.sptk.few b6=rse_clear_invalid
+(pRecurse) br.call.sptk.many b6=rse_clear_invalid
X
X }{ .mfi // cycle 2
X mov loc5=0
@@ -715,7 +707,7 @@
X }{ .mib
X mov loc6=0
X mov loc7=0
-(pReturn) br.ret.sptk.few b6
+(pReturn) br.ret.sptk.many b6
X }
X # undef pRecurse
X # undef pReturn
@@ -761,24 +753,24 @@
X ;;
X .mem.offset 0,0; st8.spill [r2]=r9 // store errno in pt_regs.r8 and set unat bit
X .mem.offset 8,0; st8.spill [r3]=r10 // store error indication in pt_regs.r10 and set unat bit
- br.cond.sptk.many ia64_leave_kernel
+ br.cond.sptk ia64_leave_kernel
X END(handle_syscall_error)
X
X /*
X * Invoke schedule_tail(task) while preserving in0-in7, which may be needed
X * in case a system call gets restarted.
X */
-ENTRY(invoke_schedule_tail)
+GLOBAL_ENTRY(ia64_invoke_schedule_tail)
X .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
X alloc loc1=ar.pfs,8,2,1,0
X mov loc0=rp
X mov out0=r8 // Address of previous task
X ;;
- br.call.sptk.few rp=schedule_tail
+ br.call.sptk.many rp=schedule_tail
X .ret11: mov ar.pfs=loc1
X mov rp=loc0
X br.ret.sptk.many rp
-END(invoke_schedule_tail)
+END(ia64_invoke_schedule_tail)
X
X #if __GNUC__ < 3
X
@@ -797,7 +789,7 @@
X mov loc0=rp
X ;;
X .body
- br.call.sptk.few rp=schedule
+ br.call.sptk.many rp=schedule
X .ret14: mov ar.pfs=loc1
X mov rp=loc0
X br.ret.sptk.many rp
@@ -824,7 +816,7 @@
X .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
X st8 [sp]=r9,-16 // allocate space for ar.unat and save it
X .body
- br.call.sptk.few rp=ia64_do_signal
+ br.call.sptk.many rp=ia64_do_signal
X .ret15: .restore sp
X adds sp=16,sp // pop scratch stack space
X ;;
@@ -849,7 +841,7 @@
X .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
X st8 [sp]=r9,-16 // allocate space for ar.unat and save it
X .body
- br.call.sptk.few rp=ia64_rt_sigsuspend
+ br.call.sptk.many rp=ia64_rt_sigsuspend
X .ret17: .restore sp
X adds sp=16,sp // pop scratch stack space
X ;;
@@ -871,15 +863,15 @@
X cmp.eq pNonSys,pSys=r0,r0 // sigreturn isn't a normal syscall...
X ;;
X adds out0=16,sp // out0 = &sigscratch
- br.call.sptk.few rp=ia64_rt_sigreturn
+ br.call.sptk.many rp=ia64_rt_sigreturn
X .ret19: .restore sp 0
X adds sp=16,sp
X ;;
X ld8 r9=[sp] // load new ar.unat
- MOVBR(.sptk,b7,r8,ia64_leave_kernel)
+ mov.sptk b7=r8,ia64_leave_kernel
X ;;
X mov ar.unat=r9
- br b7
+ br.many b7
X END(sys_rt_sigreturn)
X
X GLOBAL_ENTRY(ia64_prepare_handle_unaligned)
@@ -890,7 +882,7 @@
X mov r16=r0
X .prologue
X DO_SAVE_SWITCH_STACK
- br.call.sptk.few rp=ia64_handle_unaligned // stack frame setup in ivt
+ br.call.sptk.many rp=ia64_handle_unaligned // stack frame setup in ivt
X .ret21: .body
X DO_LOAD_SWITCH_STACK
X br.cond.sptk.many rp // goes to ia64_leave_kernel
@@ -920,14 +912,14 @@
X adds out0=16,sp // &info
X mov out1=r13 // current
X adds out2=16+EXTRA_FRAME_SIZE,sp // &switch_stack
- br.call.sptk.few rp=unw_init_frame_info
+ br.call.sptk.many rp=unw_init_frame_info
X 1: adds out0=16,sp // &info
X mov b6=loc2
X mov loc2=gp // save gp across indirect function call
X ;;
X ld8 gp=[in0]
X mov out1=in1 // arg
- br.call.sptk.few rp=b6 // invoke the callback function
+ br.call.sptk.many rp=b6 // invoke the callback function
X 1: mov gp=loc2 // restore gp
X
X // For now, we don't allow changing registers from within
@@ -1026,7 +1018,7 @@
X data8 sys_setpriority
X data8 sys_statfs
X data8 sys_fstatfs
- data8 ia64_ni_syscall // 1105
+ data8 sys_gettid // 1105
X data8 sys_semget
X data8 sys_semop
X data8 sys_semctl
@@ -1137,7 +1129,7 @@
X data8 sys_clone2
X data8 sys_getdents64
X data8 sys_getunwind // 1215
- data8 ia64_ni_syscall
+ data8 sys_readahead
X data8 ia64_ni_syscall
X data8 ia64_ni_syscall
X data8 ia64_ni_syscall
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/entry.h linux/arch/ia64/kernel/entry.h
--- v2.4.14/linux/arch/ia64/kernel/entry.h Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/entry.h Fri Nov 9 14:26:17 2001
@@ -1,12 +1,5 @@
X #include <linux/config.h>
X
-/* XXX fixme */
-#if defined(CONFIG_ITANIUM_B1_SPECIFIC)
-# define MOVBR(type,br,gr,lbl) mov br=gr
-#else
-# define MOVBR(type,br,gr,lbl) mov##type br=gr,lbl
-#endif
-
X /*
X * Preserved registers that are shared between code in ivt.S and entry.S. Be
X * careful not to step on these!
@@ -62,7 +55,7 @@
X ;; \
X .fframe IA64_SWITCH_STACK_SIZE; \
X adds sp=-IA64_SWITCH_STACK_SIZE,sp; \
- MOVBR(.ret.sptk,b7,r28,1f); \
+ mov.ret.sptk b7=r28,1f; \
X SWITCH_STACK_SAVES(0); \
X br.cond.sptk.many save_switch_stack; \
X 1:
@@ -71,7 +64,7 @@
X movl r28=1f; \
X ;; \
X invala; \
- MOVBR(.ret.sptk,b7,r28,1f); \
+ mov.ret.sptk b7=r28,1f; \
X br.cond.sptk.many load_switch_stack; \
X 1: .restore sp; \
X adds sp=IA64_SWITCH_STACK_SIZE,sp
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/fw-emu.c linux/arch/ia64/kernel/fw-emu.c
--- v2.4.14/linux/arch/ia64/kernel/fw-emu.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/fw-emu.c Fri Nov 9 14:26:17 2001
@@ -174,6 +174,43 @@
X " ;;\n"
X " mov ar.lc=r9\n"
X " mov r8=r0\n"
+" ;;\n"
+"1: cmp.eq p6,p7=15,r28 /* PAL_PERF_MON_INFO */\n"
+"(p7) br.cond.sptk.few 1f\n"
+" mov r8=0 /* status = 0 */\n"
+" movl r9 =0x12082004 /* generic=4 width=32 retired=8 cycles=18 */\n"
+" mov r10=0 /* reserved */\n"
+" mov r11=0 /* reserved */\n"
+" mov r16=0xffff /* implemented PMC */\n"
+" mov r17=0xffff /* implemented PMD */\n"
+" add r18=8,r29 /* second index */\n"
+" ;;\n"
+" st8 [r29]=r16,16 /* store implemented PMC */\n"
+" st8 [r18]=r0,16 /* clear remaining bits */\n"
+" ;;\n"
+" st8 [r29]=r0,16 /* store implemented PMC */\n"
+" st8 [r18]=r0,16 /* clear remaining bits */\n"
+" ;;\n"
+" st8 [r29]=r17,16 /* store implemented PMD */\n"
+" st8 [r18]=r0,16 /* clear remaining bits */\n"
+" mov r16=0xf0 /* cycles count capable PMC */\n"
+" ;;\n"
+" st8 [r29]=r0,16 /* store implemented PMC */\n"
+" st8 [r18]=r0,16 /* clear remaining bits */\n"
+" mov r17=0x10 /* retired bundles capable PMC */\n"
+" ;;\n"
+" st8 [r29]=r16,16 /* store cycles capable */\n"
+" st8 [r18]=r0,16 /* clear remaining bits */\n"
+" ;;\n"
+" st8 [r29]=r0,16 /* store implemented PMC */\n"
+" st8 [r18]=r0,16 /* clear remaining bits */\n"
+" ;;\n"
+" st8 [r29]=r17,16 /* store retired bundle capable */\n"
+" st8 [r18]=r0,16 /* clear remaining bits */\n"
+" ;;\n"
+" st8 [r29]=r0,16 /* store implemented PMC */\n"
+" st8 [r18]=r0,16 /* clear remaining bits */\n"
+" ;;\n"
X "1: br.cond.sptk.few rp\n"
X "stacked:\n"
X " br.ret.sptk.few rp\n"
@@ -414,11 +451,6 @@
X #ifdef CONFIG_IA64_SDV
X strcpy(sal_systab->oem_id, "Intel");
X strcpy(sal_systab->product_id, "SDV");
-#endif
-
-#ifdef CONFIG_IA64_SGI_SN1_SIM
- strcpy(sal_systab->oem_id, "SGI");
- strcpy(sal_systab->product_id, "SN1");
X #endif
X
X /* fill in an entry point: */
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/gate.S linux/arch/ia64/kernel/gate.S
--- v2.4.14/linux/arch/ia64/kernel/gate.S Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/gate.S Fri Nov 9 14:26:17 2001
@@ -3,7 +3,7 @@
X * region. For now, it contains the signal trampoline code only.
X *
X * Copyright (C) 1999-2001 Hewlett-Packard Co
- * Copyright (C) 1999-2001 David Mosberger-Tang <dav...@hpl.hp.com>


+ * David Mosberger-Tang <dav...@hpl.hp.com>

X */
X
X #include <asm/asmmacro.h>
@@ -18,7 +18,6 @@
X # define ARG0_OFF (16 + IA64_SIGFRAME_ARG0_OFFSET)
X # define ARG1_OFF (16 + IA64_SIGFRAME_ARG1_OFFSET)
X # define ARG2_OFF (16 + IA64_SIGFRAME_ARG2_OFFSET)
-# define RBS_BASE_OFF (16 + IA64_SIGFRAME_RBS_BASE_OFFSET)
X # define SIGHANDLER_OFF (16 + IA64_SIGFRAME_HANDLER_OFFSET)
X # define SIGCONTEXT_OFF (16 + IA64_SIGFRAME_SIGCONTEXT_OFFSET)
X
@@ -32,6 +31,8 @@
X # define PR_OFF IA64_SIGCONTEXT_PR_OFFSET
X # define RP_OFF IA64_SIGCONTEXT_B0_OFFSET
X # define SP_OFF IA64_SIGCONTEXT_R12_OFFSET
+# define RBS_BASE_OFF IA64_SIGCONTEXT_RBS_BASE_OFFSET
+# define LOADRS_OFF IA64_SIGCONTEXT_LOADRS_OFFSET
X # define base0 r2
X # define base1 r3
X /*
@@ -73,34 +74,37 @@
X .vframesp SP_OFF+SIGCONTEXT_OFF
X .body
X
- .prologue
+ .label_state 1
+
X adds base0=SIGHANDLER_OFF,sp
- adds base1=RBS_BASE_OFF,sp
+ adds base1=RBS_BASE_OFF+SIGCONTEXT_OFF,sp
X br.call.sptk.many rp=1f
X 1:
X ld8 r17=[base0],(ARG0_OFF-SIGHANDLER_OFF) // get pointer to signal handler's plabel
- ld8 r15=[base1],(ARG1_OFF-RBS_BASE_OFF) // get address of new RBS base (or NULL)
+ ld8 r15=[base1] // get address of new RBS base (or NULL)
X cover // push args in interrupted frame onto backing store
X ;;
+ cmp.ne p8,p0=r15,r0 // do we need to switch the rbs?
+ mov.m r9=ar.bsp // fetch ar.bsp
+ .spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
+(p8) br.cond.spnt setup_rbs // yup -> (clobbers r14, r15, and r16)
+back_from_setup_rbs:
+
X .save ar.pfs, r8
X alloc r8=ar.pfs,0,0,3,0 // get CFM0, EC0, and CPL0 into r8
X ld8 out0=[base0],16 // load arg0 (signum)
+ adds base1=(ARG1_OFF-(RBS_BASE_OFF+SIGCONTEXT_OFF)),base1
X ;;
X ld8 out1=[base1] // load arg1 (siginfop)
X ld8 r10=[r17],8 // get signal handler entry point
X ;;
X ld8 out2=[base0] // load arg2 (sigcontextp)
X ld8 gp=[r17] // get signal handler's global pointer
- cmp.ne p8,p0=r15,r0 // do we need to switch the rbs?
X
- mov.m r17=ar.bsp // fetch ar.bsp
- .spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
-(p8) br.cond.spnt.few setup_rbs // yup -> (clobbers r14 and r16)
-back_from_setup_rbs:
X adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
X ;;
X .spillsp ar.bsp, BSP_OFF+SIGCONTEXT_OFF
- st8 [base0]=r17,(CFM_OFF-BSP_OFF) // save sc_ar_bsp
+ st8 [base0]=r9,(CFM_OFF-BSP_OFF) // save sc_ar_bsp
X dep r8=0,r8,38,26 // clear EC0, CPL0 and reserved bits
X adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
X ;;
@@ -123,7 +127,7 @@
X ;;
X stf.spill [base0]=f14,32
X stf.spill [base1]=f15,32
- br.call.sptk.few rp=b6 // call the signal handler
+ br.call.sptk.many rp=b6 // call the signal handler
X .ret0: adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
X ;;
X ld8 r15=[base0],(CFM_OFF-BSP_OFF) // fetch sc_ar_bsp and advance to CFM_OFF
@@ -131,7 +135,7 @@
X ;;
X ld8 r8=[base0] // restore (perhaps modified) CFM0, EC0, and CPL0
X cmp.ne p8,p0=r14,r15 // do we need to restore the rbs?
-(p8) br.cond.spnt.few restore_rbs // yup -> (clobbers r14 and r16)
+(p8) br.cond.spnt restore_rbs // yup -> (clobbers r14 and r16)
X ;;
X back_from_restore_rbs:
X adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
@@ -154,30 +158,52 @@
X mov r15=__NR_rt_sigreturn
X break __BREAK_SYSCALL
X
+ .body
+ .copy_state 1
X setup_rbs:
- flushrs // must be first in insn
X mov ar.rsc=0 // put RSE into enforced lazy mode
- adds r16=(RNAT_OFF+SIGCONTEXT_OFF),sp
X ;;
- mov r14=ar.rnat // get rnat as updated by flushrs
- mov ar.bspstore=r15 // set new register backing store area
+ .save ar.rnat, r16
+ mov r16=ar.rnat // save RNaT before switching backing store area
+ adds r14=(RNAT_OFF+SIGCONTEXT_OFF),sp
+
+ mov ar.bspstore=r15 // switch over to new register backing store area
X ;;
X .spillsp ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
- st8 [r16]=r14 // save sc_ar_rnat
+ st8 [r14]=r16 // save sc_ar_rnat
+ adds r14=(LOADRS_OFF+SIGCONTEXT_OFF),sp
+
+ mov.m r16=ar.bsp // sc_loadrs <- (new bsp - new bspstore) << 16
+ ;;
+ invala
+ sub r15=r16,r15
+ ;;
+ shl r15=r15,16
+ ;;
+ st8 [r14]=r15 // save sc_loadrs
X mov ar.rsc=0xf // set RSE into eager mode, pl 3
- invala // invalidate ALAT
- br.cond.sptk.many back_from_setup_rbs
+ br.cond.sptk back_from_setup_rbs
X
+ .prologue
+ .copy_state 1
+ .spillsp ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
+ .body
X restore_rbs:
- flushrs
- mov ar.rsc=0 // put RSE into enforced lazy mode
+ alloc r2=ar.pfs,0,0,0,0 // alloc null frame
+ adds r16=(LOADRS_OFF+SIGCONTEXT_OFF),sp
+ ;;
+ ld8 r14=[r16]
X adds r16=(RNAT_OFF+SIGCONTEXT_OFF),sp
X ;;
+ mov ar.rsc=r14 // put RSE into enforced lazy mode
X ld8 r14=[r16] // get new rnat
- mov ar.bspstore=r15 // set old register backing store area
X ;;
- mov ar.rnat=r14 // establish new rnat
+ loadrs // restore dirty partition
+ ;;
+ mov ar.bspstore=r15 // switch back to old register backing store area
+ ;;
+ mov ar.rnat=r14 // restore RNaT
X mov ar.rsc=0xf // (will be restored later on from sc_ar_rsc)
X // invala not necessary as that will happen when returning to user-mode
- br.cond.sptk.many back_from_restore_rbs
+ br.cond.sptk back_from_restore_rbs
X END(ia64_sigtramp)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/head.S linux/arch/ia64/kernel/head.S
--- v2.4.14/linux/arch/ia64/kernel/head.S Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/head.S Fri Nov 9 14:26:17 2001
@@ -6,8 +6,8 @@
X * entry point.
X *
X * Copyright (C) 1998-2001 Hewlett-Packard Co
- * Copyright (C) 1998-2001 David Mosberger-Tang <dav...@hpl.hp.com>
- * Copyright (C) 2001 Stephane Eranian <era...@hpl.hp.com>


+ * David Mosberger-Tang <dav...@hpl.hp.com>

+ * Stephane Eranian <era...@hpl.hp.com>
X * Copyright (C) 1999 VA Linux Systems
X * Copyright (C) 1999 Walt Drummond <drum...@valinux.com>
X * Copyright (C) 1999 Intel Corp.
@@ -63,17 +63,17 @@
X * that maps the kernel's text and data:
X */
X rsm psr.i | psr.ic
- mov r16=((ia64_rid(IA64_REGION_ID_KERNEL, PAGE_OFFSET) << 8) | (KERNEL_PG_SHIFT << 2))
+ mov r16=((ia64_rid(IA64_REGION_ID_KERNEL, PAGE_OFFSET) << 8) | (IA64_GRANULE_SHIFT << 2))
X ;;
X srlz.i
- mov r18=KERNEL_PG_SHIFT<<2
- movl r17=PAGE_OFFSET + KERNEL_PG_NUM*KERNEL_PG_SIZE
+ mov r18=KERNEL_TR_PAGE_SHIFT<<2
+ movl r17=KERNEL_START
X ;;
X mov rr[r17]=r16
X mov cr.itir=r18
X mov cr.ifa=r17
X mov r16=IA64_TR_KERNEL
- movl r18=(KERNEL_PG_NUM*KERNEL_PG_SIZE | PAGE_KERNEL)
+ movl r18=((1 << KERNEL_TR_PAGE_SHIFT) | PAGE_KERNEL)
X ;;
X srlz.i
X ;;
@@ -86,7 +86,8 @@
X /*
X * Switch into virtual mode:
X */
- movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN)
+ movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN \
+ |IA64_PSR_DI)
X ;;
X mov cr.ipsr=r16
X movl r17=1f
@@ -111,7 +112,7 @@
X ;;
X
X #ifdef CONFIG_IA64_EARLY_PRINTK
- mov r3=(6<<8) | (KERNEL_PG_SHIFT<<2)
+ mov r3=(6<<8) | (IA64_GRANULE_SHIFT<<2)
X movl r2=6<<61
X ;;
X mov rr[r2]=r3
@@ -144,6 +145,7 @@
X cmp4.ne isAP,isBP=r3,r0
X ;; // RAW on r2
X extr r3=r2,0,61 // r3 == phys addr of task struct
+ mov r16=KERNEL_TR_PAGE_NUM
X ;;
X
X // load the "current" pointer (r13) and ar.k6 with the current task
@@ -151,7 +153,7 @@
X mov IA64_KR(CURRENT)=r3 // Physical address
X
X // initialize k4 to a safe value (64-128MB is mapped by TR_KERNEL)
- mov IA64_KR(CURRENT_STACK)=1
+ mov IA64_KR(CURRENT_STACK)=r16
X /*
X * Reserve space at the top of the stack for "struct pt_regs". Kernel threads
X * don't store interesting values in that structure, but the space still needs
@@ -183,31 +185,31 @@
X alloc r2=ar.pfs,0,0,2,0
X movl out0=alive_msg
X ;;
- br.call.sptk.few rp=early_printk
+ br.call.sptk.many rp=early_printk


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

echo 'End of part 029'
echo 'File patch-2.4.15 is continued in part 030'
echo "030" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:06 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part030

#!/bin/sh -x
# this is part 030 of a 115 - part archive


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

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

X 1: // force new bundle
X #endif /* CONFIG_IA64_EARLY_PRINTK */
X
X #ifdef CONFIG_SMP
-(isAP) br.call.sptk.few rp=start_secondary
+(isAP) br.call.sptk.many rp=start_secondary
X .ret0:
-(isAP) br.cond.sptk.few self
+(isAP) br.cond.sptk self
X #endif
X
X // This is executed by the bootstrap processor (bsp) only:
X
X #ifdef CONFIG_IA64_FW_EMU
X // initialize PAL & SAL emulator:
- br.call.sptk.few rp=sys_fw_init
+ br.call.sptk.many rp=sys_fw_init
X .ret1:
X #endif
- br.call.sptk.few rp=start_kernel
+ br.call.sptk.many rp=start_kernel
X .ret2: addl r3=@ltoff(halt_msg),gp
X ;;
X alloc r2=ar.pfs,8,0,2,0
X ;;
X ld8 out0=[r3]
- br.call.sptk.few b0=console_print
-self: br.sptk.few self // endless loop
+ br.call.sptk.many b0=console_print
+self: br.sptk.many self // endless loop
X END(_start)
X
X GLOBAL_ENTRY(ia64_save_debug_regs)
@@ -218,7 +220,7 @@
X add r19=IA64_NUM_DBG_REGS*8,in0
X ;;
X 1: mov r16=dbr[r18]
-#if defined(CONFIG_ITANIUM_C0_SPECIFIC)
+#ifdef CONFIG_ITANIUM
X ;;
X srlz.d
X #endif
@@ -227,17 +229,15 @@
X ;;
X st8.nta [in0]=r16,8
X st8.nta [r19]=r17,8
- br.cloop.sptk.few 1b
+ br.cloop.sptk.many 1b
X ;;
X mov ar.lc=r20 // restore ar.lc


- br.ret.sptk.few rp
+ br.ret.sptk.many rp

X END(ia64_save_debug_regs)
X
X GLOBAL_ENTRY(ia64_load_debug_regs)
X alloc r16=ar.pfs,1,0,0,0
-#if !(defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC))
X lfetch.nta [in0]
-#endif
X mov r20=ar.lc // preserve ar.lc
X add r19=IA64_NUM_DBG_REGS*8,in0
X mov ar.lc=IA64_NUM_DBG_REGS-1
@@ -248,15 +248,15 @@
X add r18=1,r18
X ;;
X mov dbr[r18]=r16
-#if defined(CONFIG_ITANIUM_BSTEP_SPECIFIC) || defined(CONFIG_ITANIUM_C0_SPECIFIC)
+#ifdef CONFIG_ITANIUM
X ;;
- srlz.d
+ srlz.d // Errata 132 (NoFix status)
X #endif
X mov ibr[r18]=r17
- br.cloop.sptk.few 1b
+ br.cloop.sptk.many 1b
X ;;
X mov ar.lc=r20 // restore ar.lc


- br.ret.sptk.few rp
+ br.ret.sptk.many rp

X END(ia64_load_debug_regs)
X
X GLOBAL_ENTRY(__ia64_save_fpu)
@@ -406,7 +406,7 @@
X ;;
X stf.spill.nta [in0]=f126,32
X stf.spill.nta [ r3]=f127,32


- br.ret.sptk.few rp
+ br.ret.sptk.many rp

X END(__ia64_save_fpu)
X
X GLOBAL_ENTRY(__ia64_load_fpu)
@@ -556,7 +556,7 @@
X ;;
X ldf.fill.nta f126=[in0],32
X ldf.fill.nta f127=[ r3],32


- br.ret.sptk.few rp
+ br.ret.sptk.many rp

X END(__ia64_load_fpu)
X
X GLOBAL_ENTRY(__ia64_init_fpu)
@@ -690,7 +690,7 @@
X ;;
X ldf.fill f126=[sp]
X mov f127=f0


- br.ret.sptk.few rp
+ br.ret.sptk.many rp

X END(__ia64_init_fpu)
X
X /*
@@ -738,7 +738,7 @@
X rfi // must be last insn in group
X ;;
X 1: mov rp=r14


- br.ret.sptk.few rp
+ br.ret.sptk.many rp

X END(ia64_switch_mode)
X
X #ifdef CONFIG_IA64_BRL_EMU
@@ -752,7 +752,7 @@
X alloc r16=ar.pfs,1,0,0,0; \
X mov reg=r32; \
X ;; \
- br.ret.sptk rp; \
+ br.ret.sptk.many rp; \
X END(ia64_set_##reg)
X
X SET_REG(b1);
@@ -816,12 +816,11 @@
X ;;
X cmp.ne p15,p0=tmp,r0
X mov tmp=ar.itc
-(p15) br.cond.sptk.few .retry // lock is still busy
+(p15) br.cond.sptk .retry // lock is still busy
X ;;
X // try acquiring lock (we know ar.ccv is still zero!):
X mov tmp=1
X ;;
- IA64_SEMFIX_INSN
X cmpxchg4.acq tmp=[r31],tmp,ar.ccv
X ;;
X cmp.eq p15,p0=tmp,r0
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/ia64_ksyms.c linux/arch/ia64/kernel/ia64_ksyms.c
--- v2.4.14/linux/arch/ia64/kernel/ia64_ksyms.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/ia64_ksyms.c Fri Nov 9 14:26:17 2001
@@ -69,6 +69,8 @@
X
X #include <asm/pgalloc.h>
X
+EXPORT_SYMBOL(flush_tlb_range);
+
X #ifdef CONFIG_SMP
X
X EXPORT_SYMBOL(smp_flush_tlb_all);
@@ -145,4 +147,3 @@
X #include <linux/proc_fs.h>
X extern struct proc_dir_entry *efi_dir;
X EXPORT_SYMBOL(efi_dir);
-
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/iosapic.c linux/arch/ia64/kernel/iosapic.c
--- v2.4.14/linux/arch/ia64/kernel/iosapic.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/iosapic.c Fri Nov 9 14:26:17 2001
@@ -53,6 +53,7 @@


X #include <asm/acpi-ext.h>
X #include <asm/acpikcfg.h>

X #include <asm/delay.h>
+#include <asm/hw_irq.h>
X #include <asm/io.h>
X #include <asm/iosapic.h>
X #include <asm/machvec.h>
@@ -325,7 +326,7 @@
X set_affinity: iosapic_set_affinity
X };
X
-static unsigned int
+unsigned int
X iosapic_version (char *addr)
X {
X /*
@@ -342,6 +343,113 @@
X }
X
X /*
+ * ACPI can describe IOSAPIC interrupts via static tables and namespace
+ * methods. This provides an interface to register those interrupts and
+ * program the IOSAPIC RTE.
+ */
+int
+iosapic_register_irq (u32 global_vector, unsigned long polarity, unsigned long
+ edge_triggered, u32 base_irq, char *iosapic_address)
+{
+ irq_desc_t *idesc;
+ struct hw_interrupt_type *irq_type;
+ int vector;
+
+ vector = iosapic_irq_to_vector(global_vector);
+ if (vector < 0)
+ vector = ia64_alloc_irq();
+
+ /* fill in information from this vector's IOSAPIC */
+ iosapic_irq[vector].addr = iosapic_address;
+ iosapic_irq[vector].base_irq = base_irq;
+ iosapic_irq[vector].pin = global_vector - iosapic_irq[vector].base_irq;
+ iosapic_irq[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW;
+ iosapic_irq[vector].dmode = IOSAPIC_LOWEST_PRIORITY;
+
+ if (edge_triggered) {
+ iosapic_irq[vector].trigger = IOSAPIC_EDGE;
+ irq_type = &irq_type_iosapic_edge;
+ } else {
+ iosapic_irq[vector].trigger = IOSAPIC_LEVEL;
+ irq_type = &irq_type_iosapic_level;
+ }
+
+ idesc = irq_desc(vector);
+ if (idesc->handler != irq_type) {
+ if (idesc->handler != &no_irq_type)
+ printk("iosapic_register_irq(): changing vector 0x%02x from"
+ "%s to %s\n", vector, idesc->handler->typename, irq_type->typename);
+ idesc->handler = irq_type;
+ }
+
+ printk("IOSAPIC %x(%s,%s) -> Vector %x\n", global_vector,
+ (polarity ? "high" : "low"), (edge_triggered ? "edge" : "level"), vector);
+
+ /* program the IOSAPIC routing table */
+ set_rte(vector, (ia64_get_lid() >> 16) & 0xffff);


+ return vector;
+}
+
+/*

+ * ACPI calls this when it finds an entry for a platform interrupt.
+ * Note that the irq_base and IOSAPIC address must be set in iosapic_init().
+ */
+int
+iosapic_register_platform_irq (u32 int_type, u32 global_vector, u32 iosapic_vector,
+ u16 eid, u16 id, unsigned long polarity,
+ unsigned long edge_triggered, u32 base_irq, char *iosapic_address)
+{
+ struct hw_interrupt_type *irq_type;
+ irq_desc_t *idesc;
+ int vector;
+
+ switch (int_type) {
+ case ACPI20_ENTRY_PIS_CPEI:
+ vector = IA64_PCE_VECTOR;
+ iosapic_irq[vector].dmode = IOSAPIC_LOWEST_PRIORITY;
+ break;
+ case ACPI20_ENTRY_PIS_INIT:
+ vector = ia64_alloc_irq();
+ iosapic_irq[vector].dmode = IOSAPIC_INIT;
+ break;
+ default:
+ printk("iosapic_register_platform_irq(): invalid int type\n");


+ return -1;
+ }
+

+ /* fill in information from this vector's IOSAPIC */
+ iosapic_irq[vector].addr = iosapic_address;
+ iosapic_irq[vector].base_irq = base_irq;
+ iosapic_irq[vector].pin = global_vector - iosapic_irq[vector].base_irq;
+ iosapic_irq[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW;
+
+ if (edge_triggered) {
+ iosapic_irq[vector].trigger = IOSAPIC_EDGE;
+ irq_type = &irq_type_iosapic_edge;
+ } else {
+ iosapic_irq[vector].trigger = IOSAPIC_LEVEL;
+ irq_type = &irq_type_iosapic_level;
+ }
+
+ idesc = irq_desc(vector);
+ if (idesc->handler != irq_type) {
+ if (idesc->handler != &no_irq_type)
+ printk("iosapic_register_platform_irq(): changing vector 0x%02x from"
+ "%s to %s\n", vector, idesc->handler->typename, irq_type->typename);
+ idesc->handler = irq_type;
+ }
+
+ printk("PLATFORM int %x: IOSAPIC %x(%s,%s) -> Vector %x CPU %.02u:%.02u\n",
+ int_type, global_vector, (polarity ? "high" : "low"),
+ (edge_triggered ? "edge" : "level"), vector, eid, id);
+
+ /* program the IOSAPIC routing table */
+ set_rte(vector, ((id << 8) | eid) & 0xffff);


+ return vector;
+}
+
+

+/*
X * ACPI calls this when it finds an entry for a legacy ISA interrupt. Note that the
X * irq_base and IOSAPIC address must be set in iosapic_init().
X */
@@ -436,7 +544,7 @@
X /* the interrupt route is for another controller... */
X continue;
X
- if (irq < 16)
+ if (pcat_compat && (irq < 16))
X vector = isa_irq_to_vector(irq);
X else {
X vector = iosapic_irq_to_vector(irq);
@@ -515,6 +623,23 @@
X printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> 0x%02x\n",
X dev->bus->number, PCI_SLOT(dev->devfn), pin, vector);
X dev->irq = vector;
+
+#ifdef CONFIG_SMP
+ /*
+ * For platforms that do not support interrupt redirect
+ * via the XTP interface, we can round-robin the PCI
+ * device interrupts to the processors
+ */
+ if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) {
+ static int cpu_index = 0;
+
+ set_rte(vector, cpu_physical_id(cpu_index) & 0xffff);
+
+ cpu_index++;
+ if (cpu_index >= smp_num_cpus)
+ cpu_index = 0;
+ }
+#endif
X }
X }
X /*
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/irq.c linux/arch/ia64/kernel/irq.c
--- v2.4.14/linux/arch/ia64/kernel/irq.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/irq.c Fri Nov 9 14:26:17 2001
@@ -33,6 +33,7 @@
X #include <linux/irq.h>
X #include <linux/proc_fs.h>
X
+#include <asm/atomic.h>
X #include <asm/io.h>
X #include <asm/smp.h>
X #include <asm/system.h>
@@ -121,7 +122,10 @@
X end_none
X };
X
-volatile unsigned long irq_err_count;
+atomic_t irq_err_count;
+#if defined(CONFIG_X86) && defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG)
+atomic_t irq_mis_count;
+#endif
X
X /*
X * Generic, controller-independent functions:
@@ -164,14 +168,17 @@
X p += sprintf(p, "%10u ",
X nmi_count(cpu_logical_map(j)));
X p += sprintf(p, "\n");
-#if defined(CONFIG_SMP) && defined(__i386__)
+#if defined(CONFIG_SMP) && defined(CONFIG_X86)
X p += sprintf(p, "LOC: ");
X for (j = 0; j < smp_num_cpus; j++)
X p += sprintf(p, "%10u ",
X apic_timer_irqs[cpu_logical_map(j)]);
X p += sprintf(p, "\n");
X #endif
- p += sprintf(p, "ERR: %10lu\n", irq_err_count);
+ p += sprintf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+#if defined(CONFIG_X86) && defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG)
+ p += sprintf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+#endif
X return p - buf;
X }
X
@@ -183,7 +190,7 @@
X
X #ifdef CONFIG_SMP
X unsigned int global_irq_holder = NO_PROC_ID;
-volatile unsigned long global_irq_lock; /* long for set_bit --RR */
+unsigned volatile long global_irq_lock; /* pedantic: long for set_bit --RR */
X
X extern void show_stack(unsigned long* esp);
X
@@ -201,14 +208,14 @@
X printk(" %d",bh_count(i));
X
X printk(" ]\nStack dumps:");
-#if defined(__ia64__)
+#if defined(CONFIG_IA64)
X /*
X * We can't unwind the stack of another CPU without access to
X * the registers of that CPU. And sending an IPI when we're
X * in a potentially wedged state doesn't sound like a smart
X * idea.
X */
-#elif defined(__i386__)
+#elif defined(CONFIG_X86)
X for(i=0;i< smp_num_cpus;i++) {
X unsigned long esp;
X if(i==cpu)
@@ -261,7 +268,7 @@
X /*
X * We have to allow irqs to arrive between __sti and __cli
X */
-# ifdef __ia64__
+# ifdef CONFIG_IA64
X # define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop 0")
X # else
X # define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop")
@@ -331,6 +338,9 @@
X /* Uhhuh.. Somebody else got it. Wait.. */
X do {
X do {
+#ifdef CONFIG_X86
+ rep_nop();
+#endif
X } while (test_bit(0,&global_irq_lock));
X } while (test_and_set_bit(0,&global_irq_lock));
X }
@@ -364,7 +374,7 @@
X {
X unsigned int flags;
X
-#ifdef __ia64__
+#ifdef CONFIG_IA64
X __save_flags(flags);
X if (flags & IA64_PSR_I) {
X __cli();
@@ -403,7 +413,7 @@
X int cpu = smp_processor_id();
X
X __save_flags(flags);
-#ifdef __ia64__
+#ifdef CONFIG_IA64
X local_enabled = (flags & IA64_PSR_I) != 0;
X #else
X local_enabled = (flags >> EFLAGS_IF_SHIFT) & 1;
@@ -476,13 +486,19 @@
X return status;
X }
X
-/*
- * Generic enable/disable code: this just calls
- * down into the PIC-specific version for the actual
- * hardware disable after having gotten the irq
- * controller lock.
+/**
+ * disable_irq_nosync - disable an irq without waiting
+ * @irq: Interrupt to disable
+ *
+ * Disable the selected interrupt line. Disables and Enables are
+ * nested.
+ * Unlike disable_irq(), this function does not ensure existing
+ * instances of the IRQ handler have completed before returning.
+ *
+ * This function may be called from IRQ context.
X */
-void inline disable_irq_nosync(unsigned int irq)
+
+inline void disable_irq_nosync(unsigned int irq)
X {
X irq_desc_t *desc = irq_desc(irq);
X unsigned long flags;
@@ -495,10 +511,19 @@
X spin_unlock_irqrestore(&desc->lock, flags);
X }
X
-/*
- * Synchronous version of the above, making sure the IRQ is
- * no longer running on any other IRQ..
+/**
+ * disable_irq - disable an irq and wait for completion
+ * @irq: Interrupt to disable
+ *
+ * Disable the selected interrupt line. Enables and Disables are
+ * nested.
+ * This function waits for any pending IRQ handlers for this interrupt
+ * to complete before returning. If you use this function while
+ * holding a resource the IRQ handler may need you will deadlock.
+ *
+ * This function may be called - with care - from IRQ context.
X */
+
X void disable_irq(unsigned int irq)
X {
X disable_irq_nosync(irq);
@@ -512,6 +537,17 @@
X #endif
X }
X
+/**
+ * enable_irq - enable handling of an irq
+ * @irq: Interrupt to enable
+ *
+ * Undoes the effect of one call to disable_irq(). If this
+ * matches the last disable, processing of interrupts on this
+ * IRQ line is re-enabled.
+ *
+ * This function may be called from IRQ context.
+ */
+
X void enable_irq(unsigned int irq)
X {
X irq_desc_t *desc = irq_desc(irq);
@@ -533,7 +569,8 @@
X desc->depth--;
X break;
X case 0:
- printk("enable_irq() unbalanced from %p\n", (void *) __builtin_return_address(0));
+ printk("enable_irq(%u) unbalanced from %p\n",
+ irq, (void *) __builtin_return_address(0));
X }
X spin_unlock_irqrestore(&desc->lock, flags);
X }
@@ -626,11 +663,41 @@
X desc->handler->end(irq);
X spin_unlock(&desc->lock);
X }
- if (local_softirq_pending())
- do_softirq();


X return 1;
X }
X

+/**
+ * request_irq - allocate an interrupt line
+ * @irq: Interrupt line to allocate
+ * @handler: Function to be called when the IRQ occurs
+ * @irqflags: Interrupt type flags
+ * @devname: An ascii name for the claiming device
+ * @dev_id: A cookie passed back to the handler function
+ *
+ * This call allocates interrupt resources and enables the
+ * interrupt line and IRQ handling. From the point this
+ * call is made your handler function may be invoked. Since
+ * your handler function must clear any interrupt the board
+ * raises, you must take care both to initialise your hardware
+ * and to set up the interrupt handler in the right order.
+ *
+ * Dev_id must be globally unique. Normally the address of the
+ * device data structure is used as the cookie. Since the handler
+ * receives this value it makes sense to use it.
+ *
+ * If your interrupt is shared you must pass a non NULL dev_id
+ * as this is required when freeing the interrupt.
+ *
+ * Flags:
+ *
+ * SA_SHIRQ Interrupt is shared
+ *
+ * SA_INTERRUPT Disable local interrupts while processing
+ *
+ * SA_SAMPLE_RANDOM The interrupt can be used for entropy
+ *
+ */
+
X int request_irq(unsigned int irq,
X void (*handler)(int, void *, struct pt_regs *),
X unsigned long irqflags,
@@ -676,6 +743,24 @@


X return retval;
X }
X

+/**
+ * free_irq - free an interrupt
+ * @irq: Interrupt line to free
+ * @dev_id: Device identity to free
+ *
+ * Remove an interrupt handler. The handler is removed and if the
+ * interrupt line is no longer in use by any driver it is disabled.
+ * On a shared IRQ the caller must ensure the interrupt is disabled
+ * on the card it drives before calling this function. The function
+ * does not return until any executing interrupts for this IRQ
+ * have completed.
+ *
+ * This function may be called from interrupt context.
+ *
+ * Bugs: Attempting to free an irq in a handler for the same irq hangs
+ * the machine.
+ */
+
X void free_irq(unsigned int irq, void *dev_id)
X {
X irq_desc_t *desc;
@@ -726,6 +811,17 @@
X * with "IRQ_WAITING" cleared and the interrupt
X * disabled.
X */
+
+static DECLARE_MUTEX(probe_sem);
+
+/**
+ * probe_irq_on - begin an interrupt autodetect
+ *
+ * Commence probing for an interrupt. The interrupts are scanned
+ * and a mask of potential interrupt lines is returned.
+ *
+ */
+
X unsigned long probe_irq_on(void)
X {
X unsigned int i;
@@ -733,6 +829,7 @@
X unsigned long val;
X unsigned long delay;
X
+ down(&probe_sem);
X /*
X * something may have generated an irq long ago and we want to
X * flush such a longstanding irq before considering it as spurious.
@@ -799,10 +896,19 @@
X return val;
X }
X
-/*
- * Return a mask of triggered interrupts (this
- * can handle only legacy ISA interrupts).
+/**
+ * probe_irq_mask - scan a bitmap of interrupt lines
+ * @val: mask of interrupts to consider
+ *
+ * Scan the ISA bus interrupt lines and return a bitmap of
+ * active interrupts. The interrupt probe logic state is then
+ * returned to its previous value.
+ *
+ * Note: we need to scan all the irq's even though we will
+ * only return ISA irq numbers - just so that we reset them
+ * all to a known state.
X */
+
X unsigned int probe_irq_mask(unsigned long val)
X {
X int i;


@@ -825,14 +931,29 @@
X }

X spin_unlock_irq(&desc->lock);
X }
+ up(&probe_sem);
X
X return mask & val;
X }
X
-/*
- * Return the one interrupt that triggered (this can
- * handle any interrupt source)
+/**
+ * probe_irq_off - end an interrupt autodetect
+ * @val: mask of potential interrupts (unused)
+ *
+ * Scans the unused interrupt lines and returns the line which
+ * appears to have triggered the interrupt. If no interrupt was
+ * found then zero is returned. If more than one interrupt is
+ * found then minus the first candidate is returned to indicate
+ * their is doubt.
+ *
+ * The interrupt probe logic state is returned to its previous
+ * value.
+ *
+ * BUGS: When used in a module (which arguably shouldnt happen)
+ * nothing prevents two IRQ probe callers from overlapping. The
+ * results of this are non-optimal.
X */
+
X int probe_irq_off(unsigned long val)
X {
X int i, irq_found, nr_irqs;
@@ -857,6 +978,7 @@
X }
X spin_unlock_irq(&desc->lock);
X }
+ up(&probe_sem);
X
X if (nr_irqs > 1)
X irq_found = -irq_found;
@@ -911,7 +1033,7 @@
X
X if (!shared) {
X desc->depth = 0;
- desc->status &= ~IRQ_DISABLED;
+ desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
X desc->handler->startup(irq);
X }
X spin_unlock_irqrestore(&desc->lock,flags);
@@ -922,20 +1044,9 @@
X
X static struct proc_dir_entry * root_irq_dir;
X static struct proc_dir_entry * irq_dir [NR_IRQS];
-static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
-
-static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
X
X #define HEX_DIGITS 8
X
-static int irq_affinity_read_proc (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- if (count < HEX_DIGITS+1)
- return -EINVAL;
- return sprintf (page, "%08lx\n", irq_affinity[(long)data]);
-}
-
X static unsigned int parse_hex_value (const char *buffer,
X unsigned long count, unsigned long *ret)
X {
@@ -973,6 +1084,20 @@


X return 0;
X }
X

+#if CONFIG_SMP
+
+static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
+
+static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
+
+static int irq_affinity_read_proc (char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ if (count < HEX_DIGITS+1)
+ return -EINVAL;
+ return sprintf (page, "%08lx\n", irq_affinity[(long)data]);
+}
+
X static int irq_affinity_write_proc (struct file *file, const char *buffer,
X unsigned long count, void *data)
X {
@@ -984,7 +1109,6 @@
X
X err = parse_hex_value(buffer, count, &new_value);
X
-#if CONFIG_SMP
X /*
X * Do not allow disabling IRQs completely - it's a too easy
X * way to make the system unusable accidentally :-) At least
@@ -992,7 +1116,6 @@
X */
X if (!(new_value & cpu_online_map))
X return -EINVAL;
-#endif
X
X irq_affinity[irq] = new_value;
X irq_desc(irq)->handler->set_affinity(irq, new_value);
@@ -1000,6 +1123,8 @@
X return full_count;
X }
X
+#endif /* CONFIG_SMP */
+
X static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
X int count, int *eof, void *data)
X {
@@ -1027,7 +1152,6 @@
X
X static void register_irq_proc (unsigned int irq)
X {
- struct proc_dir_entry *entry;
X char name [MAX_NAMELEN];
X
X if (!root_irq_dir || (irq_desc(irq)->handler == &no_irq_type))
@@ -1039,15 +1163,22 @@
X /* create /proc/irq/1234 */
X irq_dir[irq] = proc_mkdir(name, root_irq_dir);
X
- /* create /proc/irq/1234/smp_affinity */
- entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
-
- entry->nlink = 1;
- entry->data = (void *)(long)irq;
- entry->read_proc = irq_affinity_read_proc;
- entry->write_proc = irq_affinity_write_proc;
+#if CONFIG_SMP
+ {
+ struct proc_dir_entry *entry;
+ /* create /proc/irq/1234/smp_affinity */
+ entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
+
+ if (entry) {
+ entry->nlink = 1;
+ entry->data = (void *)(long)irq;
+ entry->read_proc = irq_affinity_read_proc;
+ entry->write_proc = irq_affinity_write_proc;
+ }
X
- smp_affinity_entry[irq] = entry;
+ smp_affinity_entry[irq] = entry;
+ }
+#endif
X }
X
X unsigned long prof_cpu_mask = -1;
@@ -1062,6 +1193,9 @@
X
X /* create /proc/irq/prof_cpu_mask */
X entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
+
+ if (!entry)
+ return;
X
X entry->nlink = 1;
X entry->data = (void *)&prof_cpu_mask;
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/irq_ia64.c linux/arch/ia64/kernel/irq_ia64.c
--- v2.4.14/linux/arch/ia64/kernel/irq_ia64.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/irq_ia64.c Fri Nov 9 14:26:17 2001
@@ -1,9 +1,9 @@
X /*
X * linux/arch/ia64/kernel/irq.c
X *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 Stephane Eranian <era...@hpl.hp.com>
- * Copyright (C) 1999-2000 David Mosberger-Tang <dav...@hpl.hp.com>
+ * Copyright (C) 1998-2001 Hewlett-Packard Co


+ * Stephane Eranian <era...@hpl.hp.com>

+ * David Mosberger-Tang <dav...@hpl.hp.com>
X *

X * 6/10/99: Updated to bring in sync with x86 version to facilitate
X * support for SMP and different interrupt controllers.
@@ -131,6 +131,13 @@
X ia64_eoi();
X vector = ia64_get_ivr();
X }
+ /*
+ * This must be done *after* the ia64_eoi(). For example, the keyboard softirq
+ * handler needs to be able to wait for further keyboard interrupts, which can't
+ * come through until ia64_eoi() has been done.
+ */
+ if (local_softirq_pending())
+ do_softirq();
X }
X
X #ifdef CONFIG_SMP
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/ivt.S linux/arch/ia64/kernel/ivt.S
--- v2.4.14/linux/arch/ia64/kernel/ivt.S Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/ivt.S Fri Nov 9 14:26:17 2001
@@ -2,8 +2,8 @@
X * arch/ia64/kernel/ivt.S


X *
X * Copyright (C) 1998-2001 Hewlett-Packard Co

- * Copyright (C) 1998, 1999 Stephane Eranian <era...@hpl.hp.com>
- * Copyright (C) 1998-2001 David Mosberger <dav...@hpl.hp.com>


+ * Stephane Eranian <era...@hpl.hp.com>

+ * David Mosberger <dav...@hpl.hp.com>
X *

X * 00/08/23 Asit Mallick <asit.k....@intel.com> TLB handling for SMP
X * 00/12/20 David Mosberger-Tang <dav...@hpl.hp.com> DTLB/ITLB handler now uses virtual PT.
@@ -157,7 +157,7 @@
X ;;
X (p10) itc.i r18 // insert the instruction TLB entry
X (p11) itc.d r18 // insert the data TLB entry
-(p6) br.spnt.many page_fault // handle bad address/page not present (page fault)
+(p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault)
X mov cr.ifa=r22
X
X /*
@@ -213,7 +213,7 @@
X ;;
X mov b0=r29
X tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
-(p6) br.cond.spnt.many page_fault
+(p6) br.cond.spnt page_fault
X ;;
X itc.i r18
X ;;
@@ -251,7 +251,7 @@
X ;;
X mov b0=r29
X tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
-(p6) br.cond.spnt.many page_fault
+(p6) br.cond.spnt page_fault
X ;;
X itc.d r18
X ;;
@@ -286,7 +286,7 @@
X ;;
X (p8) mov cr.iha=r17
X (p8) mov r29=b0 // save b0
-(p8) br.cond.dptk.many itlb_fault
+(p8) br.cond.dptk itlb_fault
X #endif
X extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
X shr.u r18=r16,57 // move address bit 61 to bit 4
@@ -297,7 +297,7 @@
X dep r19=r17,r19,0,12 // insert PTE control bits into r19
X ;;
X or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
-(p8) br.cond.spnt.many page_fault
+(p8) br.cond.spnt page_fault
X ;;
X itc.i r19 // insert the TLB entry
X mov pr=r31,-1
@@ -324,7 +324,7 @@
X ;;
X (p8) mov cr.iha=r17
X (p8) mov r29=b0 // save b0
-(p8) br.cond.dptk.many dtlb_fault
+(p8) br.cond.dptk dtlb_fault
X #endif
X extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
X tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
@@ -333,7 +333,7 @@
X ;;
X andcm r18=0x10,r18 // bit 4=~address-bit(61)
X cmp.ne p8,p0=r0,r23
-(p8) br.cond.spnt.many page_fault
+(p8) br.cond.spnt page_fault
X
X dep r21=-1,r21,IA64_PSR_ED_BIT,1
X dep r19=r17,r19,0,12 // insert PTE control bits into r19
@@ -429,7 +429,7 @@
X ;;
X (p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL?
X dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table entry
-(p6) br.cond.spnt.many page_fault
+(p6) br.cond.spnt page_fault
X mov b0=r30
X br.sptk.many b0 // return to continuation point
X END(nested_dtlb_miss)
@@ -534,15 +534,6 @@
X ;;
X 1: ld8 r18=[r17]
X ;;
-# if defined(CONFIG_IA32_SUPPORT) && defined(CONFIG_ITANIUM_B0_SPECIFIC)
- /*
- * Erratum 85 (Access bit fault could be reported before page not present fault)
- * If the PTE is indicates the page is not present, then just turn this into a
- * page fault.
- */
- tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
-(p6) br.sptk page_fault // page wasn't present
-# endif
X mov ar.ccv=r18 // set compare value for cmpxchg
X or r25=_PAGE_A,r18 // set the accessed bit
X ;;
@@ -564,15 +555,6 @@
X ;;
X 1: ld8 r18=[r17]
X ;;
-# if defined(CONFIG_IA32_SUPPORT) && defined(CONFIG_ITANIUM_B0_SPECIFIC)
- /*
- * Erratum 85 (Access bit fault could be reported before page not present fault)
- * If the PTE is indicates the page is not present, then just turn this into a
- * page fault.
- */
- tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
-(p6) br.sptk page_fault // page wasn't present
-# endif
X or r18=_PAGE_A,r18 // set the accessed bit
X mov b0=r29 // restore b0
X ;;
@@ -640,7 +622,7 @@
X mov r31=pr // prepare to save predicates
X ;;
X cmp.eq p0,p7=r16,r17 // is this a system call? (p7 <- false, if so)
-(p7) br.cond.spnt.many non_syscall
+(p7) br.cond.spnt non_syscall
X
X SAVE_MIN // uses r31; defines r2:
X
@@ -656,7 +638,7 @@
X adds r3=8,r2 // set up second base pointer for SAVE_REST
X ;;
X SAVE_REST
- br.call.sptk rp=demine_args // clear NaT bits in (potential) syscall args
+ br.call.sptk.many rp=demine_args // clear NaT bits in (potential) syscall args
X
X mov r3=255
X adds r15=-1024,r15 // r15 contains the syscall number---subtract 1024
@@ -698,7 +680,7 @@
X st8 [r16]=r18 // store new value for cr.isr
X
X (p8) br.call.sptk.many b6=b6 // ignore this return addr
- br.cond.sptk.many ia64_trace_syscall
+ br.cond.sptk ia64_trace_syscall
X // NOT REACHED
X END(break_fault)
X
@@ -811,8 +793,8 @@
X mov b6=r8
X ;;
X cmp.ne p6,p0=0,r8
-(p6) br.call.dpnt b6=b6 // call returns to ia64_leave_kernel
- br.sptk ia64_leave_kernel
+(p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel
+ br.sptk.many ia64_leave_kernel
X END(dispatch_illegal_op_fault)
X
X .align 1024
@@ -855,30 +837,30 @@
X adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp
X ;;
X cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
- st8 [r15]=r8 // save orignal EAX in r1 (IA32 procs don't use the GP)
+ st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP)
X ;;
X alloc r15=ar.pfs,0,0,6,0 // must first in an insn group
X ;;
- ld4 r8=[r14],8 // r8 == EAX (syscall number)
- mov r15=222 // sys_vfork - last implemented system call
+ ld4 r8=[r14],8 // r8 == eax (syscall number)
+ mov r15=230 // number of entries in ia32 system call table
X ;;
- cmp.leu.unc p6,p7=r8,r15
- ld4 out1=[r14],8 // r9 == ecx
+ cmp.ltu.unc p6,p7=r8,r15
+ ld4 out1=[r14],8 // r9 == ecx
X ;;
- ld4 out2=[r14],8 // r10 == edx
+ ld4 out2=[r14],8 // r10 == edx
X ;;
- ld4 out0=[r14] // r11 == ebx
+ ld4 out0=[r14] // r11 == ebx
X adds r14=(IA64_PT_REGS_R8_OFFSET-(8*3)) + 16,sp
X ;;
- ld4 out5=[r14],8 // r13 == ebp
+ ld4 out5=[r14],8 // r13 == ebp
X ;;
- ld4 out3=[r14],8 // r14 == esi
+ ld4 out3=[r14],8 // r14 == esi
X adds r2=IA64_TASK_PTRACE_OFFSET,r13 // r2 = &current->ptrace
X ;;
- ld4 out4=[r14] // R15 == edi
+ ld4 out4=[r14] // r15 == edi
X movl r16=ia32_syscall_table
X ;;
-(p6) shladd r16=r8,3,r16 // Force ni_syscall if not valid syscall number
+(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number
X ld8 r2=[r2] // r2 = current->ptrace
X ;;
X ld8 r16=[r16]
@@ -889,12 +871,12 @@
X ;;
X mov rp=r15
X (p8) br.call.sptk.many b6=b6
- br.cond.sptk.many ia32_trace_syscall
+ br.cond.sptk ia32_trace_syscall
X
X non_ia32_syscall:
X alloc r15=ar.pfs,0,0,2,0
- mov out0=r14 // interrupt #
- add out1=16,sp // pointer to pt_regs
+ mov out0=r14 // interrupt #
+ add out1=16,sp // pointer to pt_regs
X ;; // avoid WAW on CFM
X br.call.sptk.many rp=ia32_bad_interrupt
X .ret1: movl r15=ia64_leave_kernel
@@ -1085,7 +1067,7 @@
X mov r31=pr
X ;;
X cmp4.eq p6,p0=0,r16
-(p6) br.sptk dispatch_illegal_op_fault
+(p6) br.sptk.many dispatch_illegal_op_fault
X ;;
X mov r19=24 // fault number
X br.sptk.many dispatch_to_fault_handler
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/mca.c linux/arch/ia64/kernel/mca.c
--- v2.4.14/linux/arch/ia64/kernel/mca.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/mca.c Fri Nov 9 14:26:17 2001
@@ -3,12 +3,20 @@
X * Purpose: Generic MCA handling layer
X *
X * Updated for latest kernel
+ * Copyright (C) 2001 Intel
+ * Copyright (C) Fred Lewis (frederic...@intel.com)
+ *
X * Copyright (C) 2000 Intel
X * Copyright (C) Chuck Fleckenstein (cfl...@co.intel.com)
X *
X * Copyright (C) 1999 Silicon Graphics, Inc.
X * Copyright (C) Vijay Chander(vi...@engr.sgi.com)
X *
+ * 01/01/03 F. Lewis Added setup of CMCI and CPEI IRQs, logging of corrected
+ * platform errors, completed code for logging of
+ * corrected & uncorrected machine check errors, and
+ * updated for conformance with Nov. 2000 revision of the
+ * SAL 3.0 spec.
X * 00/03/29 C. Fleckenstein Fixed PAL/SAL update issues, began MCA bug fixes, logging issues,
X * added min save state dump, added INIT handler.
X */
@@ -16,6 +24,7 @@
X #include <linux/types.h>
X #include <linux/init.h>
X #include <linux/sched.h>
+#include <linux/interrupt.h>
X #include <linux/irq.h>
X #include <linux/smp_lock.h>
X
@@ -27,8 +36,10 @@
X #include <asm/mca.h>
X
X #include <asm/irq.h>
-#include <asm/machvec.h>
+#include <asm/hw_irq.h>
+#include <asm/acpi-ext.h>
X
+#undef MCA_PRT_XTRA_DATA
X
X typedef struct ia64_fptr {
X unsigned long fp;
@@ -38,22 +49,67 @@
X ia64_mc_info_t ia64_mc_info;
X ia64_mca_sal_to_os_state_t ia64_sal_to_os_handoff_state;
X ia64_mca_os_to_sal_state_t ia64_os_to_sal_handoff_state;
-u64 ia64_mca_proc_state_dump[256];
+u64 ia64_mca_proc_state_dump[512];
X u64 ia64_mca_stack[1024];
X u64 ia64_mca_stackframe[32];
X u64 ia64_mca_bspstore[1024];
X u64 ia64_init_stack[INIT_TASK_SIZE] __attribute__((aligned(16)));
X
-static void ia64_mca_cmc_vector_setup(int enable,
- int_vector_t cmc_vector);
X static void ia64_mca_wakeup_ipi_wait(void);
X static void ia64_mca_wakeup(int cpu);
X static void ia64_mca_wakeup_all(void);
-static void ia64_log_init(int,int);
-static void ia64_log_get(int,int, prfunc_t);
-static void ia64_log_clear(int,int,int, prfunc_t);
+static void ia64_log_init(int);
X extern void ia64_monarch_init_handler (void);
X extern void ia64_slave_init_handler (void);
+extern struct hw_interrupt_type irq_type_iosapic_level;
+
+static struct irqaction cmci_irqaction = {
+ handler: ia64_mca_cmc_int_handler,
+ flags: SA_INTERRUPT,
+ name: "cmc_hndlr"
+};
+
+static struct irqaction mca_rdzv_irqaction = {
+ handler: ia64_mca_rendez_int_handler,
+ flags: SA_INTERRUPT,
+ name: "mca_rdzv"
+};
+
+static struct irqaction mca_wkup_irqaction = {
+ handler: ia64_mca_wakeup_int_handler,
+ flags: SA_INTERRUPT,
+ name: "mca_wkup"
+};
+
+static struct irqaction mca_cpe_irqaction = {
+ handler: ia64_mca_cpe_int_handler,
+ flags: SA_INTERRUPT,
+ name: "cpe_hndlr"
+};
+
+/*
+ * ia64_mca_log_sal_error_record
+ *
+ * This function retrieves a specified error record type from SAL, sends it to
+ * the system log, and notifies SALs to clear the record from its non-volatile
+ * memory.
+ *
+ * Inputs : sal_info_type (Type of error record MCA/CMC/CPE/INIT)
+ * Outputs : None
+ */
+void
+ia64_mca_log_sal_error_record(int sal_info_type)
+{
+ /* Get the MCA error record */
+ if (!ia64_log_get(sal_info_type, (prfunc_t)printk))
+ return; // no record retrieved
+
+ /* Log the error record */
+ ia64_log_print(sal_info_type, (prfunc_t)printk);
+
+ /* Clear the CMC SAL logs now that they have been logged */
+ ia64_sal_clear_state_info(sal_info_type);
+}
X
X /*
X * hack for now, add platform dependent handlers
@@ -67,10 +123,14 @@
X }
X
X void
-cmci_handler_platform (int cmc_irq, void *arg, struct pt_regs *ptregs)
+ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
X {
+ IA64_MCA_DEBUG("ia64_mca_cpe_int_handler: received interrupt. vector = %#x\n", cpe_irq);
X
+ /* Get the CMC error record and log it */
+ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
X }
+
X /*
X * This routine will be used to deal with platform specific handling
X * of the init, i.e. drop into the kernel debugger on server machine,
@@ -81,17 +141,72 @@
X init_handler_platform (struct pt_regs *regs)
X {
X /* if a kernel debugger is available call it here else just dump the registers */
+
X show_regs(regs); /* dump the state info */
+ while (1); /* hang city if no debugger */
X }
X
+/*
+ * ia64_mca_init_platform
+ *
+ * External entry for platform specific MCA initialization.


+ *
+ * Inputs

+ * None
+ *
+ * Outputs
+ * None
+ */
X void
-log_print_platform ( void *cur_buff_ptr, prfunc_t prfunc)
+ia64_mca_init_platform (void)
X {
+
X }
X
+/*
+ * ia64_mca_check_errors
+ *
+ * External entry to check for error records which may have been posted by SAL
+ * for a prior failure which resulted in a machine shutdown before an the
+ * error could be logged. This function must be called after the filesystem
+ * is initialized.
+ *
+ * Inputs : None
+ *
+ * Outputs : None
+ */
X void
-ia64_mca_init_platform (void)
+ia64_mca_check_errors (void)
+{
+ /*
+ * If there is an MCA error record pending, get it and log it.
+ */
+ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
+}
+
+/*
+ * ia64_mca_register_cpev
+ *
+ * Register the corrected platform error vector with SAL.


+ *
+ * Inputs

+ * cpev Corrected Platform Error Vector number
+ *
+ * Outputs
+ * None
+ */
+static void
+ia64_mca_register_cpev (int cpev)
X {
+ /* Register the CPE interrupt vector with SAL */
+ if (ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0)) {
+ printk("ia64_mca_platform_init: failed to register Corrected "
+ "Platform Error interrupt vector with SAL.\n");
+ return;
+ }
+
+ IA64_MCA_DEBUG("ia64_mca_platform_init: corrected platform error "
+ "vector %#x setup and enabled\n", cpev);
X }
X
X #endif /* PLATFORM_MCA_HANDLERS */
@@ -140,30 +255,36 @@
X && !ia64_pmss_dump_bank0))
X printk("\n");
X }
- /* hang city for now, until we include debugger or copy to ptregs to show: */
- while (1);
X }
X
X /*
X * ia64_mca_cmc_vector_setup
- * Setup the correctable machine check vector register in the processor
+ *
+ * Setup the corrected machine check vector register in the processor and
+ * unmask interrupt. This function is invoked on a per-processor basis.
+ *
X * Inputs
- * Enable (1 - enable cmc interrupt , 0 - disable)
- * CMC handler entry point (if enabled)
+ * None
X *
X * Outputs
X * None
X */
-static void
-ia64_mca_cmc_vector_setup(int enable,
- int_vector_t cmc_vector)
+void
+ia64_mca_cmc_vector_setup (void)
X {
X cmcv_reg_t cmcv;
X
X cmcv.cmcv_regval = 0;
- cmcv.cmcv_mask = enable;
- cmcv.cmcv_vector = cmc_vector;
+ cmcv.cmcv_mask = 0; /* Unmask/enable interrupt */
+ cmcv.cmcv_vector = IA64_CMC_VECTOR;
X ia64_set_cmcv(cmcv.cmcv_regval);
+
+ IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d corrected "
+ "machine check vector %#x setup and enabled.\n",
+ smp_processor_id(), IA64_CMC_VECTOR);
+
+ IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d CMCV = %#016lx\n",
+ smp_processor_id(), ia64_get_cmcv());
X }
X
X
@@ -174,26 +295,58 @@
X void
X mca_test(void)
X {
- slpi_buf.slpi_valid.slpi_psi = 1;
- slpi_buf.slpi_valid.slpi_cache_check = 1;
- slpi_buf.slpi_valid.slpi_tlb_check = 1;
- slpi_buf.slpi_valid.slpi_bus_check = 1;
- slpi_buf.slpi_valid.slpi_minstate = 1;
- slpi_buf.slpi_valid.slpi_bank1_gr = 1;
- slpi_buf.slpi_valid.slpi_br = 1;
- slpi_buf.slpi_valid.slpi_cr = 1;
- slpi_buf.slpi_valid.slpi_ar = 1;
- slpi_buf.slpi_valid.slpi_rr = 1;
- slpi_buf.slpi_valid.slpi_fr = 1;
+ slpi_buf.valid.psi_static_struct = 1;
+ slpi_buf.valid.num_cache_check = 1;
+ slpi_buf.valid.num_tlb_check = 1;
+ slpi_buf.valid.num_bus_check = 1;
+ slpi_buf.valid.processor_static_info.minstate = 1;
+ slpi_buf.valid.processor_static_info.br = 1;
+ slpi_buf.valid.processor_static_info.cr = 1;
+ slpi_buf.valid.processor_static_info.ar = 1;
+ slpi_buf.valid.processor_static_info.rr = 1;
+ slpi_buf.valid.processor_static_info.fr = 1;
X
X ia64_os_mca_dispatch();
X }
X
X #endif /* #if defined(MCA_TEST) */
X
+
+/*
+ * verify_guid
+ *
+ * Compares a test guid to a target guid and returns result.


+ *
+ * Inputs

+ * test_guid * (ptr to guid to be verified)
+ * target_guid * (ptr to standard guid to be verified against)
+ *
+ * Outputs
+ * 0 (test verifies against target)
+ * non-zero (test guid does not verify)
+ */
+static int
+verify_guid (efi_guid_t *test, efi_guid_t *target)
+{
+ int rc;
+
+ if ((rc = memcmp((void *)test, (void *)target, sizeof(efi_guid_t)))) {
+ IA64_MCA_DEBUG("ia64_mca_print: invalid guid = "
+ "{ %08x, %04x, %04x, { %#02x, %#02x, %#02x, %#02x, "
+ "%#02x, %#02x, %#02x, %#02x, } } \n ",
+ test->data1, test->data2, test->data3, test->data4[0],
+ test->data4[1], test->data4[2], test->data4[3],
+ test->data4[4], test->data4[5], test->data4[6],
+ test->data4[7]);
+ }
+
+ return rc;
+}
+
X /*
X * ia64_mca_init
- * Do all the mca specific initialization on a per-processor basis.
+ *
+ * Do all the system level mca specific initialization.
X *
X * 1. Register spinloop and wakeup request interrupt vectors
X *
@@ -201,77 +354,80 @@
X *
X * 3. Register OS_INIT handler entry point
X *
- * 4. Initialize CMCV register to enable/disable CMC interrupt on the
- * processor and hook a handler in the platform-specific ia64_mca_init.
+ * 4. Initialize MCA/CMC/INIT related log buffers maintained by the OS.
X *
- * 5. Initialize MCA/CMC/INIT related log buffers maintained by the OS.
+ * Note that this initialization is done very early before some kernel
+ * services are available.
X *
- * Inputs
- * None
- * Outputs
- * None
+ * Inputs : None
+ *
+ * Outputs : None
X */
X void __init
X ia64_mca_init(void)
X {
X ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler;
X ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler;
+ ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch;
X int i;
+ s64 rc;
X
- IA64_MCA_DEBUG("ia64_mca_init : begin\n");
+ IA64_MCA_DEBUG("ia64_mca_init: begin\n");
X
X /* Clear the Rendez checkin flag for all cpus */
- for(i = 0 ; i < IA64_MAXCPUS; i++)
+ for(i = 0 ; i < NR_CPUS; i++)
X ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
X
- /* NOTE : The actual irqs for the rendez, wakeup and
- * cmc interrupts are requested in the platform-specific
- * mca initialization code.
- */
X /*
X * Register the rendezvous spinloop and wakeup mechanism with SAL
X */
X
X /* Register the rendezvous interrupt vector with SAL */
- if (ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,
- SAL_MC_PARAM_MECHANISM_INT,
- IA64_MCA_RENDEZ_VECTOR,
- IA64_MCA_RENDEZ_TIMEOUT,
- 0))
+ if ((rc = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,
+ SAL_MC_PARAM_MECHANISM_INT,
+ IA64_MCA_RENDEZ_VECTOR,
+ IA64_MCA_RENDEZ_TIMEOUT,
+ 0)))
+ {
+ printk("ia64_mca_init: Failed to register rendezvous interrupt "
+ "with SAL. rc = %ld\n", rc);
X return;
+ }
X
X /* Register the wakeup interrupt vector with SAL */
- if (ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,
- SAL_MC_PARAM_MECHANISM_INT,
- IA64_MCA_WAKEUP_VECTOR,
- 0,
- 0))
+ if ((rc = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,
+ SAL_MC_PARAM_MECHANISM_INT,
+ IA64_MCA_WAKEUP_VECTOR,
+ 0, 0)))
+ {
+ printk("ia64_mca_init: Failed to register wakeup interrupt with SAL. rc = %ld\n",
+ rc);
X return;
+ }
X
- IA64_MCA_DEBUG("ia64_mca_init : registered mca rendezvous spinloop and wakeup mech.\n");
- /*
- * Setup the correctable machine check vector
- */
- ia64_mca_cmc_vector_setup(IA64_CMC_INT_ENABLE, IA64_CMC_VECTOR);
-
- IA64_MCA_DEBUG("ia64_mca_init : correctable mca vector setup done\n");
+ IA64_MCA_DEBUG("ia64_mca_init: registered mca rendezvous spinloop and wakeup mech.\n");
X
- ia64_mc_info.imi_mca_handler = __pa(ia64_os_mca_dispatch);
+ ia64_mc_info.imi_mca_handler = __pa(mca_hldlr_ptr->fp);
X /*
X * XXX - disable SAL checksum by setting size to 0; should be
X * __pa(ia64_os_mca_dispatch_end) - __pa(ia64_os_mca_dispatch);
X */
X ia64_mc_info.imi_mca_handler_size = 0;
- /* Register the os mca handler with SAL */
- if (ia64_sal_set_vectors(SAL_VECTOR_OS_MCA,
- ia64_mc_info.imi_mca_handler,
- __pa(ia64_get_gp()),
- ia64_mc_info.imi_mca_handler_size,
- 0,0,0))
X
+ /* Register the os mca handler with SAL */
+ if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_MCA,
+ ia64_mc_info.imi_mca_handler,
+ mca_hldlr_ptr->gp,
+ ia64_mc_info.imi_mca_handler_size,
+ 0, 0, 0)))
+ {
+ printk("ia64_mca_init: Failed to register os mca handler with SAL. rc = %ld\n",
+ rc);
X return;
+ }
X
- IA64_MCA_DEBUG("ia64_mca_init : registered os mca handler with SAL\n");
+ IA64_MCA_DEBUG("ia64_mca_init: registered os mca handler with SAL at 0x%lx, gp = 0x%lx\n",
+ ia64_mc_info.imi_mca_handler, mca_hldlr_ptr->gp);
X
X /*
X * XXX - disable SAL checksum by setting size to 0, should be
@@ -282,53 +438,87 @@
X ia64_mc_info.imi_slave_init_handler = __pa(slave_init_ptr->fp);
X ia64_mc_info.imi_slave_init_handler_size = 0;
X
- IA64_MCA_DEBUG("ia64_mca_init : os init handler at %lx\n",ia64_mc_info.imi_monarch_init_handler);
+ IA64_MCA_DEBUG("ia64_mca_init: os init handler at %lx\n",
+ ia64_mc_info.imi_monarch_init_handler);
X
X /* Register the os init handler with SAL */
- if (ia64_sal_set_vectors(SAL_VECTOR_OS_INIT,
- ia64_mc_info.imi_monarch_init_handler,
- __pa(ia64_get_gp()),
- ia64_mc_info.imi_monarch_init_handler_size,
- ia64_mc_info.imi_slave_init_handler,
- __pa(ia64_get_gp()),
- ia64_mc_info.imi_slave_init_handler_size))
+ if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_INIT,
+ ia64_mc_info.imi_monarch_init_handler,
+ __pa(ia64_get_gp()),
+ ia64_mc_info.imi_monarch_init_handler_size,
+ ia64_mc_info.imi_slave_init_handler,
+ __pa(ia64_get_gp()),
+ ia64_mc_info.imi_slave_init_handler_size)))
+ {
+ printk("ia64_mca_init: Failed to register m/s init handlers with SAL. rc = %ld\n",
+ rc);
+ return;
+ }
X
+ IA64_MCA_DEBUG("ia64_mca_init: registered os init handler with SAL\n");
X
- return;
+ /*
+ * Configure the CMCI vector and handler. Interrupts for CMC are
+ * per-processor, so AP CMC interrupts are setup in smp_callin() (smp.c).
+ */
+ register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction);
+ ia64_mca_cmc_vector_setup(); /* Setup vector on BSP & enable */
+
+ /* Setup the MCA rendezvous interrupt vector */
+ register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction);
X
- IA64_MCA_DEBUG("ia64_mca_init : registered os init handler with SAL\n");
+ /* Setup the MCA wakeup interrupt vector */
+ register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
+
+ /* Setup the CPE interrupt vector */
+ {
+ irq_desc_t *desc;
+ unsigned int irq;
+ int cpev = acpi_request_vector(ACPI20_ENTRY_PIS_CPEI);
+
+ if (cpev >= 0) {
+ for (irq = 0; irq < NR_IRQS; ++irq)
+ if (irq_to_vector(irq) == cpev) {
+ desc = irq_desc(irq);
+ desc->status |= IRQ_PER_CPU;
+ desc->handler = &irq_type_iosapic_level;
+ setup_irq(irq, &mca_cpe_irqaction);
+ }
+ ia64_mca_register_cpev(cpev);
+ } else
+ printk("ia64_mca_init: Failed to get routed CPEI vector from ACPI.\n");
+ }
X
X /* Initialize the areas set aside by the OS to buffer the
X * platform/processor error states for MCA/INIT/CMC
X * handling.
X */
- ia64_log_init(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PROCESSOR);
- ia64_log_init(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PLATFORM);
- ia64_log_init(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PROCESSOR);
- ia64_log_init(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PLATFORM);
- ia64_log_init(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR);
- ia64_log_init(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PLATFORM);
-
- ia64_mca_init_platform();
-
- IA64_MCA_DEBUG("ia64_mca_init : platform-specific mca handling setup done\n");
+ ia64_log_init(SAL_INFO_TYPE_MCA);
+ ia64_log_init(SAL_INFO_TYPE_INIT);
+ ia64_log_init(SAL_INFO_TYPE_CMC);
+ ia64_log_init(SAL_INFO_TYPE_CPE);
X
X #if defined(MCA_TEST)
X mca_test();
X #endif /* #if defined(MCA_TEST) */
X
X printk("Mca related initialization done\n");
+
+#if 0 // Too early in initialization -- error log is lost
+ /* Do post-failure MCA error logging */
+ ia64_mca_check_errors();
+#endif // Too early in initialization -- error log is lost
X }
X
X /*
X * ia64_mca_wakeup_ipi_wait
+ *
X * Wait for the inter-cpu interrupt to be sent by the
X * monarch processor once it is done with handling the
X * MCA.
- * Inputs
- * None
- * Outputs
- * None
+ *
+ * Inputs : None
+ * Outputs : None
X */
X void
X ia64_mca_wakeup_ipi_wait(void)
@@ -339,16 +529,16 @@
X
X do {
X switch(irr_num) {


- case 0:
+ case 0:

X irr = ia64_get_irr0();


X break;
- case 1:
+ case 1:

X irr = ia64_get_irr1();


X break;
- case 2:

+ case 2:
X irr = ia64_get_irr2();
X break;
- case 3:
+ case 3:
X irr = ia64_get_irr3();
X break;
X }
@@ -357,26 +547,28 @@
X
X /*
X * ia64_mca_wakeup
+ *
X * Send an inter-cpu interrupt to wake-up a particular cpu
X * and mark that cpu to be out of rendez.
- * Inputs
- * cpuid
- * Outputs
- * None
+ *
+ * Inputs : cpuid
+ * Outputs : None
X */
X void
X ia64_mca_wakeup(int cpu)
X {
X platform_send_ipi(cpu, IA64_MCA_WAKEUP_VECTOR, IA64_IPI_DM_INT, 0);
X ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+
X }
+
X /*
X * ia64_mca_wakeup_all
+ *
X * Wakeup all the cpus which have rendez'ed previously.
- * Inputs
- * None
- * Outputs
- * None
+ *
+ * Inputs : None
+ * Outputs : None
X */
X void
X ia64_mca_wakeup_all(void)
@@ -389,15 +581,16 @@
X ia64_mca_wakeup(cpu);
X
X }
+
X /*
X * ia64_mca_rendez_interrupt_handler
+ *
X * This is handler used to put slave processors into spinloop
X * while the monarch processor does the mca handling and later
X * wake each slave up once the monarch is done.
- * Inputs
- * None
- * Outputs
- * None
+ *
+ * Inputs : None
+ * Outputs : None
X */
X void
X ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs)
@@ -423,23 +616,22 @@
X
X /* Enable all interrupts */
X restore_flags(flags);
-
-
X }
X
X
X /*
X * ia64_mca_wakeup_int_handler
+ *
X * The interrupt handler for processing the inter-cpu interrupt to the
X * slave cpu which was spinning in the rendez loop.
X * Since this spinning is done by turning off the interrupts and
X * polling on the wakeup-interrupt bit in the IRR, there is
X * nothing useful to be done in the handler.
- * Inputs
- * wakeup_irq (Wakeup-interrupt bit)
+ *
+ * Inputs : wakeup_irq (Wakeup-interrupt bit)
X * arg (Interrupt handler specific argument)
X * ptregs (Exception frame at the time of the interrupt)
- * Outputs
+ * Outputs : None
X *
X */
X void
@@ -450,16 +642,16 @@
X
X /*
X * ia64_return_to_sal_check
+ *
X * This is function called before going back from the OS_MCA handler
X * to the OS_MCA dispatch code which finally takes the control back
X * to the SAL.
X * The main purpose of this routine is to setup the OS_MCA to SAL
X * return state which can be used by the OS_MCA dispatch code
X * just before going back to SAL.
- * Inputs
- * None
- * Outputs
- * None
+ *
+ * Inputs : None
+ * Outputs : None
X */
X
X void
@@ -474,11 +666,13 @@
X ia64_os_to_sal_handoff_state.imots_sal_check_ra =
X ia64_sal_to_os_handoff_state.imsto_sal_check_ra;
X
- /* For now ignore the MCA */
- ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_CORRECTED;
+ /* Cold Boot for uncorrectable MCA */
+ ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT;
X }
+
X /*
X * ia64_mca_ucmc_handler
+ *
X * This is uncorrectable machine check handler called from OS_MCA
X * dispatch code which is in turn called from SAL_CHECK().
X * This is the place where the core of OS MCA handling is done.
@@ -487,93 +681,92 @@
X * monarch processor. Once the monarch is done with MCA handling
X * further MCA logging is enabled by clearing logs.
X * Monarch also has the duty of sending wakeup-IPIs to pull the
- * slave processors out of rendez. spinloop.
- * Inputs
- * None
- * Outputs
- * None
+ * slave processors out of rendezvous spinloop.
+ *
+ * Inputs : None
+ * Outputs : None
X */
X void
X ia64_mca_ucmc_handler(void)
X {
+#if 0 /* stubbed out @FVL */
+ /*
+ * Attempting to log a DBE error Causes "reserved register/field panic"
+ * in printk.
+ */
X
- /* Get the MCA processor log */
- ia64_log_get(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk);
- /* Get the MCA platform log */
- ia64_log_get(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PLATFORM, (prfunc_t)printk);
-
- ia64_log_print(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk);
+ /* Get the MCA error record and log it */
+ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
+#endif /* stubbed out @FVL */
X
X /*
- * Do some error handling - Platform-specific mca handler is called at this point
+ * Do Platform-specific mca error handling if required.
X */
-
X mca_handler_platform() ;
X
- /* Clear the SAL MCA logs */
- ia64_log_clear(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PROCESSOR, 1, printk);
- ia64_log_clear(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PLATFORM, 1, printk);
-
- /* Wakeup all the processors which are spinning in the rendezvous
- * loop.
+ /*
+ * Wakeup all the processors which are spinning in the rendezvous
+ * loop.
X */
X ia64_mca_wakeup_all();
+
+ /* Return to SAL */
X ia64_return_to_sal_check();
X }
X
X /*
X * ia64_mca_cmc_int_handler
- * This is correctable machine check interrupt handler.
+ *
+ * This is corrected machine check interrupt handler.
X * Right now the logs are extracted and displayed in a well-defined
X * format.
+ *
X * Inputs
- * None
+ * interrupt number
+ * client data arg ptr
+ * saved registers ptr
+ *
X * Outputs
X * None
X */
X void
X ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
X {
- /* Get the CMC processor log */
- ia64_log_get(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk);
- /* Get the CMC platform log */
- ia64_log_get(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PLATFORM, (prfunc_t)printk);
-
+ IA64_MCA_DEBUG("ia64_mca_cmc_int_handler: received interrupt vector = %#x on CPU %d\n",
+ cmc_irq, smp_processor_id());
X
- ia64_log_print(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk);
- cmci_handler_platform(cmc_irq, arg, ptregs);
-
- /* Clear the CMC SAL logs now that they have been saved in the OS buffer */
- ia64_sal_clear_state_info(SAL_INFO_TYPE_CMC);
+ /* Get the CMC error record and log it */
+ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC);
X }
X
X /*
X * IA64_MCA log support
X */
X #define IA64_MAX_LOGS 2 /* Double-buffering for nested MCAs */
-#define IA64_MAX_LOG_TYPES 3 /* MCA, CMC, INIT */
-#define IA64_MAX_LOG_SUBTYPES 2 /* Processor, Platform */
+#define IA64_MAX_LOG_TYPES 4 /* MCA, INIT, CMC, CPE */
X
-typedef struct ia64_state_log_s {
+typedef struct ia64_state_log_s
+{
X spinlock_t isl_lock;
X int isl_index;
- ia64_psilog_t isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */
+ ia64_err_rec_t isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */
X } ia64_state_log_t;
X
-static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES][IA64_MAX_LOG_SUBTYPES];
+static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES];
X
-#define IA64_LOG_LOCK_INIT(it, sit) spin_lock_init(&ia64_state_log[it][sit].isl_lock)
-#define IA64_LOG_LOCK(it, sit) spin_lock_irqsave(&ia64_state_log[it][sit].isl_lock, s)
-#define IA64_LOG_UNLOCK(it, sit) spin_unlock_irqrestore(&ia64_state_log[it][sit].isl_lock,\
- s)
-#define IA64_LOG_NEXT_INDEX(it, sit) ia64_state_log[it][sit].isl_index
-#define IA64_LOG_CURR_INDEX(it, sit) 1 - ia64_state_log[it][sit].isl_index
-#define IA64_LOG_INDEX_INC(it, sit) \
- ia64_state_log[it][sit].isl_index = 1 - ia64_state_log[it][sit].isl_index
-#define IA64_LOG_INDEX_DEC(it, sit) \
- ia64_state_log[it][sit].isl_index = 1 - ia64_state_log[it][sit].isl_index
-#define IA64_LOG_NEXT_BUFFER(it, sit) (void *)(&(ia64_state_log[it][sit].isl_log[IA64_LOG_NEXT_INDEX(it,sit)]))
-#define IA64_LOG_CURR_BUFFER(it, sit) (void *)(&(ia64_state_log[it][sit].isl_log[IA64_LOG_CURR_INDEX(it,sit)]))
+/* Note: Some of these macros assume IA64_MAX_LOGS is always 2. Should be */
+/* fixed. @FVL */
+#define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock)
+#define IA64_LOG_LOCK(it) spin_lock_irqsave(&ia64_state_log[it].isl_lock, s)
+#define IA64_LOG_UNLOCK(it) spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s)
+#define IA64_LOG_NEXT_INDEX(it) ia64_state_log[it].isl_index
+#define IA64_LOG_CURR_INDEX(it) 1 - ia64_state_log[it].isl_index
+#define IA64_LOG_INDEX_INC(it) \
+ ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index
+#define IA64_LOG_INDEX_DEC(it) \
+ ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index
+#define IA64_LOG_NEXT_BUFFER(it) (void *)(&(ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)]))
+#define IA64_LOG_CURR_BUFFER(it) (void *)(&(ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)]))
X
X /*
X * C portion of the OS INIT handler
@@ -584,123 +777,217 @@
X *
X * Returns:
X * 0 if SAL must warm boot the System
- * 1 if SAL must retrun to interrupted context using PAL_MC_RESUME
+ * 1 if SAL must return to interrupted context using PAL_MC_RESUME
X *
X */
-
X void
X ia64_init_handler (struct pt_regs *regs)
X {
X sal_log_processor_info_t *proc_ptr;
- ia64_psilog_t *plog_ptr;
+ ia64_err_rec_t *plog_ptr;
X
X printk("Entered OS INIT handler\n");
X
X /* Get the INIT processor log */
- ia64_log_get(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk);
- /* Get the INIT platform log */
- ia64_log_get(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PLATFORM, (prfunc_t)printk);
+ if (!ia64_log_get(SAL_INFO_TYPE_INIT, (prfunc_t)printk))
+ return; // no record retrieved
X
X #ifdef IA64_DUMP_ALL_PROC_INFO
- ia64_log_print(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk);
+ ia64_log_print(SAL_INFO_TYPE_INIT, (prfunc_t)printk);


X #endif
X
X /*

X * get pointer to min state save area
X *
X */
- plog_ptr=(ia64_psilog_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT,
- SAL_SUB_INFO_TYPE_PROCESSOR);
- proc_ptr = &plog_ptr->devlog.proclog;
+ plog_ptr=(ia64_err_rec_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT);
+ proc_ptr = &plog_ptr->proc_err;
X
- ia64_process_min_state_save(&proc_ptr->slpi_min_state_area,regs);
-
- init_handler_platform(regs); /* call platform specific routines */
+ ia64_process_min_state_save(&proc_ptr->processor_static_info.min_state_area,
+ regs);
X
X /* Clear the INIT SAL logs now that they have been saved in the OS buffer */


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

echo 'End of part 030'
echo 'File patch-2.4.15 is continued in part 031'
echo "031" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:08 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part032

#!/bin/sh -x
# this is part 032 of a 115 - part archive


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

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

@@ -52,6 +52,7 @@
X #define PFM_DISABLE 0xa6 /* freeze only */
X #define PFM_RESTART 0xcf
X #define PFM_CREATE_CONTEXT 0xa7
+#define PFM_DESTROY_CONTEXT 0xa8
X /*
X * Those 2 are just meant for debugging. I considered using sysctl() for
X * that but it is a little bit too pervasive. This solution is at least
@@ -60,6 +61,8 @@
X #define PFM_DEBUG_ON 0xe0
X #define PFM_DEBUG_OFF 0xe1
X
+#define PFM_DEBUG_BASE PFM_DEBUG_ON
+
X
X /*
X * perfmon API flags
@@ -68,7 +71,8 @@
X #define PFM_FL_INHERIT_ONCE 0x01 /* clone pfm_context only once across fork() */
X #define PFM_FL_INHERIT_ALL 0x02 /* always clone pfm_context across fork() */
X #define PFM_FL_SMPL_OVFL_NOBLOCK 0x04 /* do not block on sampling buffer overflow */
-#define PFM_FL_SYSTEMWIDE 0x08 /* create a systemwide context */
+#define PFM_FL_SYSTEM_WIDE 0x08 /* create a system wide context */
+#define PFM_FL_EXCL_INTR 0x10 /* exclude interrupt from system wide monitoring */
X
X /*
X * PMC API flags
@@ -87,7 +91,7 @@
X #endif
X
X #define PMC_IS_IMPL(i) (i < pmu_conf.num_pmcs && pmu_conf.impl_regs[i>>6] & (1<< (i&~(64-1))))
-#define PMD_IS_IMPL(i) (i < pmu_conf.num_pmds && pmu_conf.impl_regs[4+(i>>6)] & (1<< (i&~(64-1))))
+#define PMD_IS_IMPL(i) (i < pmu_conf.num_pmds && pmu_conf.impl_regs[4+(i>>6)] & (1<< (i&~(64-1))))
X #define PMD_IS_COUNTER(i) (i>=PMU_FIRST_COUNTER && i < (PMU_FIRST_COUNTER+pmu_conf.max_counters))
X #define PMC_IS_COUNTER(i) (i>=PMU_FIRST_COUNTER && i < (PMU_FIRST_COUNTER+pmu_conf.max_counters))
X
@@ -197,7 +201,8 @@
X unsigned int noblock:1; /* block/don't block on overflow with notification */
X unsigned int system:1; /* do system wide monitoring */
X unsigned int frozen:1; /* pmu must be kept frozen on ctxsw in */
- unsigned int reserved:27;
+ unsigned int exclintr:1;/* exlcude interrupts from system wide monitoring */
+ unsigned int reserved:26;
X } pfm_context_flags_t;
X
X typedef struct pfm_context {
@@ -207,26 +212,33 @@
X unsigned long ctx_iear_counter; /* which PMD holds I-EAR */
X unsigned long ctx_btb_counter; /* which PMD holds BTB */
X
- pid_t ctx_notify_pid; /* who to notify on overflow */
- int ctx_notify_sig; /* XXX: SIGPROF or other */
- pfm_context_flags_t ctx_flags; /* block/noblock */
- pid_t ctx_creator; /* pid of creator (debug) */
- unsigned long ctx_ovfl_regs; /* which registers just overflowed (notification) */
- unsigned long ctx_smpl_regs; /* which registers to record on overflow */
+ spinlock_t ctx_notify_lock;
+ pfm_context_flags_t ctx_flags; /* block/noblock */
+ int ctx_notify_sig; /* XXX: SIGPROF or other */
+ struct task_struct *ctx_notify_task; /* who to notify on overflow */
+ struct task_struct *ctx_creator; /* pid of creator (debug) */
+
+ unsigned long ctx_ovfl_regs; /* which registers just overflowed (notification) */
+ unsigned long ctx_smpl_regs; /* which registers to record on overflow */
+
+ struct semaphore ctx_restart_sem; /* use for blocking notification mode */
X
- struct semaphore ctx_restart_sem; /* use for blocking notification mode */
+ unsigned long ctx_used_pmds[4]; /* bitmask of used PMD (speedup ctxsw) */
+ unsigned long ctx_used_pmcs[4]; /* bitmask of used PMC (speedup ctxsw) */
X
X pfm_counter_t ctx_pmds[IA64_NUM_PMD_COUNTERS]; /* XXX: size should be dynamic */
+
X } pfm_context_t;
X
+#define CTX_USED_PMD(ctx,n) (ctx)->ctx_used_pmds[(n)>>6] |= 1<< ((n) % 64)
+#define CTX_USED_PMC(ctx,n) (ctx)->ctx_used_pmcs[(n)>>6] |= 1<< ((n) % 64)
+
X #define ctx_fl_inherit ctx_flags.inherit
X #define ctx_fl_noblock ctx_flags.noblock
X #define ctx_fl_system ctx_flags.system
X #define ctx_fl_frozen ctx_flags.frozen
+#define ctx_fl_exclintr ctx_flags.exclintr
X
-#define CTX_IS_DEAR(c,n) ((c)->ctx_dear_counter == (n))
-#define CTX_IS_IEAR(c,n) ((c)->ctx_iear_counter == (n))
-#define CTX_IS_BTB(c,n) ((c)->ctx_btb_counter == (n))
X #define CTX_OVFL_NOBLOCK(c) ((c)->ctx_fl_noblock == 1)
X #define CTX_INHERIT_MODE(c) ((c)->ctx_fl_inherit)
X #define CTX_HAS_SMPL(c) ((c)->ctx_smpl_buf != NULL)
@@ -234,17 +246,15 @@
X static pmu_config_t pmu_conf;
X
X /* for debug only */
-static unsigned long pfm_debug=0; /* 0= nodebug, >0= debug output on */
+static int pfm_debug=0; /* 0= nodebug, >0= debug output on */
+
X #define DBprintk(a) \
X do { \
- if (pfm_debug >0) { printk(__FUNCTION__" "); printk a; } \
+ if (pfm_debug >0) { printk(__FUNCTION__" %d: ", __LINE__); printk a; } \
X } while (0);
X
-static void perfmon_softint(unsigned long ignored);
X static void ia64_reset_pmu(void);
X
-DECLARE_TASKLET(pfm_tasklet, perfmon_softint, 0);
-
X /*
X * structure used to pass information between the interrupt handler
X * and the tasklet.
@@ -256,26 +266,42 @@
X unsigned long bitvect; /* which counters have overflowed */
X } notification_info_t;
X
-#define notification_is_invalid(i) (i->to_pid < 2)
X
-/* will need to be cache line padded */
-static notification_info_t notify_info[NR_CPUS];
+typedef struct {
+ unsigned long pfs_proc_sessions;
+ unsigned long pfs_sys_session; /* can only be 0/1 */
+ unsigned long pfs_dfl_dcr; /* XXX: hack */
+ unsigned int pfs_pp;
+} pfm_session_t;
X
-/*
- * We force cache line alignment to avoid false sharing
- * given that we have one entry per CPU.
- */
-static struct {
+struct {
X struct task_struct *owner;
X } ____cacheline_aligned pmu_owners[NR_CPUS];
-/* helper macros */
+
+
+/*
+ * helper macros
+ */
X #define SET_PMU_OWNER(t) do { pmu_owners[smp_processor_id()].owner = (t); } while(0);
X #define PMU_OWNER() pmu_owners[smp_processor_id()].owner
X
+#ifdef CONFIG_SMP
+#define PFM_CAN_DO_LAZY() (smp_num_cpus==1 && pfs_info.pfs_sys_session==0)
+#else
+#define PFM_CAN_DO_LAZY() (pfs_info.pfs_sys_session==0)
+#endif
+
+static void pfm_lazy_save_regs (struct task_struct *ta);
+
X /* for debug only */
X static struct proc_dir_entry *perfmon_dir;
X
X /*
+ * XXX: hack to indicate that a system wide monitoring session is active
+ */
+static pfm_session_t pfs_info;
+
+/*
X * finds the number of PM(C|D) registers given
X * the bitvector returned by PAL
X */
@@ -339,8 +365,7 @@
X static inline unsigned long
X kvirt_to_pa(unsigned long adr)
X {
- __u64 pa;
- __asm__ __volatile__ ("tpa %0 = %1" : "=r"(pa) : "r"(adr) : "memory");
+ __u64 pa = ia64_tpa(adr);
X DBprintk(("kv2pa(%lx-->%lx)\n", adr, pa));
X return pa;
X }
@@ -568,25 +593,44 @@
X static int
X pfx_is_sane(pfreq_context_t *pfx)
X {
+ int ctx_flags;
+
X /* valid signal */
- if (pfx->notify_sig < 1 || pfx->notify_sig >= _NSIG) return 0;
+ //if (pfx->notify_sig < 1 || pfx->notify_sig >= _NSIG) return -EINVAL;
+ if (pfx->notify_sig !=0 && pfx->notify_sig != SIGPROF) return -EINVAL;
X
X /* cannot send to process 1, 0 means do not notify */
- if (pfx->notify_pid < 0 || pfx->notify_pid == 1) return 0;
+ if (pfx->notify_pid < 0 || pfx->notify_pid == 1) return -EINVAL;
+
+ ctx_flags = pfx->flags;
X
+ if (ctx_flags & PFM_FL_SYSTEM_WIDE) {
+#ifdef CONFIG_SMP
+ if (smp_num_cpus > 1) {
+ printk("perfmon: system wide monitoring on SMP not yet supported\n");
+ return -EINVAL;
+ }
+#endif
+ if ((ctx_flags & PFM_FL_SMPL_OVFL_NOBLOCK) == 0) {
+ printk("perfmon: system wide monitoring cannot use blocking notification mode\n");


+ return -EINVAL;
+ }
+ }

X /* probably more to add here */
X
- return 1;


+ return 0;
X }
X

X static int
-pfm_context_create(struct task_struct *task, int flags, perfmon_req_t *req)
+pfm_context_create(int flags, perfmon_req_t *req)
X {
X pfm_context_t *ctx;
+ struct task_struct *task = NULL;
X perfmon_req_t tmp;
X void *uaddr = NULL;
- int ret = -EFAULT;
+ int ret;
X int ctx_flags;
+ pid_t pid;
X
X /* to go away */
X if (flags) {
@@ -595,48 +639,156 @@
X
X if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
X
+ ret = pfx_is_sane(&tmp.pfr_ctx);
+ if (ret < 0) return ret;
+
X ctx_flags = tmp.pfr_ctx.flags;
X
- /* not yet supported */
- if (ctx_flags & PFM_FL_SYSTEMWIDE) return -EINVAL;
+ if (ctx_flags & PFM_FL_SYSTEM_WIDE) {
+ /*
+ * XXX: This is not AT ALL SMP safe
+ */
+ if (pfs_info.pfs_proc_sessions > 0) return -EBUSY;
+ if (pfs_info.pfs_sys_session > 0) return -EBUSY;
+
+ pfs_info.pfs_sys_session = 1;
X
- if (!pfx_is_sane(&tmp.pfr_ctx)) return -EINVAL;
+ } else if (pfs_info.pfs_sys_session >0) {
+ /* no per-process monitoring while there is a system wide session */
+ return -EBUSY;
+ } else
+ pfs_info.pfs_proc_sessions++;
X
X ctx = pfm_context_alloc();
- if (!ctx) return -ENOMEM;
+ if (!ctx) goto error;
+
+ /* record the creator (debug only) */
+ ctx->ctx_creator = current;
+
+ pid = tmp.pfr_ctx.notify_pid;
+
+ spin_lock_init(&ctx->ctx_notify_lock);
+
+ if (pid == current->pid) {
+ ctx->ctx_notify_task = task = current;
+ current->thread.pfm_context = ctx;
+
+ atomic_set(&current->thread.pfm_notifiers_check, 1);
+
+ } else if (pid!=0) {
+ read_lock(&tasklist_lock);
+
+ task = find_task_by_pid(pid);
+ if (task) {
+ /*
+ * record who to notify
+ */
+ ctx->ctx_notify_task = task;
+
+ /*
+ * make visible
+ * must be done inside critical section
+ *
+ * if the initialization does not go through it is still
+ * okay because child will do the scan for nothing which
+ * won't hurt.
+ */
+ current->thread.pfm_context = ctx;
+
+ /*
+ * will cause task to check on exit for monitored
+ * processes that would notify it. see release_thread()
+ * Note: the scan MUST be done in release thread, once the
+ * task has been detached from the tasklist otherwise you are
+ * exposed to race conditions.
+ */
+ atomic_add(1, &task->thread.pfm_notifiers_check);
+ }
+ read_unlock(&tasklist_lock);
+ }
X
- /* record who the creator is (for debug) */
- ctx->ctx_creator = task->pid;
+ /*
+ * notification process does not exist
+ */
+ if (pid != 0 && task == NULL) {
+ ret = -EINVAL;
+ goto buffer_error;
+ }
X
- ctx->ctx_notify_pid = tmp.pfr_ctx.notify_pid;
X ctx->ctx_notify_sig = SIGPROF; /* siginfo imposes a fixed signal */
X
X if (tmp.pfr_ctx.smpl_entries) {
X DBprintk((" sampling entries=%ld\n",tmp.pfr_ctx.smpl_entries));
- if ((ret=pfm_smpl_buffer_alloc(ctx, tmp.pfr_ctx.smpl_regs, tmp.pfr_ctx.smpl_entries, &uaddr)) ) goto buffer_error;
+
+ ret = pfm_smpl_buffer_alloc(ctx, tmp.pfr_ctx.smpl_regs,
+ tmp.pfr_ctx.smpl_entries, &uaddr);
+ if (ret<0) goto buffer_error;
+
X tmp.pfr_ctx.smpl_vaddr = uaddr;
X }
X /* initialization of context's flags */
- ctx->ctx_fl_inherit = ctx_flags & PFM_FL_INHERIT_MASK;
- ctx->ctx_fl_noblock = (ctx_flags & PFM_FL_SMPL_OVFL_NOBLOCK) ? 1 : 0;
- ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEMWIDE) ? 1: 0;
- ctx->ctx_fl_frozen = 0;
+ ctx->ctx_fl_inherit = ctx_flags & PFM_FL_INHERIT_MASK;
+ ctx->ctx_fl_noblock = (ctx_flags & PFM_FL_SMPL_OVFL_NOBLOCK) ? 1 : 0;
+ ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0;
+ ctx->ctx_fl_exclintr = (ctx_flags & PFM_FL_EXCL_INTR) ? 1: 0;
+ ctx->ctx_fl_frozen = 0;
+
+ /*
+ * Keep track of the pmds we want to sample
+ * XXX: may be we don't need to save/restore the DEAR/IEAR pmds
+ * but we do need the BTB for sure. This is because of a hardware
+ * buffer of 1 only for non-BTB pmds.
+ */
+ ctx->ctx_used_pmds[0] = tmp.pfr_ctx.smpl_regs;
+ ctx->ctx_used_pmcs[0] = 1; /* always save/restore PMC[0] */
X
X sema_init(&ctx->ctx_restart_sem, 0); /* init this semaphore to locked */
X
- if (copy_to_user(req, &tmp, sizeof(tmp))) goto buffer_error;
X
- DBprintk((" context=%p, pid=%d notify_sig %d notify_pid=%d\n",(void *)ctx, task->pid, ctx->ctx_notify_sig, ctx->ctx_notify_pid));
- DBprintk((" context=%p, pid=%d flags=0x%x inherit=%d noblock=%d system=%d\n",(void *)ctx, task->pid, ctx_flags, ctx->ctx_fl_inherit, ctx->ctx_fl_noblock, ctx->ctx_fl_system));
+ if (copy_to_user(req, &tmp, sizeof(tmp))) {
+ ret = -EFAULT;
+ goto buffer_error;
+ }
+
+ DBprintk((" context=%p, pid=%d notify_sig %d notify_task=%p\n",(void *)ctx, current->pid, ctx->ctx_notify_sig, ctx->ctx_notify_task));
+ DBprintk((" context=%p, pid=%d flags=0x%x inherit=%d noblock=%d system=%d\n",(void *)ctx, current->pid, ctx_flags, ctx->ctx_fl_inherit, ctx->ctx_fl_noblock, ctx->ctx_fl_system));
+
+ /*
+ * when no notification is required, we can make this visible at the last moment
+ */
+ if (pid == 0) current->thread.pfm_context = ctx;
+
+ /*
+ * by default, we always include interrupts for system wide
+ * DCR.pp is set by default to zero by kernel in cpu_init()
+ */
+ if (ctx->ctx_fl_system) {
+ if (ctx->ctx_fl_exclintr == 0) {
+ unsigned long dcr = ia64_get_dcr();
+
+ ia64_set_dcr(dcr|IA64_DCR_PP);
+ /*
+ * keep track of the kernel default value
+ */
+ pfs_info.pfs_dfl_dcr = dcr;
X
- /* link with task */
- task->thread.pfm_context = ctx;
+ DBprintk((" dcr.pp is set\n"));
+ }
+ }
X
X return 0;
X
X buffer_error:
- vfree(ctx);
-
+ pfm_context_free(ctx);
+error:
+ /*
+ * undo session reservation
+ */
+ if (ctx_flags & PFM_FL_SYSTEM_WIDE) {
+ pfs_info.pfs_sys_session = 0;
+ } else {
+ pfs_info.pfs_proc_sessions--;
+ }


X return ret;
X }
X

@@ -656,8 +808,20 @@
X
X /* upper part is ignored on rval */
X ia64_set_pmd(cnum, ctx->ctx_pmds[i].smpl_rval);
+
+ /*
+ * we must reset BTB index (clears pmd16.full to make
+ * sure we do not report the same branches twice.
+ * The non-blocking case in handled in update_counters()
+ */
+ if (cnum == ctx->ctx_btb_counter) {
+ DBprintk(("reseting PMD16\n"));
+ ia64_set_pmd(16, 0);
+ }
X }
X }
+ /* just in case ! */
+ ctx->ctx_ovfl_regs = 0;


X }
X
X static int

@@ -695,20 +859,23 @@
X } else if (PMC_IS_BTB(&tmp.pfr_reg.reg_value)) {
X ctx->ctx_btb_counter = cnum;
X }
-
+#if 0
X if (tmp.pfr_reg.reg_flags & PFM_REGFL_OVFL_NOTIFY)
X ctx->ctx_pmds[cnum - PMU_FIRST_COUNTER].flags |= PFM_REGFL_OVFL_NOTIFY;
+#endif
X }
-
+ /* keep track of what we use */
+ CTX_USED_PMC(ctx, cnum);
X ia64_set_pmc(cnum, tmp.pfr_reg.reg_value);
- DBprintk((" setting PMC[%ld]=0x%lx flags=0x%x\n", cnum, tmp.pfr_reg.reg_value, ctx->ctx_pmds[cnum - PMU_FIRST_COUNTER].flags));
+
+ DBprintk((" setting PMC[%ld]=0x%lx flags=0x%x used_pmcs=0%lx\n", cnum, tmp.pfr_reg.reg_value, ctx->ctx_pmds[cnum - PMU_FIRST_COUNTER].flags, ctx->ctx_used_pmcs[0]));
X
X }
X /*
X * we have to set this here event hough we haven't necessarily started monitoring
X * because we may be context switched out
X */
- th->flags |= IA64_THREAD_PM_VALID;
+ if (ctx->ctx_fl_system==0) th->flags |= IA64_THREAD_PM_VALID;


X
X return 0;
X }

@@ -741,25 +908,32 @@
X ctx->ctx_pmds[k].val = tmp.pfr_reg.reg_value & ~pmu_conf.perf_ovfl_val;
X ctx->ctx_pmds[k].smpl_rval = tmp.pfr_reg.reg_smpl_reset;
X ctx->ctx_pmds[k].ovfl_rval = tmp.pfr_reg.reg_ovfl_reset;
+
+ if (tmp.pfr_reg.reg_flags & PFM_REGFL_OVFL_NOTIFY)
+ ctx->ctx_pmds[cnum - PMU_FIRST_COUNTER].flags |= PFM_REGFL_OVFL_NOTIFY;
X }
+ /* keep track of what we use */
+ CTX_USED_PMD(ctx, cnum);
X
X /* writes to unimplemented part is ignored, so this is safe */
X ia64_set_pmd(cnum, tmp.pfr_reg.reg_value);
X
X /* to go away */
X ia64_srlz_d();
- DBprintk((" setting PMD[%ld]: pmd.val=0x%lx pmd.ovfl_rval=0x%lx pmd.smpl_rval=0x%lx pmd=%lx\n",
+ DBprintk((" setting PMD[%ld]: ovfl_notify=%d pmd.val=0x%lx pmd.ovfl_rval=0x%lx pmd.smpl_rval=0x%lx pmd=%lx used_pmds=0%lx\n",
X cnum,
+ PMD_OVFL_NOTIFY(ctx, cnum - PMU_FIRST_COUNTER),
X ctx->ctx_pmds[k].val,
X ctx->ctx_pmds[k].ovfl_rval,
X ctx->ctx_pmds[k].smpl_rval,
- ia64_get_pmd(cnum) & pmu_conf.perf_ovfl_val));
+ ia64_get_pmd(cnum) & pmu_conf.perf_ovfl_val,
+ ctx->ctx_used_pmds[0]));
X }
X /*
X * we have to set this here event hough we haven't necessarily started monitoring
X * because we may be context switched out
X */
- th->flags |= IA64_THREAD_PM_VALID;
+ if (ctx->ctx_fl_system==0) th->flags |= IA64_THREAD_PM_VALID;


X
X return 0;
X }

@@ -783,6 +957,8 @@
X /* XXX: ctx locking may be required here */
X
X for (i = 0; i < count; i++, req++) {
+ unsigned long reg_val = ~0, ctx_val = ~0;
+
X if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
X
X if (!PMD_IS_IMPL(tmp.pfr_reg.reg_num)) return -EINVAL;
@@ -791,23 +967,25 @@
X if (ta == current){
X val = ia64_get_pmd(tmp.pfr_reg.reg_num);
X } else {
- val = th->pmd[tmp.pfr_reg.reg_num];
+ val = reg_val = th->pmd[tmp.pfr_reg.reg_num];
X }
X val &= pmu_conf.perf_ovfl_val;
X /*
X * lower part of .val may not be zero, so we must be an addition because of
X * residual count (see update_counters).
X */
- val += ctx->ctx_pmds[tmp.pfr_reg.reg_num - PMU_FIRST_COUNTER].val;
+ val += ctx_val = ctx->ctx_pmds[tmp.pfr_reg.reg_num - PMU_FIRST_COUNTER].val;
X } else {
X /* for now */
X if (ta != current) return -EINVAL;
X
+ ia64_srlz_d();
X val = ia64_get_pmd(tmp.pfr_reg.reg_num);
X }
X tmp.pfr_reg.reg_value = val;
X
- DBprintk((" reading PMD[%ld]=0x%lx\n", tmp.pfr_reg.reg_num, val));
+ DBprintk((" reading PMD[%ld]=0x%lx reg=0x%lx ctx_val=0x%lx pmc=0x%lx\n",
+ tmp.pfr_reg.reg_num, val, reg_val, ctx_val, ia64_get_pmc(tmp.pfr_reg.reg_num)));
X
X if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT;
X }
@@ -822,7 +1000,7 @@
X void *sem = &ctx->ctx_restart_sem;
X
X if (task == current) {
- DBprintk((" restartig self %d frozen=%d \n", current->pid, ctx->ctx_fl_frozen));
+ DBprintk((" restarting self %d frozen=%d \n", current->pid, ctx->ctx_fl_frozen));
X
X pfm_reset_regs(ctx);
X
@@ -871,6 +1049,23 @@


X return 0;
X }
X

+/*
+ * system-wide mode: propagate activation/desactivation throughout the tasklist
+ *
+ * XXX: does not work for SMP, of course
+ */
+static void
+pfm_process_tasklist(int cmd)
+{
+ struct task_struct *p;
+ struct pt_regs *regs;
+
+ for_each_task(p) {
+ regs = (struct pt_regs *)((unsigned long)p + IA64_STK_OFFSET);
+ regs--;
+ ia64_psr(regs)->pp = cmd;
+ }
+}
X
X static int
X do_perfmonctl (struct task_struct *task, int cmd, int flags, perfmon_req_t *req, int count, struct pt_regs *regs)
@@ -881,19 +1076,26 @@
X
X memset(&tmp, 0, sizeof(tmp));
X
+ if (ctx == NULL && cmd != PFM_CREATE_CONTEXT && cmd < PFM_DEBUG_BASE) {
+ DBprintk((" PFM_WRITE_PMCS: no context for task %d\n", task->pid));


+ return -EINVAL;
+ }
+

X switch (cmd) {
X case PFM_CREATE_CONTEXT:
X /* a context has already been defined */
X if (ctx) return -EBUSY;
X
- /* may be a temporary limitation */
+ /*
+ * cannot directly create a context in another process
+ */
X if (task != current) return -EINVAL;
X
X if (req == NULL || count != 1) return -EINVAL;
X
X if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;
X
- return pfm_context_create(task, flags, req);
+ return pfm_context_create(flags, req);
X
X case PFM_WRITE_PMCS:
X /* we don't quite support this right now */
@@ -901,10 +1103,6 @@
X
X if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;
X
- if (!ctx) {
- DBprintk((" PFM_WRITE_PMCS: no context for task %d\n", task->pid));
- return -EINVAL;
- }
X return pfm_write_pmcs(task, req, count);
X
X case PFM_WRITE_PMDS:
@@ -913,45 +1111,41 @@
X
X if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;
X
- if (!ctx) {
- DBprintk((" PFM_WRITE_PMDS: no context for task %d\n", task->pid));
- return -EINVAL;
- }
X return pfm_write_pmds(task, req, count);
X
X case PFM_START:
X /* we don't quite support this right now */
X if (task != current) return -EINVAL;
X
- if (!ctx) {
- DBprintk((" PFM_START: no context for task %d\n", task->pid));
- return -EINVAL;
- }
+ if (PMU_OWNER() && PMU_OWNER() != current && PFM_CAN_DO_LAZY()) pfm_lazy_save_regs(PMU_OWNER());
X
X SET_PMU_OWNER(current);
X
X /* will start monitoring right after rfi */
X ia64_psr(regs)->up = 1;
+ ia64_psr(regs)->pp = 1;
+
+ if (ctx->ctx_fl_system) {
+ pfm_process_tasklist(1);
+ pfs_info.pfs_pp = 1;
+ }
X
X /*
X * mark the state as valid.
X * this will trigger save/restore at context switch
X */
- th->flags |= IA64_THREAD_PM_VALID;
+ if (ctx->ctx_fl_system==0) th->flags |= IA64_THREAD_PM_VALID;
X
X ia64_set_pmc(0, 0);
X ia64_srlz_d();
X
- break;
+ break;
X
X case PFM_ENABLE:
X /* we don't quite support this right now */
X if (task != current) return -EINVAL;
X
- if (!ctx) {
- DBprintk((" PFM_ENABLE: no context for task %d\n", task->pid));
- return -EINVAL;
- }
+ if (PMU_OWNER() && PMU_OWNER() != current && PFM_CAN_DO_LAZY()) pfm_lazy_save_regs(PMU_OWNER());
X
X /* reset all registers to stable quiet state */
X ia64_reset_pmu();
@@ -969,7 +1163,7 @@
X * mark the state as valid.
X * this will trigger save/restore at context switch
X */
- th->flags |= IA64_THREAD_PM_VALID;
+ if (ctx->ctx_fl_system==0) th->flags |= IA64_THREAD_PM_VALID;
X
X /* simply unfreeze */
X ia64_set_pmc(0, 0);
@@ -983,54 +1177,41 @@
X /* simply freeze */
X ia64_set_pmc(0, 1);
X ia64_srlz_d();
+ /*
+ * XXX: cannot really toggle IA64_THREAD_PM_VALID
+ * but context is still considered valid, so any
+ * read request would return something valid. Same
+ * thing when this task terminates (pfm_flush_regs()).
+ */
X break;
X
X case PFM_READ_PMDS:
X if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;
X if (!access_ok(VERIFY_WRITE, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;
X
- if (!ctx) {
- DBprintk((" PFM_READ_PMDS: no context for task %d\n", task->pid));
- return -EINVAL;
- }
X return pfm_read_pmds(task, req, count);
X
X case PFM_STOP:
X /* we don't quite support this right now */
X if (task != current) return -EINVAL;
X
- ia64_set_pmc(0, 1);
- ia64_srlz_d();
-
+ /* simply stop monitors, not PMU */
X ia64_psr(regs)->up = 0;
+ ia64_psr(regs)->pp = 0;
X
- th->flags &= ~IA64_THREAD_PM_VALID;
-
- SET_PMU_OWNER(NULL);
-
- /* we probably will need some more cleanup here */
- break;
-
- case PFM_DEBUG_ON:
- printk(" debugging on\n");
- pfm_debug = 1;
- break;
+ if (ctx->ctx_fl_system) {
+ pfm_process_tasklist(0);
+ pfs_info.pfs_pp = 0;
+ }
X
- case PFM_DEBUG_OFF:
- printk(" debugging off\n");
- pfm_debug = 0;
X break;
X
X case PFM_RESTART: /* temporary, will most likely end up as a PFM_ENABLE */
X
- if ((th->flags & IA64_THREAD_PM_VALID) == 0) {
+ if ((th->flags & IA64_THREAD_PM_VALID) == 0 && ctx->ctx_fl_system==0) {
X printk(" PFM_RESTART not monitoring\n");
X return -EINVAL;
X }
- if (!ctx) {
- printk(" PFM_RESTART no ctx for %d\n", task->pid);
- return -EINVAL;
- }
X if (CTX_OVFL_NOBLOCK(ctx) == 0 && ctx->ctx_fl_frozen==0) {
X printk("task %d without pmu_frozen set\n", task->pid);
X return -EINVAL;
@@ -1038,6 +1219,37 @@
X
X return pfm_do_restart(task); /* we only look at first entry */
X
+ case PFM_DESTROY_CONTEXT:
+ /* we don't quite support this right now */
+ if (task != current) return -EINVAL;
+
+ /* first stop monitors */
+ ia64_psr(regs)->up = 0;
+ ia64_psr(regs)->pp = 0;
+
+ /* then freeze PMU */
+ ia64_set_pmc(0, 1);
+ ia64_srlz_d();
+
+ /* don't save/restore on context switch */
+ if (ctx->ctx_fl_system ==0) task->thread.flags &= ~IA64_THREAD_PM_VALID;
+
+ SET_PMU_OWNER(NULL);
+
+ /* now free context and related state */
+ pfm_context_exit(task);
+ break;
+
+ case PFM_DEBUG_ON:
+ printk("perfmon debugging on\n");
+ pfm_debug = 1;
+ break;
+
+ case PFM_DEBUG_OFF:
+ printk("perfmon debugging off\n");
+ pfm_debug = 0;
+ break;
+
X default:
X DBprintk((" UNknown command 0x%x\n", cmd));
X return -EINVAL;
@@ -1074,11 +1286,8 @@
X /* XXX: pid interface is going away in favor of pfm context */
X if (pid != current->pid) {
X read_lock(&tasklist_lock);
- {
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- }
+
+ child = find_task_by_pid(pid);
X
X if (!child) goto abort_call;
X
@@ -1101,93 +1310,44 @@


X return ret;
X }
X

-
-/*
- * This function is invoked on the exit path of the kernel. Therefore it must make sure
- * it does does modify the caller's input registers (in0-in7) in case of entry by system call
- * which can be restarted. That's why it's declared as a system call and all 8 possible args
- * are declared even though not used.
- */
X #if __GNUC__ >= 3
X void asmlinkage
-pfm_overflow_notify(void)
+pfm_block_on_overflow(void)
X #else
X void asmlinkage
-pfm_overflow_notify(u64 arg0, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7)
+pfm_block_on_overflow(u64 arg0, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7)
X #endif
X {
- struct task_struct *task;
X struct thread_struct *th = &current->thread;
X pfm_context_t *ctx = current->thread.pfm_context;
- struct siginfo si;
X int ret;
X
X /*
- * do some sanity checks first
- */
- if (!ctx) {
- printk("perfmon: process %d has no PFM context\n", current->pid);
- return;
- }
- if (ctx->ctx_notify_pid < 2) {
- printk("perfmon: process %d invalid notify_pid=%d\n", current->pid, ctx->ctx_notify_pid);
- return;
- }
-
- DBprintk((" current=%d ctx=%p bv=0%lx\n", current->pid, (void *)ctx, ctx->ctx_ovfl_regs));
- /*
X * NO matter what notify_pid is,
X * we clear overflow, won't notify again
X */
- th->pfm_pend_notify = 0;
+ th->pfm_must_block = 0;
X
X /*
- * When measuring in kernel mode and non-blocking fashion, it is possible to
- * get an overflow while executing this code. Therefore the state of pend_notify
- * and ovfl_regs can be altered. The important point is not to loose any notification.
- * It is fine to get called for nothing. To make sure we do collect as much state as
- * possible, update_counters() always uses |= to add bit to the ovfl_regs field.
- *
- * In certain cases, it is possible to come here, with ovfl_regs == 0;
- *
- * XXX: pend_notify and ovfl_regs could be merged maybe !
+ * do some sanity checks first
X */
- if (ctx->ctx_ovfl_regs == 0) {
- printk("perfmon: spurious overflow notification from pid %d\n", current->pid);
+ if (!ctx) {
+ printk("perfmon: process %d has no PFM context\n", current->pid);
X return;
X }
- read_lock(&tasklist_lock);
-
- task = find_task_by_pid(ctx->ctx_notify_pid);
-
- if (task) {
- si.si_signo = ctx->ctx_notify_sig;
- si.si_errno = 0;
- si.si_code = PROF_OVFL; /* goes to user */
- si.si_addr = NULL;
- si.si_pid = current->pid; /* who is sending */
- si.si_pfm_ovfl = ctx->ctx_ovfl_regs;
-
- DBprintk((" SIGPROF to %d @ %p\n", task->pid, (void *)task));
-
- /* must be done with tasklist_lock locked */
- ret = send_sig_info(ctx->ctx_notify_sig, &si, task);
- if (ret != 0) {
- DBprintk((" send_sig_info(process %d, SIGPROF)=%d\n", ctx->ctx_notify_pid, ret));
- task = NULL; /* will cause return */
- }
- } else {
- printk("perfmon: notify_pid %d not found\n", ctx->ctx_notify_pid);
+ if (ctx->ctx_notify_task == 0) {
+ printk("perfmon: process %d has no task to notify\n", current->pid);
+ return;
X }
X
- read_unlock(&tasklist_lock);
+ DBprintk((" current=%d task=%d\n", current->pid, ctx->ctx_notify_task->pid));
X
- /* now that we have released the lock handle error condition */
- if (!task || CTX_OVFL_NOBLOCK(ctx)) {
- /* we clear all pending overflow bits in noblock mode */
- ctx->ctx_ovfl_regs = 0;
+ /* should not happen */
+ if (CTX_OVFL_NOBLOCK(ctx)) {
+ printk("perfmon: process %d non-blocking ctx should not be here\n", current->pid);
X return;
X }
+
X DBprintk((" CPU%d %d before sleep\n", smp_processor_id(), current->pid));
X
X /*
@@ -1211,9 +1371,6 @@
X
X pfm_reset_regs(ctx);
X
- /* now we can clear this mask */
- ctx->ctx_ovfl_regs = 0;
-
X /*
X * Unlock sampling buffer and reset index atomically
X * XXX: not really needed when blocking
@@ -1232,84 +1389,14 @@


X }
X }
X
-static void

-perfmon_softint(unsigned long ignored)
-{
- notification_info_t *info;
- int my_cpu = smp_processor_id();
- struct task_struct *task;
- struct siginfo si;
-
- info = notify_info+my_cpu;
-
- DBprintk((" CPU%d current=%d to_pid=%d from_pid=%d bv=0x%lx\n", \
- smp_processor_id(), current->pid, info->to_pid, info->from_pid, info->bitvect));
-
- /* assumption check */
- if (info->from_pid == info->to_pid) {
- DBprintk((" Tasklet assumption error: from=%d tor=%d\n", info->from_pid, info->to_pid));
- return;
- }
-
- if (notification_is_invalid(info)) {
- DBprintk((" invalid notification information\n"));
- return;
- }
-
- /* sanity check */
- if (info->to_pid == 1) {
- DBprintk((" cannot notify init\n"));
- return;
- }
- /*
- * XXX: needs way more checks here to make sure we send to a task we have control over
- */
- read_lock(&tasklist_lock);
-
- task = find_task_by_pid(info->to_pid);
-
- DBprintk((" after find %p\n", (void *)task));
-
- if (task) {
- int ret;
-
- si.si_signo = SIGPROF;
- si.si_errno = 0;
- si.si_code = PROF_OVFL; /* goes to user */
- si.si_addr = NULL;
- si.si_pid = info->from_pid; /* who is sending */
- si.si_pfm_ovfl = info->bitvect;
-
- DBprintk((" SIGPROF to %d @ %p\n", task->pid, (void *)task));
-
- /* must be done with tasklist_lock locked */
- ret = send_sig_info(SIGPROF, &si, task);
- if (ret != 0)
- DBprintk((" send_sig_info(process %d, SIGPROF)=%d\n", info->to_pid, ret));
-
- /* invalidate notification */
- info->to_pid = info->from_pid = 0;
- info->bitvect = 0;
- }
-
- read_unlock(&tasklist_lock);
-
- DBprintk((" after unlock %p\n", (void *)task));
-
- if (!task) {
- printk("perfmon: CPU%d cannot find process %d\n", smp_processor_id(), info->to_pid);
- }
-}
-
X /*
X * main overflow processing routine.
X * it can be called from the interrupt path or explicitely during the context switch code
X * Return:
- * 0 : do not unfreeze the PMU
- * 1 : PMU can be unfrozen
+ * new value of pmc[0]. if 0x0 then unfreeze, else keep frozen
X */
-static unsigned long
-update_counters (struct task_struct *ta, u64 pmc0, struct pt_regs *regs)
+unsigned long
+update_counters (struct task_struct *task, u64 pmc0, struct pt_regs *regs)
X {
X unsigned long mask, i, cnum;
X struct thread_struct *th;
@@ -1317,7 +1404,9 @@
X unsigned long bv = 0;
X int my_cpu = smp_processor_id();
X int ret = 1, buffer_is_full = 0;
- int ovfl_is_smpl, can_notify, need_reset_pmd16=0;
+ int ovfl_has_long_recovery, can_notify, need_reset_pmd16=0;
+ struct siginfo si;
+
X /*
X * It is never safe to access the task for which the overflow interrupt is destinated
X * using the current variable as the interrupt may occur in the middle of a context switch
@@ -1331,23 +1420,23 @@
X * valid one, i.e. the one that caused the interrupt.
X */
X
- if (ta == NULL) {
+ if (task == NULL) {
X DBprintk((" owners[%d]=NULL\n", my_cpu));
X return 0x1;
X }
- th = &ta->thread;
+ th = &task->thread;
X ctx = th->pfm_context;
X
X /*
X * XXX: debug test
X * Don't think this could happen given upfront tests
X */
- if ((th->flags & IA64_THREAD_PM_VALID) == 0) {
- printk("perfmon: Spurious overflow interrupt: process %d not using perfmon\n", ta->pid);
+ if ((th->flags & IA64_THREAD_PM_VALID) == 0 && ctx->ctx_fl_system == 0) {
+ printk("perfmon: Spurious overflow interrupt: process %d not using perfmon\n", task->pid);
X return 0x1;
X }
X if (!ctx) {
- printk("perfmon: Spurious overflow interrupt: process %d has no PFM context\n", ta->pid);
+ printk("perfmon: Spurious overflow interrupt: process %d has no PFM context\n", task->pid);


X return 0;
X }
X

@@ -1355,16 +1444,21 @@
X * sanity test. Should never happen
X */
X if ((pmc0 & 0x1 )== 0) {
- printk("perfmon: pid %d pmc0=0x%lx assumption error for freeze bit\n", ta->pid, pmc0);
+ printk("perfmon: pid %d pmc0=0x%lx assumption error for freeze bit\n", task->pid, pmc0);
X return 0x0;
X }
X
X mask = pmc0 >> PMU_FIRST_COUNTER;
X
- DBprintk(("pmc0=0x%lx pid=%d\n", pmc0, ta->pid));
-
- DBprintk(("ctx is in %s mode\n", CTX_OVFL_NOBLOCK(ctx) ? "NO-BLOCK" : "BLOCK"));
+ DBprintk(("pmc0=0x%lx pid=%d owner=%d iip=0x%lx, ctx is in %s mode used_pmds=0x%lx used_pmcs=0x%lx\n",
+ pmc0, task->pid, PMU_OWNER()->pid, regs->cr_iip,
+ CTX_OVFL_NOBLOCK(ctx) ? "NO-BLOCK" : "BLOCK",
+ ctx->ctx_used_pmds[0],
+ ctx->ctx_used_pmcs[0]));
X
+ /*
+ * XXX: need to record sample only when an EAR/BTB has overflowed
+ */
X if (CTX_HAS_SMPL(ctx)) {
X pfm_smpl_buffer_desc_t *psb = ctx->ctx_smpl_buf;
X unsigned long *e, m, idx=0;
@@ -1372,11 +1466,15 @@
X int j;
X
X idx = ia64_fetch_and_add(1, &psb->psb_index);
- DBprintk((" trying to record index=%ld entries=%ld\n", idx, psb->psb_entries));
+ DBprintk((" recording index=%ld entries=%ld\n", idx, psb->psb_entries));
X
X /*
X * XXX: there is a small chance that we could run out on index before resetting
X * but index is unsigned long, so it will take some time.....
+ * We use > instead of == because fetch_and_add() is off by one (see below)
+ *
+ * This case can happen in non-blocking mode or with multiple processes.
+ * For non-blocking, we need to reload and continue.
X */
X if (idx > psb->psb_entries) {
X buffer_is_full = 1;
@@ -1388,7 +1486,7 @@
X
X h = (perfmon_smpl_entry_t *)(((char *)psb->psb_addr) + idx*(psb->psb_entry_size));
X
- h->pid = ta->pid;
+ h->pid = task->pid;
X h->cpu = my_cpu;
X h->rate = 0;
X h->ip = regs ? regs->cr_iip : 0x0; /* where did the fault happened */
@@ -1398,6 +1496,7 @@
X h->stamp = perfmon_get_stamp();
X
X e = (unsigned long *)(h+1);
+
X /*
X * selectively store PMDs in increasing index number
X */
@@ -1406,35 +1505,66 @@
X if (PMD_IS_COUNTER(j))
X *e = ctx->ctx_pmds[j-PMU_FIRST_COUNTER].val
X + (ia64_get_pmd(j) & pmu_conf.perf_ovfl_val);
- else
+ else {
X *e = ia64_get_pmd(j); /* slow */
+ }
X DBprintk((" e=%p pmd%d =0x%lx\n", (void *)e, j, *e));
X e++;
X }
X }
- /* make the new entry visible to user, needs to be atomic */
+ /*
+ * make the new entry visible to user, needs to be atomic
+ */
X ia64_fetch_and_add(1, &psb->psb_hdr->hdr_count);
X
X DBprintk((" index=%ld entries=%ld hdr_count=%ld\n", idx, psb->psb_entries, psb->psb_hdr->hdr_count));
-
- /* sampling buffer full ? */
+ /*
+ * sampling buffer full ?
+ */
X if (idx == (psb->psb_entries-1)) {
- bv = mask;
+ /*
+ * will cause notification, cannot be 0
+ */
+ bv = mask << PMU_FIRST_COUNTER;
+
X buffer_is_full = 1;
X
X DBprintk((" sampling buffer full must notify bv=0x%lx\n", bv));
X
- if (!CTX_OVFL_NOBLOCK(ctx)) goto buffer_full;
+ /*
+ * we do not reload here, when context is blocking
+ */
+ if (!CTX_OVFL_NOBLOCK(ctx)) goto no_reload;
+
X /*
X * here, we have a full buffer but we are in non-blocking mode
- * so we need to reloads overflowed PMDs with sampling reset values
- * and restart
+ * so we need to reload overflowed PMDs with sampling reset values
+ * and restart right away.
X */
X }
+ /* FALL THROUGH */
X }
X reload_pmds:
- ovfl_is_smpl = CTX_OVFL_NOBLOCK(ctx) && buffer_is_full;
- can_notify = CTX_HAS_SMPL(ctx) == 0 && ctx->ctx_notify_pid;
+
+ /*
+ * in the case of a non-blocking context, we reload
+ * with the ovfl_rval when no user notification is taking place (short recovery)
+ * otherwise when the buffer is full which requires user interaction) then we use
+ * smpl_rval which is the long_recovery path (disturbance introduce by user execution).
+ *
+ * XXX: implies that when buffer is full then there is always notification.
+ */
+ ovfl_has_long_recovery = CTX_OVFL_NOBLOCK(ctx) && buffer_is_full;
+
+ /*
+ * XXX: CTX_HAS_SMPL() should really be something like CTX_HAS_SMPL() and is activated,i.e.,
+ * one of the PMC is configured for EAR/BTB.
+ *
+ * When sampling, we can only notify when the sampling buffer is full.
+ */
+ can_notify = CTX_HAS_SMPL(ctx) == 0 && ctx->ctx_notify_task;
+
+ DBprintk((" ovfl_has_long_recovery=%d can_notify=%d\n", ovfl_has_long_recovery, can_notify));
X
X for (i = 0, cnum = PMU_FIRST_COUNTER; mask ; cnum++, i++, mask >>= 1) {
X
@@ -1456,7 +1586,7 @@
X DBprintk((" pmod[%ld].val=0x%lx pmd=0x%lx\n", i, ctx->ctx_pmds[i].val, ia64_get_pmd(cnum)&pmu_conf.perf_ovfl_val));
X
X if (can_notify && PMD_OVFL_NOTIFY(ctx, i)) {
- DBprintk((" CPU%d should notify process %d with signal %d\n", my_cpu, ctx->ctx_notify_pid, ctx->ctx_notify_sig));
+ DBprintk((" CPU%d should notify task %p with signal %d\n", my_cpu, ctx->ctx_notify_task, ctx->ctx_notify_sig));
X bv |= 1 << i;
X } else {
X DBprintk((" CPU%d PMD[%ld] overflow, no notification\n", my_cpu, cnum));
@@ -1467,93 +1597,150 @@
X */
X
X /* writes to upper part are ignored, so this is safe */
- if (ovfl_is_smpl) {
- DBprintk((" CPU%d PMD[%ld] reloaded with smpl_val=%lx\n", my_cpu, cnum,ctx->ctx_pmds[i].smpl_rval));
+ if (ovfl_has_long_recovery) {
+ DBprintk((" CPU%d PMD[%ld] reload with smpl_val=%lx\n", my_cpu, cnum,ctx->ctx_pmds[i].smpl_rval));
X ia64_set_pmd(cnum, ctx->ctx_pmds[i].smpl_rval);
X } else {
- DBprintk((" CPU%d PMD[%ld] reloaded with ovfl_val=%lx\n", my_cpu, cnum,ctx->ctx_pmds[i].smpl_rval));
+ DBprintk((" CPU%d PMD[%ld] reload with ovfl_val=%lx\n", my_cpu, cnum,ctx->ctx_pmds[i].smpl_rval));
X ia64_set_pmd(cnum, ctx->ctx_pmds[i].ovfl_rval);
X }
X }
X if (cnum == ctx->ctx_btb_counter) need_reset_pmd16=1;
X }
X /*
- * In case of BTB, overflow
- * we need to reset the BTB index.
+ * In case of BTB overflow we need to reset the BTB index.
X */
X if (need_reset_pmd16) {
X DBprintk(("reset PMD16\n"));
X ia64_set_pmd(16, 0);
X }
-buffer_full:
- /* see pfm_overflow_notify() on details for why we use |= here */
- ctx->ctx_ovfl_regs |= bv;
X
- /* nobody to notify, return and unfreeze */
+no_reload:
+
+ /*
+ * some counters overflowed, but they did not require
+ * user notification, so after having reloaded them above
+ * we simply restart
+ */
X if (!bv) return 0x0;
X
+ ctx->ctx_ovfl_regs = bv; /* keep track of what to reset when unblocking */
+ /*
+ * Now we know that:
+ * - we have some counters which overflowed (contains in bv)
+ * - someone has asked to be notified on overflow.
+ */
+
+
+ /*
+ * If the notification task is still present, then notify_task is non
+ * null. It is clean by that task if it ever exits before we do.
+ */
X
- if (ctx->ctx_notify_pid == ta->pid) {
- struct siginfo si;
+ if (ctx->ctx_notify_task) {
X
X si.si_errno = 0;
X si.si_addr = NULL;
- si.si_pid = ta->pid; /* who is sending */
-
+ si.si_pid = task->pid; /* who is sending */
X
X si.si_signo = ctx->ctx_notify_sig; /* is SIGPROF */
X si.si_code = PROF_OVFL; /* goes to user */
X si.si_pfm_ovfl = bv;


X
X
+
X /*

- * in this case, we don't stop the task, we let it go on. It will
- * necessarily go to the signal handler (if any) when it goes back to
- * user mode.
+ * when the target of the signal is not ourself, we have to be more
+ * careful. The notify_task may being cleared by the target task itself
+ * in release_thread(). We must ensure mutual exclusion here such that
+ * the signal is delivered (even to a dying task) safely.
X */
- DBprintk((" sending %d notification to self %d\n", si.si_signo, ta->pid));
-
X
- /* this call is safe in an interrupt handler */
- ret = send_sig_info(ctx->ctx_notify_sig, &si, ta);
- if (ret != 0)
- printk(" send_sig_info(process %d, SIGPROF)=%d\n", ta->pid, ret);
- /*
- * no matter if we block or not, we keep PMU frozen and do not unfreeze on ctxsw
- */
- ctx->ctx_fl_frozen = 1;
+ if (ctx->ctx_notify_task != current) {
+ /*
+ * grab the notification lock for this task
+ */
+ spin_lock(&ctx->ctx_notify_lock);
X
- } else {
-#if 0
X /*
- * The tasklet is guaranteed to be scheduled for this CPU only
+ * now notify_task cannot be modified until we're done
+ * if NULL, they it got modified while we were in the handler
X */
- notify_info[my_cpu].to_pid = ctx->notify_pid;
- notify_info[my_cpu].from_pid = ta->pid; /* for debug only */
- notify_info[my_cpu].bitvect = bv;
- /* tasklet is inserted and active */
- tasklet_schedule(&pfm_tasklet);
-#endif
+ if (ctx->ctx_notify_task == NULL) {
+ spin_unlock(&ctx->ctx_notify_lock);
+ goto lost_notify;
+ }
X /*
- * stored the vector of overflowed registers for use in notification
- * mark that a notification/blocking is pending (arm the trap)
+ * required by send_sig_info() to make sure the target
+ * task does not disappear on us.
X */
- th->pfm_pend_notify = 1;
+ read_lock(&tasklist_lock);
+ }
+ /*
+ * in this case, we don't stop the task, we let it go on. It will
+ * necessarily go to the signal handler (if any) when it goes back to
+ * user mode.
+ */
+ DBprintk((" %d sending %d notification to %d\n", task->pid, si.si_signo, ctx->ctx_notify_task->pid));
+
+
+ /*
+ * this call is safe in an interrupt handler, so does read_lock() on tasklist_lock
+ */
+ ret = send_sig_info(ctx->ctx_notify_sig, &si, ctx->ctx_notify_task);
+ if (ret != 0) printk(" send_sig_info(process %d, SIGPROF)=%d\n", ctx->ctx_notify_task->pid, ret);
+ /*
+ * now undo the protections in order
+ */
+ if (ctx->ctx_notify_task != current) {
+ read_unlock(&tasklist_lock);
+ spin_unlock(&ctx->ctx_notify_lock);
+ }
X
X /*
- * if we do block, then keep PMU frozen until restart
+ * if we block set the pfm_must_block bit
+ * when in block mode, we can effectively block only when the notified
+ * task is not self, otherwise we would deadlock.
+ * in this configuration, the notification is sent, the task will not
+ * block on the way back to user mode, but the PMU will be kept frozen
+ * until PFM_RESTART.
+ * Note that here there is still a race condition with notify_task
+ * possibly being nullified behind our back, but this is fine because
+ * it can only be changed to NULL which by construction, can only be
+ * done when notify_task != current. So if it was already different
+ * before, changing it to NULL will still maintain this invariant.
+ * Of course, when it is equal to current it cannot change at this point.
X */
- if (!CTX_OVFL_NOBLOCK(ctx)) ctx->ctx_fl_frozen = 1;
+ if (!CTX_OVFL_NOBLOCK(ctx) && ctx->ctx_notify_task != current) {
+ th->pfm_must_block = 1; /* will cause blocking */
+ }
+ } else {
+lost_notify:
+ DBprintk((" notification task has disappeared !\n"));
+ /*
+ * for a non-blocking context, we make sure we do not fall into the pfm_overflow_notify()
+ * trap. Also in the case of a blocking context with lost notify process, then we do not
+ * want to block either (even though it is interruptible). In this case, the PMU will be kept
+ * frozen and the process will run to completion without monitoring enabled.
+ *
+ * Of course, we cannot loose notify process when self-monitoring.
+ */
+ th->pfm_must_block = 0;
X
- DBprintk((" process %d notify ovfl_regs=0x%lx\n", ta->pid, bv));
X }
X /*
- * keep PMU frozen (and overflowed bits cleared) when we have to stop,
- * otherwise return a resume 'value' for PMC[0]
- *
- * XXX: maybe that's enough to get rid of ctx_fl_frozen ?
+ * if we block, we keep the PMU frozen. If non-blocking we restart.
+ * in the case of non-blocking were the notify process is lost, we also
+ * restart.
X */
- DBprintk((" will return pmc0=0x%x\n",ctx->ctx_fl_frozen ? 0x1 : 0x0));
+ if (!CTX_OVFL_NOBLOCK(ctx))
+ ctx->ctx_fl_frozen = 1;
+ else
+ ctx->ctx_fl_frozen = 0;
+
+ DBprintk((" reload pmc0=0x%x must_block=%ld\n",
+ ctx->ctx_fl_frozen ? 0x1 : 0x0, th->pfm_must_block));
+
X return ctx->ctx_fl_frozen ? 0x1 : 0x0;
X }
X
@@ -1595,10 +1782,17 @@
X u64 pmc0 = ia64_get_pmc(0);
X int i;
X
- p += sprintf(p, "PMC[0]=%lx\nPerfmon debug: %s\n", pmc0, pfm_debug ? "On" : "Off");
+ p += sprintf(p, "CPU%d.pmc[0]=%lx\nPerfmon debug: %s\n", smp_processor_id(), pmc0, pfm_debug ? "On" : "Off");
+ p += sprintf(p, "proc_sessions=%lu sys_sessions=%lu\n",
+ pfs_info.pfs_proc_sessions,
+ pfs_info.pfs_sys_session);
+
X for(i=0; i < NR_CPUS; i++) {
- if (cpu_is_online(i))
- p += sprintf(p, "CPU%d.PMU %d\n", i, pmu_owners[i].owner ? pmu_owners[i].owner->pid: 0);
+ if (cpu_is_online(i)) {
+ p += sprintf(p, "CPU%d.pmu_owner: %-6d\n",
+ i,
+ pmu_owners[i].owner ? pmu_owners[i].owner->pid: -1);
+ }
X }
X return p - page;
X }
@@ -1648,8 +1842,8 @@
X }
X pmu_conf.perf_ovfl_val = (1L << pm_info.pal_perf_mon_info_s.width) - 1;
X pmu_conf.max_counters = pm_info.pal_perf_mon_info_s.generic;
- pmu_conf.num_pmds = find_num_pm_regs(pmu_conf.impl_regs);
- pmu_conf.num_pmcs = find_num_pm_regs(&pmu_conf.impl_regs[4]);
+ pmu_conf.num_pmcs = find_num_pm_regs(pmu_conf.impl_regs);
+ pmu_conf.num_pmds = find_num_pm_regs(&pmu_conf.impl_regs[4]);
X
X printk("perfmon: %d bits counters (max value 0x%lx)\n", pm_info.pal_perf_mon_info_s.width, pmu_conf.perf_ovfl_val);
X printk("perfmon: %ld PMC/PMD pairs, %ld PMCs, %ld PMDs\n", pmu_conf.max_counters, pmu_conf.num_pmcs, pmu_conf.num_pmds);
@@ -1681,21 +1875,19 @@
X ia64_srlz_d();
X }
X
-/*
- * XXX: for system wide this function MUST never be called
- */
X void
X pfm_save_regs (struct task_struct *ta)
X {
X struct task_struct *owner;
+ pfm_context_t *ctx;
X struct thread_struct *t;
X u64 pmc0, psr;
+ unsigned long mask;
X int i;
X
- if (ta == NULL) {
- panic(__FUNCTION__" task is NULL\n");
- }
- t = &ta->thread;
+ t = &ta->thread;
+ ctx = ta->thread.pfm_context;
+
X /*
X * We must make sure that we don't loose any potential overflow
X * interrupt while saving PMU context. In this code, external
@@ -1715,7 +1907,7 @@
X * in kernel.
X * By now, we could still have an overflow interrupt in-flight.
X */
- __asm__ __volatile__ ("rum psr.up;;"::: "memory");
+ __asm__ __volatile__ ("rsm psr.up|psr.pp;;"::: "memory");
X
X /*
X * Mark the PMU as not owned
@@ -1744,7 +1936,6 @@
X * next process does not start with monitoring on if not requested
X */
X ia64_set_pmc(0, 1);
- ia64_srlz_d();
X
X /*
X * Check for overflow bits and proceed manually if needed
@@ -1755,94 +1946,111 @@
X * next time the task exits from the kernel.
X */
X if (pmc0 & ~0x1) {
- if (owner != ta) printk(__FUNCTION__" owner=%p task=%p\n", (void *)owner, (void *)ta);
- printk(__FUNCTION__" Warning: pmc[0]=0x%lx explicit call\n", pmc0);
-
- pmc0 = update_counters(owner, pmc0, NULL);
+ update_counters(owner, pmc0, NULL);
X /* we will save the updated version of pmc0 */
X }
-
X /*
X * restore PSR for context switch to save
X */
X __asm__ __volatile__ ("mov psr.l=%0;; srlz.i;;"::"r"(psr): "memory");
X
+ /*
+ * we do not save registers if we can do lazy
+ */
+ if (PFM_CAN_DO_LAZY()) {
+ SET_PMU_OWNER(owner);
+ return;
+ }
X
X /*
X * XXX needs further optimization.
X * Also must take holes into account
X */
- for (i=0; i< pmu_conf.num_pmds; i++) {
- t->pmd[i] = ia64_get_pmd(i);
+ mask = ctx->ctx_used_pmds[0];
+ for (i=0; mask; i++, mask>>=1) {
+ if (mask & 0x1) t->pmd[i] =ia64_get_pmd(i);
X }
X
X /* skip PMC[0], we handle it separately */
- for (i=1; i< pmu_conf.num_pmcs; i++) {
- t->pmc[i] = ia64_get_pmc(i);
+ mask = ctx->ctx_used_pmcs[0]>>1;
+ for (i=1; mask; i++, mask>>=1) {
+ if (mask & 0x1) t->pmc[i] = ia64_get_pmc(i);
X }
-
X /*
X * Throughout this code we could have gotten an overflow interrupt. It is transformed
X * into a spurious interrupt as soon as we give up pmu ownership.
X */
X }
X
-void
-pfm_load_regs (struct task_struct *ta)
+static void
+pfm_lazy_save_regs (struct task_struct *ta)
X {
- struct thread_struct *t = &ta->thread;
- pfm_context_t *ctx = ta->thread.pfm_context;
+ pfm_context_t *ctx;
+ struct thread_struct *t;
+ unsigned long mask;
X int i;
X
+ DBprintk((" on [%d] by [%d]\n", ta->pid, current->pid));
+
+ t = &ta->thread;
+ ctx = ta->thread.pfm_context;
X /*
X * XXX needs further optimization.
X * Also must take holes into account
X */
- for (i=0; i< pmu_conf.num_pmds; i++) {
- ia64_set_pmd(i, t->pmd[i]);
+ mask = ctx->ctx_used_pmds[0];
+ for (i=0; mask; i++, mask>>=1) {
+ if (mask & 0x1) t->pmd[i] =ia64_get_pmd(i);
X }
-
- /* skip PMC[0] to avoid side effects */
- for (i=1; i< pmu_conf.num_pmcs; i++) {
- ia64_set_pmc(i, t->pmc[i]);
+
+ /* skip PMC[0], we handle it separately */
+ mask = ctx->ctx_used_pmcs[0]>>1;
+ for (i=1; mask; i++, mask>>=1) {
+ if (mask & 0x1) t->pmc[i] = ia64_get_pmc(i);
X }
+ SET_PMU_OWNER(NULL);
+}
+
+void
+pfm_load_regs (struct task_struct *ta)
+{
+ struct thread_struct *t = &ta->thread;
+ pfm_context_t *ctx = ta->thread.pfm_context;
+ struct task_struct *owner;
+ unsigned long mask;
+ int i;
+
+ owner = PMU_OWNER();
+ if (owner == ta) goto skip_restore;
+ if (owner) pfm_lazy_save_regs(owner);
X
- /*
- * we first restore ownership of the PMU to the 'soon to be current'
- * context. This way, if, as soon as we unfreeze the PMU at the end
- * of this function, we get an interrupt, we attribute it to the correct
- * task
- */
X SET_PMU_OWNER(ta);
X
-#if 0
- /*
- * check if we had pending overflow before context switching out
- * If so, we invoke the handler manually, i.e. simulate interrupt.
- *
- * XXX: given that we do not use the tasklet anymore to stop, we can
- * move this back to the pfm_save_regs() routine.
- */
- if (t->pmc[0] & ~0x1) {
- /* freeze set in pfm_save_regs() */
- DBprintk((" pmc[0]=0x%lx manual interrupt\n",t->pmc[0]));
- update_counters(ta, t->pmc[0], NULL);
+ mask = ctx->ctx_used_pmds[0];
+ for (i=0; mask; i++, mask>>=1) {
+ if (mask & 0x1) ia64_set_pmd(i, t->pmd[i]);
X }
-#endif
X
+ /* skip PMC[0] to avoid side effects */
+ mask = ctx->ctx_used_pmcs[0]>>1;
+ for (i=1; mask; i++, mask>>=1) {
+ if (mask & 0x1) ia64_set_pmc(i, t->pmc[i]);
+ }
+skip_restore:
X /*
X * unfreeze only when possible
X */
X if (ctx->ctx_fl_frozen == 0) {
X ia64_set_pmc(0, 0);
X ia64_srlz_d();
+ /* place where we potentially (kernel level) start monitoring again */
X }


X }
X
X
X /*

X * This function is called when a thread exits (from exit_thread()).
- * This is a simplified pfm_save_regs() that simply flushes hthe current
+ * This is a simplified pfm_save_regs() that simply flushes the current
X * register state into the save area taking into account any pending
X * overflow. This time no notification is sent because the taks is dying
X * anyway. The inline processing of overflows avoids loosing some counts.
@@ -1933,12 +2141,20 @@
X /* collect latest results */
X ctx->ctx_pmds[i].val += ia64_get_pmd(j) & pmu_conf.perf_ovfl_val;
X
+ /*
+ * now everything is in ctx_pmds[] and we need
+ * to clear the saved context from save_regs() such that
+ * pfm_read_pmds() gets the correct value
+ */
+ ta->thread.pmd[j] = 0;
+
X /* take care of overflow inline */
X if (mask & 0x1) {
X ctx->ctx_pmds[i].val += 1 + pmu_conf.perf_ovfl_val;
X DBprintk((" PMD[%d] overflowed pmd=0x%lx pmds.val=0x%lx\n",
X j, ia64_get_pmd(j), ctx->ctx_pmds[i].val));
X }
+ mask >>=1;
X }
X }
X
@@ -1977,7 +2193,7 @@
X
X /* clears all PMD registers */
X for(i=0;i< pmu_conf.num_pmds; i++) {
- if (PMD_IS_IMPL(i)) ia64_set_pmd(i,0);
+ if (PMD_IS_IMPL(i)) ia64_set_pmd(i,0);
X }
X ia64_srlz_d();
X }
@@ -1986,7 +2202,7 @@
X * task is the newly created task
X */
X int
-pfm_inherit(struct task_struct *task)
+pfm_inherit(struct task_struct *task, struct pt_regs *regs)
X {
X pfm_context_t *ctx = current->thread.pfm_context;
X pfm_context_t *nctx;
@@ -1994,12 +2210,22 @@
X int i, cnum;
X
X /*
+ * bypass completely for system wide
+ */
+ if (pfs_info.pfs_sys_session) {
+ DBprintk((" enabling psr.pp for %d\n", task->pid));
+ ia64_psr(regs)->pp = pfs_info.pfs_pp;


+ return 0;
+ }
+

+ /*
X * takes care of easiest case first
X */
X if (CTX_INHERIT_MODE(ctx) == PFM_FL_INHERIT_NONE) {
X DBprintk((" removing PFM context for %d\n", task->pid));
X task->thread.pfm_context = NULL;
- task->thread.pfm_pend_notify = 0;
+ task->thread.pfm_must_block = 0;
+ atomic_set(&task->thread.pfm_notifiers_check, 0);
X /* copy_thread() clears IA64_THREAD_PM_VALID */
X return 0;
X }
@@ -2009,9 +2235,11 @@
X /* copy content */
X *nctx = *ctx;
X
- if (ctx->ctx_fl_inherit == PFM_FL_INHERIT_ONCE) {
+ if (CTX_INHERIT_MODE(ctx) == PFM_FL_INHERIT_ONCE) {
X nctx->ctx_fl_inherit = PFM_FL_INHERIT_NONE;
+ atomic_set(&task->thread.pfm_notifiers_check, 0);
X DBprintk((" downgrading to INHERIT_NONE for %d\n", task->pid));
+ pfs_info.pfs_proc_sessions++;
X }
X
X /* initialize counters in new context */
@@ -2033,7 +2261,7 @@
X sema_init(&nctx->ctx_restart_sem, 0); /* reset this semaphore to locked */
X
X /* clear pending notification */
- th->pfm_pend_notify = 0;
+ th->pfm_must_block = 0;
X
X /* link with new task */
X th->pfm_context = nctx;
@@ -2052,7 +2280,10 @@


X return 0;
X }
X

-/* called from exit_thread() */
+/*
+ * called from release_thread(), at this point this task is not in the
+ * tasklist anymore
+ */
X void
X pfm_context_exit(struct task_struct *task)
X {
@@ -2068,16 +2299,126 @@
X pfm_smpl_buffer_desc_t *psb = ctx->ctx_smpl_buf;
X
X /* if only user left, then remove */
- DBprintk((" pid %d: task %d sampling psb->refcnt=%d\n", current->pid, task->pid, psb->psb_refcnt.counter));
+ DBprintk((" [%d] [%d] psb->refcnt=%d\n", current->pid, task->pid, psb->psb_refcnt.counter));
X
X if (atomic_dec_and_test(&psb->psb_refcnt) ) {
X rvfree(psb->psb_hdr, psb->psb_size);
X vfree(psb);
- DBprintk((" pid %d: cleaning task %d sampling buffer\n", current->pid, task->pid ));
+ DBprintk((" [%d] cleaning [%d] sampling buffer\n", current->pid, task->pid ));
+ }
+ }
+ DBprintk((" [%d] cleaning [%d] pfm_context @%p\n", current->pid, task->pid, (void *)ctx));
+
+ /*
+ * To avoid getting the notified task scan the entire process list
+ * when it exits because it would have pfm_notifiers_check set, we
+ * decrease it by 1 to inform the task, that one less task is going
+ * to send it notification. each new notifer increases this field by
+ * 1 in pfm_context_create(). Of course, there is race condition between
+ * decreasing the value and the notified task exiting. The danger comes
+ * from the fact that we have a direct pointer to its task structure
+ * thereby bypassing the tasklist. We must make sure that if we have
+ * notify_task!= NULL, the target task is still somewhat present. It may
+ * already be detached from the tasklist but that's okay. Note that it is
+ * okay if we 'miss the deadline' and the task scans the list for nothing,
+ * it will affect performance but not correctness. The correctness is ensured
+ * by using the notify_lock whic prevents the notify_task from changing on us.
+ * Once holdhing this lock, if we see notify_task!= NULL, then it will stay like
+ * that until we release the lock. If it is NULL already then we came too late.
+ */
+ spin_lock(&ctx->ctx_notify_lock);
+
+ if (ctx->ctx_notify_task) {
+ DBprintk((" [%d] [%d] atomic_sub on [%d] notifiers=%u\n", current->pid, task->pid,
+ ctx->ctx_notify_task->pid,
+ atomic_read(&ctx->ctx_notify_task->thread.pfm_notifiers_check)));
+
+ atomic_sub(1, &ctx->ctx_notify_task->thread.pfm_notifiers_check);
+ }
+
+ spin_unlock(&ctx->ctx_notify_lock);
+
+ if (ctx->ctx_fl_system) {
+ /*
+ * if included interrupts (true by default), then reset
+ * to get default value
+ */
+ if (ctx->ctx_fl_exclintr == 0) {
+ /*
+ * reload kernel default DCR value
+ */
+ ia64_set_dcr(pfs_info.pfs_dfl_dcr);
+ DBprintk((" restored dcr to 0x%lx\n", pfs_info.pfs_dfl_dcr));
X }
+ /*
+ * free system wide session slot
+ */
+ pfs_info.pfs_sys_session = 0;
+ } else {
+ pfs_info.pfs_proc_sessions--;
X }
- DBprintk((" pid %d: task %d pfm_context is freed @%p\n", current->pid, task->pid, (void *)ctx));
+
X pfm_context_free(ctx);
+ /*
+ * clean pfm state in thread structure,
+ */
+ task->thread.pfm_context = NULL;
+ task->thread.pfm_must_block = 0;
+ /* pfm_notifiers is cleaned in pfm_cleanup_notifiers() */
+
+}
+
+void
+pfm_cleanup_notifiers(struct task_struct *task)
+{
+ struct task_struct *p;
+ pfm_context_t *ctx;
+
+ DBprintk((" [%d] called\n", task->pid));
+
+ read_lock(&tasklist_lock);
+
+ for_each_task(p) {
+ /*
+ * It is safe to do the 2-step test here, because thread.ctx
+ * is cleaned up only in release_thread() and at that point
+ * the task has been detached from the tasklist which is an
+ * operation which uses the write_lock() on the tasklist_lock
+ * so it cannot run concurrently to this loop. So we have the
+ * guarantee that if we find p and it has a perfmon ctx then
+ * it is going to stay like this for the entire execution of this
+ * loop.
+ */
+ ctx = p->thread.pfm_context;
+
+ DBprintk((" [%d] scanning task [%d] ctx=%p\n", task->pid, p->pid, ctx));
+
+ if (ctx && ctx->ctx_notify_task == task) {
+ DBprintk((" trying for notifier %d in %d\n", task->pid, p->pid));
+ /*
+ * the spinlock is required to take care of a race condition
+ * with the send_sig_info() call. We must make sure that
+ * either the send_sig_info() completes using a valid task,
+ * or the notify_task is cleared before the send_sig_info()
+ * can pick up a stale value. Note that by the time this
+ * function is executed the 'task' is already detached from the
+ * tasklist. The problem is that the notifiers have a direct
+ * pointer to it. It is okay to send a signal to a task in this
+ * stage, it simply will have no effect. But it is better than sending
+ * to a completely destroyed task or worse to a new task using the same


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

echo 'End of part 032'
echo 'File patch-2.4.15 is continued in part 033'
echo "033" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:10 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part034

#!/bin/sh -x
# this is part 034 of a 115 - part archive


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

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

X shr.u count=count,1 // we do 16 bytes per loop
X ;;
@@ -225,7 +224,7 @@
X ;;
X add first2=8,first1
X ;;
-(p9) br.cond.sptk.few do_csum_exit
+(p9) br.cond.sptk .do_csum_exit
X ;;
X nop.m 0
X nop.i 0
@@ -241,7 +240,7 @@
X 2:
X (p16) ld8 word1[0]=[first1],16
X (p16) ld8 word2[0]=[first2],16
- br.ctop.sptk.few 1b
+ br.ctop.sptk 1b
X ;;
X // Since len is a 32-bit value, carry cannot be larger than
X // a 64-bit value.
@@ -263,7 +262,7 @@
X ;;
X (p6) adds result1[0]=1,result1[0]
X ;;
-do_csum_exit:
+.do_csum_exit:
X movl tmp3=0xffffffff
X ;;
X // XXX Fixme
@@ -299,7 +298,7 @@
X ;;
X mov ar.lc=saved_lc
X (p15) shr.u ret0=ret0,64-16 // + shift back to position = swap bytes


- br.ret.sptk.few rp
+ br.ret.sptk.many rp
X

X // I (Jun Nakajima) wrote an equivalent code (see below), but it was
X // not much better than the original. So keep the original there so that
@@ -331,6 +330,6 @@
X //(p15) mux1 ret0=ret0,@rev // reverse word
X // ;;
X //(p15) shr.u ret0=ret0,64-16 // + shift back to position = swap bytes
-// br.ret.sptk.few rp
+// br.ret.sptk.many rp
X
X END(do_csum)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/lib/idiv32.S linux/arch/ia64/lib/idiv32.S
--- v2.4.14/linux/arch/ia64/lib/idiv32.S Mon Oct 9 17:54:56 2000
+++ linux/arch/ia64/lib/idiv32.S Fri Nov 9 14:26:17 2001
@@ -79,5 +79,5 @@
X ;;
X #endif
X getf.sig r8 = f6 // transfer result to result register


- br.ret.sptk rp
+ br.ret.sptk.many rp

X END(NAME)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/lib/idiv64.S linux/arch/ia64/lib/idiv64.S
--- v2.4.14/linux/arch/ia64/lib/idiv64.S Thu Apr 5 12:51:47 2001
+++ linux/arch/ia64/lib/idiv64.S Fri Nov 9 14:26:17 2001
@@ -89,5 +89,5 @@
X #endif
X getf.sig r8 = f17 // transfer result to result register
X ldf.fill f17 = [sp]


- br.ret.sptk rp
+ br.ret.sptk.many rp

X END(NAME)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/lib/memcpy.S linux/arch/ia64/lib/memcpy.S
--- v2.4.14/linux/arch/ia64/lib/memcpy.S Thu Apr 5 12:51:47 2001
+++ linux/arch/ia64/lib/memcpy.S Fri Nov 9 14:26:17 2001
@@ -9,20 +9,14 @@
X * Output:
X * no return value
X *
- * Copyright (C) 2000 Hewlett-Packard Co
- * Copyright (C) 2000 Stephane Eranian <era...@hpl.hp.com>
- * Copyright (C) 2000 David Mosberger-Tang <dav...@hpl.hp.com>
+ * Copyright (C) 2000-2001 Hewlett-Packard Co


+ * Stephane Eranian <era...@hpl.hp.com>
+ * David Mosberger-Tang <dav...@hpl.hp.com>

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

X #include <asm/asmmacro.h>
X
-#if defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC)
-# define BRP(args...) nop.b 0
-#else
-# define BRP(args...) brp.loop.imp args
-#endif
-
X GLOBAL_ENTRY(bcopy)
X .regstk 3,0,0,0
X mov r8=in0
@@ -103,8 +97,8 @@
X cmp.ne p6,p0=t0,r0
X
X mov src=in1 // copy because of rotation
-(p7) br.cond.spnt.few memcpy_short
-(p6) br.cond.spnt.few memcpy_long
+(p7) br.cond.spnt.few .memcpy_short
+(p6) br.cond.spnt.few .memcpy_long
X ;;
X nop.m 0
X ;;
@@ -119,7 +113,7 @@
X 1: { .mib
X (p[0]) ld8 val[0]=[src],8
X nop.i 0
- BRP(1b, 2f)
+ brp.loop.imp 1b, 2f
X }
X 2: { .mfb
X (p[N-1])st8 [dst]=val[N-1],8
@@ -139,14 +133,14 @@
X * issues, we want to avoid read-modify-write of entire words.
X */
X .align 32
-memcpy_short:
+.memcpy_short:
X adds cnt=-1,in2 // br.ctop is repeat/until
X mov ar.ec=MEM_LAT
- BRP(1f, 2f)
+ brp.loop.imp 1f, 2f
X ;;
X mov ar.lc=cnt
X ;;
- nop.m 0
+ nop.m 0
X ;;
X nop.m 0
X nop.i 0
@@ -163,7 +157,7 @@
X 1: { .mib
X (p[0]) ld1 val[0]=[src],1
X nop.i 0
- BRP(1b, 2f)
+ brp.loop.imp 1b, 2f
X } ;;
X 2: { .mfb
X (p[MEM_LAT-1])st1 [dst]=val[MEM_LAT-1],1
@@ -202,7 +196,7 @@
X
X #define LOG_LOOP_SIZE 6
X
-memcpy_long:
+.memcpy_long:
X alloc t3=ar.pfs,3,Nrot,0,Nrot // resize register frame
X and t0=-8,src // t0 = src & ~7
X and t2=7,src // t2 = src & 7
@@ -247,7 +241,7 @@
X mov t4=ip
X } ;;
X and src2=-8,src // align source pointer
- adds t4=memcpy_loops-1b,t4
+ adds t4=.memcpy_loops-1b,t4
X mov ar.ec=N
X
X and t0=7,src // t0 = src & 7
@@ -266,7 +260,7 @@
X mov pr=cnt,0x38 // set (p5,p4,p3) to # of bytes last-word bytes to copy
X mov ar.lc=t2
X ;;
- nop.m 0
+ nop.m 0
X ;;
X nop.m 0
X nop.i 0
@@ -278,7 +272,7 @@
X br.sptk.few b6
X ;;
X
-memcpy_tail:
+.memcpy_tail:
X // At this point, (p5,p4,p3) are set to the number of bytes left to copy (which is
X // less than 8) and t0 contains the last few bytes of the src buffer:
X (p5) st4 [dst]=t0,4
@@ -300,7 +294,7 @@
X 1: { .mib \
X (p[0]) ld8 val[0]=[src2],8; \
X (p[MEM_LAT+3]) shrp w[0]=val[MEM_LAT+3],val[MEM_LAT+4-index],shift; \
- BRP(1b, 2f) \
+ brp.loop.imp 1b, 2f \
X }; \
X 2: { .mfb \
X (p[MEM_LAT+4]) st8 [dst]=w[1],8; \
@@ -311,8 +305,8 @@
X ld8 val[N-1]=[src_end]; /* load last word (may be same as val[N]) */ \
X ;; \
X shrp t0=val[N-1],val[N-index],shift; \
- br memcpy_tail
-memcpy_loops:
+ br .memcpy_tail
+.memcpy_loops:
X COPY(0, 1) /* no point special casing this---it doesn't go any faster without shrp */
X COPY(8, 0)
X COPY(16, 0)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/lib/memset.S linux/arch/ia64/lib/memset.S
--- v2.4.14/linux/arch/ia64/lib/memset.S Thu Apr 5 12:51:47 2001
+++ linux/arch/ia64/lib/memset.S Fri Nov 9 14:26:17 2001
@@ -43,11 +43,11 @@
X
X adds tmp=-1,len // br.ctop is repeat/until
X tbit.nz p6,p0=buf,0 // odd alignment
-(p8) br.ret.spnt.few rp
+(p8) br.ret.spnt.many rp
X
X cmp.lt p7,p0=16,len // if len > 16 then long memset
X mux1 val=val,@brcst // prepare value
-(p7) br.cond.dptk.few long_memset
+(p7) br.cond.dptk .long_memset
X ;;
X mov ar.lc=tmp // initialize lc for small count
X ;; // avoid RAW and WAW on ar.lc
@@ -57,11 +57,11 @@
X ;; // avoid RAW on ar.lc
X mov ar.lc=saved_lc
X mov ar.pfs=saved_pfs
- br.ret.sptk.few rp // end of short memset
+ br.ret.sptk.many rp // end of short memset
X
X // at this point we know we have more than 16 bytes to copy
X // so we focus on alignment
-long_memset:
+.long_memset:
X (p6) st1 [buf]=val,1 // 1-byte aligned
X (p6) adds len=-1,len;; // sync because buf is modified
X tbit.nz p6,p0=buf,1
@@ -80,7 +80,7 @@
X ;;
X cmp.eq p6,p0=r0,cnt
X adds tmp=-1,cnt
-(p6) br.cond.dpnt.few .dotail // we have less than 16 bytes left
+(p6) br.cond.dpnt .dotail // we have less than 16 bytes left
X ;;
X adds buf2=8,buf // setup second base pointer
X mov ar.lc=tmp
@@ -104,5 +104,5 @@
X mov ar.lc=saved_lc
X ;;
X (p6) st1 [buf]=val // only 1 byte left
- br.ret.dptk.few rp
+ br.ret.sptk.many rp
X END(memset)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/lib/strlen.S linux/arch/ia64/lib/strlen.S
--- v2.4.14/linux/arch/ia64/lib/strlen.S Thu Apr 5 12:51:47 2001
+++ linux/arch/ia64/lib/strlen.S Fri Nov 9 14:26:17 2001
@@ -11,7 +11,7 @@
X * does not count the \0
X *
X * Copyright (C) 1999, 2001 Hewlett-Packard Co
- * Copyright (C) 1999 Stephane Eranian <era...@hpl.hp.com>


+ * Stephane Eranian <era...@hpl.hp.com>
X *

X * 09/24/99 S.Eranian add speculation recovery code
X */
@@ -116,7 +116,7 @@
X ld8.s w[0]=[src],8 // speculatively load next to next
X cmp.eq.and p6,p0=8,val1 // p6 = p6 and val1==8
X cmp.eq.and p6,p0=8,val2 // p6 = p6 and mask==8
-(p6) br.wtop.dptk.few 1b // loop until p6 == 0
+(p6) br.wtop.dptk 1b // loop until p6 == 0
X ;;
X //
X // We must return try the recovery code iff
@@ -127,14 +127,14 @@
X //
X cmp.eq p8,p9=8,val1 // p6 = val1 had zero (disambiguate)
X tnat.nz p6,p7=val1 // test NaT on val1
-(p6) br.cond.spnt.few recover// jump to recovery if val1 is NaT
+(p6) br.cond.spnt .recover // jump to recovery if val1 is NaT
X ;;
X //
X // if we come here p7 is true, i.e., initialized for // cmp
X //
X cmp.eq.and p7,p0=8,val1// val1==8?
X tnat.nz.and p7,p0=val2 // test NaT if val2
-(p7) br.cond.spnt.few recover// jump to recovery if val2 is NaT
+(p7) br.cond.spnt .recover // jump to recovery if val2 is NaT
X ;;
X (p8) mov val1=val2 // the other test got us out of the loop
X (p8) adds src=-16,src // correct position when 3 ahead
@@ -146,7 +146,7 @@
X ;;
X sub ret0=ret0,tmp // adjust
X mov ar.pfs=saved_pfs // because of ar.ec, restore no matter what
- br.ret.sptk.few rp // end of normal execution
+ br.ret.sptk.many rp // end of normal execution
X
X //
X // Outlined recovery code when speculation failed
@@ -165,7 +165,7 @@
X // - today we restart from the beginning of the string instead
X // of trying to continue where we left off.
X //
-recover:
+.recover:
X ld8 val=[base],8 // will fail if unrecoverable fault
X ;;
X or val=val,mask // remask first bytes
@@ -180,7 +180,7 @@
X czx1.r val1=val // search 0 byte from right
X ;;
X cmp.eq p6,p0=8,val1 // val1==8 ?
-(p6) br.wtop.dptk.few 2b // loop until p6 == 0
+(p6) br.wtop.dptk 2b // loop until p6 == 0
X ;; // (avoid WAW on p63)
X sub ret0=base,orig // distance from base
X sub tmp=8,val1
@@ -188,5 +188,5 @@
X ;;
X sub ret0=ret0,tmp // length=now - back -1
X mov ar.pfs=saved_pfs // because of ar.ec, restore no matter what
- br.ret.sptk.few rp // end of successful recovery code
+ br.ret.sptk.many rp // end of successful recovery code
X END(strlen)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/lib/strlen_user.S linux/arch/ia64/lib/strlen_user.S
--- v2.4.14/linux/arch/ia64/lib/strlen_user.S Thu Apr 5 12:51:47 2001
+++ linux/arch/ia64/lib/strlen_user.S Fri Nov 9 14:26:17 2001
@@ -8,8 +8,8 @@
X * ret0 0 in case of fault, strlen(buffer)+1 otherwise
X *
X * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
- * Copyright (C) 1998, 1999, 2001 David Mosberger-Tang <dav...@hpl.hp.com>


- * Copyright (C) 1998, 1999 Stephane Eranian <era...@hpl.hp.com>

+ * David Mosberger-Tang <dav...@hpl.hp.com>
+ * Stephane Eranian <era...@hpl.hp.com>

X *
X * 01/19/99 S.Eranian heavily enhanced version (see details below)
X * 09/24/99 S.Eranian added speculation recovery code
@@ -108,7 +108,7 @@
X mov ar.ec=r0 // clear epilogue counter (saved in ar.pfs)
X ;;
X add base=-16,src // keep track of aligned base
- chk.s v[1], recover // if already NaT, then directly skip to recover
+ chk.s v[1], .recover // if already NaT, then directly skip to recover
X or v[1]=v[1],mask // now we have a safe initial byte pattern
X ;;
X 1:
@@ -130,14 +130,14 @@
X //
X cmp.eq p8,p9=8,val1 // p6 = val1 had zero (disambiguate)
X tnat.nz p6,p7=val1 // test NaT on val1
-(p6) br.cond.spnt.few recover// jump to recovery if val1 is NaT
+(p6) br.cond.spnt .recover // jump to recovery if val1 is NaT
X ;;
X //
X // if we come here p7 is true, i.e., initialized for // cmp
X //
X cmp.eq.and p7,p0=8,val1// val1==8?
X tnat.nz.and p7,p0=val2 // test NaT if val2
-(p7) br.cond.spnt.few recover// jump to recovery if val2 is NaT
+(p7) br.cond.spnt .recover // jump to recovery if val2 is NaT
X ;;
X (p8) mov val1=val2 // val2 contains the value
X (p8) adds src=-16,src // correct position when 3 ahead
@@ -149,7 +149,7 @@
X ;;
X sub ret0=ret0,tmp // length=now - back -1
X mov ar.pfs=saved_pfs // because of ar.ec, restore no matter what
- br.ret.sptk.few rp // end of normal execution
+ br.ret.sptk.many rp // end of normal execution
X
X //
X // Outlined recovery code when speculation failed
@@ -162,7 +162,7 @@
X // - today we restart from the beginning of the string instead
X // of trying to continue where we left off.
X //
-recover:
+.recover:
X EX(.Lexit1, ld8 val=[base],8) // load the initial bytes
X ;;
X or val=val,mask // remask first bytes
@@ -185,7 +185,7 @@
X ;;
X sub ret0=ret0,tmp // length=now - back -1
X mov ar.pfs=saved_pfs // because of ar.ec, restore no matter what
- br.ret.sptk.few rp // end of successful recovery code
+ br.ret.sptk.many rp // end of successful recovery code
X
X //
X // We failed even on the normal load (called from exception handler)
@@ -194,5 +194,5 @@
X mov ret0=0
X mov pr=saved_pr,0xffffffffffff0000
X mov ar.pfs=saved_pfs // because of ar.ec, restore no matter what


- br.ret.sptk.few rp
+ br.ret.sptk.many rp

X END(__strlen_user)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/lib/strncpy_from_user.S linux/arch/ia64/lib/strncpy_from_user.S
--- v2.4.14/linux/arch/ia64/lib/strncpy_from_user.S Thu Apr 5 12:51:47 2001
+++ linux/arch/ia64/lib/strncpy_from_user.S Fri Nov 9 14:26:17 2001
@@ -40,5 +40,5 @@
X (p6) mov r8=in2 // buffer filled up---return buffer length
X (p7) sub r8=in1,r9,1 // return string length (excluding NUL character)
X [.Lexit:]


- br.ret.sptk.few rp
+ br.ret.sptk.many rp

X END(__strncpy_from_user)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/lib/strnlen_user.S linux/arch/ia64/lib/strnlen_user.S
--- v2.4.14/linux/arch/ia64/lib/strnlen_user.S Thu Apr 5 12:51:47 2001
+++ linux/arch/ia64/lib/strnlen_user.S Fri Nov 9 14:26:17 2001
@@ -33,7 +33,7 @@
X add r9=1,r9
X ;;
X cmp.eq p6,p0=r8,r0
-(p6) br.dpnt.few .Lexit
+(p6) br.cond.dpnt .Lexit
X br.cloop.dptk.few .Loop1
X
X add r9=1,in1 // NUL not found---return N+1
@@ -41,5 +41,5 @@
X .Lexit:
X mov r8=r9
X mov ar.lc=r16 // restore ar.lc


- br.ret.sptk.few rp
+ br.ret.sptk.many rp

X END(__strnlen_user)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/lib/swiotlb.c linux/arch/ia64/lib/swiotlb.c
--- v2.4.14/linux/arch/ia64/lib/swiotlb.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/lib/swiotlb.c Tue Nov 13 09:01:16 2001
@@ -27,6 +27,10 @@
X #define ALIGN(val, align) ((unsigned long) \
X (((unsigned long) (val) + ((align) - 1)) & ~((align) - 1)))
X
+#define SG_ENT_VIRT_ADDRESS(sg) ((sg)->address ? (sg)->address \
+ : page_address((sg)->page) + (sg)->offset)
+#define SG_ENT_PHYS_ADDRESS(SG) virt_to_phys(SG_ENT_VIRT_ADDRESS(SG))
+
X /*
X * log of the size of each IO TLB slab. The number of slabs is command line controllable.
X */
@@ -392,15 +396,20 @@
X int
X swiotlb_map_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction)
X {
+ void *addr;
X int i;
X
X if (direction == PCI_DMA_NONE)
X BUG();
X
X for (i = 0; i < nelems; i++, sg++) {
- sg->orig_address = sg->address;
- if ((virt_to_phys(sg->address) & ~hwdev->dma_mask) != 0) {
- sg->address = map_single(hwdev, sg->address, sg->length, direction);
+ sg->orig_address = SG_ENT_VIRT_ADDRESS(sg);
+ if ((SG_ENT_PHYS_ADDRESS(sg) & ~hwdev->dma_mask) != 0) {
+ addr = map_single(hwdev, sg->address, sg->length, direction);
+ if (sg->address)
+ sg->address = addr;
+ else
+ sg->page = virt_to_page(addr);
X }
X }
X return nelems;
@@ -419,9 +428,12 @@
X BUG();
X
X for (i = 0; i < nelems; i++, sg++)
- if (sg->orig_address != sg->address) {
- unmap_single(hwdev, sg->address, sg->length, direction);
- sg->address = sg->orig_address;
+ if (sg->orig_address != SG_ENT_VIRT_ADDRESS(sg)) {
+ unmap_single(hwdev, SG_ENT_VIRT_ADDRESS(sg), sg->length, direction);
+ if (sg->address)
+ sg->address = sg->orig_address;
+ else
+ sg->page = virt_to_page(sg->orig_address);
X } else if (direction == PCI_DMA_FROMDEVICE)
X mark_clean(sg->address, sg->length);
X }
@@ -442,14 +454,14 @@
X BUG();
X
X for (i = 0; i < nelems; i++, sg++)
- if (sg->orig_address != sg->address)
- sync_single(hwdev, sg->address, sg->length, direction);
+ if (sg->orig_address != SG_ENT_VIRT_ADDRESS(sg))
+ sync_single(hwdev, SG_ENT_VIRT_ADDRESS(sg), sg->length, direction);


X }
X
X unsigned long

X swiotlb_dma_address (struct scatterlist *sg)
X {
- return virt_to_phys(sg->address);
+ return SG_ENT_PHYS_ADDRESS(sg);
X }
X
X EXPORT_SYMBOL(swiotlb_init);
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/mm/fault.c linux/arch/ia64/mm/fault.c
--- v2.4.14/linux/arch/ia64/mm/fault.c Thu Apr 5 12:51:47 2001
+++ linux/arch/ia64/mm/fault.c Fri Nov 9 14:26:17 2001
@@ -1,8 +1,8 @@
X /*
X * MMU fault handling support.


X *
- * Copyright (C) 1998-2000 Hewlett-Packard Co

- * Copyright (C) 1998-2000 David Mosberger-Tang <dav...@hpl.hp.com>


+ * Copyright (C) 1998-2001 Hewlett-Packard Co

+ * David Mosberger-Tang <dav...@hpl.hp.com>
X */

X #include <linux/sched.h>
X #include <linux/kernel.h>
@@ -16,7 +16,7 @@
X #include <asm/uaccess.h>
X #include <asm/hardirq.h>
X
-extern void die_if_kernel (char *, struct pt_regs *, long);
+extern void die (char *, struct pt_regs *, long);
X
X /*
X * This routine is analogous to expand_stack() but instead grows the
@@ -46,16 +46,15 @@
X void
X ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
X {
+ int signal = SIGSEGV, code = SEGV_MAPERR;
+ struct vm_area_struct *vma, *prev_vma;
X struct mm_struct *mm = current->mm;
X struct exception_fixup fix;
- struct vm_area_struct *vma, *prev_vma;
X struct siginfo si;
- int signal = SIGSEGV;
X unsigned long mask;
X
X /*
- * If we're in an interrupt or have no user
- * context, we must not take the fault..
+ * If we're in an interrupt or have no user context, we must not take the fault..
X */
X if (in_interrupt() || !mm)
X goto no_context;
@@ -71,6 +70,8 @@
X goto check_expansion;
X
X good_area:
+ code = SEGV_ACCERR;
+
X /* OK, we've got a good vm_area for this memory area. Check the access permissions: */
X
X # define VM_READ_BIT 0
@@ -89,12 +90,13 @@
X if ((vma->vm_flags & mask) != mask)
X goto bad_area;
X
+ survive:
X /*
X * If for any reason at all we couldn't handle the fault, make
X * sure we exit gracefully rather than endlessly redo the
X * fault.
X */
- switch (handle_mm_fault(mm, vma, address, mask) != 0) {
+ switch (handle_mm_fault(mm, vma, address, mask)) {
X case 1:
X ++current->min_flt;
X break;
@@ -147,7 +149,7 @@
X if (user_mode(regs)) {
X si.si_signo = signal;
X si.si_errno = 0;
- si.si_code = SI_KERNEL;
+ si.si_code = code;
X si.si_addr = (void *) address;
X force_sig_info(signal, &si, current);
X return;
@@ -174,17 +176,29 @@
X }
X
X /*
- * Oops. The kernel tried to access some bad page. We'll have
- * to terminate things with extreme prejudice.
+ * Oops. The kernel tried to access some bad page. We'll have to terminate things
+ * with extreme prejudice.
X */
- printk(KERN_ALERT "Unable to handle kernel paging request at "
- "virtual address %016lx\n", address);
- die_if_kernel("Oops", regs, isr);
+ bust_spinlocks(1);
+
+ if (address < PAGE_SIZE)
+ printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+ else
+ printk(KERN_ALERT "Unable to handle kernel paging request at "
+ "virtual address %016lx\n", address);
+ die("Oops", regs, isr);
+ bust_spinlocks(0);
X do_exit(SIGKILL);
X return;
X
X out_of_memory:
X up_read(&mm->mmap_sem);
+ if (current->pid == 1) {
+ current->policy |= SCHED_YIELD;
+ schedule();
+ down_read(&mm->mmap_sem);
+ goto survive;
+ }
X printk("VM: killing process %s\n", current->comm);
X if (user_mode(regs))
X do_exit(SIGKILL);
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/mm/init.c linux/arch/ia64/mm/init.c
--- v2.4.14/linux/arch/ia64/mm/init.c Sun Sep 23 11:40:55 2001
+++ linux/arch/ia64/mm/init.c Fri Nov 9 14:26:17 2001
@@ -167,13 +167,40 @@
X }
X
X void
-show_mem (void)
+show_mem(void)
X {
X int i, total = 0, reserved = 0;
X int shared = 0, cached = 0;
X
X printk("Mem-info:\n");
X show_free_areas();
+
+#ifdef CONFIG_DISCONTIGMEM
+ {
+ pg_data_t *pgdat = pgdat_list;
+
+ printk("Free swap: %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ do {
+ printk("Node ID: %d\n", pgdat->node_id);
+ for(i = 0; i < pgdat->node_size; i++) {
+ if (PageReserved(pgdat->node_mem_map+i))
+ reserved++;
+ else if (PageSwapCache(pgdat->node_mem_map+i))
+ cached++;
+ else if (page_count(pgdat->node_mem_map + i))
+ shared += page_count(pgdat->node_mem_map + i) - 1;
+ }
+ printk("\t%d pages of RAM\n", pgdat->node_size);
+ printk("\t%d reserved pages\n", reserved);
+ printk("\t%d pages shared\n", shared);
+ printk("\t%d pages swap cached\n", cached);
+ pgdat = pgdat->node_next;
+ } while (pgdat);
+ printk("Total of %ld pages in page table cache\n", pgtable_cache_size);
+ show_buffers();
+ printk("%d free buffer pages\n", nr_free_buffer_pages());
+ }
+#else /* !CONFIG_DISCONTIGMEM */
X printk("Free swap: %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
X i = max_mapnr;
X while (i-- > 0) {
@@ -191,6 +218,7 @@
X printk("%d pages swap cached\n", cached);
X printk("%ld pages in page table cache\n", pgtable_cache_size);
X show_buffers();
+#endif /* !CONFIG_DISCONTIGMEM */
X }
X
X /*
@@ -248,7 +276,7 @@
X ia64_clear_ic(flags);
X
X rid = ia64_rid(IA64_REGION_ID_KERNEL, __IA64_UNCACHED_OFFSET);
- ia64_set_rr(__IA64_UNCACHED_OFFSET, (rid << 8) | (KERNEL_PG_SHIFT << 2));
+ ia64_set_rr(__IA64_UNCACHED_OFFSET, (rid << 8) | (IA64_GRANULE_SHIFT << 2));
X
X rid = ia64_rid(IA64_REGION_ID_KERNEL, VMALLOC_START);
X ia64_set_rr(VMALLOC_START, (rid << 8) | (PAGE_SHIFT << 2) | 1);
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/mm/tlb.c linux/arch/ia64/mm/tlb.c
--- v2.4.14/linux/arch/ia64/mm/tlb.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/mm/tlb.c Fri Nov 9 14:26:17 2001
@@ -2,7 +2,7 @@
X * TLB support routines.


X *
X * Copyright (C) 1998-2001 Hewlett-Packard Co

- * Copyright (C) 1998-2001 David Mosberger-Tang <dav...@hpl.hp.com>


+ * David Mosberger-Tang <dav...@hpl.hp.com>
X *

X * 08/02/00 A. Mallick <asit.k....@intel.com>
X * Modified RID allocation for SMP
@@ -41,89 +41,6 @@
X };
X
X /*
- * Seralize usage of ptc.g
- */
-spinlock_t ptcg_lock = SPIN_LOCK_UNLOCKED; /* see <asm/pgtable.h> */
-
-#if defined(CONFIG_SMP) && !defined(CONFIG_ITANIUM_PTCG)
-
-#include <linux/irq.h>
-
-unsigned long flush_end, flush_start, flush_nbits, flush_rid;
-atomic_t flush_cpu_count;
-
-/*
- * flush_tlb_no_ptcg is called with ptcg_lock locked
- */
-static inline void
-flush_tlb_no_ptcg (unsigned long start, unsigned long end, unsigned long nbits)
-{
- extern void smp_send_flush_tlb (void);
- unsigned long saved_tpr = 0;
- unsigned long flags;
-
- /*
- * Some times this is called with interrupts disabled and causes
- * dead-lock; to avoid this we enable interrupt and raise the TPR
- * to enable ONLY IPI.
- */
- __save_flags(flags);
- if (!(flags & IA64_PSR_I)) {
- saved_tpr = ia64_get_tpr();
- ia64_srlz_d();
- ia64_set_tpr(IA64_IPI_VECTOR - 16);
- ia64_srlz_d();
- local_irq_enable();
- }
-
- spin_lock(&ptcg_lock);
- flush_rid = ia64_get_rr(start);
- ia64_srlz_d();
- flush_start = start;
- flush_end = end;
- flush_nbits = nbits;
- atomic_set(&flush_cpu_count, smp_num_cpus - 1);
- smp_send_flush_tlb();
- /*
- * Purge local TLB entries. ALAT invalidation is done in ia64_leave_kernel.
- */
- do {
- asm volatile ("ptc.l %0,%1" :: "r"(start), "r"(nbits<<2) : "memory");
- start += (1UL << nbits);
- } while (start < end);
-
- ia64_srlz_i(); /* srlz.i implies srlz.d */
-
- /*
- * Wait for other CPUs to finish purging entries.
- */
-#if defined(CONFIG_ITANIUM_BSTEP_SPECIFIC)
- {
- extern void smp_resend_flush_tlb (void);
- unsigned long start = ia64_get_itc();
-
- while (atomic_read(&flush_cpu_count) > 0) {
- if ((ia64_get_itc() - start) > 400000UL) {
- smp_resend_flush_tlb();
- start = ia64_get_itc();
- }
- }
- }
-#else
- while (atomic_read(&flush_cpu_count)) {
- /* Nothing */
- }
-#endif
- if (!(flags & IA64_PSR_I)) {
- local_irq_disable();
- ia64_set_tpr(saved_tpr);
- ia64_srlz_d();
- }
-}
-
-#endif /* CONFIG_SMP && !CONFIG_ITANIUM_PTCG */
-
-/*
X * Acquire the ia64_ctx.lock before calling this function!
X */
X void
@@ -162,6 +79,26 @@
X flush_tlb_all();


X }
X
+static inline void

+ia64_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits)
+{
+ static spinlock_t ptcg_lock = SPIN_LOCK_UNLOCKED;
+
+ /* HW requires global serialization of ptc.ga. */
+ spin_lock(&ptcg_lock);
+ {
+ do {
+ /*
+ * Flush ALAT entries also.
+ */
+ asm volatile ("ptc.ga %0,%1;;srlz.i;;" :: "r"(start), "r"(nbits<<2)
+ : "memory");
+ start += (1UL << nbits);
+ } while (start < end);
+ }
+ spin_unlock(&ptcg_lock);
+}
+
X void
X __flush_tlb_all (void)
X {
@@ -222,23 +159,15 @@
X }
X start &= ~((1UL << nbits) - 1);
X
-#if defined(CONFIG_SMP) && !defined(CONFIG_ITANIUM_PTCG)
- flush_tlb_no_ptcg(start, end, nbits);
-#else
- spin_lock(&ptcg_lock);
- do {
X # ifdef CONFIG_SMP
- /*
- * Flush ALAT entries also.
- */
- asm volatile ("ptc.ga %0,%1;;srlz.i;;" :: "r"(start), "r"(nbits<<2) : "memory");
+ platform_global_tlb_purge(start, end, nbits);
X # else
+ do {
X asm volatile ("ptc.l %0,%1" :: "r"(start), "r"(nbits<<2) : "memory");
-# endif
X start += (1UL << nbits);
X } while (start < end);
-#endif /* CONFIG_SMP && !defined(CONFIG_ITANIUM_PTCG) */
- spin_unlock(&ptcg_lock);
+# endif
+
X ia64_insn_group_barrier();
X ia64_srlz_i(); /* srlz.i implies srlz.d */
X ia64_insn_group_barrier();
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/sn/sn1/llsc4.c linux/arch/ia64/sn/sn1/llsc4.c
--- v2.4.14/linux/arch/ia64/sn/sn1/llsc4.c Thu Apr 5 12:51:47 2001
+++ linux/arch/ia64/sn/sn1/llsc4.c Fri Nov 9 14:26:17 2001
@@ -35,16 +35,6 @@
X static int inttest=0;
X #endif
X
-#ifdef IA64_SEMFIX_INSN
-#undef IA64_SEMFIX_INSN
-#endif
-#ifdef IA64_SEMFIX
-#undef IA64_SEMFIX
-#endif
-# define IA64_SEMFIX_INSN
-# define IA64_SEMFIX ""
-
-
X /*
X * Test parameter table for AUTOTEST
X */
@@ -192,7 +182,6 @@
X printk (" llscfail \t%s\tForce a failure to test the trigger & error messages\n", fail_enabled ? "on" : "off");
X printk (" llscselt \t%s\tSelective triger on failures\n", selective_trigger ? "on" : "off");
X printk (" llscblkadr \t%s\tDump data block addresses\n", dump_block_addrs_opt ? "on" : "off");
- printk (" SEMFIX: %s\n", IA64_SEMFIX);
X printk ("\n");
X }
X __setup("autotest", autotest_enable);
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/tools/print_offsets.c linux/arch/ia64/tools/print_offsets.c
--- v2.4.14/linux/arch/ia64/tools/print_offsets.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/tools/print_offsets.c Fri Nov 9 14:26:17 2001
@@ -57,11 +57,8 @@
X { "IA64_TASK_PROCESSOR_OFFSET", offsetof (struct task_struct, processor) },
X { "IA64_TASK_THREAD_OFFSET", offsetof (struct task_struct, thread) },
X { "IA64_TASK_THREAD_KSP_OFFSET", offsetof (struct task_struct, thread.ksp) },
-#ifdef CONFIG_IA32_SUPPORT
- { "IA64_TASK_THREAD_SIGMASK_OFFSET",offsetof (struct task_struct, thread.un.sigmask) },
-#endif
X #ifdef CONFIG_PERFMON
- { "IA64_TASK_PFM_NOTIFY_OFFSET", offsetof(struct task_struct, thread.pfm_pend_notify) },
+ { "IA64_TASK_PFM_MUST_BLOCK_OFFSET",offsetof(struct task_struct, thread.pfm_must_block) },
X #endif
X { "IA64_TASK_PID_OFFSET", offsetof (struct task_struct, pid) },
X { "IA64_TASK_MM_OFFSET", offsetof (struct task_struct, mm) },
@@ -165,17 +162,18 @@
X { "IA64_SIGCONTEXT_FR6_OFFSET", offsetof (struct sigcontext, sc_fr[6]) },
X { "IA64_SIGCONTEXT_PR_OFFSET", offsetof (struct sigcontext, sc_pr) },
X { "IA64_SIGCONTEXT_R12_OFFSET", offsetof (struct sigcontext, sc_gr[12]) },
+ { "IA64_SIGCONTEXT_RBS_BASE_OFFSET",offsetof (struct sigcontext, sc_rbs_base) },
+ { "IA64_SIGCONTEXT_LOADRS_OFFSET", offsetof (struct sigcontext, sc_loadrs) },
X { "IA64_SIGFRAME_ARG0_OFFSET", offsetof (struct sigframe, arg0) },
X { "IA64_SIGFRAME_ARG1_OFFSET", offsetof (struct sigframe, arg1) },
X { "IA64_SIGFRAME_ARG2_OFFSET", offsetof (struct sigframe, arg2) },
- { "IA64_SIGFRAME_RBS_BASE_OFFSET", offsetof (struct sigframe, rbs_base) },
X { "IA64_SIGFRAME_HANDLER_OFFSET", offsetof (struct sigframe, handler) },
X { "IA64_SIGFRAME_SIGCONTEXT_OFFSET", offsetof (struct sigframe, sc) },
X { "IA64_CLONE_VFORK", CLONE_VFORK },
X { "IA64_CLONE_VM", CLONE_VM },
X { "IA64_CPU_IRQ_COUNT_OFFSET", offsetof (struct cpuinfo_ia64, irq_stat.f.irq_count) },
X { "IA64_CPU_BH_COUNT_OFFSET", offsetof (struct cpuinfo_ia64, irq_stat.f.bh_count) },
- { "IA64_CPU_PHYS_STACKED_SIZE_P8_OFFSET", offsetof (struct cpuinfo_ia64, phys_stacked_size_p8) },
+ { "IA64_CPU_PHYS_STACKED_SIZE_P8_OFFSET",offsetof (struct cpuinfo_ia64, phys_stacked_size_p8)},
X };
X
X static const char *tabs = "\t\t\t\t\t\t\t\t\t\t";
diff -u --recursive --new-file v2.4.14/linux/arch/mips/kernel/smp.c linux/arch/mips/kernel/smp.c
--- v2.4.14/linux/arch/mips/kernel/smp.c Tue Jul 3 17:08:18 2001
+++ linux/arch/mips/kernel/smp.c Wed Nov 21 10:31:09 2001


@@ -126,7 +126,7 @@
X

X /* Schedule the first task manually */
X p->processor = i;
- p->has_cpu = 1;
+ p->cpus_runnable = 1 << i; /* we schedule the first task manually */
X
X /* Attach to the address space of init_task. */
X atomic_inc(&init_mm.mm_count);
@@ -155,7 +155,7 @@
X sprintf(p->comm, "%s%d", "Idle", i);
X init_tasks[i] = p;
X p->processor = i;
- p->has_cpu = 1; /* we schedule the first task manually */
+ p->cpus_runnable = 1 << i; /* we schedule the first task manually *
X del_from_runqueue(p);
X unhash_process(p);
X /* Attach to the address space of init_task. */
diff -u --recursive --new-file v2.4.14/linux/arch/mips64/sgi-ip27/ip27-init.c linux/arch/mips64/sgi-ip27/ip27-init.c
--- v2.4.14/linux/arch/mips64/sgi-ip27/ip27-init.c Sun Sep 23 11:40:56 2001
+++ linux/arch/mips64/sgi-ip27/ip27-init.c Wed Nov 21 10:31:09 2001
@@ -497,7 +497,7 @@
X alloc_cpupda(cpu, num_cpus);
X del_from_runqueue(p);
X p->processor = num_cpus;
- p->has_cpu = 1; /* we schedule the first task manually */
+ p->cpus_runnable = 1 << num_cpus; /* we schedule the first task manually */
X unhash_process(p);
X /* Attach to the address space of init_task. */
X atomic_inc(&init_mm.mm_count);
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/8xx_io/micropatch.c linux/arch/ppc/8xx_io/micropatch.c
--- v2.4.14/linux/arch/ppc/8xx_io/micropatch.c Sun Sep 23 11:40:56 2001
+++ linux/arch/ppc/8xx_io/micropatch.c Wed Nov 21 09:59:11 2001
@@ -17,7 +17,7 @@
X #include <asm/page.h>
X #include <asm/pgtable.h>
X #include <asm/8xx_immap.h>
-#include "commproc.h"
+#include <asm/commproc.h>
X
X /* Define this to get SMC patches as well. You need to modify the uart
X * driver as well......
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.4.14/linux/arch/ppc/config.in Mon Nov 5 15:55:26 2001
+++ linux/arch/ppc/config.in Fri Nov 16 10:10:08 2001
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.config.in 1.43 10/16/01 15:18:50 trini
+# BK Id: SCCS/s.config.in 1.45 11/08/01 07:57:40 paulus
X #
X # For a description of the syntax of this configuration file,
X # see Documentation/kbuild/config-language.txt.
@@ -6,6 +6,7 @@
X define_bool CONFIG_UID16 n
X define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
X define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
+define_bool CONFIG_HAVE_DEC_LOCK y
X
X mainmenu_name "Linux/PowerPC Kernel Configuration"
X
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c
--- v2.4.14/linux/arch/ppc/kernel/apus_setup.c Mon Nov 5 15:55:26 2001
+++ linux/arch/ppc/kernel/apus_setup.c Fri Nov 16 10:10:08 2001
@@ -1,5 +1,5 @@
X /*
- * BK Id: SCCS/s.apus_setup.c 1.22 10/18/01 11:16:27 trini
+ * BK Id: SCCS/s.apus_setup.c 1.24 11/13/01 21:26:07 paulus
X */
X /*
X * linux/arch/ppc/kernel/apus_setup.c
@@ -25,6 +25,7 @@
X #include <linux/hdreg.h>
X #include <linux/blk.h>


X #include <linux/pci.h>
+#include <linux/seq_file.h>
X

X #ifdef CONFIG_APUS
X #include <asm/logging.h>
@@ -263,24 +264,20 @@
X }
X
X int
-apus_get_cpuinfo(char *buffer)
+apus_show_cpuinfo(struct seq_file *m)
X {
-#ifdef CONFIG_APUS
X extern int __map_without_bats;
X extern unsigned long powerup_PCI_present;
- int len;
X
- len = sprintf(buffer, "machine\t\t: Amiga\n");
- len += sprintf(buffer+len, "bus speed\t: %d%s", __bus_speed,
- (__speed_test_failed) ? " [failed]\n" : "\n");
- len += sprintf(buffer+len, "using BATs\t: %s\n",
- (__map_without_bats) ? "No" : "Yes");
- len += sprintf(buffer+len, "ram speed\t: %dns\n",
- (__60nsram) ? 60 : 70);
- len += sprintf(buffer+len, "PCI bridge\t: %s\n",
- (powerup_PCI_present) ? "Yes" : "No");
- return len;
-#endif
+ seq_printf(m, "machine\t\t: Amiga\n");
+ seq_printf(m, "bus speed\t: %d%s", __bus_speed,
+ (__speed_test_failed) ? " [failed]\n" : "\n");
+ seq_printf(m, "using BATs\t: %s\n",
+ (__map_without_bats) ? "No" : "Yes");
+ seq_printf(m, "ram speed\t: %dns\n", (__60nsram) ? 60 : 70);
+ seq_printf(m, "PCI bridge\t: %s\n",
+ (powerup_PCI_present) ? "Yes" : "No");


+ return 0;
X }
X

X static void get_current_tb(unsigned long long *time)
@@ -1069,8 +1066,7 @@
X ISA_DMA_THRESHOLD = 0x00ffffff;
X
X ppc_md.setup_arch = apus_setup_arch;
- ppc_md.setup_residual = NULL;
- ppc_md.get_cpuinfo = apus_get_cpuinfo;
+ ppc_md.show_cpuinfo = apus_show_cpuinfo;
X ppc_md.irq_cannonicalize = apus_irq_cannonicalize;
X ppc_md.init_IRQ = apus_init_IRQ;
X ppc_md.get_irq = apus_get_irq;
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.4.14/linux/arch/ppc/kernel/chrp_setup.c Sun Sep 23 11:40:56 2001
+++ linux/arch/ppc/kernel/chrp_setup.c Fri Nov 16 10:10:08 2001
@@ -1,5 +1,5 @@
X /*
- * BK Id: SCCS/s.chrp_setup.c 1.36 09/08/01 15:47:42 paulus
+ * BK Id: SCCS/s.chrp_setup.c 1.38 11/13/01 21:26:07 paulus
X */
X /*
X * linux/arch/ppc/kernel/setup.c
@@ -38,6 +38,7 @@
X #include <linux/module.h>
X #include <linux/delay.h>
X #include <linux/ide.h>
+#include <linux/seq_file.h>
X
X #include <asm/mmu.h>
X #include <asm/processor.h>
@@ -81,6 +82,7 @@
X extern void pckbd_init_hw(void);
X extern unsigned char pckbd_sysrq_xlate[128];
X extern void select_adb_keyboard(void);
+extern int of_show_percpuinfo(struct seq_file *, int);
X
X extern kdev_t boot_dev;
X
@@ -110,9 +112,9 @@
X };
X
X int __chrp
-chrp_get_cpuinfo(char *buffer)
+chrp_show_cpuinfo(struct seq_file *m)
X {
- int i, len, sdramen;
+ int i, sdramen;
X unsigned int t;
X struct device_node *root;
X const char *model = "";
@@ -120,11 +122,10 @@
X root = find_path_device("/");
X if (root)
X model = get_property(root, "model", NULL);
- len = sprintf(buffer,"machine\t\t: CHRP %s\n", model);
+ seq_printf(m, "machine\t\t: CHRP %s\n", model);
X
X /* longtrail (goldengate) stuff */
- if ( !strncmp( model, "IBM,LongTrail", 13 ) )
- {
+ if (!strncmp(model, "IBM,LongTrail", 13)) {
X /* VLSI VAS96011/12 `Golden Gate 2' */
X /* Memory banks */
X sdramen = (in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+
@@ -159,17 +160,17 @@
X model = "Reserved";
X break;
X }
- len += sprintf(buffer+len, "memory bank %d\t: %s %s\n", i, model,
- gg2_memtypes[sdramen ? 1 : ((t>>1) & 3)]);
+ seq_printf(m, "memory bank %d\t: %s %s\n", i, model,
+ gg2_memtypes[sdramen ? 1 : ((t>>1) & 3)]);
X }
X /* L2 cache */
X t = in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+GG2_PCI_CC_CTRL));
- len += sprintf(buffer+len, "board l2\t: %s %s (%s)\n",
- gg2_cachesizes[(t>>7) & 3],
- gg2_cachetypes[(t>>2) & 3],
- gg2_cachemodes[t & 3]);
+ seq_printf(m, "board l2\t: %s %s (%s)\n",
+ gg2_cachesizes[(t>>7) & 3],
+ gg2_cachetypes[(t>>2) & 3],
+ gg2_cachemodes[t & 3]);
X }
- return len;


+ return 0;
X }
X

X /*
@@ -341,13 +342,8 @@
X chrp_irq_cannonicalize(u_int irq)
X {
X if (irq == 2)
- {
X return 9;
- }
- else
- {
- return irq;
- }
+ return irq;
X }
X
X void __init chrp_init_IRQ(void)
@@ -513,8 +509,8 @@
X isa_io_base = CHRP_ISA_IO_BASE; /* default value */
X
X ppc_md.setup_arch = chrp_setup_arch;
- ppc_md.setup_residual = NULL;
- ppc_md.get_cpuinfo = chrp_get_cpuinfo;
+ ppc_md.show_percpuinfo = of_show_percpuinfo;
+ ppc_md.show_cpuinfo = chrp_show_cpuinfo;
X ppc_md.irq_cannonicalize = chrp_irq_cannonicalize;
X #ifndef CONFIG_POWER4
X ppc_md.init_IRQ = chrp_init_IRQ;
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/kernel/gemini_setup.c linux/arch/ppc/kernel/gemini_setup.c
--- v2.4.14/linux/arch/ppc/kernel/gemini_setup.c Mon Nov 5 15:55:26 2001
+++ linux/arch/ppc/kernel/gemini_setup.c Fri Nov 16 10:10:08 2001
@@ -24,6 +24,7 @@
X #include <linux/major.h>


X #include <linux/blk.h>
X #include <linux/console.h>

+#include <linux/seq_file.h>
X
X #include <asm/system.h>
X #include <asm/pgtable.h>


@@ -82,9 +83,8 @@
X }
X

X int
-gemini_get_cpuinfo(char *buffer)
+gemini_show_cpuinfo(struct seq_file *m)
X {
- int len;
X unsigned char reg, rev;
X char *family;
X unsigned int type;
@@ -100,22 +100,20 @@
X
X reg = readb(GEMINI_BECO);
X
- len = sprintf( buffer, "machine\t\t: Gemini %s%d, rev %c, eco %d\n",
- family, type, (rev + 'A'), (reg & 0xf));
+ seq_printf(m, "machine\t\t: Gemini %s%d, rev %c, eco %d\n",
+ family, type, (rev + 'A'), (reg & 0xf));
X
- len = sprintf(buffer, "board\t\t: Gemini %s", family);
+ seq_printf(m, "board\t\t: Gemini %s", family);
X if (type > 9)
- len += sprintf(buffer+len, "%c", (type - 10) + 'A');
+ seq_printf(m, "%c", (type - 10) + 'A');
X else
- len += sprintf(buffer+len, "%d", type);
+ seq_printf(m, "%d", type);
X
- len += sprintf(buffer+len, ", rev %c, eco %d\n",
- (rev + 'A'), (reg & 0xf));
+ seq_printf(m, ", rev %c, eco %d\n", (rev + 'A'), (reg & 0xf));
X
- len += sprintf(buffer+len, "clock\t\t: %dMhz\n",
- gemini_get_clock_speed());
+ seq_printf(m, "clock\t\t: %dMhz\n", gemini_get_clock_speed());
X
- return len;


+ return 0;
X }
X

X static u_char gemini_openpic_initsenses[] = {
@@ -150,11 +148,12 @@
X void
X gemini_heartbeat(void)
X {
- /* We only want to do this on 1 CPU */
- if ( smp_processor_id() )
- return;
X static unsigned long led = GEMINI_LEDBASE+(4*8);
X static char direction = 8;
+
+ /* We only want to do this on 1 CPU */
+ if (smp_processor_id())
+ return;
X *(char *)led = 0;
X if ( (led + direction) > (GEMINI_LEDBASE+(7*8)) ||
X (led + direction) < (GEMINI_LEDBASE+(4*8)) )
@@ -551,8 +550,7 @@
X #endif
X
X ppc_md.setup_arch = gemini_setup_arch;
- ppc_md.setup_residual = NULL;
- ppc_md.get_cpuinfo = gemini_get_cpuinfo;
+ ppc_md.show_cpuinfo = gemini_show_cpuinfo;
X ppc_md.irq_cannonicalize = NULL;
X ppc_md.init_IRQ = gemini_init_IRQ;
X ppc_md.get_irq = openpic_get_irq;
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/kernel/m8260_setup.c linux/arch/ppc/kernel/m8260_setup.c
--- v2.4.14/linux/arch/ppc/kernel/m8260_setup.c Mon Nov 5 15:55:26 2001
+++ linux/arch/ppc/kernel/m8260_setup.c Fri Nov 16 10:10:08 2001
@@ -1,5 +1,5 @@
X /*
- * BK Id: SCCS/s.m8260_setup.c 1.28 10/18/01 11:16:28 trini
+ * BK Id: SCCS/s.m8260_setup.c 1.30 11/13/01 21:26:07 paulus
X */
X /*
X * linux/arch/ppc/kernel/setup.c
@@ -34,6 +34,7 @@
X #include <linux/blk.h>
X #include <linux/ioport.h>
X #include <linux/ide.h>
+#include <linux/seq_file.h>
X
X #include <asm/mmu.h>
X #include <asm/processor.h>
@@ -144,21 +145,20 @@
X
X
X static int
-m8260_setup_residual(char *buffer)
+m8260_show_percpuinfo(struct seq_file *m, int i)
X {
- int len = 0;
X bd_t *bp;
X
X bp = (bd_t *)__res;
X
- len += sprintf(len+buffer,"core clock\t: %d MHz\n"
- "CPM clock\t: %d MHz\n"
- "bus clock\t: %d MHz\n",
- bp->bi_intfreq / 1000000,
- bp->bi_cpmfreq / 1000000,
- bp->bi_busfreq / 1000000);
+ seq_printf(m, "core clock\t: %d MHz\n"
+ "CPM clock\t: %d MHz\n"
+ "bus clock\t: %d MHz\n",
+ bp->bi_intfreq / 1000000,
+ bp->bi_cpmfreq / 1000000,
+ bp->bi_busfreq / 1000000);
X
- return len;


+ return 0;
X }
X

X /* Initialize the internal interrupt controller. The number of
@@ -240,8 +240,7 @@
X }
X
X ppc_md.setup_arch = m8260_setup_arch;
- ppc_md.setup_residual = m8260_setup_residual;
- ppc_md.get_cpuinfo = NULL;
+ ppc_md.show_percpuinfo = m8260_show_percpuinfo;
X ppc_md.irq_cannonicalize = NULL;
X ppc_md.init_IRQ = m8260_init_IRQ;
X ppc_md.get_irq = m8260_get_irq;
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c
--- v2.4.14/linux/arch/ppc/kernel/m8xx_setup.c Mon Nov 5 15:55:26 2001
+++ linux/arch/ppc/kernel/m8xx_setup.c Fri Nov 16 10:10:08 2001
@@ -1,5 +1,5 @@
X /*
- * BK Id: SCCS/s.m8xx_setup.c 1.38 10/18/01 11:16:28 trini
+ * BK Id: SCCS/s.m8xx_setup.c 1.40 11/13/01 21:26:07 paulus
X *
X * linux/arch/ppc/kernel/setup.c
X *
@@ -33,6 +33,7 @@
X #include <linux/blk.h>
X #include <linux/ioport.h>


X #include <linux/bootmem.h>
+#include <linux/seq_file.h>
X

X #include <asm/mmu.h>
X #include <asm/processor.h>
@@ -240,19 +241,18 @@
X
X
X static int
-m8xx_setup_residual(char *buffer)
+m8xx_show_percpuinfo(struct seq_file *m, int i)
X {
- int len = 0;
X bd_t *bp;
X
X bp = (bd_t *)__res;
X
- len += sprintf(len+buffer,"clock\t\t: %ldMHz\n"
- "bus clock\t: %ldMHz\n",
- bp->bi_intfreq / 1000000,
- bp->bi_busfreq / 1000000);
+ seq_printf(m, "clock\t\t: %ldMHz\n"
+ "bus clock\t: %ldMHz\n",
+ bp->bi_intfreq / 1000000,
+ bp->bi_busfreq / 1000000);
X
- return len;


+ return 0;
X }
X

X /* Initialize the internal interrupt controller. The number of
@@ -372,8 +372,7 @@
X }
X
X ppc_md.setup_arch = m8xx_setup_arch;
- ppc_md.setup_residual = m8xx_setup_residual;
- ppc_md.get_cpuinfo = NULL;
+ ppc_md.show_percpuinfo = m8xx_show_percpuinfo;
X ppc_md.irq_cannonicalize = NULL;
X ppc_md.init_IRQ = m8xx_init_IRQ;
X ppc_md.get_irq = m8xx_get_irq;
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/kernel/oak_setup.c linux/arch/ppc/kernel/oak_setup.c
--- v2.4.14/linux/arch/ppc/kernel/oak_setup.c Mon Nov 5 15:55:26 2001
+++ linux/arch/ppc/kernel/oak_setup.c Fri Nov 16 10:10:08 2001
@@ -1,5 +1,5 @@
X /*
- * BK Id: SCCS/s.oak_setup.c 1.10 10/18/01 11:16:28 trini
+ * BK Id: SCCS/s.oak_setup.c 1.12 11/13/01 21:26:07 paulus
X */
X /*
X *
@@ -23,6 +23,7 @@
X #include <linux/param.h>
X #include <linux/string.h>
X #include <linux/blk.h>
+#include <linux/seq_file.h>
X
X #include <asm/processor.h>
X #include <asm/board.h>
@@ -106,8 +107,7 @@
X /* Initialize machine-dependency vectors */
X
X ppc_md.setup_arch = oak_setup_arch;
- ppc_md.setup_residual = oak_setup_residual;
- ppc_md.get_cpuinfo = NULL;
+ ppc_md.show_percpuinfo = oak_show_percpuinfo;
X ppc_md.irq_cannonicalize = NULL;
X ppc_md.init_IRQ = oak_init_IRQ;
X ppc_md.get_irq = oak_get_irq;
@@ -141,7 +141,7 @@
X }
X
X /*
- * int oak_setup_residual()
+ * int oak_show_percpuinfo()
X *
X * Description:
X * This routine pretty-prints the platform's internal CPU and bus clock
@@ -159,18 +159,16 @@
X * on error.
X */
X int
-oak_setup_residual(char *buffer)
+oak_show_percpuinfo(struct seq_file *m, int i)
X {
- int len = 0;
X bd_t *bp = (bd_t *)__res;
X
- len += sprintf(len + buffer,
- "clock\t\t: %dMHz\n"
- "bus clock\t\t: %dMHz\n",
- bp->bi_intfreq / 1000000,
- bp->bi_busfreq / 1000000);
+ seq_printf(m, "clock\t\t: %dMHz\n"
+ "bus clock\t\t: %dMHz\n",
+ bp->bi_intfreq / 1000000,
+ bp->bi_busfreq / 1000000);
X
- return (len);


+ return 0;
X }
X

X /*
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- v2.4.14/linux/arch/ppc/kernel/pci.c Mon Nov 5 15:55:26 2001
+++ linux/arch/ppc/kernel/pci.c Fri Nov 16 10:10:08 2001
@@ -1,5 +1,5 @@
X /*
- * BK Id: SCCS/s.pci.c 1.31 11/01/01 12:24:55 trini
+ * BK Id: SCCS/s.pci.c 1.35 11/13/01 08:19:57 trini
X */
X /*
X * Common pmac/prep/chrp pci routines. -- Cort
@@ -44,6 +44,7 @@
X
X static void pcibios_fixup_resources(struct pci_dev* dev);
X static void fixup_broken_pcnet32(struct pci_dev* dev);
+static void fixup_rev1_53c810(struct pci_dev* dev);
X #ifdef CONFIG_ALL_PPC
X static void pcibios_fixup_cardbus(struct pci_dev* dev);
X static u8* pci_to_OF_bus_map;
@@ -60,14 +61,28 @@
X static int pci_bus_count;
X

X struct pci_fixup pcibios_fixups[] = {

- { PCI_FIXUP_HEADER, PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32 },
- { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32 },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810 },
+ { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources },
X #ifdef CONFIG_ALL_PPC
X /* We should add per-machine fixup support in xxx_setup.c or xxx_pci.c */
- { PCI_FIXUP_FINAL, PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1211, pcibios_fixup_cardbus },
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1211, pcibios_fixup_cardbus },
X #endif /* CONFIG_ALL_PPC */
X { 0 }
X };
+
+static void
+fixup_rev1_53c810(struct pci_dev* dev)
+{
+ /* rev 1 ncr53c810 chips don't set the class at all which means
+ * they don't get their resources remapped. Fix that here.
+ */
+
+ if ((dev->class == PCI_CLASS_NOT_DEFINED)) {
+ printk("NCR 53c810 rev 1 detected, setting PCI class.\n");
+ dev->class = PCI_CLASS_STORAGE_SCSI;
+ }
+}
X
X static void
X fixup_broken_pcnet32(struct pci_dev* dev)
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- v2.4.14/linux/arch/ppc/kernel/pmac_setup.c Mon Nov 5 15:55:26 2001
+++ linux/arch/ppc/kernel/pmac_setup.c Fri Nov 16 10:10:08 2001
@@ -1,5 +1,5 @@
X /*
- * BK Id: SCCS/s.pmac_setup.c 1.41 10/18/01 11:16:28 trini
+ * BK Id: SCCS/s.pmac_setup.c 1.43 11/13/01 21:26:07 paulus
X */
X /*
X * linux/arch/ppc/kernel/setup.c
@@ -49,6 +49,7 @@
X #include <linux/adb.h>
X #include <linux/cuda.h>
X #include <linux/pmu.h>
+#include <linux/seq_file.h>
X
X #include <asm/processor.h>
X #include <asm/sections.h>
@@ -157,36 +158,56 @@
X }
X #endif /* CONFIG_SMP */
X
+/*
+ * Assume here that all clock rates are the same in a
+ * smp system. -- Cort
+ */
+int __openfirmware
+of_show_percpuinfo(struct seq_file *m, int i)
+{
+ struct device_node *cpu_node;
+ int *fp, s;
+
+ cpu_node = find_type_devices("cpu");
+ if (!cpu_node)
+ return 0;
+ for (s = 0; s < i && cpu_node->next; s++)
+ cpu_node = cpu_node->next;
+ fp = (int *) get_property(cpu_node, "clock-frequency", NULL);
+ if (fp)
+ seq_printf(m, "clock\t\t: %dMHz\n", *fp / 1000000);


+ return 0;
+}
+

X int __pmac
-pmac_get_cpuinfo(char *buffer)
+pmac_show_cpuinfo(struct seq_file *m)
X {
- int len;
X struct device_node *np;
X char *pp;
X int plen;
X
X /* find motherboard type */
- len = sprintf(buffer, "machine\t\t: ");
+ seq_printf(m, "machine\t\t: ");
X np = find_devices("device-tree");
X if (np != NULL) {
X pp = (char *) get_property(np, "model", NULL);
X if (pp != NULL)
- len += sprintf(buffer+len, "%s\n", pp);
+ seq_printf(m, "%s\n", pp);
X else
- len += sprintf(buffer+len, "PowerMac\n");
+ seq_printf(m, "PowerMac\n");
X pp = (char *) get_property(np, "compatible", &plen);
X if (pp != NULL) {
- len += sprintf(buffer+len, "motherboard\t:");
+ seq_printf(m, "motherboard\t:");
X while (plen > 0) {
X int l = strlen(pp) + 1;
- len += sprintf(buffer+len, " %s", pp);
+ seq_printf(m, " %s", pp);
X plen -= l;
X pp += l;
X }
- buffer[len++] = '\n';
+ seq_printf(m, "\n");
X }
X } else
- len += sprintf(buffer+len, "PowerMac\n");
+ seq_printf(m, "PowerMac\n");
X
X /* find l2 cache info */
X np = find_devices("l2-cache");
@@ -197,22 +218,21 @@
X get_property(np, "i-cache-size", NULL);
X unsigned int *dc = (unsigned int *)
X get_property(np, "d-cache-size", NULL);
- len += sprintf(buffer+len, "L2 cache\t:");
+ seq_printf(m, "L2 cache\t:");
X has_l2cache = 1;
X if (get_property(np, "cache-unified", NULL) != 0 && dc) {
- len += sprintf(buffer+len, " %dK unified", *dc / 1024);
+ seq_printf(m, " %dK unified", *dc / 1024);
X } else {
X if (ic)
- len += sprintf(buffer+len, " %dK instruction",
- *ic / 1024);
+ seq_printf(m, " %dK instruction", *ic / 1024);
X if (dc)
- len += sprintf(buffer+len, "%s %dK data",
- (ic? " +": ""), *dc / 1024);
+ seq_printf(m, "%s %dK data",
+ (ic? " +": ""), *dc / 1024);
X }
X pp = get_property(np, "ram-type", NULL);
X if (pp)
- len += sprintf(buffer+len, " %s", pp);
- buffer[len++] = '\n';
+ seq_printf(m, " %s", pp);
+ seq_printf(m, "\n");
X }
X
X /* find ram info */


@@ -227,8 +247,7 @@
X

X for (n /= sizeof(struct reg_property); n > 0; --n)
X total += (reg++)->size;
- len += sprintf(buffer+len, "memory\t\t: %luMB\n",
- total >> 20);
+ seq_printf(m, "memory\t\t: %luMB\n", total >> 20);
X }
X }
X
@@ -240,16 +259,16 @@
X unsigned int *l2cr = (unsigned int *)
X get_property(np, "l2cr-value", NULL);
X if (l2cr != 0) {
- len += sprintf(buffer+len, "l2cr override\t: 0x%x\n", *l2cr);
+ seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr);
X }
X }
X
X /* Indicate newworld/oldworld */
- len += sprintf(buffer+len, "pmac-generation\t: %s\n",
- pmac_newworld ? "NewWorld" : "OldWorld");
+ seq_printf(m, "pmac-generation\t: %s\n",
+ pmac_newworld ? "NewWorld" : "OldWorld");
X
X
- return len;


+ return 0;
X }
X

X #ifdef CONFIG_SCSI
@@ -765,8 +784,8 @@
X DMA_MODE_WRITE = 2;
X
X ppc_md.setup_arch = pmac_setup_arch;
- ppc_md.setup_residual = NULL;
- ppc_md.get_cpuinfo = pmac_get_cpuinfo;
+ ppc_md.show_cpuinfo = pmac_show_cpuinfo;
+ ppc_md.show_percpuinfo = of_show_percpuinfo;
X ppc_md.irq_cannonicalize = NULL;
X ppc_md.init_IRQ = pmac_pic_init;
X ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.4.14/linux/arch/ppc/kernel/ppc_ksyms.c Mon Nov 5 15:55:26 2001
+++ linux/arch/ppc/kernel/ppc_ksyms.c Fri Nov 16 10:10:08 2001
@@ -1,5 +1,5 @@
X /*
- * BK Id: SCCS/s.ppc_ksyms.c 1.57 10/16/01 15:58:42 trini
+ * BK Id: SCCS/s.ppc_ksyms.c 1.59 11/04/01 22:58:20 paulus


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

X #include <linux/module.h>
@@ -58,6 +58,7 @@
X /* Tell string.h we don't want memcpy etc. as cpp defines */
X #define EXPORT_SYMTAB_STROPS
X
+extern void ppc_generic_ide_fix_driveid(struct hd_driveid *id);
X extern void transfer_to_handler(void);
X extern void syscall_trace(void);
X extern void do_IRQ(struct pt_regs *regs);
@@ -167,6 +168,7 @@
X EXPORT_SYMBOL(mm_ptov);
X
X EXPORT_SYMBOL(ppc_ide_md);
+EXPORT_SYMBOL(ppc_generic_ide_fix_driveid);
X
X #ifdef CONFIG_PCI
X EXPORT_SYMBOL_NOVERS(isa_io_base);
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- v2.4.14/linux/arch/ppc/kernel/prep_setup.c Mon Nov 5 15:55:26 2001
+++ linux/arch/ppc/kernel/prep_setup.c Fri Nov 16 10:10:08 2001
@@ -1,5 +1,5 @@
X /*
- * BK Id: SCCS/s.prep_setup.c 1.41 10/18/01 11:16:28 trini
+ * BK Id: SCCS/s.prep_setup.c 1.44 11/13/01 21:26:07 paulus
X */
X /*
X * linux/arch/ppc/kernel/setup.c
@@ -40,6 +40,7 @@
X #include <linux/timex.h>
X #include <linux/pci.h>
X #include <linux/ide.h>
+#include <linux/seq_file.h>
X
X #include <asm/sections.h>
X #include <asm/mmu.h>
@@ -122,107 +123,107 @@
X #endif
X
X static int __prep
-prep_get_cpuinfo(char *buffer)
+prep_show_cpuinfo(struct seq_file *m)
X {
X extern char *Motherboard_map_name;
- int len;
+ int cachew;
X #ifdef CONFIG_PREP_RESIDUAL
X int i;
X #endif
X
-#ifdef CONFIG_SMP
-#define CD(X) (cpu_data[n].X)
-#else
-#define CD(X) (X)
-#endif
+ seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name);
X
- len = sprintf(buffer,"machine\t\t: PReP %s\n",Motherboard_map_name);
-
-
- switch ( _prep_type )
- {
+ switch ( _prep_type ) {
X case _PREP_IBM:
- if ((*(unsigned char *)0x8000080c) & (1<<6))
- len += sprintf(buffer+len,"Upgrade CPU\n");
- len += sprintf(buffer+len,"L2\t\t: ");
- if ((*(unsigned char *)0x8000080c) & (1<<7))
- {
- len += sprintf(buffer+len,"not present\n");
+ cachew = inw(0x80c);
+ if (cachew & (1<<6))
+ seq_printf(m, "Upgrade CPU\n");
+ seq_printf(m, "L2\t\t: ");
+ if (cachew & (1<<7)) {
+ seq_printf(m, "not present\n");
X goto no_l2;
X }
- len += sprintf(buffer+len,"%sKb,",
- (((*(unsigned char *)0x8000080d)>>2)&1)
- ? "512" : "256");
- len += sprintf(buffer+len,"%ssync\n",
- ((*(unsigned char *)0x8000080d)>>7) ? "" : "a");
+ seq_printf(m, "%sKb,", (cachew & (1 << 10))? "512" : "256");
+ seq_printf(m, "%ssync\n", (cachew & (1 << 15))? "" : "a");
X break;
X case _PREP_Motorola:
- len += sprintf(buffer+len,"L2\t\t: ");
- switch(*((unsigned char *)CACHECRBA) & L2CACHE_MASK)
- {
+ cachew = *((unsigned char *)CACHECRBA);
+ seq_printf(m, "L2\t\t: ");
+ switch (cachew & L2CACHE_MASK) {
X case L2CACHE_512KB:
- len += sprintf(buffer+len,"512Kb");
+ seq_printf(m, "512Kb");
X break;
X case L2CACHE_256KB:
- len += sprintf(buffer+len,"256Kb");
+ seq_printf(m, "256Kb");
X break;
X case L2CACHE_1MB:
- len += sprintf(buffer+len,"1MB");
+ seq_printf(m, "1MB");
X break;
X case L2CACHE_NONE:
- len += sprintf(buffer+len,"none\n");
+ seq_printf(m, "none\n");
X goto no_l2;
X break;
X default:
- len += sprintf(buffer+len, "%x\n",
- *((unsigned char *)CACHECRBA));
+ seq_printf(m, "%x\n", cachew);
X }
X
- len += sprintf(buffer+len,",parity %s",
- (*((unsigned char *)CACHECRBA) & L2CACHE_PARITY)
- ? "enabled" : "disabled");
+ seq_printf(m, ", parity %s",
+ (cachew & L2CACHE_PARITY)? "enabled" : "disabled");
X
- len += sprintf(buffer+len, " SRAM:");
+ seq_printf(m, " SRAM:");
X
- switch ( ((*((unsigned char *)CACHECRBA) & 0xf0) >> 4) & ~(0x3) )
- {
- case 1: len += sprintf(buffer+len,
- "synchronous,parity,flow-through\n");
+ switch ( ((cachew & 0xf0) >> 4) & ~(0x3) ) {
+ case 1: seq_printf(m, "synchronous,parity,flow-through\n");
X break;
- case 2: len += sprintf(buffer+len,"asynchronous,no parity\n");
+ case 2: seq_printf(m, "asynchronous,no parity\n");
X break;
- case 3: len += sprintf(buffer+len,"asynchronous,parity\n");
+ case 3: seq_printf(m, "asynchronous,parity\n");
X break;
- default:len += sprintf(buffer+len,
- "synchronous,pipelined,no parity\n");
+ default:seq_printf(m, "synchronous,pipelined,no parity\n");
X break;
X }
X break;
X default:
X break;
X }
-
-
+
X no_l2:
-#ifndef CONFIG_PREP_RESIDUAL
- return len;
-#else
- if ( res->ResidualLength == 0 )
- return len;
-
- /* print info about SIMMs */
- len += sprintf(buffer+len,"simms\t\t: ");
- for ( i = 0 ; (res->ActualNumMemories) && (i < MAX_MEMS) ; i++ )
- {
- if ( res->Memories[i].SIMMSize != 0 )
- len += sprintf(buffer+len,"%d:%ldM ", i,
+#ifdef CONFIG_PREP_RESIDUAL
+ if (res->ResidualLength == 0) {
+ /* print info about SIMMs */
+ seq_printf(m, "simms\t\t: ");
+ for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {
+ if (res->Memories[i].SIMMSize != 0)
+ seq_printf(m, "%d:%ldM ", i,
X (res->Memories[i].SIMMSize > 1024) ?
X res->Memories[i].SIMMSize>>20 :
X res->Memories[i].SIMMSize);
+ }
+ seq_printf(m, "\n");
X }
- len += sprintf(buffer+len,"\n");
- return len;
X #endif
+


+ return 0;
+}
+

+static int __prep
+prep_show_percpuinfo(struct seq_file *m, int i)
+{
+ int len = 0;
+
+ /* PREP's without residual data will give incorrect values here */
+ seq_printf(m, "clock\t\t: ");
+#ifdef CONFIG_PREP_RESIDUAL
+ if (res->ResidualLength)
+ seq_printf(m, "%ldMHz\n",
+ (res->VitalProductData.ProcessorHz > 1024) ?
+ res->VitalProductData.ProcessorHz>>20 :
+ res->VitalProductData.ProcessorHz);
+ else
+#endif /* CONFIG_PREP_RESIDUAL */
+ seq_printf(m, "???\n");
+


+ return 0;
X }
X

X static void __init
@@ -628,26 +629,6 @@
X }
X }
X
-static int __prep
-prep_setup_residual(char *buffer)
-{
- int len = 0;
-
- /* PREP's without residual data will give incorrect values here */
- len += sprintf(len+buffer, "clock\t\t: ");
-#ifdef CONFIG_PREP_RESIDUAL
- if ( res->ResidualLength )
- len += sprintf(len+buffer, "%ldMHz\n",
- (res->VitalProductData.ProcessorHz > 1024) ?
- res->VitalProductData.ProcessorHz>>20 :
- res->VitalProductData.ProcessorHz);
- else
-#endif /* CONFIG_PREP_RESIDUAL */
- len += sprintf(len+buffer, "???\n");
-
- return len;
-}
-
X static unsigned int __prep
X prep_irq_cannonicalize(u_int irq)
X {
@@ -852,11 +833,8 @@
X unsigned long r6, unsigned long r7)
X {
X #ifdef CONFIG_PREP_RESIDUAL
- RESIDUAL *old_res = (RESIDUAL *)(r3 + KERNELBASE);
-
X /* make a copy of residual data */
- if ( r3 )
- {
+ if ( r3 ) {
X memcpy((void *)res,(void *)(r3+KERNELBASE),
X sizeof(RESIDUAL));
X }
@@ -900,8 +878,8 @@
X }
X
X ppc_md.setup_arch = prep_setup_arch;
- ppc_md.setup_residual = prep_setup_residual;
- ppc_md.get_cpuinfo = prep_get_cpuinfo;
+ ppc_md.show_percpuinfo = prep_show_percpuinfo;
+ ppc_md.show_cpuinfo = prep_show_cpuinfo;
X ppc_md.irq_cannonicalize = prep_irq_cannonicalize;
X ppc_md.init_IRQ = prep_init_IRQ;
X /* this gets changed later on if we have an OpenPIC -- Cort */
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.4.14/linux/arch/ppc/kernel/setup.c Mon Nov 5 15:55:26 2001
+++ linux/arch/ppc/kernel/setup.c Wed Nov 21 09:59:11 2001
@@ -1,5 +1,5 @@
X /*
- * BK Id: SCCS/s.setup.c 1.61 10/12/01 16:35:34 trini
+ * BK Id: SCCS/s.setup.c 1.65 11/18/01 20:57:25 trini
X */
X /*
X * Common prep/pmac/chrp boot and setup code.
@@ -16,6 +16,7 @@
X #include <linux/ide.h>
X #include <linux/tty.h>


X #include <linux/bootmem.h>
+#include <linux/seq_file.h>
X

X #include <asm/residual.h>
X #include <asm/io.h>
@@ -136,150 +137,128 @@
X extern u32 cpu_temp_both(unsigned long cpu);
X #endif /* CONFIG_TAU */
X
-int get_cpuinfo(char *buffer)
+int show_cpuinfo(struct seq_file *m, void *v)
X {
- unsigned long len = 0;
- unsigned long bogosum = 0;
- unsigned long i;
+ int i = (int) v - 1;


+ int err = 0;

X unsigned int pvr;
X unsigned short maj, min;
+ unsigned long lpj;
X
+ if (i >= NR_CPUS) {
+ /* Show summary information */
X #ifdef CONFIG_SMP
-#define CPU_PRESENT(x) (cpu_callin_map[(x)])
-#define GET_PVR ((long int)(cpu_data[i].pvr))
-#define CD(x) (cpu_data[i].x)
+ unsigned long bogosum = 0;


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

echo 'End of part 034'
echo 'File patch-2.4.15 is continued in part 035'
echo "035" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:11 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part035

#!/bin/sh -x
# this is part 035 of a 115 - part archive


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

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

+ for (i = 0; i < smp_num_cpus; ++i)
+ if (cpu_online_map & (1 << i))
+ bogosum += cpu_data[i].loops_per_jiffy;
+ seq_printf(m, "total bogomips\t: %lu.%02lu\n",
+ bogosum/(500000/HZ), bogosum/(5000/HZ) % 100);


+#endif /* CONFIG_SMP */
+

+ if (ppc_md.show_cpuinfo != NULL)
+ err = ppc_md.show_cpuinfo(m);


+ return err;
+ }
+

+#ifdef CONFIG_SMP
+ if (!(cpu_online_map & (1 << i)))
+ return 0;
+ pvr = cpu_data[i].pvr;
+ lpj = cpu_data[i].loops_per_jiffy;
+ seq_printf(m, "processor\t: %lu\n", i);
X #else
-#define CPU_PRESENT(x) ((x)==0)
-#define smp_num_cpus 1
-#define GET_PVR (mfspr(PVR))
-#define CD(x) (x)
-#endif
+ pvr = mfspr(PVR);
+ lpj = loops_per_jiffy;
+#endif
X
- for ( i = 0; i < smp_num_cpus ; i++ )
- {
- if ( !CPU_PRESENT(i) )
- continue;
- if ( i )
- len += sprintf(len+buffer,"\n");
- len += sprintf(len+buffer,"processor\t: %lu\n",i);
- len += sprintf(len+buffer,"cpu\t\t: ");
-
- pvr = GET_PVR;
-
- if (cur_cpu_spec[i]->pvr_mask)
- len += sprintf(len+buffer, "%s", cur_cpu_spec[i]->cpu_name);
- else
- len += sprintf(len+buffer, "unknown (%08x)", pvr);
+ seq_printf(m, "cpu\t\t: ");
+
+ if (cur_cpu_spec[i]->pvr_mask)
+ seq_printf(m, "%s", cur_cpu_spec[i]->cpu_name);
+ else
+ seq_printf(m, "unknown (%08x)", pvr);
X #ifdef CONFIG_ALTIVEC
- if (cur_cpu_spec[i]->cpu_features & CPU_FTR_ALTIVEC)
- len += sprintf(len+buffer, ", altivec supported");
-#endif
- len += sprintf(len+buffer, "\n");
+ if (cur_cpu_spec[i]->cpu_features & CPU_FTR_ALTIVEC)
+ seq_printf(m, ", altivec supported");
+#endif
+ seq_printf(m, "\n");
+
X #ifdef CONFIG_TAU
- if (cur_cpu_spec[i]->cpu_features & CPU_FTR_TAU) {
-#ifdef CONFIG_TAU_AVERAGE /* more straightforward, but potentially misleading */
- len += sprintf(len+buffer, "temperature \t: %u C (uncalibrated)\n",
- cpu_temp(i));
+ if (cur_cpu_spec[i]->cpu_features & CPU_FTR_TAU) {
+#ifdef CONFIG_TAU_AVERAGE
+ /* more straightforward, but potentially misleading */
+ seq_printf(m, "temperature \t: %u C (uncalibrated)\n",
+ cpu_temp(i));
X #else
- /* show the actual temp sensor range */
- u32 temp;
- temp = cpu_temp_both(i);
- len += sprintf(len+buffer, "temperature \t: %u-%u C (uncalibrated)\n",
- temp & 0xff, temp >> 16);
-#endif
- }
+ /* show the actual temp sensor range */
+ u32 temp;
+ temp = cpu_temp_both(i);
+ seq_printf(m, "temperature \t: %u-%u C (uncalibrated)\n",
+ temp & 0xff, temp >> 16);
X #endif
+ }
+#endif /* CONFIG_TAU */
X
- /*
- * Assume here that all clock rates are the same in a
- * smp system. -- Cort
- */
-#if defined(CONFIG_ALL_PPC)
- if ( have_of )
- {
- struct device_node *cpu_node;
- int *fp;
-
- cpu_node = find_type_devices("cpu");
- if ( !cpu_node ) break;
- {
- int s;
- for ( s = 0; (s < i) && cpu_node->next ;
- s++, cpu_node = cpu_node->next )
- /* nothing */ ;
-#if 0 /* SMP Pmacs don't have all cpu nodes -- Cort */
- if ( s != i )
- printk("get_cpuinfo(): ran out of "
- "cpu nodes.\n");
-#endif
- }
- fp = (int *) get_property(cpu_node, "clock-frequency", NULL);
- if ( !fp ) break;
- len += sprintf(len+buffer, "clock\t\t: %dMHz\n",
- *fp / 1000000);
- }
-#endif /* CONFIG_ALL_PPC */
+ if (ppc_md.show_percpuinfo != NULL) {
+ err = ppc_md.show_percpuinfo(m, i);
+ if (err)
+ return err;
+ }
X
- if (ppc_md.setup_residual != NULL)
- {
- len += ppc_md.setup_residual(buffer + len);
- }
-
- switch (PVR_VER(pvr))
- {
- case 0x0020:
- maj = PVR_MAJ(pvr) + 1;
- min = PVR_MIN(pvr);
- break;
- case 0x1008:
- maj = ((pvr >> 8) & 0xFF) - 1;
- min = pvr & 0xFF;
- break;
- default:
- maj = (pvr >> 8) & 0xFF;
- min = pvr & 0xFF;
- break;
- }
+ switch (PVR_VER(pvr)) {
+ case 0x0020: /* 403 family */
+ maj = PVR_MAJ(pvr) + 1;
+ min = PVR_MIN(pvr);
+ break;
+ case 0x1008: /* 740P/750P ?? */
+ maj = ((pvr >> 8) & 0xFF) - 1;
+ min = pvr & 0xFF;
+ break;
+ default:
+ maj = (pvr >> 8) & 0xFF;
+ min = pvr & 0xFF;
+ break;
+ }
X
- len += sprintf(len+buffer, "revision\t: %hd.%hd (pvr %04x %04x)\n",
- maj, min, PVR_VER(pvr), PVR_REV(pvr));
+ seq_printf(m, "revision\t: %hd.%hd (pvr %04x %04x)\n",
+ maj, min, PVR_VER(pvr), PVR_REV(pvr));
X
- len += sprintf(buffer+len, "bogomips\t: %lu.%02lu\n",
- CD(loops_per_jiffy)/(500000/HZ),
- CD(loops_per_jiffy)/(5000/HZ) % 100);
- bogosum += CD(loops_per_jiffy);
- }
+ seq_printf(m, "bogomips\t: %lu.%02lu\n",
+ lpj / (500000/HZ), (lpj / (5000/HZ)) % 100);
X
X #ifdef CONFIG_SMP
- if ( i && smp_num_cpus > 1)


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

- len += sprintf(buffer+len,"total bogomips\t: %lu.%02lu\n",
- bogosum/(500000/HZ),
- bogosum/(5000/HZ) % 100);
-#endif /* CONFIG_SMP */
+ seq_printf(m, "\n");
+#endif
X
- /*
- * Ooh's and aah's info about zero'd pages in idle task
- */
- len += sprintf(buffer+len,"zero pages\t: total: %u (%luKb) "
- "current: %u (%luKb) hits: %u/%u (%u%%)\n",
- atomic_read(&zero_cache_total),
- (atomic_read(&zero_cache_total)*PAGE_SIZE)>>10,
- atomic_read(&zero_cache_sz),
- (atomic_read(&zero_cache_sz)*PAGE_SIZE)>>10,
- atomic_read(&zero_cache_hits),atomic_read(&zero_cache_calls),
- /* : 1 below is so we don't div by zero */
- (atomic_read(&zero_cache_hits)*100) /
- ((atomic_read(&zero_cache_calls))?atomic_read(&zero_cache_calls):1));


+ return 0;
+}
X

- if (ppc_md.get_cpuinfo != NULL)
- {
- len += ppc_md.get_cpuinfo(buffer+len);
- }
X
- return len;


+static void *c_start(struct seq_file *m, loff_t *pos)
+{

+ int i = *pos;
+
+ return i <= NR_CPUS? (void *) (i + 1): NULL;
+}


+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return c_start(m, pos);

X }
X

+static void c_stop(struct seq_file *m, void *v)
+{

+}
+


+struct seq_operations cpuinfo_op = {
+ start: c_start,
+ next: c_next,
+ stop: c_stop,
+ show: show_cpuinfo,
+};

+
X /*
X * We're called here very early in the boot. We determine the machine
X * type and call the appropriate low-level setup functions.
@@ -468,8 +447,7 @@
X extern char __bss_start[];
X
X rec = (struct bi_record *)_ALIGN((ulong)__bss_start+(1<<20)-1,(1<<20));
- if ( rec->tag != BI_FIRST )
- {
+ if ( rec->tag != BI_FIRST ) {
X /*
X * This 0x10000 offset is a terrible hack but it will go away when
X * we have the bootloader handle all the relocation and
@@ -483,8 +461,7 @@
X rec = (struct bi_record *)((ulong)rec + rec->size) )
X {
X ulong *data = rec->data;
- switch (rec->tag)
- {
+ switch (rec->tag) {
X case BI_CMD_LINE:
X memcpy(cmd_line, (void *)data, rec->size);
X break;
@@ -495,8 +472,8 @@
X break;
X #ifdef CONFIG_BLK_DEV_INITRD
X case BI_INITRD:
- initrd_start = data[0];
- initrd_end = data[0] + data[1];
+ initrd_start = data[0] + KERNELBASE;
+ initrd_end = data[0] + data[1] + KERNELBASE;
X break;
X #endif /* CONFIG_BLK_DEV_INITRD */
X #ifdef CONFIG_ALL_PPC
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.4.14/linux/arch/ppc/kernel/smp.c Mon Nov 5 15:55:26 2001
+++ linux/arch/ppc/kernel/smp.c Wed Nov 21 10:31:09 2001
@@ -349,7 +349,7 @@


X init_tasks[i] = p;
X

X p->processor = i;
- p->has_cpu = 1;
+ p->cpus_runnable = 1 << i; /* we schedule the first task manually */

X current_set[i] = p;
X
X /*
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/kernel/walnut_setup.c linux/arch/ppc/kernel/walnut_setup.c
--- v2.4.14/linux/arch/ppc/kernel/walnut_setup.c Mon Nov 5 15:55:26 2001
+++ linux/arch/ppc/kernel/walnut_setup.c Fri Nov 16 10:10:08 2001


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

- * BK Id: SCCS/s.walnut_setup.c 1.8 10/18/01 11:16:28 trini
+ * BK Id: SCCS/s.walnut_setup.c 1.10 11/13/01 21:26:07 paulus


X */
X /*
X *
@@ -23,6 +23,7 @@
X #include <linux/param.h>
X #include <linux/string.h>
X #include <linux/blk.h>
+#include <linux/seq_file.h>
X
X #include <asm/processor.h>
X #include <asm/board.h>

@@ -101,8 +102,7 @@


X /* Initialize machine-dependency vectors */
X

X ppc_md.setup_arch = walnut_setup_arch;
- ppc_md.setup_residual = walnut_setup_residual;
- ppc_md.get_cpuinfo = NULL;
+ ppc_md.show_percpuinfo = walnut_show_percpuinfo;
X ppc_md.irq_cannonicalize = NULL;
X ppc_md.init_IRQ = walnut_init_IRQ;
X ppc_md.get_irq = walnut_get_irq;
@@ -136,7 +136,7 @@
X }
X
X /*
- * int walnut_setup_residual()
+ * int walnut_show_percpuinfo()


X *
X * Description:
X * This routine pretty-prints the platform's internal CPU and bus clock

@@ -154,18 +154,16 @@


X * on error.
X */
X int

-walnut_setup_residual(char *buffer)
+walnut_show_percpuinfo(struct seq_file *m)
X {


- int len = 0;
X bd_t *bp = (bd_t *)__res;
X
- len += sprintf(len + buffer,
- "clock\t\t: %dMHz\n"
- "bus clock\t\t: %dMHz\n",
- bp->bi_intfreq / 1000000,
- bp->bi_busfreq / 1000000);
+ seq_printf(m, "clock\t\t: %dMHz\n"
+ "bus clock\t\t: %dMHz\n",
+ bp->bi_intfreq / 1000000,
+ bp->bi_busfreq / 1000000);
X
- return (len);
+ return 0;
X }
X
X /*

diff -u --recursive --new-file v2.4.14/linux/arch/ppc/lib/Makefile linux/arch/ppc/lib/Makefile
--- v2.4.14/linux/arch/ppc/lib/Makefile Mon May 21 17:04:47 2001
+++ linux/arch/ppc/lib/Makefile Fri Nov 16 10:10:08 2001
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.7 05/17/01 18:14:22 cort
+# BK Id: SCCS/s.Makefile 1.10 11/08/01 07:57:40 paulus
X #
X #
X # Makefile for ppc-specific library files..
@@ -8,7 +8,9 @@
X
X O_TARGET := lib.o
X
-obj-y := checksum.o string.o strcase.o
+export-objs := dec_and_lock.o
+
+obj-y := checksum.o string.o strcase.o dec_and_lock.o
X
X obj-$(CONFIG_SMP) += locks.o
X
diff -u --recursive --new-file v2.4.14/linux/arch/ppc/lib/dec_and_lock.c linux/arch/ppc/lib/dec_and_lock.c
--- v2.4.14/linux/arch/ppc/lib/dec_and_lock.c Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/lib/dec_and_lock.c Fri Nov 16 10:10:08 2001
@@ -0,0 +1,46 @@
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+
+/*
+ * This is an implementation of the notion of "decrement a
+ * reference count, and return locked if it decremented to zero".
+ *
+ * This implementation can be used on any architecture that
+ * has a cmpxchg, and where atomic->value is an int holding
+ * the value of the atomic (i.e. the high bits aren't used
+ * for a lock or anything like that).
+ *
+ * N.B. ATOMIC_DEC_AND_LOCK gets defined in include/linux/spinlock.h
+ * if spinlocks are empty and thus atomic_dec_and_lock is defined
+ * to be atomic_dec_and_test - in that case we don't need it
+ * defined here as well.
+ */
+
+#ifndef ATOMIC_DEC_AND_LOCK
+int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
+{
+ int counter;
+ int newcount;
+
+ for (;;) {
+ counter = atomic_read(atomic);
+ newcount = counter - 1;
+ if (!newcount)
+ break; /* do it the slow way */
+
+ newcount = cmpxchg(&atomic->counter, counter, newcount);
+ if (newcount == counter)


+ return 0;
+ }
+

+ spin_lock(lock);
+ if (atomic_dec_and_test(atomic))
+ return 1;
+ spin_unlock(lock);


+ return 0;
+}
+

+EXPORT_SYMBOL(atomic_dec_and_lock);
+#endif /* ATOMIC_DEC_AND_LOCK */
diff -u --recursive --new-file v2.4.14/linux/arch/s390/config.in linux/arch/s390/config.in
--- v2.4.14/linux/arch/s390/config.in Sun Aug 12 13:27:58 2001
+++ linux/arch/s390/config.in Fri Nov 9 13:58:02 2001
@@ -9,6 +9,7 @@
X define_bool CONFIG_UID16 y


X define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
X define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n

+define_bool CONFIG_GENERIC_BUST_SPINLOCK n
X
X mainmenu_name "Linux Kernel Configuration"
X define_bool CONFIG_ARCH_S390 y
diff -u --recursive --new-file v2.4.14/linux/arch/s390/defconfig linux/arch/s390/defconfig
--- v2.4.14/linux/arch/s390/defconfig Sun Aug 12 13:27:58 2001
+++ linux/arch/s390/defconfig Fri Nov 9 13:58:02 2001
@@ -7,6 +7,7 @@
X CONFIG_UID16=y
X CONFIG_RWSEM_GENERIC_SPINLOCK=y
X # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_BUST_SPINLOCK=n
X CONFIG_ARCH_S390=y
X
X #
@@ -72,6 +73,7 @@
X CONFIG_MD_RAID0=m
X CONFIG_MD_RAID1=m
X CONFIG_MD_RAID5=m


+# CONFIG_MD_MULTIPATH is not set

X CONFIG_BLK_DEV_LVM=m
X
X #
@@ -183,19 +185,25 @@


X # CONFIG_AFFS_FS is not set
X # CONFIG_HFS_FS is not set
X # CONFIG_BFS_FS is not set

+# CONFIG_CMS_FS is not set


+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set

+# CONFIG_JBD_DEBUG is not set
X # CONFIG_FAT_FS is not set
X # CONFIG_MSDOS_FS is not set
X # CONFIG_UMSDOS_FS is not set
X # CONFIG_VFAT_FS is not set
X # CONFIG_EFS_FS is not set
X # CONFIG_JFFS_FS is not set


+# CONFIG_JFFS2_FS is not set
X # CONFIG_CRAMFS is not set

X # CONFIG_TMPFS is not set
X # CONFIG_RAMFS is not set
X # CONFIG_ISO9660_FS is not set


X # CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
X # CONFIG_MINIX_FS is not set

-# CONFIG_VXFS_FS is not set
+# CONFIG_FREEVXFS_FS is not set


X # CONFIG_NTFS_FS is not set

X # CONFIG_NTFS_RW is not set


X # CONFIG_HPFS_FS is not set

@@ -218,6 +226,7 @@


X # Network File Systems
X #
X # CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
X CONFIG_NFS_FS=y

X # CONFIG_NFS_V3 is not set
X # CONFIG_ROOT_NFS is not set
@@ -235,6 +244,8 @@
X # CONFIG_NCPFS_SMALLDOS is not set
X # CONFIG_NCPFS_NLS is not set
X # CONFIG_NCPFS_EXTRAS is not set


+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
X
X #
X # Partition Types

@@ -247,6 +258,7 @@
X CONFIG_IBM_PARTITION=y
X # CONFIG_MAC_PARTITION is not set
X # CONFIG_MSDOS_PARTITION is not set


+# CONFIG_LDM_PARTITION is not set

X # CONFIG_SGI_PARTITION is not set
X # CONFIG_ULTRIX_PARTITION is not set
X # CONFIG_SUN_PARTITION is not set
diff -u --recursive --new-file v2.4.14/linux/arch/s390/kernel/entry.S linux/arch/s390/kernel/entry.S
--- v2.4.14/linux/arch/s390/kernel/entry.S Tue Oct 23 22:48:49 2001
+++ linux/arch/s390/kernel/entry.S Fri Nov 9 13:58:02 2001
@@ -256,9 +256,17 @@
X #
X sysc_tracesys:
X l %r1,BASED(.Ltrace)
- l %r2,BASED(.Lc_ENOSYS)
- st %r2,SP_R2(%r15) # give sysc_trace an -ENOSYS retval
+ l %r7,BASED(.Lc_ENOSYS)
+ st %r7,SP_R2(%r15) # give sysc_trace an -ENOSYS retval
X basr %r14,%r1
+ l %r2,SP_R2(%r15)
+ cr %r2,%r7 # compare with saved -ENOSYS
+ be BASED(sysc_tracesys_dn1)
+ # strace wants to change the syscall
+ sll %r2,24
+ srl %r2,22
+ l %r8,sys_call_table-entry_base(2,%r13) # get address of system call
+sysc_tracesys_dn1:
X lm %r3,%r6,SP_R3(%r15)
X l %r2,SP_ORIG_R2(%r15)
X basr %r14,%r8 # call sys_xxx
@@ -689,10 +697,7 @@
X l %r5,SP_PSW+4(15) # load psw addr
X sr %r5,%r7 # substract ilc from psw
X st %r5,SP_PSW+4(15) # store corrected psw addr
-pgm_per:cl %r3,BASED(.Lc20) # pseudo page fault ?
- be BASED(pgm_go) # if yes then don't reenable interrupts
- stosm 24(%r15),0x03 # reenable interrupts
-pgm_go: basr %r14,%r1 # branch to interrupt-handler
+pgm_per:basr %r14,%r1 # branch to interrupt-handler
X pgm_dn: n %r8,BASED(.Lc128) # check for per excepton
X be BASED(pgm_return)
X la %r2,SP_PTREGS(15) # address of register-save area
diff -u --recursive --new-file v2.4.14/linux/arch/s390/kernel/head.S linux/arch/s390/kernel/head.S
--- v2.4.14/linux/arch/s390/kernel/head.S Tue Oct 23 22:48:49 2001
+++ linux/arch/s390/kernel/head.S Fri Nov 9 13:58:02 2001
@@ -338,12 +338,12 @@
X # reset files in VM reader
X #
X stidp __LC_CPUID # store cpuid
- lh %r0,__LC_CPUID+4 # get cpu version
- chi %r0,0x7490 # running on P/390 ?
- be start # no -> skip reset
+ tm __LC_CPUID,0xff # running VM ?
+ bno .Lnoreset
X la %r2,.Lreset
X lhi %r3,26
X .long 0x83230008
+.Lnoreset:
X #endif
X
X #
diff -u --recursive --new-file v2.4.14/linux/arch/s390/kernel/init_task.c linux/arch/s390/kernel/init_task.c
--- v2.4.14/linux/arch/s390/kernel/init_task.c Sun Sep 23 11:40:56 2001
+++ linux/arch/s390/kernel/init_task.c Fri Nov 9 13:58:02 2001
@@ -12,6 +12,7 @@
X #include <asm/uaccess.h>
X #include <asm/pgtable.h>


X
+static struct vm_area_struct init_mmap = INIT_MMAP;
X static struct fs_struct init_fs = INIT_FS;
X static struct files_struct init_files = INIT_FILES;
X static struct signal_struct init_signals = INIT_SIGNALS;

diff -u --recursive --new-file v2.4.14/linux/arch/s390/kernel/s390_ksyms.c linux/arch/s390/kernel/s390_ksyms.c
--- v2.4.14/linux/arch/s390/kernel/s390_ksyms.c Tue Oct 23 22:48:49 2001
+++ linux/arch/s390/kernel/s390_ksyms.c Fri Nov 9 13:58:02 2001
@@ -59,4 +59,3 @@
X EXPORT_SYMBOL_NOVERS(do_call_softirq);
X
X
-
diff -u --recursive --new-file v2.4.14/linux/arch/s390/kernel/setup.c linux/arch/s390/kernel/setup.c
--- v2.4.14/linux/arch/s390/kernel/setup.c Tue Oct 23 22:48:50 2001
+++ linux/arch/s390/kernel/setup.c Fri Nov 16 18:38:39 2001
@@ -34,6 +34,7 @@
X #endif
X #include <linux/bootmem.h>


X #include <linux/console.h>
+#include <linux/seq_file.h>

X #include <asm/uaccess.h>
X #include <asm/system.h>
X #include <asm/smp.h>
@@ -478,49 +479,48 @@
X }
X
X /*
- * get_cpuinfo - Get information on one CPU for use by procfs.


- *
- * Prints info on the next CPU into buffer. Beware, doesn't check for
- * buffer overflow. Current implementation of procfs assumes that the
- * resulting data is <= 1K.
- *
- * Args:

- * buffer -- you guessed it, the data buffer
- * cpu_np -- Input: next cpu to get (start at 0). Output: Updated.
- *
- * Returns number of bytes written to buffer.
+ * show_cpuinfo - Get information on one CPU for use by procfs.
X */
X

-int get_cpuinfo(char *buffer, unsigned *cpu_np)

+static int show_cpuinfo(struct seq_file *m, void *v)
X {
X struct cpuinfo_S390 *cpuinfo;


- char *p = buffer;

- unsigned n;
+ unsigned n = v;
X
- n = *cpu_np;
- while (n < NR_CPUS && (cpu_online_map & (1 << n)) == 0)
- n++;
- if (n >= NR_CPUS) {
- *cpu_np = NR_CPUS;
- return (0);
- }
- *cpu_np = n + 1;
-
- if (n == 0) {
- p += sprintf(p,"vendor_id : IBM/S390\n"
+ if (!n--) {
+ seq_printf(m, "vendor_id : IBM/S390\n"
X "# processors : %i\n"
X "bogomips per cpu: %lu.%02lu\n",
X smp_num_cpus, loops_per_jiffy/(500000/HZ),
X (loops_per_jiffy/(5000/HZ))%100);
+ } else if (cpu_online_map & (1 << n)) {
+ cpuinfo = &safe_get_cpu_lowcore(n).cpu_data;
+ seq_printf(m, "processor %i: "
+ "version = %02X, "
+ "identification = %06X, "
+ "machine = %04X\n",
+ n, cpuinfo->cpu_id.version,
+ cpuinfo->cpu_id.ident,
+ cpuinfo->cpu_id.machine);
X }
- cpuinfo = &safe_get_cpu_lowcore(n).cpu_data;
- p += sprintf(p,"processor %i: "
- "version = %02X, "
- "identification = %06X, "
- "machine = %04X\n",
- n, cpuinfo->cpu_id.version,
- cpuinfo->cpu_id.ident,
- cpuinfo->cpu_id.machine);


- return p - buffer;

+ return 0;
X }
X

+static void *c_start(struct seq_file *m, loff_t *pos)
+{

+ return *pos <= NR_CPUS ? (void)(*pos+1) : NULL;


+}
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return c_start(m, pos);
+}
+static void c_stop(struct seq_file *m, void *v)
+{

+}


+struct seq_operations cpuinfo_op = {
+ start: c_start,
+ next: c_next,
+ stop: c_stop,
+ show: show_cpuinfo,

+};
diff -u --recursive --new-file v2.4.14/linux/arch/s390/kernel/smp.c linux/arch/s390/kernel/smp.c
--- v2.4.14/linux/arch/s390/kernel/smp.c Tue Oct 23 22:48:50 2001
+++ linux/arch/s390/kernel/smp.c Wed Nov 21 10:31:09 2001
@@ -531,7 +531,7 @@
X if (!idle)


X panic("No idle process for CPU %d",cpu);

X idle->processor = cpu;

- idle->has_cpu = 1; /* we schedule the first task manually */
+ idle->cpus_runnable = 1 << cpu; /* we schedule the first task manually */
X
X del_from_runqueue(idle);
X unhash_process(idle);
diff -u --recursive --new-file v2.4.14/linux/arch/s390/kernel/traps.c linux/arch/s390/kernel/traps.c
--- v2.4.14/linux/arch/s390/kernel/traps.c Tue Oct 23 22:48:50 2001
+++ linux/arch/s390/kernel/traps.c Fri Nov 9 13:58:02 2001
@@ -94,8 +94,16 @@
X static void inline do_trap(long interruption_code, int signr, char *str,
X struct pt_regs *regs, siginfo_t *info)
X {
+ /*
+ * We got all needed information from the lowcore and can
+ * now safely switch on interrupts.
+ */
+ if (regs->psw.mask & PSW_PROBLEM_STATE)
+ __sti();
+
X if (regs->psw.mask & PSW_PROBLEM_STATE) {
X struct task_struct *tsk = current;
+
X tsk->thread.trap_no = interruption_code;
X if (info)
X force_sig_info(signr, info, tsk);
@@ -160,20 +168,27 @@
X __u8 opcode[6];
X __u16 *location;
X int signal = 0;
- int problem_state=(regs->psw.mask & PSW_PROBLEM_STATE);
X
X location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
- if(problem_state)
+
+ /*
+ * We got all needed information from the lowcore and can
+ * now safely switch on interrupts.
+ */
+ if (regs->psw.mask & PSW_PROBLEM_STATE)
+ __sti();
+
+ if (regs->psw.mask & PSW_PROBLEM_STATE)
X get_user(*((__u16 *) opcode), location);
X else
X *((__u16 *)opcode)=*((__u16 *)location);
- if(*((__u16 *)opcode)==S390_BREAKPOINT_U16)
+ if (*((__u16 *)opcode)==S390_BREAKPOINT_U16)
X {
X if(do_debugger_trap(regs,SIGTRAP))
X signal = SIGILL;
X }
X #ifdef CONFIG_MATHEMU
- else if (problem_state)
+ else if (regs->psw.mask & PSW_PROBLEM_STATE)
X {
X if (opcode[0] == 0xb3) {
X get_user(*((__u16 *) (opcode+2)), location+1);
@@ -216,8 +231,16 @@
X __u16 *location = NULL;
X int signal = 0;
X
+ location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
+
+ /*
+ * We got all needed information from the lowcore and can
+ * now safely switch on interrupts.
+ */
+ if (regs->psw.mask & PSW_PROBLEM_STATE)
+ __sti();
+
X if (regs->psw.mask & PSW_PROBLEM_STATE) {
- location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
X get_user(*((__u16 *) opcode), location);
X switch (opcode[0]) {
X case 0x28: /* LDR Rx,Ry */
@@ -267,6 +290,14 @@
X int signal = 0;
X
X location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
+
+ /*
+ * We got all needed information from the lowcore and can
+ * now safely switch on interrupts.
+ */
+ if (regs->psw.mask & PSW_PROBLEM_STATE)
+ __sti();
+
X if (MACHINE_HAS_IEEE)
X __asm__ volatile ("stfpc %0\n\t"
X : "=m" (current->thread.fp_regs.fpc));
diff -u --recursive --new-file v2.4.14/linux/arch/s390/mm/fault.c linux/arch/s390/mm/fault.c
--- v2.4.14/linux/arch/s390/mm/fault.c Tue Oct 23 22:48:50 2001
+++ linux/arch/s390/mm/fault.c Fri Nov 9 13:58:02 2001
@@ -159,14 +159,17 @@
X /*
X * Check whether we have a user MM in the first place.
X */
- if (in_interrupt() || !mm)
+ if (in_interrupt() || !mm || !(regs->psw.mask & _PSW_IO_MASK_BIT))
X goto no_context;
X
X /*
X * When we get here, the fault happened in the current
- * task's user address space, so we search the VMAs
+ * task's user address space, so we can switch on the
+ * interrupts again and then search the VMAs
X */
X
+ __sti();
+
X down_read(&mm->mmap_sem);
X
X vma = find_vma(mm, address);
@@ -415,7 +418,11 @@
X " la 2,0(%0)\n"
X " sacf 512\n"
X " ic 2,0(2)\n"
- " sacf 0"
+ "0:sacf 0\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .long 0b,0b\n"
+ ".previous"
X : : "a" (address) : "2" );
X
X return;
@@ -513,7 +520,7 @@
X * external interrupt.
X */
X subcode = S390_lowcore.cpu_addr;
- if ((subcode & 0xff00) != 0x0600)
+ if ((subcode & 0xff00) != 0x0200)
X return;
X
X /*
@@ -522,6 +529,13 @@
X tsk = (struct task_struct *)
X (*((unsigned long *) __LC_PFAULT_INTPARM) - THREAD_SIZE);
X
+ /*
+ * We got all needed information from the lowcore and can
+ * now safely switch on interrupts.
+ */
+ if (regs->psw.mask & PSW_PROBLEM_STATE)
+ __sti();
+
X if (subcode & 0x0080) {
X /* signal bit is set -> a page has been swapped in by VM */
X qp = (wait_queue_head_t *)
diff -u --recursive --new-file v2.4.14/linux/arch/s390x/defconfig linux/arch/s390x/defconfig
--- v2.4.14/linux/arch/s390x/defconfig Tue Oct 23 22:48:50 2001
+++ linux/arch/s390x/defconfig Fri Nov 9 13:58:02 2001
@@ -185,19 +185,25 @@


X # CONFIG_AFFS_FS is not set
X # CONFIG_HFS_FS is not set
X # CONFIG_BFS_FS is not set

+# CONFIG_CMS_FS is not set


+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set

+# CONFIG_JBD_DEBUG is not set
X # CONFIG_FAT_FS is not set
X # CONFIG_MSDOS_FS is not set
X # CONFIG_UMSDOS_FS is not set
X # CONFIG_VFAT_FS is not set
X # CONFIG_EFS_FS is not set
X # CONFIG_JFFS_FS is not set


+# CONFIG_JFFS2_FS is not set
X # CONFIG_CRAMFS is not set

X # CONFIG_TMPFS is not set
X # CONFIG_RAMFS is not set
X # CONFIG_ISO9660_FS is not set


X # CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
X # CONFIG_MINIX_FS is not set

-# CONFIG_VXFS_FS is not set
+# CONFIG_FREEVXFS_FS is not set


X # CONFIG_NTFS_FS is not set

X # CONFIG_NTFS_RW is not set


X # CONFIG_HPFS_FS is not set

@@ -220,6 +226,7 @@


X # Network File Systems
X #
X # CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
X CONFIG_NFS_FS=y

X # CONFIG_NFS_V3 is not set
X # CONFIG_ROOT_NFS is not set
@@ -237,6 +244,8 @@
X # CONFIG_NCPFS_SMALLDOS is not set
X # CONFIG_NCPFS_NLS is not set
X # CONFIG_NCPFS_EXTRAS is not set


+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
X
X #
X # Partition Types

diff -u --recursive --new-file v2.4.14/linux/arch/s390x/kernel/entry.S linux/arch/s390x/kernel/entry.S
--- v2.4.14/linux/arch/s390x/kernel/entry.S Tue Oct 23 22:48:50 2001
+++ linux/arch/s390x/kernel/entry.S Fri Nov 9 13:58:02 2001
@@ -247,6 +247,17 @@
X lghi %r2,-ENOSYS
X stg %r2,SP_R2(%r15) # give sysc_trace an -ENOSYS retval
X brasl %r14,syscall_trace
+ lg %r2,SP_R2(%r15)
+ cghi %r2,-ENOSYS
+ je sysc_tracesys_dn1
+ sllg %r2,%r2,56 # strace wants to change the syscall
+ srlg %r2,%r2,53 # zap unused bits & multiply by 8
+ tm SP_PSW+3(%r15),0x01 # are we running in 31 bit mode ?
+ jo sysc_tracesys_noemu
+ la %r2,4(%r2) # use 31 bit emulation system calls
+sysc_tracesys_noemu:
+ lgf %r8,0(%r2,%r7) # load address of system call routine
+sysc_tracesys_dn1:
X lmg %r3,%r6,SP_R3(%r15)
X lg %r2,SP_ORIG_R2(%r15)
X basr %r14,%r8 # call sys_xxx
@@ -672,7 +683,6 @@
X GET_CURRENT
X pgm_no_sv:
X llgh %r8,__LC_PGM_INT_CODE # N.B. saved int code used later KEEP it
- stosm 48(%r15),0x03 # reenable interrupts
X lghi %r3,0x7f
X nr %r3,%r8 # clear per-event-bit & move to r3
X je pgm_dn # none of Martins exceptions occurred bypass
diff -u --recursive --new-file v2.4.14/linux/arch/s390x/kernel/head.S linux/arch/s390x/kernel/head.S
--- v2.4.14/linux/arch/s390x/kernel/head.S Tue Oct 23 22:48:50 2001
+++ linux/arch/s390x/kernel/head.S Fri Nov 9 13:58:02 2001
@@ -337,12 +337,12 @@
X # reset files in VM reader
X #
X stidp __LC_CPUID # store cpuid
- lh %r0,__LC_CPUID+4 # get cpu version
- chi %r0,0x7490 # running on P/390 ?
- be start # no -> skip reset
+ tm __LC_CPUID,0xff # running VM ?
+ bno .Lnoreset
X la %r2,.Lreset
X lhi %r3,26
X .long 0x83230008
+.Lnoreset:
X #endif
X
X #
diff -u --recursive --new-file v2.4.14/linux/arch/s390x/kernel/init_task.c linux/arch/s390x/kernel/init_task.c
--- v2.4.14/linux/arch/s390x/kernel/init_task.c Sun Sep 23 11:40:56 2001
+++ linux/arch/s390x/kernel/init_task.c Fri Nov 9 13:58:02 2001
@@ -12,6 +12,7 @@
X #include <asm/uaccess.h>
X #include <asm/pgtable.h>


X
+static struct vm_area_struct init_mmap = INIT_MMAP;
X static struct fs_struct init_fs = INIT_FS;
X static struct files_struct init_files = INIT_FILES;
X static struct signal_struct init_signals = INIT_SIGNALS;

diff -u --recursive --new-file v2.4.14/linux/arch/s390x/kernel/ioctl32.c linux/arch/s390x/kernel/ioctl32.c
--- v2.4.14/linux/arch/s390x/kernel/ioctl32.c Tue Oct 23 22:48:50 2001
+++ linux/arch/s390x/kernel/ioctl32.c Wed Nov 7 14:39:36 2001
@@ -487,6 +487,13 @@
X IOCTL32_HANDLER(SIOCADDRT, routing_ioctl),
X IOCTL32_HANDLER(SIOCDELRT, routing_ioctl),
X
+ IOCTL32_HANDLER(SIOCBONDENSLAVE, bond_ioctl),
+ IOCTL32_HANDLER(SIOCBONDRELEASE, bond_ioctl),
+ IOCTL32_HANDLER(SIOCBONDSETHWADDR, bond_ioctl),
+ IOCTL32_HANDLER(SIOCBONDSLAVEINFOQUERY, bond_ioctl),
+ IOCTL32_HANDLER(SIOCBONDINFOQUERY, bond_ioctl),
+ IOCTL32_HANDLER(SIOCBONDCHANGEACTIVE, bond_ioctl),
+
X IOCTL32_HANDLER(EXT2_IOC32_GETFLAGS, do_ext2_ioctl),
X IOCTL32_HANDLER(EXT2_IOC32_SETFLAGS, do_ext2_ioctl),
X IOCTL32_HANDLER(EXT2_IOC32_GETVERSION, do_ext2_ioctl),
diff -u --recursive --new-file v2.4.14/linux/arch/s390x/kernel/setup.c linux/arch/s390x/kernel/setup.c
--- v2.4.14/linux/arch/s390x/kernel/setup.c Tue Oct 23 22:48:50 2001
+++ linux/arch/s390x/kernel/setup.c Fri Nov 16 18:38:39 2001
@@ -34,6 +34,7 @@
X #endif
X #include <linux/bootmem.h>


X #include <linux/console.h>
+#include <linux/seq_file.h>

X #include <asm/uaccess.h>
X #include <asm/system.h>
X #include <asm/smp.h>
@@ -467,49 +468,48 @@
X }
X
X /*
- * get_cpuinfo - Get information on one CPU for use by procfs.


- *
- * Prints info on the next CPU into buffer. Beware, doesn't check for
- * buffer overflow. Current implementation of procfs assumes that the
- * resulting data is <= 1K.
- *
- * Args:

- * buffer -- you guessed it, the data buffer
- * cpu_np -- Input: next cpu to get (start at 0). Output: Updated.
- *
- * Returns number of bytes written to buffer.
+ * show_cpuinfo - Get information on one CPU for use by procfs.
X */
X

-int get_cpuinfo(char *buffer, unsigned *cpu_np)

+static int show_cpuinfo(struct seq_file *m, void *v)
X {
X struct cpuinfo_S390 *cpuinfo;


- char *p = buffer;

- unsigned n;
+ unsigned n = v;
X
- n = *cpu_np;
- while (n < NR_CPUS && (cpu_online_map & (1 << n)) == 0)
- n++;
- if (n >= NR_CPUS) {
- *cpu_np = NR_CPUS;
- return (0);
- }
- *cpu_np = n + 1;
-
- if (n == 0) {
- p += sprintf(p, "vendor_id : IBM/S390\n"
+ if (!n--) {
+ seq_printf(m, "vendor_id : IBM/S390\n"
X "# processors : %i\n"
X "bogomips per cpu: %lu.%02lu\n",
X smp_num_cpus, loops_per_jiffy/(500000/HZ),
X (loops_per_jiffy/(5000/HZ))%100);
+ } else if (cpu_online_map & (1 << n)) {
+ cpuinfo = &safe_get_cpu_lowcore(n).cpu_data;
+ seq_printf(m, "processor %i: "
+ "version = %02X, "
+ "identification = %06X, "
+ "machine = %04X\n",
+ n, cpuinfo->cpu_id.version,
+ cpuinfo->cpu_id.ident,
+ cpuinfo->cpu_id.machine);
X }
- cpuinfo = &safe_get_cpu_lowcore(n).cpu_data;
- p += sprintf(p, "processor %i: "
- "version = %02X, "
- "identification = %06X, "
- "machine = %04X\n",
- n, cpuinfo->cpu_id.version,
- cpuinfo->cpu_id.ident,
- cpuinfo->cpu_id.machine);


- return p - buffer;

+ return 0;
X }
X

+static void *c_start(struct seq_file *m, loff_t *pos)
+{

+ return *pos <= NR_CPUS ? (void)(*pos+1) : NULL;


+}
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return c_start(m, pos);
+}
+static void c_stop(struct seq_file *m, void *v)
+{

+}


+struct seq_operations cpuinfo_op = {
+ start: c_start,
+ next: c_next,
+ stop: c_stop,
+ show: show_cpuinfo,

+};
diff -u --recursive --new-file v2.4.14/linux/arch/s390x/kernel/smp.c linux/arch/s390x/kernel/smp.c
--- v2.4.14/linux/arch/s390x/kernel/smp.c Tue Oct 23 22:48:50 2001
+++ linux/arch/s390x/kernel/smp.c Wed Nov 21 10:31:09 2001
@@ -510,7 +510,7 @@
X if (!idle)


X panic("No idle process for CPU %d",cpu);

X idle->processor = cpu;

- idle->has_cpu = 1; /* we schedule the first task manually */
+ idle->cpus_runnable = 1 << cpu; /* we schedule the first task manually */
X
X del_from_runqueue(idle);
X unhash_process(idle);
diff -u --recursive --new-file v2.4.14/linux/arch/s390x/kernel/traps.c linux/arch/s390x/kernel/traps.c
--- v2.4.14/linux/arch/s390x/kernel/traps.c Tue Oct 23 22:48:50 2001
+++ linux/arch/s390x/kernel/traps.c Fri Nov 9 13:58:02 2001
@@ -92,6 +92,13 @@
X static void inline do_trap(long interruption_code, int signr, char *str,
X struct pt_regs *regs, siginfo_t *info)
X {
+ /*
+ * We got all needed information from the lowcore and can
+ * now safely switch on interrupts.
+ */
+ if (regs->psw.mask & PSW_PROBLEM_STATE)
+ __sti();
+
X if (regs->psw.mask & PSW_PROBLEM_STATE) {
X struct task_struct *tsk = current;
X tsk->thread.trap_no = interruption_code;
@@ -161,6 +168,14 @@
X int do_sig = 0;
X
X location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
+
+ /*
+ * We got all needed information from the lowcore and can
+ * now safely switch on interrupts.
+ */
+ if (regs->psw.mask & PSW_PROBLEM_STATE)
+ __sti();
+
X /* WARNING don't change this check back to */
X /* int problem_state=(regs->psw.mask & PSW_PROBLEM_STATE); */
X /* & then doing if(problem_state) an int is too small for this */
@@ -186,6 +201,14 @@
X int do_sig = 0;
X
X location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
+
+ /*
+ * We got all needed information from the lowcore and can
+ * now safely switch on interrupts.
+ */
+ if (regs->psw.mask & PSW_PROBLEM_STATE)
+ __sti();
+
X __asm__ volatile ("stfpc %0\n\t"
X : "=m" (current->thread.fp_regs.fpc));
X /* Same code should work when we implement fpu emulation */
diff -u --recursive --new-file v2.4.14/linux/arch/s390x/kernel/wrapper32.S linux/arch/s390x/kernel/wrapper32.S
--- v2.4.14/linux/arch/s390x/kernel/wrapper32.S Tue Oct 23 22:48:50 2001
+++ linux/arch/s390x/kernel/wrapper32.S Fri Nov 9 13:58:02 2001
@@ -629,8 +629,10 @@
X .globl sys32_llseek_wrapper
X sys32_llseek_wrapper:
X llgfr %r2,%r2 # unsigned int
- lgfr %r3,%r3 # off_t
- llgfr %r4,%r4 # unsigned int
+ llgfr %r3,%r3 # unsigned long
+ llgfr %r4,%r4 # unsigned long
+ llgtr %r5,%r5 # loff_t *
+ llgfr %r6,%r6 # unsigned int
X jg sys_llseek # branch to system call
X
X .globl sys32_getdents_wrapper
diff -u --recursive --new-file v2.4.14/linux/arch/s390x/mm/fault.c linux/arch/s390x/mm/fault.c
--- v2.4.14/linux/arch/s390x/mm/fault.c Tue Oct 23 22:48:50 2001
+++ linux/arch/s390x/mm/fault.c Fri Nov 9 13:58:02 2001
@@ -159,14 +159,17 @@
X /*
X * Check whether we have a user MM in the first place.
X */
- if (in_interrupt() || !mm)
+ if (in_interrupt() || !mm || !(regs->psw.mask & _PSW_IO_MASK_BIT))
X goto no_context;
X
X /*
X * When we get here, the fault happened in the current
- * task's user address space, so we search the VMAs
+ * task's user address space, so we can switch on the
+ * interrupts again and then search the VMAs
X */
X
+ __sti();
+
X down_read(&mm->mmap_sem);
X
X vma = find_vma(mm, address);
@@ -419,6 +422,13 @@
X */
X tsk = (struct task_struct *)
X (*((unsigned long *) __LC_PFAULT_INTPARM) - THREAD_SIZE);
+
+ /*
+ * We got all needed information from the lowcore and can
+ * now safely switch on interrupts.
+ */
+ if (regs->psw.mask & PSW_PROBLEM_STATE)
+ __sti();
X
X if (subcode & 0x0080) {
X /* signal bit is set -> a page has been swapped in by VM */
diff -u --recursive --new-file v2.4.14/linux/arch/s390x/mm/init.c linux/arch/s390x/mm/init.c
--- v2.4.14/linux/arch/s390x/mm/init.c Tue Oct 23 22:48:50 2001
+++ linux/arch/s390x/mm/init.c Fri Nov 9 13:58:02 2001
@@ -59,7 +59,7 @@
X }
X if(pte_quicklist) {
X pte_free_slow(pte_alloc_one_fast(NULL, 0));
- freed += 4;
+ freed += 1;
X }
X } while(pgtable_cache_size > low);
X }
diff -u --recursive --new-file v2.4.14/linux/arch/sh/kernel/setup.c linux/arch/sh/kernel/setup.c
--- v2.4.14/linux/arch/sh/kernel/setup.c Sun Sep 23 11:40:56 2001
+++ linux/arch/sh/kernel/setup.c Fri Nov 16 18:38:39 2001
@@ -31,6 +31,7 @@
X #include <linux/bootmem.h>
X #include <linux/console.h>
X #include <linux/ctype.h>
+#include <linux/seq_file.h>
X #include <asm/processor.h>
X #include <asm/page.h>
X #include <asm/pgtable.h>
@@ -517,24 +518,22 @@


X * Get CPU information for use by the procfs.
X */

X #ifdef CONFIG_PROC_FS
-int get_cpuinfo(char *buffer)
+static int show_cpuinfo(struct seq_file *m, void *v)
X {


- char *p = buffer;
-

X #if defined(__sh3__)
- p += sprintf(p,"cpu family\t: SH-3\n"
- "cache size\t: 8K-byte\n");
+ seq_printf(m, "cpu family\t: SH-3\n"
+ "cache size\t: 8K-byte\n");
X #elif defined(__SH4__)
- p += sprintf(p,"cpu family\t: SH-4\n"
- "cache size\t: 8K-byte/16K-byte\n");
+ seq_printf(m, "cpu family\t: SH-4\n"
+ "cache size\t: 8K-byte/16K-byte\n");
X #endif
- p += sprintf(p, "bogomips\t: %lu.%02lu\n\n",
+ seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
X loops_per_jiffy/(500000/HZ),
X (loops_per_jiffy/(5000/HZ)) % 100);
- p += sprintf(p, "Machine: %s\n", sh_mv.mv_name);
+ seq_printf(m, "Machine: %s\n", sh_mv.mv_name);
X
X #define PRINT_CLOCK(name, value) \
- p += sprintf(p, name " clock: %d.%02dMHz\n", \
+ seq_printf(m, name " clock: %d.%02dMHz\n", \
X ((value) / 1000000), ((value) % 1000000)/10000)
X
X PRINT_CLOCK("CPU", boot_cpu_data.cpu_clock);
@@ -544,6 +543,24 @@
X #endif
X PRINT_CLOCK("Peripheral module", boot_cpu_data.module_clock);
X

- return p - buffer;

+ return 0;
+}
+

+static void *c_start(struct seq_file *m, loff_t *pos)
+{

+ return (void*)(*pos == 0);
X }


+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{

+ return NULL;


+}
+static void c_stop(struct seq_file *m, void *v)
+{

+}


+struct seq_operations cpuinfo_op = {
+ start: c_start,
+ next: c_next,
+ stop: c_stop,
+ show: show_cpuinfo,
+};

X #endif
diff -u --recursive --new-file v2.4.14/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.4.14/linux/arch/sparc/defconfig Mon Nov 5 15:55:26 2001
+++ linux/arch/sparc/defconfig Tue Nov 13 09:16:05 2001
@@ -270,11 +270,15 @@
X CONFIG_AUTOFS4_FS=m


X # CONFIG_REISERFS_FS is not set
X # CONFIG_REISERFS_CHECK is not set

+# CONFIG_REISERFS_PROC_INFO is not set


X # CONFIG_ADFS_FS is not set

X # CONFIG_ADFS_FS_RW is not set
X CONFIG_AFFS_FS=m


X # CONFIG_HFS_FS is not set
X # CONFIG_BFS_FS is not set

+CONFIG_EXT3_FS=m
+CONFIG_JBD=m


+# CONFIG_JBD_DEBUG is not set

X CONFIG_FAT_FS=m
X CONFIG_MSDOS_FS=m


X # CONFIG_UMSDOS_FS is not set

@@ -287,6 +291,7 @@


X # CONFIG_RAMFS is not set

X CONFIG_ISO9660_FS=m


X # CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set

X CONFIG_MINIX_FS=m
X # CONFIG_VXFS_FS is not set


X # CONFIG_NTFS_FS is not set

@@ -311,6 +316,7 @@


X # Network File Systems
X #

X CONFIG_CODA_FS=m
+CONFIG_INTERMEZZO_FS=m
X CONFIG_NFS_FS=y
X # CONFIG_NFS_V3 is not set
X # CONFIG_ROOT_NFS is not set
@@ -329,6 +335,8 @@
X # CONFIG_NCPFS_SMALLDOS is not set
X # CONFIG_NCPFS_NLS is not set
X # CONFIG_NCPFS_EXTRAS is not set


+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
X
X #
X # Partition Types

diff -u --recursive --new-file v2.4.14/linux/arch/sparc/kernel/ebus.c linux/arch/sparc/kernel/ebus.c
--- v2.4.14/linux/arch/sparc/kernel/ebus.c Sun Aug 12 13:27:59 2001
+++ linux/arch/sparc/kernel/ebus.c Tue Nov 13 09:16:05 2001
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.17 2001/08/06 13:12:57 davem Exp $
+/* $Id: ebus.c,v 1.18 2001/11/08 04:41:33 davem Exp $
X * ebus.c: PCI to EBus bridge device.
X *
X * Copyright (C) 1997 Eddie C. Dost (e...@skynet.be)
@@ -113,6 +113,9 @@
X dev->resource[i].start = dev->parent->resource[regs[i]].start; /* XXX resource */
X }
X
+ for (i = 0; i < PROMINTR_MAX; i++)
+ dev->irqs[i] = PCI_IRQ_NONE;
+
X if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) {
X dev->num_irqs = 1;
X } else if ((len = prom_getproperty(node, "interrupts",
@@ -204,6 +207,9 @@
X }
X dev->resource[i].start = baseaddr; /* XXX Unaligned */
X }
+
+ for (i = 0; i < PROMINTR_MAX; i++)
+ dev->irqs[i] = PCI_IRQ_NONE;
X
X if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) {
X dev->num_irqs = 1;
diff -u --recursive --new-file v2.4.14/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S
--- v2.4.14/linux/arch/sparc/kernel/entry.S Mon Jan 29 08:08:46 2001
+++ linux/arch/sparc/kernel/entry.S Tue Nov 13 09:16:05 2001
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.169 2001/01/25 21:47:20 davem Exp $
+/* $Id: entry.S,v 1.170 2001/11/13 00:57:05 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)
@@ -1461,21 +1461,12 @@
X b 2f
X mov %i4, %o4
X
- .globl C_LABEL(ret_from_syscall)
-C_LABEL(ret_from_syscall):
- b C_LABEL(ret_sys_call)
- ld [%sp + REGWIN_SZ + PT_I0], %o0
-
-#ifdef CONFIG_SMP
- .globl C_LABEL(ret_from_smpfork)
-C_LABEL(ret_from_smpfork):
- wr %l0, PSR_ET, %psr
- WRITE_PAUSE
+ .globl C_LABEL(ret_from_fork)
+C_LABEL(ret_from_fork):
X call schedule_tail
X mov %g3, %o0
X b C_LABEL(ret_sys_call)
X ld [%sp + REGWIN_SZ + PT_I0], %o0
-#endif
X
X /* Linux native and SunOS system calls enter here... */
X .align 4
diff -u --recursive --new-file v2.4.14/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- v2.4.14/linux/arch/sparc/kernel/process.c Thu Oct 11 08:02:26 2001
+++ linux/arch/sparc/kernel/process.c Tue Nov 13 09:16:05 2001
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.156 2001/10/02 02:22:26 davem Exp $
+/* $Id: process.c,v 1.157 2001/11/13 00:57:05 davem Exp $
X * linux/arch/sparc/kernel/process.c
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -455,11 +455,7 @@
X * allocate the task_struct and kernel stack in
X * do_fork().
X */
-#ifdef CONFIG_SMP
-extern void ret_from_smpfork(void);
-#else
-extern void ret_from_syscall(void);
-#endif
+extern void ret_from_fork(void);
X
X int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
X unsigned long unused,
@@ -493,13 +489,8 @@
X copy_regwin(new_stack, (((struct reg_window *) regs) - 1));
X
X p->thread.ksp = (unsigned long) new_stack;
-#ifdef CONFIG_SMP
- p->thread.kpc = (((unsigned long) ret_from_smpfork) - 0x8);
- p->thread.kpsr = current->thread.fork_kpsr | PSR_PIL;
-#else
- p->thread.kpc = (((unsigned long) ret_from_syscall) - 0x8);
+ p->thread.kpc = (((unsigned long) ret_from_fork) - 0x8);
X p->thread.kpsr = current->thread.fork_kpsr;
-#endif
X p->thread.kwim = current->thread.fork_kwim;
X
X /* This is used for sun4c only */
diff -u --recursive --new-file v2.4.14/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c
--- v2.4.14/linux/arch/sparc/kernel/setup.c Sun Sep 23 11:40:56 2001
+++ linux/arch/sparc/kernel/setup.c Tue Nov 13 09:16:05 2001
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.125 2001/09/20 00:35:30 davem Exp $
+/* $Id: setup.c,v 1.126 2001/11/13 00:49:27 davem Exp $
X * linux/arch/sparc/kernel/setup.c
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -20,6 +20,7 @@
X #include <linux/delay.h>
X #include <linux/config.h>
X #include <linux/fs.h>
+#include <linux/seq_file.h>
X #include <linux/kdev_t.h>
X #include <linux/major.h>
X #include <linux/string.h>
@@ -455,42 +456,72 @@
X return -EIO;
X }
X
-/* BUFFER is PAGE_SIZE bytes long. */
-
X extern char *sparc_cpu_type[];
X extern char *sparc_fpu_type[];
X
-int get_cpuinfo(char *buffer)
+static int show_cpuinfo(struct seq_file *m, void *__unused)
X {
- int cpuid=hard_smp_processor_id();
- int len;
+ int cpuid = hard_smp_processor_id();
X
- len = sprintf(buffer, "cpu\t\t: %s\n"


- "fpu\t\t: %s\n"

- "promlib\t\t: Version %d Revision %d\n"
- "prom\t\t: %d.%d\n"
- "type\t\t: %s\n"
- "ncpus probed\t: %d\n"
- "ncpus active\t: %d\n"
+ seq_printf(m,
+ "cpu\t\t: %s\n"


+ "fpu\t\t: %s\n"

+ "promlib\t\t: Version %d Revision %d\n"
+ "prom\t\t: %d.%d\n"
+ "type\t\t: %s\n"
+ "ncpus probed\t: %d\n"
+ "ncpus active\t: %d\n"
X #ifndef CONFIG_SMP
- "BogoMips\t: %lu.%02lu\n"
+ "BogoMips\t: %lu.%02lu\n"
X #endif
- ,
- sparc_cpu_type[cpuid] ? : "undetermined",
- sparc_fpu_type[cpuid] ? : "undetermined",
- romvec->pv_romvers, prom_rev, romvec->pv_printrev >> 16, (short)romvec->pv_printrev,
- &cputypval,
- linux_num_cpus, smp_num_cpus
+ ,
+ sparc_cpu_type[cpuid] ? : "undetermined",
+ sparc_fpu_type[cpuid] ? : "undetermined",
+ romvec->pv_romvers,
+ prom_rev,
+ romvec->pv_printrev >> 16,
+ (short) romvec->pv_printrev,
+ &cputypval,
+ linux_num_cpus,
+ smp_num_cpus
X #ifndef CONFIG_SMP
- , loops_per_jiffy/(500000/HZ), (loops_per_jiffy/(5000/HZ)) % 100
+ , loops_per_jiffy/(500000/HZ),
+ (loops_per_jiffy/(5000/HZ)) % 100
X #endif
- );
+ );
+
X #ifdef CONFIG_SMP
- len += smp_bogo_info(buffer + len);
+ smp_bogo_info(m);
X #endif
- len += mmu_info(buffer + len);
+ mmu_info(m);


X #ifdef CONFIG_SMP
- len += smp_info(buffer + len);

+ smp_info(m);
X #endif


- return len;
+ return 0;

+}
+


+static void *c_start(struct seq_file *m, loff_t *pos)
+{

+ /* The pointer we are returning is arbitrary,
+ * it just has to be non-NULL and not IS_ERR
+ * in the success case.
+ */
+ return *pos == 0 ? &c_start : NULL;
+}


+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return c_start(m, pos);

X }


+
+static void c_stop(struct seq_file *m, void *v)
+{

+}
+


+struct seq_operations cpuinfo_op = {
+ start: c_start,
+ next: c_next,
+ stop: c_stop,
+ show: show_cpuinfo,

+};
diff -u --recursive --new-file v2.4.14/linux/arch/sparc/kernel/smp.c linux/arch/sparc/kernel/smp.c
--- v2.4.14/linux/arch/sparc/kernel/smp.c Mon Jan 1 10:37:41 2001
+++ linux/arch/sparc/kernel/smp.c Tue Nov 13 09:16:05 2001
@@ -16,6 +16,8 @@
X #include <linux/init.h>
X #include <linux/spinlock.h>
X #include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
X
X #include <asm/ptrace.h>
X #include <asm/atomic.h>
@@ -276,25 +278,26 @@


X return 0;
X }
X

-int smp_bogo_info(char *buf)
+void smp_bogo_info(struct seq_file *m)
X {
- int len = 0, i;
+ int i;
X
- for (i = 0; i < NR_CPUS; i++)
+ for (i = 0; i < NR_CPUS; i++) {
X if (cpu_present_map & (1 << i))
- len += sprintf(buf + len, "Cpu%dBogo\t: %lu.%02lu\n",
- i,
- cpu_data[i].udelay_val/(500000/HZ),
- (cpu_data[i].udelay_val/(5000/HZ))%100);
- return len;
+ seq_printf(m,
+ "Cpu%dBogo\t: %lu.%02lu\n",
+ i,
+ cpu_data[i].udelay_val/(500000/HZ),
+ (cpu_data[i].udelay_val/(5000/HZ))%100);
+ }
X }
X
-int smp_info(char *buf)
+void smp_info(struct seq_file *m)
X {
- int len = 0, i;
+ int i;
X
- for (i = 0; i < NR_CPUS; i++)
+ for (i = 0; i < NR_CPUS; i++) {
X if (cpu_present_map & (1 << i))
- len += sprintf(buf + len, "CPU%d\t\t: online\n", i);
- return len;
+ seq_printf(m, "CPU%d\t\t: online\n", i);
+ }
X }
diff -u --recursive --new-file v2.4.14/linux/arch/sparc/kernel/sun4d_smp.c linux/arch/sparc/kernel/sun4d_smp.c
--- v2.4.14/linux/arch/sparc/kernel/sun4d_smp.c Fri Feb 9 11:37:03 2001
+++ linux/arch/sparc/kernel/sun4d_smp.c Wed Nov 21 10:31:09 2001
@@ -225,7 +225,7 @@


X init_tasks[i] = p;
X
X p->processor = i;
- p->has_cpu = 1; /* we schedule the first task manually */

+ p->cpus_runnable = 1 << i; /* we schedule the first task manually */
X
X current_set[i] = p;
X
diff -u --recursive --new-file v2.4.14/linux/arch/sparc/kernel/sun4m_smp.c linux/arch/sparc/kernel/sun4m_smp.c
--- v2.4.14/linux/arch/sparc/kernel/sun4m_smp.c Fri Feb 9 11:37:03 2001
+++ linux/arch/sparc/kernel/sun4m_smp.c Wed Nov 21 10:31:09 2001
@@ -198,7 +198,7 @@


X init_tasks[i] = p;
X
X p->processor = i;
- p->has_cpu = 1; /* we schedule the first task manually */

+ p->cpus_runnable = 1 << i; /* we schedule the first task manually */
X
X current_set[i] = p;
X
diff -u --recursive --new-file v2.4.14/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- v2.4.14/linux/arch/sparc/mm/srmmu.c Mon Nov 5 15:55:27 2001
+++ linux/arch/sparc/mm/srmmu.c Tue Nov 13 09:16:05 2001
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.232 2001/10/30 04:54:22 davem Exp $
+/* $Id: srmmu.c,v 1.233 2001/11/13 00:49:27 davem Exp $
X * srmmu.c: SRMMU specific routines for memory management.
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -18,6 +18,8 @@
X #include <linux/blk.h>
X #include <linux/spinlock.h>
X #include <linux/bootmem.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
X
X #include <asm/page.h>
X #include <asm/pgalloc.h>
@@ -1209,18 +1211,17 @@
X }
X }
X
-static int srmmu_mmu_info(char *buf)
+static void srmmu_mmu_info(struct seq_file *m)
X {
- return sprintf(buf,
- "MMU type\t: %s\n"
- "contexts\t: %d\n"
- "nocache total\t: %ld\n"
- "nocache used\t: %d\n"
- , srmmu_name,
- num_contexts,
- SRMMU_NOCACHE_SIZE,
- (srmmu_nocache_used << SRMMU_NOCACHE_BITMAP_SHIFT)
- );
+ seq_printf(m,
+ "MMU type\t: %s\n"
+ "contexts\t: %d\n"
+ "nocache total\t: %ld\n"
+ "nocache used\t: %d\n",
+ srmmu_name,
+ num_contexts,
+ SRMMU_NOCACHE_SIZE,
+ (srmmu_nocache_used << SRMMU_NOCACHE_BITMAP_SHIFT));
X }
X
X static void srmmu_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte)
diff -u --recursive --new-file v2.4.14/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c
--- v2.4.14/linux/arch/sparc/mm/sun4c.c Mon Nov 5 15:55:27 2001
+++ linux/arch/sparc/mm/sun4c.c Tue Nov 13 09:16:05 2001
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.208 2001/10/30 04:54:22 davem Exp $
+/* $Id: sun4c.c,v 1.210 2001/11/13 03:27:47 davem Exp $
X * sun4c.c: Doing in software what should be done in hardware.
X *
X * Copyright (C) 1996 David S. Miller (da...@caip.rutgers.edu)
@@ -16,6 +16,8 @@
X #include <linux/init.h>
X #include <linux/bootmem.h>
X #include <linux/highmem.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
X
X #include <asm/scatterlist.h>
X #include <asm/page.h>
@@ -2043,40 +2045,37 @@
X }
X }
X
-static int sun4c_mmu_info(char *buf)
+static void sun4c_mmu_info(struct seq_file *m)
X {
X int used_user_entries, i;
- int len;
X
X used_user_entries = 0;
X for (i = 0; i < num_contexts; i++)
X used_user_entries += sun4c_context_ring[i].num_entries;
X
- len = sprintf(buf,
- "vacsize\t\t: %d bytes\n"
- "vachwflush\t: %s\n"
- "vaclinesize\t: %d bytes\n"
- "mmuctxs\t\t: %d\n"
- "mmupsegs\t: %d\n"
- "kernelpsegs\t: %d\n"
- "kfreepsegs\t: %d\n"
- "usedpsegs\t: %d\n"
- "ufreepsegs\t: %d\n"
- "user_taken\t: %d\n"
- "max_taken\t: %d\n",
- sun4c_vacinfo.num_bytes,
- (sun4c_vacinfo.do_hwflushes ? "yes" : "no"),
- sun4c_vacinfo.linesize,
- num_contexts,
- (invalid_segment + 1),
- sun4c_kernel_ring.num_entries,
- sun4c_kfree_ring.num_entries,
- used_user_entries,
- sun4c_ufree_ring.num_entries,
- sun4c_user_taken_entries,
- max_user_taken_entries);
-
- return len;
+ seq_printf(m,
+ "vacsize\t\t: %d bytes\n"
+ "vachwflush\t: %s\n"
+ "vaclinesize\t: %d bytes\n"
+ "mmuctxs\t\t: %d\n"
+ "mmupsegs\t: %d\n"
+ "kernelpsegs\t: %d\n"
+ "kfreepsegs\t: %d\n"
+ "usedpsegs\t: %d\n"
+ "ufreepsegs\t: %d\n"
+ "user_taken\t: %d\n"
+ "max_taken\t: %d\n",
+ sun4c_vacinfo.num_bytes,
+ (sun4c_vacinfo.do_hwflushes ? "yes" : "no"),
+ sun4c_vacinfo.linesize,
+ num_contexts,
+ (invalid_segment + 1),
+ sun4c_kernel_ring.num_entries,
+ sun4c_kfree_ring.num_entries,
+ used_user_entries,
+ sun4c_ufree_ring.num_entries,
+ sun4c_user_taken_entries,
+ max_user_taken_entries);
X }
X
X /* Nothing below here should touch the mmu hardware nor the mmu_entry
@@ -2100,7 +2099,6 @@
X }
X static void sun4c_pte_clear(pte_t *ptep) { *ptep = __pte(0); }
X
-static int sun4c_pmd_none(pmd_t pmd) { return !pmd_val(pmd); }
X static int sun4c_pmd_bad(pmd_t pmd)
X {
X return (((pmd_val(pmd) & ~PAGE_MASK) != PGD_TABLE) ||
diff -u --recursive --new-file v2.4.14/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.4.14/linux/arch/sparc64/config.in Sun Sep 23 11:40:56 2001
+++ linux/arch/sparc64/config.in Tue Nov 13 09:16:05 2001
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.150 2001/09/18 00:36:03 davem Exp $
+# $Id: config.in,v 1.152 2001/11/12 10:20:47 davem Exp $


X # For a description of the syntax of this configuration file,

X # see the Configure script.
X #
@@ -181,8 +181,17 @@
X bool ' Collect statistics to report in /proc' CONFIG_AIC7XXX_OLD_PROC_STATS
X fi
X fi
- dep_tristate 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI
- dep_tristate 'SYM53C8XX SCSI support' CONFIG_SCSI_SYM53C8XX $CONFIG_SCSI
+ dep_tristate 'SYM53C8XX Version 2 SCSI support' CONFIG_SCSI_SYM53C8XX_2 $CONFIG_SCSI
+ if [ "$CONFIG_SCSI_SYM53C8XX_2" != "n" ]; then
+ int ' DMA addressing mode' CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE 1
+ int ' default tagged command queue depth' CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS 16
+ int ' maximum number of queued commands' CONFIG_SCSI_SYM53C8XX_MAX_TAGS 64
+ bool ' use normal IO' CONFIG_SCSI_SYM53C8XX_IOMAPPED
+ fi
+ if [ "$CONFIG_SCSI_SYM53C8XX_2" != "y" ]; then
+ dep_tristate 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI
+ dep_tristate 'SYM53C8XX SCSI support' CONFIG_SCSI_SYM53C8XX $CONFIG_SCSI
+ fi
X if [ "$CONFIG_SCSI_NCR53C8XX" != "n" -o "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then
X int 'default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8
X int 'maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32
@@ -211,7 +220,9 @@
X
X source drivers/fc4/Config.in
X
-source drivers/message/fusion/Config.in


+if [ "$CONFIG_PCI" = "y" ]; then
+ source drivers/message/fusion/Config.in
+fi

X
X source drivers/ieee1394/Config.in
X
diff -u --recursive --new-file v2.4.14/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.4.14/linux/arch/sparc64/defconfig Mon Nov 5 15:55:27 2001
+++ linux/arch/sparc64/defconfig Tue Nov 13 09:16:05 2001
@@ -70,6 +70,7 @@
X # CONFIG_PARPORT_AMIGA is not set
X # CONFIG_PARPORT_MFC3 is not set
X # CONFIG_PARPORT_ATARI is not set
+# CONFIG_PARPORT_GSC is not set
X # CONFIG_PARPORT_SUNBPP is not set
X # CONFIG_PARPORT_OTHER is not set
X CONFIG_PARPORT_1284=y
@@ -215,7 +216,27 @@
X #
X # QoS and/or fair queueing
X #
-# CONFIG_NET_SCHED is not set
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_CSZ=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_POLICE=y
X
X #
X # ATA/IDE/MFM/RLL support
@@ -333,6 +354,7 @@
X CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y
X CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=8
X CONFIG_AIC7XXX_OLD_PROC_STATS=y


+# CONFIG_SCSI_SYM53C8XX_2 is not set

X CONFIG_SCSI_NCR53C8XX=m
X CONFIG_SCSI_SYM53C8XX=y
X CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=4
@@ -411,6 +433,9 @@
X # Appletalk devices
X #
X # CONFIG_APPLETALK is not set
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+# CONFIG_IPDDP is not set
X CONFIG_DUMMY=m
X CONFIG_BONDING=m
X CONFIG_EQUALIZER=m
@@ -560,11 +585,15 @@
X CONFIG_AUTOFS4_FS=m


X # CONFIG_REISERFS_FS is not set
X # CONFIG_REISERFS_CHECK is not set

+# CONFIG_REISERFS_PROC_INFO is not set


X # CONFIG_ADFS_FS is not set

X # CONFIG_ADFS_FS_RW is not set
X CONFIG_AFFS_FS=m


X # CONFIG_HFS_FS is not set

X CONFIG_BFS_FS=m
+CONFIG_EXT3_FS=m
+CONFIG_JBD=m


+# CONFIG_JBD_DEBUG is not set

X CONFIG_FAT_FS=m
X CONFIG_MSDOS_FS=m


X # CONFIG_UMSDOS_FS is not set

@@ -577,6 +606,7 @@
X CONFIG_RAMFS=m
X CONFIG_ISO9660_FS=m
X CONFIG_JOLIET=y


+# CONFIG_ZISOFS is not set

X CONFIG_MINIX_FS=m
X # CONFIG_VXFS_FS is not set


X # CONFIG_NTFS_FS is not set

@@ -601,6 +631,7 @@


X # Network File Systems
X #

X CONFIG_CODA_FS=m
+CONFIG_INTERMEZZO_FS=m
X CONFIG_NFS_FS=y
X CONFIG_NFS_V3=y


X # CONFIG_ROOT_NFS is not set

@@ -619,6 +650,8 @@
X # CONFIG_NCPFS_SMALLDOS is not set
X # CONFIG_NCPFS_NLS is not set
X # CONFIG_NCPFS_EXTRAS is not set


+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
X
X #
X # Partition Types

@@ -708,7 +741,6 @@
X CONFIG_USB_DEVICEFS=y
X # CONFIG_USB_BANDWIDTH is not set
X # CONFIG_USB_LONG_TIMEOUT is not set
-# CONFIG_USB_LARGE_CONFIG is not set
X
X #
X # USB Controllers
diff -u --recursive --new-file v2.4.14/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c
--- v2.4.14/linux/arch/sparc64/kernel/ebus.c Tue Jul 3 17:08:19 2001
+++ linux/arch/sparc64/kernel/ebus.c Tue Nov 13 09:16:05 2001
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.63 2001/06/08 02:27:16 davem Exp $
+/* $Id: ebus.c,v 1.64 2001/11/08 04:41:33 davem Exp $
X * ebus.c: PCI to EBus bridge device.
X *
X * Copyright (C) 1997 Eddie C. Dost (e...@skynet.be)
@@ -134,6 +134,9 @@
X }
X }
X
+ for (i = 0; i < PROMINTR_MAX; i++)
+ dev->irqs[i] = PCI_IRQ_NONE;
+
X len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
X if ((len == -1) || (len == 0)) {
X dev->num_irqs = 0;
@@ -221,6 +224,9 @@
X }


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

echo 'End of part 035'
echo 'File patch-2.4.15 is continued in part 036'
echo "036" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:07 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part031

#!/bin/sh -x
# this is part 031 of a 115 - part archive


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

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

X ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT);
+
+ init_handler_platform(regs); /* call platform specific routines */
+}
+
+/*
+ * ia64_log_prt_guid
+ *
+ * Print a formatted GUID.
+ *
+ * Inputs : p_guid (ptr to the GUID)
+ * prfunc (print function)


+ * Outputs : None
+ *

+ */
+void
+ia64_log_prt_guid (efi_guid_t *p_guid, prfunc_t prfunc)
+{
+ printk("GUID = { %08x, %04x, %04x, { %#02x, %#02x, %#02x, %#02x, "
+ "%#02x, %#02x, %#02x, %#02x, } } \n ", p_guid->data1,
+ p_guid->data2, p_guid->data3, p_guid->data4[0], p_guid->data4[1],
+ p_guid->data4[2], p_guid->data4[3], p_guid->data4[4],
+ p_guid->data4[5], p_guid->data4[6], p_guid->data4[7]);
+}
+
+static void
+ia64_log_hexdump(unsigned char *p, unsigned long n_ch, prfunc_t prfunc)
+{
+ int i, j;
+
+ if (!p)
+ return;
+
+ for (i = 0; i < n_ch;) {
+ prfunc("%p ", (void *)p);
+ for (j = 0; (j < 16) && (i < n_ch); i++, j++, p++) {
+ prfunc("%02x ", *p);
+ }
+ prfunc("\n");
+ }
+}
+
+#ifdef MCA_PRT_XTRA_DATA // for test only @FVL
+
+static void
+ia64_log_prt_record_header (sal_log_record_header_t *rh, prfunc_t prfunc)
+{
+ prfunc("SAL RECORD HEADER: Record buffer = %p, header size = %ld\n",
+ (void *)rh, sizeof(sal_log_record_header_t));
+ ia64_log_hexdump((unsigned char *)rh, sizeof(sal_log_record_header_t),
+ (prfunc_t)prfunc);
+ prfunc("Total record length = %d\n", rh->len);
+ ia64_log_prt_guid(&rh->platform_guid, prfunc);
+ prfunc("End of SAL RECORD HEADER\n");
+}
+
+static void
+ia64_log_prt_section_header (sal_log_section_hdr_t *sh, prfunc_t prfunc)
+{
+ prfunc("SAL SECTION HEADER: Record buffer = %p, header size = %ld\n",
+ (void *)sh, sizeof(sal_log_section_hdr_t));
+ ia64_log_hexdump((unsigned char *)sh, sizeof(sal_log_section_hdr_t),
+ (prfunc_t)prfunc);
+ prfunc("Length of section & header = %d\n", sh->len);
+ ia64_log_prt_guid(&sh->guid, prfunc);
+ prfunc("End of SAL SECTION HEADER\n");
X }
+#endif // MCA_PRT_XTRA_DATA for test only @FVL
X
X /*
X * ia64_log_init
X * Reset the OS ia64 log buffer
- * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC})
- * sub_info_type (SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM})
+ * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
X * Outputs : None
X */
X void
-ia64_log_init(int sal_info_type, int sal_sub_info_type)
+ia64_log_init(int sal_info_type)
X {
- IA64_LOG_LOCK_INIT(sal_info_type, sal_sub_info_type);
- IA64_LOG_NEXT_INDEX(sal_info_type, sal_sub_info_type) = 0;
- memset(IA64_LOG_NEXT_BUFFER(sal_info_type, sal_sub_info_type), 0,
- sizeof(ia64_psilog_t) * IA64_MAX_LOGS);
+ IA64_LOG_LOCK_INIT(sal_info_type);
+ IA64_LOG_NEXT_INDEX(sal_info_type) = 0;
+ memset(IA64_LOG_NEXT_BUFFER(sal_info_type), 0,
+ sizeof(ia64_err_rec_t) * IA64_MAX_LOGS);
X }
X
X /*
X * ia64_log_get
+ *
X * Get the current MCA log from SAL and copy it into the OS log buffer.
- * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC})
- * sub_info_type (SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM})
- * Outputs : None
+ *
+ * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
+ * prfunc (fn ptr of log output function)
+ * Outputs : size (total record length)
X *
X */
-void
-ia64_log_get(int sal_info_type, int sal_sub_info_type, prfunc_t prfunc)
+u64
+ia64_log_get(int sal_info_type, prfunc_t prfunc)
X {
- sal_log_header_t *log_buffer;
- int s,total_len=0;
-
- IA64_LOG_LOCK(sal_info_type, sal_sub_info_type);
+ sal_log_record_header_t *log_buffer;
+ u64 total_len = 0;
+ int s;
X
+ IA64_LOG_LOCK(sal_info_type);
X
X /* Get the process state information */
- log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type, sal_sub_info_type);
-
- if (!(total_len=ia64_sal_get_state_info(sal_info_type,(u64 *)log_buffer)))
- prfunc("ia64_mca_log_get : Getting processor log failed\n");
+ log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type);
X
- IA64_MCA_DEBUG("ia64_log_get: retrieved %d bytes of error information\n",total_len);
-
- IA64_LOG_INDEX_INC(sal_info_type, sal_sub_info_type);
-
- IA64_LOG_UNLOCK(sal_info_type, sal_sub_info_type);
+ total_len = ia64_sal_get_state_info(sal_info_type, (u64 *)log_buffer);
X
+ if (total_len) {
+ IA64_LOG_INDEX_INC(sal_info_type);
+ IA64_LOG_UNLOCK(sal_info_type);
+ IA64_MCA_DEBUG("ia64_log_get: SAL error record type %d retrieved. "
+ "Record length = %ld\n", sal_info_type, total_len);
+ return total_len;
+ } else {
+ IA64_LOG_UNLOCK(sal_info_type);
+ prfunc("ia64_log_get: Failed to retrieve SAL error record type %d\n",
+ sal_info_type);


+ return 0;
+ }
X }

X
X /*
- * ia64_log_clear
- * Clear the current MCA log from SAL and dpending on the clear_os_buffer flags
- * clear the OS log buffer also
- * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC})
- * sub_info_type (SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM})
- * clear_os_buffer
+ * ia64_log_prt_oem_data
+ *
+ * Print OEM specific data if included.
+ *
+ * Inputs : header_len (length passed in section header)
+ * sect_len (default length of section type)
+ * p_data (ptr to data)
X * prfunc (print function)
X * Outputs : None


X *
X */
X void

-ia64_log_clear(int sal_info_type, int sal_sub_info_type, int clear_os_buffer, prfunc_t prfunc)
+ia64_log_prt_oem_data (int header_len, int sect_len, u8 *p_data, prfunc_t prfunc)
X {
- if (ia64_sal_clear_state_info(sal_info_type))
- prfunc("ia64_mca_log_get : Clearing processor log failed\n");
-
- if (clear_os_buffer) {
- sal_log_header_t *log_buffer;
- int s;
-
- IA64_LOG_LOCK(sal_info_type, sal_sub_info_type);
-
- /* Get the process state information */
- log_buffer = IA64_LOG_CURR_BUFFER(sal_info_type, sal_sub_info_type);
-
- memset(log_buffer, 0, sizeof(ia64_psilog_t));
+ int oem_data_len, i;
X
- IA64_LOG_INDEX_DEC(sal_info_type, sal_sub_info_type);
-
- IA64_LOG_UNLOCK(sal_info_type, sal_sub_info_type);
+ if ((oem_data_len = header_len - sect_len) > 0) {
+ prfunc(" OEM Specific Data:");
+ for (i = 0; i < oem_data_len; i++, p_data++)
+ prfunc(" %02x", *p_data);
X }
+ prfunc("\n");
+}
X
+/*
+ * ia64_log_rec_header_print
+ *
+ * Log info from the SAL error record header.
+ *
+ * Inputs : lh * (ptr to SAL log error record header)
+ * prfunc (fn ptr of log output function to use)


+ * Outputs : None
+ */
+void

+ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc)
+{
+ char str_buf[32];
+
+ sprintf(str_buf, "%2d.%02d",
+ (lh->revision.major >> 4) * 10 + (lh->revision.major & 0xf),
+ (lh->revision.minor >> 4) * 10 + (lh->revision.minor & 0xf));
+ prfunc("+Err Record ID: %d SAL Rev: %s\n", lh->id, str_buf);
+ sprintf(str_buf, "%02d/%02d/%04d/ %02d:%02d:%02d",
+ (lh->timestamp.slh_month >> 4) * 10 +
+ (lh->timestamp.slh_month & 0xf),
+ (lh->timestamp.slh_day >> 4) * 10 +
+ (lh->timestamp.slh_day & 0xf),
+ (lh->timestamp.slh_century >> 4) * 1000 +
+ (lh->timestamp.slh_century & 0xf) * 100 +
+ (lh->timestamp.slh_year >> 4) * 10 +
+ (lh->timestamp.slh_year & 0xf),
+ (lh->timestamp.slh_hour >> 4) * 10 +
+ (lh->timestamp.slh_hour & 0xf),
+ (lh->timestamp.slh_minute >> 4) * 10 +
+ (lh->timestamp.slh_minute & 0xf),
+ (lh->timestamp.slh_second >> 4) * 10 +
+ (lh->timestamp.slh_second & 0xf));
+ prfunc("+Time: %s Severity %d\n", str_buf, lh->severity);
X }
X
X /*
@@ -729,6 +1016,33 @@
X prfunc("+ %s[%d] 0x%lx\n", reg_prefix, i, regs[i]);
X }
X
+/*
+ * ia64_log_processor_fp_regs_print
+ * Print the contents of the saved floating page register(s) in the format
+ * <reg_prefix>[<index>] <value>
+ *
+ * Inputs: ia64_fpreg (Register save buffer)
+ * reg_num (# of registers)
+ * reg_class (application/banked/control/bank1_general)
+ * reg_prefix (ar/br/cr/b1_gr)


+ * Outputs: None
+ *

+ */
+void
+ia64_log_processor_fp_regs_print (struct ia64_fpreg *regs,
+ int reg_num,
+ char *reg_class,
+ char *reg_prefix,
+ prfunc_t prfunc)
+{
+ int i;
+
+ prfunc("+%s Registers\n", reg_class);
+ for (i = 0; i < reg_num; i++)
+ prfunc("+ %s[%d] 0x%lx%016lx\n", reg_prefix, i, regs[i].u.bits[1],
+ regs[i].u.bits[0]);
+}
+
X static char *pal_mesi_state[] = {
X "Invalid",
X "Shared",
@@ -754,69 +1068,91 @@
X /*
X * ia64_log_cache_check_info_print
X * Display the machine check information related to cache error(s).
- * Inputs : i (Multiple errors are logged, i - index of logged error)
- * info (Machine check info logged by the PAL and later
+ * Inputs: i (Multiple errors are logged, i - index of logged error)
+ * cc_info * (Ptr to cache check info logged by the PAL and later
X * captured by the SAL)
- * target_addr (Address which caused the cache error)
- * Outputs : None
+ * prfunc (fn ptr of print function to be used for output)


+ * Outputs: None
X */
X void

-ia64_log_cache_check_info_print(int i,
- pal_cache_check_info_t info,
- u64 target_addr,
- prfunc_t prfunc)
+ia64_log_cache_check_info_print (int i,
+ sal_log_mod_error_info_t *cache_check_info,
+ prfunc_t prfunc)
X {
+ pal_cache_check_info_t *info;
+ u64 target_addr;
+
+ if (!cache_check_info->valid.check_info) {
+ IA64_MCA_DEBUG("ia64_mca_log_print: invalid cache_check_info[%d]\n",i);
+ return; /* If check info data not valid, skip it */
+ }
+
+ info = (pal_cache_check_info_t *)&cache_check_info->check_info;
+ target_addr = cache_check_info->target_identifier;
+
X prfunc("+ Cache check info[%d]\n+", i);
- prfunc(" Level: L%d",info.level);
- if (info.mv)
- prfunc(" ,Mesi: %s",pal_mesi_state[info.mesi]);
- prfunc(" ,Index: %d,", info.index);
- if (info.ic)
- prfunc(" ,Cache: Instruction");
- if (info.dc)
- prfunc(" ,Cache: Data");
- if (info.tl)
- prfunc(" ,Line: Tag");
- if (info.dl)
- prfunc(" ,Line: Data");
- prfunc(" ,Operation: %s,", pal_cache_op[info.op]);
- if (info.wv)
- prfunc(" ,Way: %d,", info.way);
- if (info.tv)
- prfunc(" ,Target Addr: 0x%lx", target_addr);
- if (info.mc)
- prfunc(" ,MC: Corrected");
+ prfunc(" Level: L%d,",info->level);
+ if (info->mv)
+ prfunc(" Mesi: %s,",pal_mesi_state[info->mesi]);
+ prfunc(" Index: %d,", info->index);
+ if (info->ic)
+ prfunc(" Cache: Instruction,");
+ if (info->dc)
+ prfunc(" Cache: Data,");
+ if (info->tl)
+ prfunc(" Line: Tag,");
+ if (info->dl)
+ prfunc(" Line: Data,");
+ prfunc(" Operation: %s,", pal_cache_op[info->op]);
+ if (info->wv)
+ prfunc(" Way: %d,", info->way);
+ if (cache_check_info->valid.target_identifier)
+ /* Hope target address is saved in target_identifier */
+ if (info->tv)
+ prfunc(" Target Addr: 0x%lx,", target_addr);
+ if (info->mc)
+ prfunc(" MC: Corrected");
X prfunc("\n");
X }
X
X /*
X * ia64_log_tlb_check_info_print
X * Display the machine check information related to tlb error(s).
- * Inputs : i (Multiple errors are logged, i - index of logged error)
- * info (Machine check info logged by the PAL and later
+ * Inputs: i (Multiple errors are logged, i - index of logged error)
+ * tlb_info * (Ptr to machine check info logged by the PAL and later
X * captured by the SAL)
- * Outputs : None
+ * prfunc (fn ptr of print function to be used for output)


+ * Outputs: None
X */

-
X void
-ia64_log_tlb_check_info_print(int i,
- pal_tlb_check_info_t info,
- prfunc_t prfunc)
+ia64_log_tlb_check_info_print (int i,
+ sal_log_mod_error_info_t *tlb_check_info,
+ prfunc_t prfunc)
+
X {
+ pal_tlb_check_info_t *info;
+
+ if (!tlb_check_info->valid.check_info) {
+ IA64_MCA_DEBUG("ia64_mca_log_print: invalid tlb_check_info[%d]\n", i);
+ return; /* If check info data not valid, skip it */
+ }
+
+ info = (pal_tlb_check_info_t *)&tlb_check_info->check_info;
+
X prfunc("+ TLB Check Info [%d]\n+", i);
- if (info.itc)
+ if (info->itc)
X prfunc(" Failure: Instruction Translation Cache");
- if (info.dtc)
+ if (info->dtc)
X prfunc(" Failure: Data Translation Cache");
- if (info.itr) {
+ if (info->itr) {
X prfunc(" Failure: Instruction Translation Register");
- prfunc(" ,Slot: %d", info.tr_slot);
+ prfunc(" ,Slot: %d", info->tr_slot);
X }
- if (info.dtr) {
+ if (info->dtr) {
X prfunc(" Failure: Data Translation Register");
- prfunc(" ,Slot: %d", info.tr_slot);
+ prfunc(" ,Slot: %d", info->tr_slot);
X }
- if (info.mc)
+ if (info->mc)
X prfunc(" ,MC: Corrected");
X prfunc("\n");
X }
@@ -824,159 +1160,721 @@
X /*
X * ia64_log_bus_check_info_print
X * Display the machine check information related to bus error(s).
- * Inputs : i (Multiple errors are logged, i - index of logged error)
- * info (Machine check info logged by the PAL and later
+ * Inputs: i (Multiple errors are logged, i - index of logged error)
+ * bus_info * (Ptr to machine check info logged by the PAL and later
X * captured by the SAL)
- * req_addr (Address of the requestor of the transaction)
- * resp_addr (Address of the responder of the transaction)
- * target_addr (Address where the data was to be delivered to or
- * obtained from)
- * Outputs : None
+ * prfunc (fn ptr of print function to be used for output)


+ * Outputs: None
X */
X void

-ia64_log_bus_check_info_print(int i,
- pal_bus_check_info_t info,
- u64 req_addr,
- u64 resp_addr,
- u64 targ_addr,
- prfunc_t prfunc)
-{
+ia64_log_bus_check_info_print (int i,
+ sal_log_mod_error_info_t *bus_check_info,
+ prfunc_t prfunc)
+{
+ pal_bus_check_info_t *info;
+ u64 req_addr; /* Address of the requestor of the transaction */
+ u64 resp_addr; /* Address of the responder of the transaction */
+ u64 targ_addr; /* Address where the data was to be delivered to */
+ /* or obtained from */
+
+ if (!bus_check_info->valid.check_info) {
+ IA64_MCA_DEBUG("ia64_mca_log_print: invalid bus_check_info[%d]\n", i);
+ return; /* If check info data not valid, skip it */
+ }
+
+ info = (pal_bus_check_info_t *)&bus_check_info->check_info;
+ req_addr = bus_check_info->requestor_identifier;
+ resp_addr = bus_check_info->responder_identifier;
+ targ_addr = bus_check_info->target_identifier;
+
X prfunc("+ BUS Check Info [%d]\n+", i);
- prfunc(" Status Info: %d", info.bsi);
- prfunc(" ,Severity: %d", info.sev);
- prfunc(" ,Transaction Type: %d", info.type);
- prfunc(" ,Transaction Size: %d", info.size);
- if (info.cc)
+ prfunc(" Status Info: %d", info->bsi);
+ prfunc(" ,Severity: %d", info->sev);
+ prfunc(" ,Transaction Type: %d", info->type);
+ prfunc(" ,Transaction Size: %d", info->size);
+ if (info->cc)
X prfunc(" ,Cache-cache-transfer");
- if (info.ib)
+ if (info->ib)
X prfunc(" ,Error: Internal");
- if (info.eb)
+ if (info->eb)
X prfunc(" ,Error: External");
- if (info.mc)
+ if (info->mc)
X prfunc(" ,MC: Corrected");
- if (info.tv)
+ if (info->tv)
X prfunc(" ,Target Address: 0x%lx", targ_addr);
- if (info.rq)
+ if (info->rq)
X prfunc(" ,Requestor Address: 0x%lx", req_addr);
- if (info.tv)
+ if (info->tv)
X prfunc(" ,Responder Address: 0x%lx", resp_addr);
X prfunc("\n");
X }
X
X /*
+ * ia64_log_mem_dev_err_info_print
+ *
+ * Format and log the platform memory device error record section data.
+ *
+ * Inputs: mem_dev_err_info * (Ptr to memory device error record section
+ * returned by SAL)
+ * prfunc (fn ptr of print function to be used for output)


+ * Outputs: None
+ */
+void

+ia64_log_mem_dev_err_info_print (sal_log_mem_dev_err_info_t *mdei,
+ prfunc_t prfunc)
+{
+ prfunc("+ Mem Error Detail: ");
+
+ if (mdei->valid.error_status)
+ prfunc(" Error Status: %#lx,", mdei->error_status);
+ if (mdei->valid.physical_addr)
+ prfunc(" Physical Address: %#lx,", mdei->physical_addr);
+ if (mdei->valid.addr_mask)
+ prfunc(" Address Mask: %#lx,", mdei->addr_mask);
+ if (mdei->valid.node)
+ prfunc(" Node: %d,", mdei->node);
+ if (mdei->valid.card)
+ prfunc(" Card: %d,", mdei->card);
+ if (mdei->valid.module)
+ prfunc(" Module: %d,", mdei->module);
+ if (mdei->valid.bank)
+ prfunc(" Bank: %d,", mdei->bank);
+ if (mdei->valid.device)
+ prfunc(" Device: %d,", mdei->device);
+ if (mdei->valid.row)
+ prfunc(" Row: %d,", mdei->row);
+ if (mdei->valid.column)
+ prfunc(" Column: %d,", mdei->column);
+ if (mdei->valid.bit_position)
+ prfunc(" Bit Position: %d,", mdei->bit_position);
+ if (mdei->valid.target_id)
+ prfunc(" ,Target Address: %#lx,", mdei->target_id);
+ if (mdei->valid.requestor_id)
+ prfunc(" ,Requestor Address: %#lx,", mdei->requestor_id);
+ if (mdei->valid.responder_id)
+ prfunc(" ,Responder Address: %#lx,", mdei->responder_id);
+ if (mdei->valid.bus_spec_data)
+ prfunc(" Bus Specific Data: %#lx,", mdei->bus_spec_data);
+ prfunc("\n");
+
+ if (mdei->valid.oem_id) {
+ u8 *p_data = &(mdei->oem_id[0]);
+ int i;
+
+ prfunc(" OEM Memory Controller ID:");
+ for (i = 0; i < 16; i++, p_data++)
+ prfunc(" %02x", *p_data);
+ prfunc("\n");
+ }
+
+ if (mdei->valid.oem_data) {
+ ia64_log_prt_oem_data((int)mdei->header.len,
+ (int)sizeof(sal_log_mem_dev_err_info_t) - 1,
+ &(mdei->oem_data[0]), prfunc);
+ }
+}
+
+/*
+ * ia64_log_sel_dev_err_info_print
+ *
+ * Format and log the platform SEL device error record section data.
+ *
+ * Inputs: sel_dev_err_info * (Ptr to the SEL device error record section
+ * returned by SAL)
+ * prfunc (fn ptr of print function to be used for output)


+ * Outputs: None
+ */
+void

+ia64_log_sel_dev_err_info_print (sal_log_sel_dev_err_info_t *sdei,
+ prfunc_t prfunc)
+{
+ int i;
+
+ prfunc("+ SEL Device Error Detail: ");
+
+ if (sdei->valid.record_id)
+ prfunc(" Record ID: %#x", sdei->record_id);
+ if (sdei->valid.record_type)
+ prfunc(" Record Type: %#x", sdei->record_type);
+ prfunc(" Time Stamp: ");
+ for (i = 0; i < 4; i++)
+ prfunc("%1d", sdei->timestamp[i]);
+ if (sdei->valid.generator_id)
+ prfunc(" Generator ID: %#x", sdei->generator_id);
+ if (sdei->valid.evm_rev)
+ prfunc(" Message Format Version: %#x", sdei->evm_rev);
+ if (sdei->valid.sensor_type)
+ prfunc(" Sensor Type: %#x", sdei->sensor_type);
+ if (sdei->valid.sensor_num)
+ prfunc(" Sensor Number: %#x", sdei->sensor_num);
+ if (sdei->valid.event_dir)
+ prfunc(" Event Direction Type: %#x", sdei->event_dir);
+ if (sdei->valid.event_data1)
+ prfunc(" Data1: %#x", sdei->event_data1);
+ if (sdei->valid.event_data2)
+ prfunc(" Data2: %#x", sdei->event_data2);
+ if (sdei->valid.event_data3)
+ prfunc(" Data3: %#x", sdei->event_data3);
+ prfunc("\n");
+
+}
+
+/*
+ * ia64_log_pci_bus_err_info_print
+ *
+ * Format and log the platform PCI bus error record section data.
+ *
+ * Inputs: pci_bus_err_info * (Ptr to the PCI bus error record section
+ * returned by SAL)
+ * prfunc (fn ptr of print function to be used for output)


+ * Outputs: None
+ */
+void

+ia64_log_pci_bus_err_info_print (sal_log_pci_bus_err_info_t *pbei,
+ prfunc_t prfunc)
+{
+ prfunc("+ PCI Bus Error Detail: ");
+
+ if (pbei->valid.err_status)
+ prfunc(" Error Status: %#lx", pbei->err_status);
+ if (pbei->valid.err_type)
+ prfunc(" Error Type: %#x", pbei->err_type);
+ if (pbei->valid.bus_id)
+ prfunc(" Bus ID: %#x", pbei->bus_id);
+ if (pbei->valid.bus_address)
+ prfunc(" Bus Address: %#lx", pbei->bus_address);
+ if (pbei->valid.bus_data)
+ prfunc(" Bus Data: %#lx", pbei->bus_data);
+ if (pbei->valid.bus_cmd)
+ prfunc(" Bus Command: %#lx", pbei->bus_cmd);
+ if (pbei->valid.requestor_id)
+ prfunc(" Requestor ID: %#lx", pbei->requestor_id);
+ if (pbei->valid.responder_id)
+ prfunc(" Responder ID: %#lx", pbei->responder_id);
+ if (pbei->valid.target_id)
+ prfunc(" Target ID: %#lx", pbei->target_id);
+ if (pbei->valid.oem_data)
+ prfunc("\n");
+
+ if (pbei->valid.oem_data) {
+ ia64_log_prt_oem_data((int)pbei->header.len,
+ (int)sizeof(sal_log_pci_bus_err_info_t) - 1,
+ &(pbei->oem_data[0]), prfunc);
+ }
+}
+
+/*
+ * ia64_log_smbios_dev_err_info_print
+ *
+ * Format and log the platform SMBIOS device error record section data.
+ *
+ * Inputs: smbios_dev_err_info * (Ptr to the SMBIOS device error record
+ * section returned by SAL)
+ * prfunc (fn ptr of print function to be used for output)


+ * Outputs: None
+ */
+void

+ia64_log_smbios_dev_err_info_print (sal_log_smbios_dev_err_info_t *sdei,
+ prfunc_t prfunc)
+{
+ u8 i;
+
+ prfunc("+ SMBIOS Device Error Detail: ");
+
+ if (sdei->valid.event_type)
+ prfunc(" Event Type: %#x", sdei->event_type);
+ if (sdei->valid.time_stamp) {
+ prfunc(" Time Stamp: ");
+ for (i = 0; i < 6; i++)
+ prfunc("%d", sdei->time_stamp[i]);
+ }
+ if ((sdei->valid.data) && (sdei->valid.length)) {
+ prfunc(" Data: ");
+ for (i = 0; i < sdei->length; i++)
+ prfunc(" %02x", sdei->data[i]);
+ }
+ prfunc("\n");
+}
+
+/*
+ * ia64_log_pci_comp_err_info_print
+ *
+ * Format and log the platform PCI component error record section data.
+ *
+ * Inputs: pci_comp_err_info * (Ptr to the PCI component error record section
+ * returned by SAL)
+ * prfunc (fn ptr of print function to be used for output)


+ * Outputs: None
+ */
+void

+ia64_log_pci_comp_err_info_print(sal_log_pci_comp_err_info_t *pcei,
+ prfunc_t prfunc)
+{
+ u32 n_mem_regs, n_io_regs;
+ u64 i, n_pci_data;
+ u64 *p_reg_data;
+ u8 *p_oem_data;
+
+ prfunc("+ PCI Component Error Detail: ");
+
+ if (pcei->valid.err_status)
+ prfunc(" Error Status: %#lx\n", pcei->err_status);
+ if (pcei->valid.comp_info)
+ prfunc(" Component Info: Vendor Id = %#x, Device Id = %#x,"
+ " Class Code = %#x, Seg/Bus/Dev/Func = %d/%d/%d/%d\n",
+ pcei->comp_info.vendor_id, pcei->comp_info.device_id,
+ pcei->comp_info.class_code, pcei->comp_info.seg_num,
+ pcei->comp_info.bus_num, pcei->comp_info.dev_num,
+ pcei->comp_info.func_num);
+
+ n_mem_regs = (pcei->valid.num_mem_regs) ? pcei->num_mem_regs : 0;
+ n_io_regs = (pcei->valid.num_io_regs) ? pcei->num_io_regs : 0;
+ p_reg_data = &(pcei->reg_data_pairs[0]);
+ p_oem_data = (u8 *)p_reg_data +
+ (n_mem_regs + n_io_regs) * 2 * sizeof(u64);
+ n_pci_data = p_oem_data - (u8 *)pcei;
+
+ if (n_pci_data > pcei->header.len) {
+ prfunc(" Invalid PCI Component Error Record format: length = %ld, "
+ " Size PCI Data = %d, Num Mem-Map/IO-Map Regs = %ld/%ld\n",
+ pcei->header.len, n_pci_data, n_mem_regs, n_io_regs);
+ return;
+ }
+
+ if (n_mem_regs) {
+ prfunc(" Memory Mapped Registers\n Address \tValue\n");
+ for (i = 0; i < pcei->num_mem_regs; i++) {
+ prfunc(" %#lx %#lx\n", p_reg_data[0], p_reg_data[1]);
+ p_reg_data += 2;
+ }
+ }
+ if (n_io_regs) {
+ prfunc(" I/O Mapped Registers\n Address \tValue\n");
+ for (i = 0; i < pcei->num_io_regs; i++) {
+ prfunc(" %#lx %#lx\n", p_reg_data[0], p_reg_data[1]);
+ p_reg_data += 2;
+ }
+ }
+ if (pcei->valid.oem_data) {
+ ia64_log_prt_oem_data((int)pcei->header.len, n_pci_data,
+ p_oem_data, prfunc);
+ prfunc("\n");
+ }
+}
+
+/*
+ * ia64_log_plat_specific_err_info_print
+ *
+ * Format and log the platform specifie error record section data.
+ *
+ * Inputs: sel_dev_err_info * (Ptr to the platform specific error record
+ * section returned by SAL)
+ * prfunc (fn ptr of print function to be used for output)


+ * Outputs: None
+ */
+void

+ia64_log_plat_specific_err_info_print (sal_log_plat_specific_err_info_t *psei,
+ prfunc_t prfunc)
+{
+ prfunc("+ Platform Specific Error Detail: ");
+
+ if (psei->valid.err_status)
+ prfunc(" Error Status: %#lx", psei->err_status);
+ if (psei->valid.guid) {
+ prfunc(" GUID: ");
+ ia64_log_prt_guid(&psei->guid, prfunc);
+ }
+ if (psei->valid.oem_data) {
+ ia64_log_prt_oem_data((int)psei->header.len,
+ (int)sizeof(sal_log_plat_specific_err_info_t) - 1,
+ &(psei->oem_data[0]), prfunc);
+ }
+ prfunc("\n");
+}
+
+/*
+ * ia64_log_host_ctlr_err_info_print
+ *
+ * Format and log the platform host controller error record section data.
+ *
+ * Inputs: host_ctlr_err_info * (Ptr to the host controller error record
+ * section returned by SAL)
+ * prfunc (fn ptr of print function to be used for output)


+ * Outputs: None
+ */
+void

+ia64_log_host_ctlr_err_info_print (sal_log_host_ctlr_err_info_t *hcei,
+ prfunc_t prfunc)
+{
+ prfunc("+ Host Controller Error Detail: ");
+
+ if (hcei->valid.err_status)
+ prfunc(" Error Status: %#lx", hcei->err_status);
+ if (hcei->valid.requestor_id)
+ prfunc(" Requestor ID: %#lx", hcei->requestor_id);
+ if (hcei->valid.responder_id)
+ prfunc(" Responder ID: %#lx", hcei->responder_id);
+ if (hcei->valid.target_id)
+ prfunc(" Target ID: %#lx", hcei->target_id);
+ if (hcei->valid.bus_spec_data)
+ prfunc(" Bus Specific Data: %#lx", hcei->bus_spec_data);
+ if (hcei->valid.oem_data) {
+ ia64_log_prt_oem_data((int)hcei->header.len,
+ (int)sizeof(sal_log_host_ctlr_err_info_t) - 1,
+ &(hcei->oem_data[0]), prfunc);
+ }
+ prfunc("\n");
+}
+
+/*
+ * ia64_log_plat_bus_err_info_print
+ *
+ * Format and log the platform bus error record section data.
+ *
+ * Inputs: plat_bus_err_info * (Ptr to the platform bus error record section
+ * returned by SAL)
+ * prfunc (fn ptr of print function to be used for output)


+ * Outputs: None
+ */
+void

+ia64_log_plat_bus_err_info_print (sal_log_plat_bus_err_info_t *pbei,
+ prfunc_t prfunc)
+{
+ prfunc("+ Platform Bus Error Detail: ");
+
+ if (pbei->valid.err_status)
+ prfunc(" Error Status: %#lx", pbei->err_status);
+ if (pbei->valid.requestor_id)
+ prfunc(" Requestor ID: %#lx", pbei->requestor_id);
+ if (pbei->valid.responder_id)
+ prfunc(" Responder ID: %#lx", pbei->responder_id);
+ if (pbei->valid.target_id)
+ prfunc(" Target ID: %#lx", pbei->target_id);
+ if (pbei->valid.bus_spec_data)
+ prfunc(" Bus Specific Data: %#lx", pbei->bus_spec_data);
+ if (pbei->valid.oem_data) {
+ ia64_log_prt_oem_data((int)pbei->header.len,
+ (int)sizeof(sal_log_plat_bus_err_info_t) - 1,
+ &(pbei->oem_data[0]), prfunc);
+ }
+ prfunc("\n");
+}
+
+/*
+ * ia64_log_proc_dev_err_info_print
+ *
+ * Display the processor device error record.
+ *
+ * Inputs: sal_log_processor_info_t * (Ptr to processor device error record
+ * section body).
+ * prfunc (fn ptr of print function to be used
+ * for output).


+ * Outputs: None
+ */
+void

+ia64_log_proc_dev_err_info_print (sal_log_processor_info_t *slpi,
+ prfunc_t prfunc)
+{
+#ifdef MCA_PRT_XTRA_DATA
+ size_t d_len = slpi->header.len - sizeof(sal_log_section_hdr_t);
+#endif
+ sal_processor_static_info_t *spsi;
+ int i;
+ sal_log_mod_error_info_t *p_data;
+
+ prfunc("+Processor Device Error Info Section\n");
+
+#ifdef MCA_PRT_XTRA_DATA // for test only @FVL
+ {
+ char *p_data = (char *)&slpi->valid;
+
+ prfunc("SAL_PROC_DEV_ERR SECTION DATA: Data buffer = %p, "
+ "Data size = %ld\n", (void *)p_data, d_len);
+ ia64_log_hexdump(p_data, d_len, prfunc);
+ prfunc("End of SAL_PROC_DEV_ERR SECTION DATA\n");
+ }
+#endif // MCA_PRT_XTRA_DATA for test only @FVL
+
+ if (slpi->valid.proc_error_map)
+ prfunc(" Processor Error Map: %#lx\n", slpi->proc_error_map);
+
+ if (slpi->valid.proc_state_param)
+ prfunc(" Processor State Param: %#lx\n", slpi->proc_state_parameter);
+
+ if (slpi->valid.proc_cr_lid)
+ prfunc(" Processor LID: %#lx\n", slpi->proc_cr_lid);
+
+ /*
+ * Note: March 2001 SAL spec states that if the number of elements in any
+ * of the MOD_ERROR_INFO_STRUCT arrays is zero, the entire array is
+ * absent. Also, current implementations only allocate space for number of
+ * elements used. So we walk the data pointer from here on.
+ */
+ p_data = &slpi->cache_check_info[0];
+
+ /* Print the cache check information if any*/
+ for (i = 0 ; i < slpi->valid.num_cache_check; i++, p_data++)
+ ia64_log_cache_check_info_print(i, p_data, prfunc);
+
+ /* Print the tlb check information if any*/
+ for (i = 0 ; i < slpi->valid.num_tlb_check; i++, p_data++)
+ ia64_log_tlb_check_info_print(i, p_data, prfunc);
+
+ /* Print the bus check information if any*/
+ for (i = 0 ; i < slpi->valid.num_bus_check; i++, p_data++)
+ ia64_log_bus_check_info_print(i, p_data, prfunc);
+
+ /* Print the reg file check information if any*/
+ for (i = 0 ; i < slpi->valid.num_reg_file_check; i++, p_data++)
+ ia64_log_hexdump((u8 *)p_data, sizeof(sal_log_mod_error_info_t),
+ prfunc); /* Just hex dump for now */
+
+ /* Print the ms check information if any*/
+ for (i = 0 ; i < slpi->valid.num_ms_check; i++, p_data++)
+ ia64_log_hexdump((u8 *)p_data, sizeof(sal_log_mod_error_info_t),
+ prfunc); /* Just hex dump for now */
+
+ /* Print CPUID registers if any*/
+ if (slpi->valid.cpuid_info) {
+ u64 *p = (u64 *)p_data;
+
+ prfunc(" CPUID Regs: %#lx %#lx %#lx %#lx\n", p[0], p[1], p[2], p[3]);
+ p_data++;
+ }
+
+ /* Print processor static info if any */
+ if (slpi->valid.psi_static_struct) {
+ spsi = (sal_processor_static_info_t *)p_data;
+
+ /* Print branch register contents if valid */
+ if (spsi->valid.br)
+ ia64_log_processor_regs_print(spsi->br, 8, "Branch", "br",
+ prfunc);
+
+ /* Print control register contents if valid */
+ if (spsi->valid.cr)
+ ia64_log_processor_regs_print(spsi->cr, 128, "Control", "cr",
+ prfunc);
+
+ /* Print application register contents if valid */
+ if (spsi->valid.ar)
+ ia64_log_processor_regs_print(spsi->ar, 128, "Application",
+ "ar", prfunc);
+
+ /* Print region register contents if valid */
+ if (spsi->valid.rr)
+ ia64_log_processor_regs_print(spsi->rr, 8, "Region", "rr",
+ prfunc);
+
+ /* Print floating-point register contents if valid */
+ if (spsi->valid.fr)
+ ia64_log_processor_fp_regs_print(spsi->fr, 128, "Floating-point", "fr",
+ prfunc);
+ }
+}
+
+/*
X * ia64_log_processor_info_print
+ *
X * Display the processor-specific information logged by PAL as a part
X * of MCA or INIT or CMC.
- * Inputs : lh (Pointer of the sal log header which specifies the format
- * of SAL state info as specified by the SAL spec).
+ *
+ * Inputs : lh (Pointer of the sal log header which specifies the
+ * format of SAL state info as specified by the SAL spec).
+ * prfunc (fn ptr of print function to be used for output).
X * Outputs : None
X */
X void
-ia64_log_processor_info_print(sal_log_header_t *lh, prfunc_t prfunc)
+ia64_log_processor_info_print(sal_log_record_header_t *lh, prfunc_t prfunc)
X {
- sal_log_processor_info_t *slpi;
- int i;
+ sal_log_section_hdr_t *slsh;
+ int n_sects;
+ int ercd_pos;
X
X if (!lh)
X return;
X
- if (lh->slh_log_type != SAL_SUB_INFO_TYPE_PROCESSOR)
+#ifdef MCA_PRT_XTRA_DATA // for test only @FVL
+ ia64_log_prt_record_header(lh, prfunc);
+#endif // MCA_PRT_XTRA_DATA for test only @FVL
+
+ if ((ercd_pos = sizeof(sal_log_record_header_t)) >= lh->len) {
+ IA64_MCA_DEBUG("ia64_mca_log_print: "
+ "truncated SAL CMC error record. len = %d\n",
+ lh->len);
X return;
+ }
X
- slpi = (sal_log_processor_info_t *)((char *)lh+sizeof(sal_log_header_t)); /* point to proc info */
+ /* Print record header info */
+ ia64_log_rec_header_print(lh, prfunc);
X
- if (!slpi) {
- prfunc("No Processor Error Log found\n");
- return;
+ for (n_sects = 0; (ercd_pos < lh->len); n_sects++, ercd_pos += slsh->len) {
+ /* point to next section header */
+ slsh = (sal_log_section_hdr_t *)((char *)lh + ercd_pos);
+
+#ifdef MCA_PRT_XTRA_DATA // for test only @FVL
+ ia64_log_prt_section_header(slsh, prfunc);
+#endif // MCA_PRT_XTRA_DATA for test only @FVL
+
+ if (verify_guid((void *)&slsh->guid, (void *)&(SAL_PROC_DEV_ERR_SECT_GUID))) {
+ IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n");
+ continue;
+ }
+
+ /*
+ * Now process processor device error record section
+ */
+ ia64_log_proc_dev_err_info_print((sal_log_processor_info_t *)slsh,
+ printk);
X }
X
- /* Print branch register contents if valid */
- if (slpi->slpi_valid.slpi_br)
- ia64_log_processor_regs_print(slpi->slpi_br, 8, "Branch", "br", prfunc);
+ IA64_MCA_DEBUG("ia64_mca_log_print: "
+ "found %d sections in SAL CMC error record. len = %d\n",
+ n_sects, lh->len);
+ if (!n_sects) {
+ prfunc("No Processor Device Error Info Section found\n");
+ return;
+ }
+}
X
- /* Print control register contents if valid */
- if (slpi->slpi_valid.slpi_cr)
- ia64_log_processor_regs_print(slpi->slpi_cr, 128, "Control", "cr", prfunc);
+/*
+ * ia64_log_platform_info_print
+ *
+ * Format and Log the SAL Platform Error Record.
+ *
+ * Inputs : lh (Pointer to the sal error record header with format
+ * specified by the SAL spec).
+ * prfunc (fn ptr of log output function to use)


+ * Outputs : None
+ */
+void

+ia64_log_platform_info_print (sal_log_record_header_t *lh, prfunc_t prfunc)
+{
+ sal_log_section_hdr_t *slsh;
+ int n_sects;
+ int ercd_pos;
X
- /* Print application register contents if valid */
- if (slpi->slpi_valid.slpi_ar)
- ia64_log_processor_regs_print(slpi->slpi_br, 128, "Application", "ar", prfunc);
+ if (!lh)
+ return;
X
- /* Print region register contents if valid */
- if (slpi->slpi_valid.slpi_rr)
- ia64_log_processor_regs_print(slpi->slpi_rr, 8, "Region", "rr", prfunc);
+#ifdef MCA_PRT_XTRA_DATA // for test only @FVL
+ ia64_log_prt_record_header(lh, prfunc);
+#endif // MCA_PRT_XTRA_DATA for test only @FVL
+
+ if ((ercd_pos = sizeof(sal_log_record_header_t)) >= lh->len) {
+ IA64_MCA_DEBUG("ia64_mca_log_print: "
+ "truncated SAL error record. len = %d\n",
+ lh->len);
+ return;
+ }
X
- /* Print floating-point register contents if valid */
- if (slpi->slpi_valid.slpi_fr)
- ia64_log_processor_regs_print(slpi->slpi_fr, 128, "Floating-point", "fr",
- prfunc);
+ /* Print record header info */
+ ia64_log_rec_header_print(lh, prfunc);
X
- /* Print the cache check information if any*/
- for (i = 0 ; i < MAX_CACHE_ERRORS; i++)
- ia64_log_cache_check_info_print(i,
- slpi->slpi_cache_check_info[i].slpi_cache_check,
- slpi->slpi_cache_check_info[i].slpi_target_address,
- prfunc);
- /* Print the tlb check information if any*/
- for (i = 0 ; i < MAX_TLB_ERRORS; i++)
- ia64_log_tlb_check_info_print(i,slpi->slpi_tlb_check_info[i], prfunc);
+ for (n_sects = 0; (ercd_pos < lh->len); n_sects++, ercd_pos += slsh->len) {
+ /* point to next section header */
+ slsh = (sal_log_section_hdr_t *)((char *)lh + ercd_pos);
+
+#ifdef MCA_PRT_XTRA_DATA // for test only @FVL
+ ia64_log_prt_section_header(slsh, prfunc);
+
+ if (efi_guidcmp(slsh->guid, SAL_PROC_DEV_ERR_SECT_GUID) != 0) {
+ size_t d_len = slsh->len - sizeof(sal_log_section_hdr_t);
+ char *p_data = (char *)&((sal_log_mem_dev_err_info_t *)slsh)->valid;
+
+ prfunc("Start of Platform Err Data Section: Data buffer = %p, "
+ "Data size = %ld\n", (void *)p_data, d_len);
+ ia64_log_hexdump(p_data, d_len, prfunc);
+ prfunc("End of Platform Err Data Section\n");
+ }
+#endif // MCA_PRT_XTRA_DATA for test only @FVL
X
- /* Print the bus check information if any*/
- for (i = 0 ; i < MAX_BUS_ERRORS; i++)
- ia64_log_bus_check_info_print(i,
- slpi->slpi_bus_check_info[i].slpi_bus_check,
- slpi->slpi_bus_check_info[i].slpi_requestor_addr,
- slpi->slpi_bus_check_info[i].slpi_responder_addr,
- slpi->slpi_bus_check_info[i].slpi_target_addr,
- prfunc);
+ /*
+ * Now process CPE error record section
+ */
+ if (efi_guidcmp(slsh->guid, SAL_PROC_DEV_ERR_SECT_GUID) == 0) {
+ ia64_log_proc_dev_err_info_print((sal_log_processor_info_t *)slsh,
+ prfunc);
+ } else if (efi_guidcmp(slsh->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID) == 0) {
+ prfunc("+Platform Memory Device Error Info Section\n");
+ ia64_log_mem_dev_err_info_print((sal_log_mem_dev_err_info_t *)slsh,
+ prfunc);
+ } else if (efi_guidcmp(slsh->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID) == 0) {
+ prfunc("+Platform SEL Device Error Info Section\n");
+ ia64_log_sel_dev_err_info_print((sal_log_sel_dev_err_info_t *)slsh,
+ prfunc);
+ } else if (efi_guidcmp(slsh->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID) == 0) {
+ prfunc("+Platform PCI Bus Error Info Section\n");
+ ia64_log_pci_bus_err_info_print((sal_log_pci_bus_err_info_t *)slsh,
+ prfunc);
+ } else if (efi_guidcmp(slsh->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID) == 0) {
+ prfunc("+Platform SMBIOS Device Error Info Section\n");
+ ia64_log_smbios_dev_err_info_print((sal_log_smbios_dev_err_info_t *)slsh,
+ prfunc);
+ } else if (efi_guidcmp(slsh->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID) == 0) {
+ prfunc("+Platform PCI Component Error Info Section\n");
+ ia64_log_pci_comp_err_info_print((sal_log_pci_comp_err_info_t *)slsh,
+ prfunc);
+ } else if (efi_guidcmp(slsh->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID) == 0) {
+ prfunc("+Platform Specific Error Info Section\n");
+ ia64_log_plat_specific_err_info_print((sal_log_plat_specific_err_info_t *)
+ slsh,
+ prfunc);
+ } else if (efi_guidcmp(slsh->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID) == 0) {
+ prfunc("+Platform Host Controller Error Info Section\n");
+ ia64_log_host_ctlr_err_info_print((sal_log_host_ctlr_err_info_t *)slsh,
+ prfunc);
+ } else if (efi_guidcmp(slsh->guid, SAL_PLAT_BUS_ERR_SECT_GUID) == 0) {
+ prfunc("+Platform Bus Error Info Section\n");
+ ia64_log_plat_bus_err_info_print((sal_log_plat_bus_err_info_t *)slsh,
+ prfunc);
+ } else {
+ IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n");
+ continue;
+ }
+ }
X
+ IA64_MCA_DEBUG("ia64_mca_log_print: found %d sections in SAL error record. len = %d\n",
+ n_sects, lh->len);
+ if (!n_sects) {
+ prfunc("No Platform Error Info Sections found\n");
+ return;
+ }
X }
X
X /*
X * ia64_log_print
- * Display the contents of the OS error log information
- * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC})
- * sub_info_type (SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM})
+ *
+ * Displays the contents of the OS error log information
+ *
+ * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
+ * prfunc (fn ptr of log output function to use)
X * Outputs : None
X */
X void
-ia64_log_print(int sal_info_type, int sal_sub_info_type, prfunc_t prfunc)
+ia64_log_print(int sal_info_type, prfunc_t prfunc)
X {
- char *info_type, *sub_info_type;
-
X switch(sal_info_type) {
- case SAL_INFO_TYPE_MCA:
- info_type = "MCA";
+ case SAL_INFO_TYPE_MCA:
+ prfunc("+BEGIN HARDWARE ERROR STATE AT MCA\n");
+ ia64_log_platform_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
+ prfunc("+END HARDWARE ERROR STATE AT MCA\n");
X break;
- case SAL_INFO_TYPE_INIT:
- info_type = "INIT";
+ case SAL_INFO_TYPE_INIT:
+ prfunc("+MCA INIT ERROR LOG (UNIMPLEMENTED)\n");
X break;
- case SAL_INFO_TYPE_CMC:
- info_type = "CMC";
+ case SAL_INFO_TYPE_CMC:
+ prfunc("+BEGIN HARDWARE ERROR STATE AT CMC\n");
+ ia64_log_processor_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
+ prfunc("+END HARDWARE ERROR STATE AT CMC\n");
X break;
- default:
- info_type = "UNKNOWN";
+ case SAL_INFO_TYPE_CPE:
+ prfunc("+BEGIN HARDWARE ERROR STATE AT CPE\n");
+ ia64_log_platform_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
+ prfunc("+END HARDWARE ERROR STATE AT CPE\n");
X break;
- }
-
- switch(sal_sub_info_type) {
- case SAL_SUB_INFO_TYPE_PROCESSOR:
- sub_info_type = "PROCESSOR";
- break;
- case SAL_SUB_INFO_TYPE_PLATFORM:
- sub_info_type = "PLATFORM";
- break;
- default:
- sub_info_type = "UNKNOWN";
+ default:
+ prfunc("+MCA UNKNOWN ERROR LOG (UNIMPLEMENTED)\n");
X break;
X }
-
- prfunc("+BEGIN HARDWARE ERROR STATE [%s %s]\n", info_type, sub_info_type);
- if (sal_sub_info_type == SAL_SUB_INFO_TYPE_PROCESSOR)
- ia64_log_processor_info_print(
- IA64_LOG_CURR_BUFFER(sal_info_type, sal_sub_info_type),
- prfunc);
- else
- log_print_platform(IA64_LOG_CURR_BUFFER(sal_info_type, sal_sub_info_type),prfunc);
- prfunc("+END HARDWARE ERROR STATE [%s %s]\n", info_type, sub_info_type);
X }
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/mca_asm.S linux/arch/ia64/kernel/mca_asm.S
--- v2.4.14/linux/arch/ia64/kernel/mca_asm.S Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/mca_asm.S Fri Nov 9 14:26:17 2001
@@ -9,6 +9,7 @@
X //
X #include <linux/config.h>
X
+#include <asm/asmmacro.h>
X #include <asm/pgtable.h>
X #include <asm/processor.h>
X #include <asm/mca_asm.h>
@@ -23,7 +24,7 @@
X #include "minstate.h"
X
X /*
- * SAL_TO_OS_MCA_HANDOFF_STATE
+ * SAL_TO_OS_MCA_HANDOFF_STATE (SAL 3.0 spec)
X * 1. GR1 = OS GP
X * 2. GR8 = PAL_PROC physical address
X * 3. GR9 = SAL_PROC physical address
@@ -33,6 +34,7 @@
X */
X #define SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(_tmp) \
X movl _tmp=ia64_sal_to_os_handoff_state;; \
+ DATA_VA_TO_PA(_tmp);; \
X st8 [_tmp]=r1,0x08;; \
X st8 [_tmp]=r8,0x08;; \
X st8 [_tmp]=r9,0x08;; \
@@ -41,47 +43,29 @@
X st8 [_tmp]=r12,0x08;;
X
X /*
- * OS_MCA_TO_SAL_HANDOFF_STATE
- * 1. GR8 = OS_MCA status
- * 2. GR9 = SAL GP (physical)
- * 3. GR22 = New min state save area pointer
+ * OS_MCA_TO_SAL_HANDOFF_STATE (SAL 3.0 spec)
+ * 1. GR8 = OS_MCA return status
+ * 2. GR9 = SAL GP (physical)
+ * 3. GR10 = 0/1 returning same/new context
+ * 4. GR22 = New min state save area pointer
+ * returns ptr to SAL rtn save loc in _tmp
X */
-#define OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(_tmp) \
- movl _tmp=ia64_os_to_sal_handoff_state;; \
- DATA_VA_TO_PA(_tmp);; \
- ld8 r8=[_tmp],0x08;; \
- ld8 r9=[_tmp],0x08;; \
- ld8 r22=[_tmp],0x08;;
-
-/*
- * BRANCH
- * Jump to the instruction referenced by
- * "to_label".
- * Branch is taken only if the predicate
- * register "p" is true.
- * "ip" is the address of the instruction
- * located at "from_label".
- * "temp" is a scratch register like r2
- * "adjust" needed for HP compiler.
- * A screwup somewhere with constant arithmetic.
- */
-#define BRANCH(to_label, temp, p, adjust) \
-100: (p) mov temp=ip; \
- ;; \
- (p) adds temp=to_label-100b,temp;\
- ;; \
- (p) adds temp=adjust,temp; \
- ;; \
- (p) mov b1=temp ; \
- (p) br b1
+#define OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(_tmp) \
+ movl _tmp=ia64_os_to_sal_handoff_state;; \
+ DATA_VA_TO_PA(_tmp);; \
+ ld8 r8=[_tmp],0x08;; \
+ ld8 r9=[_tmp],0x08;; \
+ ld8 r10=[_tmp],0x08;; \
+ ld8 r22=[_tmp],0x08;; \
+ movl _tmp=ia64_sal_to_os_handoff_state;; \
+ DATA_VA_TO_PA(_tmp);; \
+ add _tmp=0x28,_tmp;; // point to SAL rtn save location
X
X .global ia64_os_mca_dispatch
X .global ia64_os_mca_dispatch_end
X .global ia64_sal_to_os_handoff_state
X .global ia64_os_to_sal_handoff_state
- .global ia64_os_mca_ucmc_handler
X .global ia64_mca_proc_state_dump
- .global ia64_mca_proc_state_restore
X .global ia64_mca_stack
X .global ia64_mca_stackframe
X .global ia64_mca_bspstore
@@ -100,7 +84,7 @@


X #endif /* #if defined(MCA_TEST) */
X

X // Save the SAL to OS MCA handoff state as defined
- // by SAL SPEC 2.5
+ // by SAL SPEC 3.0
X // NOTE : The order in which the state gets saved
X // is dependent on the way the C-structure
X // for ia64_mca_sal_to_os_state_t has been
@@ -110,15 +94,20 @@
X // LOG PROCESSOR STATE INFO FROM HERE ON..
X ;;
X begin_os_mca_dump:
- BRANCH(ia64_os_mca_proc_state_dump, r2, p0, 0x0)
- ;;
+ br ia64_os_mca_proc_state_dump;;
+
X ia64_os_mca_done_dump:
X
X // Setup new stack frame for OS_MCA handling
- movl r2=ia64_mca_bspstore // local bspstore area location in r2
- movl r3=ia64_mca_stackframe // save stack frame to memory in r3
+ movl r2=ia64_mca_bspstore;; // local bspstore area location in r2
+ DATA_VA_TO_PA(r2);;
+ movl r3=ia64_mca_stackframe;; // save stack frame to memory in r3
+ DATA_VA_TO_PA(r3);;
X rse_switch_context(r6,r3,r2);; // RSC management in this new context
X movl r12=ia64_mca_stack;;
+ mov r2=8*1024;; // stack size must be same as c array
+ add r12=r2,r12;; // stack base @ bottom of array
+ DATA_VA_TO_PA(r12);;
X
X // Enter virtual mode from physical mode
X VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4)
@@ -127,7 +116,7 @@
X // call our handler
X movl r2=ia64_mca_ucmc_handler;;
X mov b6=r2;;
- br.call.sptk.few b0=b6
+ br.call.sptk.many b0=b6;;
X .ret0:
X // Revert back to physical mode before going back to SAL
X PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4)
@@ -135,9 +124,9 @@
X
X #if defined(MCA_TEST)
X // Pretend that we are in interrupt context
- mov r2=psr
- dep r2=0, r2, PSR_IC, 2;
- mov psr.l = r2
+ mov r2=psr;;
+ dep r2=0, r2, PSR_IC, 2;;
+ mov psr.l = r2;;


X #endif /* #if defined(MCA_TEST) */
X

X // restore the original stack frame here
@@ -152,15 +141,14 @@
X mov r8=gp
X ;;
X begin_os_mca_restore:
- BRANCH(ia64_os_mca_proc_state_restore, r2, p0, 0x0)
- ;;
+ br ia64_os_mca_proc_state_restore;;
X
X ia64_os_mca_done_restore:
X ;;
X // branch back to SALE_CHECK
X OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(r2)
X ld8 r3=[r2];;
- mov b0=r3 // SAL_CHECK return address
+ mov b0=r3;; // SAL_CHECK return address
X br b0
X ;;
X ia64_os_mca_dispatch_end:
@@ -178,8 +166,10 @@
X //--
X
X ia64_os_mca_proc_state_dump:
-// Get and save GR0-31 from Proc. Min. State Save Area to SAL PSI
+// Save bank 1 GRs 16-31 which will be used by c-language code when we switch
+// to virtual addressing mode.
X movl r2=ia64_mca_proc_state_dump;; // Os state dump area
+ DATA_VA_TO_PA(r2) // convert to to physical address
X
X // save ar.NaT
X mov r5=ar.unat // ar.unat
@@ -250,16 +240,16 @@
X // if PSR.ic=0, reading interruption registers causes an illegal operation fault
X mov r3=psr;;
X tbit.nz.unc p6,p0=r3,PSR_IC;; // PSI Valid Log bit pos. test
-(p6) st8 [r2]=r0,9*8+160 // increment by 168 byte inc.
+(p6) st8 [r2]=r0,9*8+160 // increment by 232 byte inc.
X begin_skip_intr_regs:
- BRANCH(SkipIntrRegs, r9, p6, 0x0)
- ;;
+(p6) br SkipIntrRegs;;
+
X add r4=8,r2 // duplicate r2 in r4
X add r6=2*8,r2 // duplicate r2 in r6
X
X mov r3=cr16 // cr.ipsr
X mov r5=cr17 // cr.isr
- mov r7=r0;; // cr.ida => cr18
+ mov r7=r0;; // cr.ida => cr18 (reserved)
X st8 [r2]=r3,3*8
X st8 [r4]=r5,3*8
X st8 [r6]=r7,3*8;;
@@ -394,8 +384,7 @@
X br.cloop.sptk.few cStRR
X ;;
X end_os_mca_dump:
- BRANCH(ia64_os_mca_done_dump, r2, p0, -0x10)
- ;;
+ br ia64_os_mca_done_dump;;
X
X //EndStub//////////////////////////////////////////////////////////////////////
X
@@ -484,11 +473,10 @@
X // if PSR.ic=1, reading interruption registers causes an illegal operation fault
X mov r3=psr;;
X tbit.nz.unc p6,p0=r3,PSR_IC;; // PSI Valid Log bit pos. test
-(p6) st8 [r2]=r0,9*8+160 // increment by 160 byte inc.
+(p6) st8 [r2]=r0,9*8+160 // increment by 232 byte inc.
X
X begin_rskip_intr_regs:
- BRANCH(rSkipIntrRegs, r9, p6, 0x0)
- ;;
+(p6) br rSkipIntrRegs;;
X
X add r4=8,r2 // duplicate r2 in r4
X add r6=2*8,r2;; // duplicate r2 in r4
@@ -498,7 +486,7 @@
X ld8 r7=[r6],3*8;;
X mov cr16=r3 // cr.ipsr
X mov cr17=r5 // cr.isr is read only
-// mov cr18=r7;; // cr.ida
+// mov cr18=r7;; // cr.ida (reserved - don't restore)
X
X ld8 r3=[r2],3*8
X ld8 r5=[r4],3*8
@@ -629,8 +617,8 @@
X mov ar.lc=r5
X ;;
X end_os_mca_restore:
- BRANCH(ia64_os_mca_done_restore, r2, p0, -0x20)
- ;;
+ br ia64_os_mca_done_restore;;
+
X //EndStub//////////////////////////////////////////////////////////////////////
X
X // ok, the issue here is that we need to save state information so
@@ -660,12 +648,7 @@
X // 6. GR12 = Return address to location within SAL_INIT procedure
X
X
- .text
- .align 16
-.global ia64_monarch_init_handler
-.proc ia64_monarch_init_handler
-ia64_monarch_init_handler:
-
+GLOBAL_ENTRY(ia64_monarch_init_handler)
X #if defined(CONFIG_SMP) && defined(SAL_MPINIT_WORKAROUND)
X //
X // work around SAL bug that sends all processors to monarch entry
@@ -741,13 +724,12 @@
X adds out0=16,sp // out0 = pointer to pt_regs
X ;;
X
- br.call.sptk.few rp=ia64_init_handler
+ br.call.sptk.many rp=ia64_init_handler
X .ret1:
X
X return_from_init:
X br.sptk return_from_init
-
- .endp
+END(ia64_monarch_init_handler)
X
X //
X // SAL to OS entry point for INIT on the slave processor
@@ -755,14 +737,6 @@
X // as a part of ia64_mca_init.
X //
X
- .text
- .align 16
-.global ia64_slave_init_handler
-.proc ia64_slave_init_handler
-ia64_slave_init_handler:
-
-
-slave_init_spin_me:
- br.sptk slave_init_spin_me
- ;;
- .endp
+GLOBAL_ENTRY(ia64_slave_init_handler)
+1: br.sptk 1b
+END(ia64_slave_init_handler)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/pal.S linux/arch/ia64/kernel/pal.S
--- v2.4.14/linux/arch/ia64/kernel/pal.S Thu Apr 5 12:51:47 2001
+++ linux/arch/ia64/kernel/pal.S Fri Nov 9 14:26:17 2001
@@ -4,8 +4,9 @@
X *
X * Copyright (C) 1999 Don Dugger <don.d...@intel.com>
X * Copyright (C) 1999 Walt Drummond <drum...@valinux.com>
- * Copyright (C) 1999-2000 David Mosberger <dav...@hpl.hp.com>
- * Copyright (C) 2000 Stephane Eranian <era...@hpl.hp.com>


+ * Copyright (C) 1999-2001 Hewlett-Packard Co

+ * David Mosberger <dav...@hpl.hp.com>

+ * Stephane Eranian <era...@hpl.hp.com>

X *
X * 05/22/2000 eranian Added support for stacked register calls
X * 05/24/2000 eranian Added support for physical mode static calls
@@ -31,7 +32,7 @@
X movl r2=pal_entry_point
X ;;
X st8 [r2]=in0


- br.ret.sptk.few rp
+ br.ret.sptk.many rp

X END(ia64_pal_handler_init)
X
X /*
@@ -41,7 +42,7 @@
X */
X GLOBAL_ENTRY(ia64_pal_default_handler)
X mov r8=-1
- br.cond.sptk.few rp
+ br.cond.sptk.many rp
X END(ia64_pal_default_handler)
X
X /*
@@ -79,13 +80,13 @@
X ;;
X (p6) srlz.i
X mov rp = r8


- br.cond.sptk.few b7
+ br.cond.sptk.many b7

X 1: mov psr.l = loc3
X mov ar.pfs = loc1
X mov rp = loc0
X ;;
X srlz.d // seralize restoration of psr.l
- br.ret.sptk.few b0
+ br.ret.sptk.many b0
X END(ia64_pal_call_static)
X
X /*
@@ -120,7 +121,7 @@
X mov rp = loc0
X ;;
X srlz.d // serialize restoration of psr.l
- br.ret.sptk.few b0
+ br.ret.sptk.many b0
X END(ia64_pal_call_stacked)
X
X /*
@@ -173,13 +174,13 @@
X or loc3=loc3,r17 // add in psr the bits to set
X ;;
X andcm r16=loc3,r16 // removes bits to clear from psr


- br.call.sptk.few rp=ia64_switch_mode
+ br.call.sptk.many rp=ia64_switch_mode

X .ret1: mov rp = r8 // install return address (physical)


- br.cond.sptk.few b7
+ br.cond.sptk.many b7

X 1:
X mov ar.rsc=0 // put RSE in enforced lazy, LE mode
X mov r16=loc3 // r16= original psr


- br.call.sptk.few rp=ia64_switch_mode // return to virtual mode
+ br.call.sptk.many rp=ia64_switch_mode // return to virtual mode
X .ret2:

X mov psr.l = loc3 // restore init PSR
X
@@ -188,7 +189,7 @@
X ;;
X mov ar.rsc=loc4 // restore RSE configuration
X srlz.d // seralize restoration of psr.l
- br.ret.sptk.few b0
+ br.ret.sptk.many b0
X END(ia64_pal_call_phys_static)
X
X /*
@@ -227,13 +228,13 @@
X mov b7 = loc2 // install target to branch reg
X ;;
X andcm r16=loc3,r16 // removes bits to clear from psr


- br.call.sptk.few rp=ia64_switch_mode
+ br.call.sptk.many rp=ia64_switch_mode

X .ret6:
X br.call.sptk.many rp=b7 // now make the call
X .ret7:
X mov ar.rsc=0 // put RSE in enforced lazy, LE mode
X mov r16=loc3 // r16= original psr


- br.call.sptk.few rp=ia64_switch_mode // return to virtual mode
+ br.call.sptk.many rp=ia64_switch_mode // return to virtual mode
X

X .ret8: mov psr.l = loc3 // restore init PSR
X mov ar.pfs = loc1


@@ -241,6 +242,6 @@
X ;;

X mov ar.rsc=loc4 // restore RSE configuration
X srlz.d // seralize restoration of psr.l
- br.ret.sptk.few b0
+ br.ret.sptk.many b0
X END(ia64_pal_call_phys_stacked)
X
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/palinfo.c linux/arch/ia64/kernel/palinfo.c
--- v2.4.14/linux/arch/ia64/kernel/palinfo.c Thu Apr 5 12:51:47 2001
+++ linux/arch/ia64/kernel/palinfo.c Fri Nov 9 14:26:17 2001
@@ -6,12 +6,13 @@
X * Intel IA-64 Architecture Software Developer's Manual v1.0.
X *
X *
- * Copyright (C) 2000 Hewlett-Packard Co
- * Copyright (C) 2000 Stephane Eranian <era...@hpl.hp.com>
+ * Copyright (C) 2000-2001 Hewlett-Packard Co


+ * Stephane Eranian <era...@hpl.hp.com>

X *
X * 05/26/2000 S.Eranian initial release
X * 08/21/2000 S.Eranian updated to July 2000 PAL specs
X * 02/05/2001 S.Eranian fixed module support
+ * 10/23/2001 S.Eranian updated pal_perf_mon_info bug fixes
X */
X #include <linux/config.h>
X #include <linux/types.h>
@@ -32,8 +33,9 @@
X
X MODULE_AUTHOR("Stephane Eranian <era...@hpl.hp.com>");
X MODULE_DESCRIPTION("/proc interface to IA-64 PAL");
+MODULE_LICENSE("GPL");
X
-#define PALINFO_VERSION "0.4"
+#define PALINFO_VERSION "0.5"
X
X #ifdef CONFIG_SMP
X #define cpu_is_online(i) (cpu_online_map & (1UL << i))
@@ -606,15 +608,6 @@
X
X if (ia64_pal_perf_mon_info(pm_buffer, &pm_info) != 0) return 0;
X
-#ifdef IA64_PAL_PERF_MON_INFO_BUG
- /*
- * This bug has been fixed in PAL 2.2.9 and higher
- */
- pm_buffer[5]=0x3;
- pm_info.pal_perf_mon_info_s.cycles = 0x12;
- pm_info.pal_perf_mon_info_s.retired = 0x08;
-#endif
-
X p += sprintf(p, "PMC/PMD pairs : %d\n" \
X "Counter width : %d bits\n" \
X "Cycle event number : %d\n" \
@@ -636,6 +629,14 @@
X p = bitregister_process(p, pm_buffer+8, 256);
X
X p += sprintf(p, "\nRetired bundles count capable : ");
+
+#ifdef CONFIG_ITANIUM
+ /*
+ * PAL_PERF_MON_INFO reports that only PMC4 can be used to count CPU_CYCLES
+ * which is wrong, both PMC4 and PMD5 support it.
+ */
+ if (pm_buffer[12] == 0x10) pm_buffer[12]=0x30;
+#endif
X
X p = bitregister_process(p, pm_buffer+12, 256);
X
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/pci.c linux/arch/ia64/kernel/pci.c
--- v2.4.14/linux/arch/ia64/kernel/pci.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/pci.c Fri Nov 9 14:26:17 2001
@@ -38,6 +38,10 @@
X #define DBG(x...)
X #endif
X
+#ifdef CONFIG_IA64_MCA
+extern void ia64_mca_check_errors( void );
+#endif
+
X /*
X * This interrupt-safe spinlock protects all accesses to PCI
X * configuration space.
@@ -122,6 +126,10 @@
X # define PCI_BUSES_TO_SCAN 255
X int i;
X
+#ifdef CONFIG_IA64_MCA
+ ia64_mca_check_errors(); /* For post-failure MCA error logging */
+#endif
+
X platform_pci_fixup(0); /* phase 0 initialization (before PCI bus has been scanned) */
X
X printk("PCI: Probing PCI hardware\n");
@@ -194,4 +202,40 @@
X pcibios_setup (char *str)
X {
X return NULL;
+}
+
+int
+pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine)
+{
+ /*
+ * I/O space cannot be accessed via normal processor loads and stores on this
+ * platform.
+ */
+ if (mmap_state == pci_mmap_io)
+ /*
+ * XXX we could relax this for I/O spaces for which ACPI indicates that
+ * the space is 1-to-1 mapped. But at the moment, we don't support
+ * multiple PCI address spaces and the legacy I/O space is not 1-to-1
+ * mapped, so this is moot.
+ */
+ return -EINVAL;
+
+ /*
+ * Leave vm_pgoff as-is, the PCI space address is the physical address on this
+ * platform.
+ */
+ vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
+
+ if (write_combine)
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ else
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ if (remap_page_range(vma->vm_start, vma->vm_pgoff << PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot))
+ return -EAGAIN;
+
+ return 0;
X }
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/perfmon.c linux/arch/ia64/kernel/perfmon.c
--- v2.4.14/linux/arch/ia64/kernel/perfmon.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/perfmon.c Fri Nov 9 14:26:17 2001
@@ -38,7 +38,7 @@
X
X #ifdef CONFIG_PERFMON
X
-#define PFM_VERSION "0.2"
+#define PFM_VERSION "0.3"
X #define PFM_SMPL_HDR_VERSION 1
X
X #define PMU_FIRST_COUNTER 4 /* first generic counter */


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

echo 'End of part 031'
echo 'File patch-2.4.15 is continued in part 032'
echo "032" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:14 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part038

#!/bin/sh -x
# this is part 038 of a 115 - part archive


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

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

+ writel((SAR_FBQ3_LOW << 28) | 0x00000000 | 0x00000000 |
+ (SAR_FB_SIZE_3 / 48), SAR_REG_FBQS3);
+
+ /* Initialize rate table */
+ for (i = 0; i < 256; i++) {
+ write_sram(card, card->rt_base + i, log_to_rate[i]);
+ }
+
+ for (i = 0; i < 128; i++) {
+ unsigned int tmp;
+
+ tmp = rate_to_log[(i << 2) + 0] << 0;
+ tmp |= rate_to_log[(i << 2) + 1] << 8;
+ tmp |= rate_to_log[(i << 2) + 2] << 16;
+ tmp |= rate_to_log[(i << 2) + 3] << 24;
+ write_sram(card, card->rt_base + 256 + i, tmp);
+ }
+
+#if 0 /* Fill RDF and AIR tables. */
+ for (i = 0; i < 128; i++) {
+ unsigned int tmp;
+
+ tmp = RDF[0][(i << 1) + 0] << 16;
+ tmp |= RDF[0][(i << 1) + 1] << 0;
+ write_sram(card, card->rt_base + 512 + i, tmp);
+ }
+
+ for (i = 0; i < 128; i++) {
+ unsigned int tmp;
+
+ tmp = AIR[0][(i << 1) + 0] << 16;
+ tmp |= AIR[0][(i << 1) + 1] << 0;
+ write_sram(card, card->rt_base + 640 + i, tmp);
+ }
+#endif
+
+ IPRINTK("%s: initialize rate table ...\n", card->name);
+ writel(card->rt_base << 2, SAR_REG_RTBL);
+
+ /* Initialize TSTs */
+ IPRINTK("%s: initialize TST ...\n", card->name);
+ card->tst_free = card->tst_size - 2; /* last two are jumps */
+
+ for (i = card->tst[0]; i < card->tst[0] + card->tst_size - 2; i++)
+ write_sram(card, i, TSTE_OPC_VAR);
+ write_sram(card, i++, TSTE_OPC_JMP | (card->tst[0] << 2));
+ idt77252_sram_write_errors = 1;
+ write_sram(card, i++, TSTE_OPC_JMP | (card->tst[1] << 2));
+ idt77252_sram_write_errors = 0;
+ for (i = card->tst[1]; i < card->tst[1] + card->tst_size - 2; i++)
+ write_sram(card, i, TSTE_OPC_VAR);
+ write_sram(card, i++, TSTE_OPC_JMP | (card->tst[1] << 2));
+ idt77252_sram_write_errors = 1;
+ write_sram(card, i++, TSTE_OPC_JMP | (card->tst[0] << 2));
+ idt77252_sram_write_errors = 0;
+
+ card->tst_index = 0;
+ writel(card->tst[0] << 2, SAR_REG_TSTB);
+
+ /* Initialize ABRSTD and Receive FIFO */
+ IPRINTK("%s: initialize ABRSTD ...\n", card->name);
+ writel(card->abrst_size | (card->abrst_base << 2),
+ SAR_REG_ABRSTD);
+
+ IPRINTK("%s: initialize receive fifo ...\n", card->name);
+ writel(card->fifo_size | (card->fifo_base << 2),
+ SAR_REG_RXFD);
+
+ IPRINTK("%s: SRAM initialization complete.\n", card->name);


+ return 0;
+}
+

+static int __devinit
+init_card(struct atm_dev *dev)
+{
+ struct idt77252_dev *card = dev->dev_data;
+ struct pci_dev *pcidev = card->pcidev;
+ unsigned long tmpl, modl;
+ unsigned int linkrate, rsvdcr;
+ unsigned int tst_entries;
+ struct net_device *tmp;
+ char tname[10];
+
+ u32 size;
+ u_char pci_byte;
+ u32 conf;
+ int i, k;
+
+ if (test_bit(IDT77252_BIT_INIT, &card->flags)) {
+ printk("Error: SAR already initialized.\n");


+ return -1;
+ }
+

+/*****************************************************************/
+/* P C I C O N F I G U R A T I O N */
+/*****************************************************************/
+
+ /* Set PCI Retry-Timeout and TRDY timeout */
+ IPRINTK("%s: Checking PCI retries.\n", card->name);
+ if (pci_read_config_byte(pcidev, 0x40, &pci_byte) != 0) {
+ printk("%s: can't read PCI retry timeout.\n", card->name);
+ deinit_card(card);
+ return -1;
+ }
+ if (pci_byte != 0) {
+ IPRINTK("%s: PCI retry timeout: %d, set to 0.\n",
+ card->name, pci_byte);
+ if (pci_write_config_byte(pcidev, 0x40, 0) != 0) {
+ printk("%s: can't set PCI retry timeout.\n",
+ card->name);
+ deinit_card(card);


+ return -1;
+ }
+ }

+ IPRINTK("%s: Checking PCI TRDY.\n", card->name);
+ if (pci_read_config_byte(pcidev, 0x41, &pci_byte) != 0) {
+ printk("%s: can't read PCI TRDY timeout.\n", card->name);
+ deinit_card(card);
+ return -1;
+ }
+ if (pci_byte != 0) {
+ IPRINTK("%s: PCI TRDY timeout: %d, set to 0.\n",
+ card->name, pci_byte);
+ if (pci_write_config_byte(pcidev, 0x41, 0) != 0) {
+ printk("%s: can't set PCI TRDY timeout.\n", card->name);
+ deinit_card(card);


+ return -1;
+ }
+ }

+ /* Reset Timer register */
+ if (readl(SAR_REG_STAT) & SAR_STAT_TMROF) {
+ printk("%s: resetting timer overflow.\n", card->name);
+ writel(SAR_STAT_TMROF, SAR_REG_STAT);
+ }
+ IPRINTK("%s: Request IRQ ... ", card->name);
+ if (request_irq(pcidev->irq, idt77252_interrupt, SA_INTERRUPT|SA_SHIRQ,
+ card->name, card) != 0) {
+ printk("%s: can't allocate IRQ.\n", card->name);
+ deinit_card(card);
+ return -1;
+ }
+ IPRINTK("got %d.\n", pcidev->irq);
+
+/*****************************************************************/
+/* C H E C K A N D I N I T S R A M */
+/*****************************************************************/
+
+ IPRINTK("%s: Initializing SRAM\n", card->name);
+
+ /* preset size of connecton table, so that init_sram() knows about it */
+ conf = SAR_CFG_TX_FIFO_SIZE_9 | /* Use maximum fifo size */
+ SAR_CFG_RXSTQ_SIZE_8k | /* Receive Status Queue is 8k */
+ SAR_CFG_IDLE_CLP | /* Set CLP on idle cells */
+#ifndef CONFIG_ATM_IDT77252_SEND_IDLE
+ SAR_CFG_NO_IDLE | /* Do not send idle cells */
+#endif
+ 0;
+
+ if (card->sramsize == (512 * 1024))
+ conf |= SAR_CFG_CNTBL_1k;
+ else
+ conf |= SAR_CFG_CNTBL_512;
+
+ switch (vpibits) {
+ case 0:
+ conf |= SAR_CFG_VPVCS_0;
+ break;
+ default:
+ case 1:
+ conf |= SAR_CFG_VPVCS_1;


+ break;
+ case 2:

+ conf |= SAR_CFG_VPVCS_2;
+ break;
+ case 8:
+ conf |= SAR_CFG_VPVCS_8;
+ break;
+ }
+
+ writel(readl(SAR_REG_CFG) | conf, SAR_REG_CFG);
+
+ if (init_sram(card) < 0)
+ return -1;
+
+/********************************************************************/
+/* A L L O C R A M A N D S E T V A R I O U S T H I N G S */
+/********************************************************************/
+ /* Initialize TSQ */
+ if (0 != init_tsq(card)) {
+ deinit_card(card);
+ return -1;
+ }
+ /* Initialize RSQ */
+ if (0 != init_rsq(card)) {
+ deinit_card(card);


+ return -1;
+ }
+

+ card->vpibits = vpibits;
+ if (card->sramsize == (512 * 1024)) {
+ card->vcibits = 10 - card->vpibits;
+ } else {
+ card->vcibits = 9 - card->vpibits;
+ }
+
+ card->vcimask = 0;
+ for (k = 0, i = 1; k < card->vcibits; k++) {
+ card->vcimask |= i;
+ i <<= 1;
+ }
+
+ IPRINTK("%s: Setting VPI/VCI mask to zero.\n", card->name);
+ writel(0, SAR_REG_VPM);
+
+ /* Little Endian Order */
+ writel(0, SAR_REG_GP);
+
+ /* Initialize RAW Cell Handle Register */
+ card->raw_cell_hnd = pci_alloc_consistent(card->pcidev, 2 * sizeof(u32),
+ &card->raw_cell_paddr);
+ if (!card->raw_cell_hnd) {
+ printk("%s: memory allocation failure.\n", card->name);
+ deinit_card(card);
+ return -1;
+ }
+ memset(card->raw_cell_hnd, 0, 2 * sizeof(u32));
+ writel(card->raw_cell_paddr, SAR_REG_RAWHND);
+ IPRINTK("%s: raw cell handle is at 0x%p.\n", card->name,
+ card->raw_cell_hnd);
+
+ size = sizeof(struct vc_map *) * card->tct_size;
+ IPRINTK("%s: allocate %d byte for VC map.\n", card->name, size);
+ if (NULL == (card->vcs = vmalloc(size))) {
+ printk("%s: memory allocation failure.\n", card->name);
+ deinit_card(card);
+ return -1;
+ }
+ memset(card->vcs, 0, size);
+
+ size = sizeof(struct vc_map *) * card->scd_size;
+ IPRINTK("%s: allocate %d byte for SCD to VC mapping.\n",
+ card->name, size);
+ if (NULL == (card->scd2vc = vmalloc(size))) {
+ printk("%s: memory allocation failure.\n", card->name);
+ deinit_card(card);
+ return -1;
+ }
+ memset(card->scd2vc, 0, size);
+
+ size = sizeof(struct tst_info) * (card->tst_size - 2);
+ IPRINTK("%s: allocate %d byte for TST to VC mapping.\n",
+ card->name, size);
+ if (NULL == (card->soft_tst = vmalloc(size))) {
+ printk("%s: memory allocation failure.\n", card->name);
+ deinit_card(card);
+ return -1;
+ }
+ for (i = 0; i < card->tst_size - 2; i++) {
+ card->soft_tst[i].tste = TSTE_OPC_VAR;
+ card->soft_tst[i].vc = NULL;
+ }
+
+ if (dev->phy == NULL) {
+ printk("%s: No LT device defined.\n", card->name);
+ deinit_card(card);
+ return -1;
+ }
+ if (dev->phy->ioctl == NULL) {
+ printk("%s: LT had no IOCTL funtion defined.\n", card->name);
+ deinit_card(card);


+ return -1;
+ }
+

+#ifdef CONFIG_ATM_IDT77252_USE_SUNI
+ /*
+ * this is a jhs hack to get around special functionality in the
+ * phy driver for the atecom hardware; the functionality doesn't
+ * exist in the linux atm suni driver
+ *
+ * it isn't the right way to do things, but as the guy from NIST
+ * said, talking about their measurement of the fine structure
+ * constant, "it's good enough for government work."
+ */
+ linkrate = 149760000;
+#endif
+
+ card->link_pcr = (linkrate / 8 / 53);
+ printk("%s: Linkrate on ATM line : %u bit/s, %u cell/s.\n",
+ card->name, linkrate, card->link_pcr);
+
+#ifdef CONFIG_ATM_IDT77252_SEND_IDLE
+ card->utopia_pcr = card->link_pcr;
+#else
+ card->utopia_pcr = (160000000 / 8 / 54);
+#endif
+
+ rsvdcr = 0;
+ if (card->utopia_pcr > card->link_pcr)
+ rsvdcr = card->utopia_pcr - card->link_pcr;
+
+ tmpl = (unsigned long) rsvdcr * ((unsigned long) card->tst_size - 2);
+ modl = tmpl % (unsigned long)card->utopia_pcr;
+ tst_entries = (int) (tmpl / (unsigned long)card->utopia_pcr);
+ if (modl)
+ tst_entries++;
+ card->tst_free -= tst_entries;
+ fill_tst(card, NULL, tst_entries, TSTE_OPC_NULL);
+
+#ifdef HAVE_EEPROM
+ idt77252_eeprom_init(card);
+ printk("%s: EEPROM: %02x:", card->name,
+ idt77252_eeprom_read_status(card));
+
+ for (i = 0; i < 0x80; i++) {
+ printk(" %02x",
+ idt77252_eeprom_read_byte(card, i)
+ );


+ }
+ printk("\n");

+#endif /* HAVE_EEPROM */
+
+ /*
+ * XXX: <hack>
+ */
+ sprintf(tname, "eth%d", card->index);
+ tmp = dev_get_by_name(tname); /* jhs: was "tmp = dev_get(tname);" */
+ if (tmp) {
+ memcpy(card->atmdev->esi, tmp->dev_addr, 6);
+
+ printk("%s: ESI %02x:%02x:%02x:%02x:%02x:%02x\n",
+ card->name, card->atmdev->esi[0], card->atmdev->esi[1],
+ card->atmdev->esi[2], card->atmdev->esi[3],
+ card->atmdev->esi[4], card->atmdev->esi[5]);
+ }
+ /*
+ * XXX: </hack>
+ */
+
+ /* Set Maximum Deficit Count for now. */
+ writel(0xffff, SAR_REG_MDFCT);
+
+ set_bit(IDT77252_BIT_INIT, &card->flags);
+
+ XPRINTK("%s: IDT77252 ABR SAR initialization complete.\n", card->name);


+ return 0;
+}
+
+

+/*****************************************************************************/
+/* */
+/* Probing of IDT77252 ABR SAR */
+/* */
+/*****************************************************************************/
+
+
+static int __devinit
+idt77252_preset(struct idt77252_dev *card)
+{
+ u16 pci_command;
+
+/*****************************************************************/
+/* P C I C O N F I G U R A T I O N */
+/*****************************************************************/
+
+ XPRINTK("%s: Enable PCI master and memory access for SAR.\n",
+ card->name);
+ if (pci_read_config_word(card->pcidev, PCI_COMMAND, &pci_command)) {
+ printk("%s: can't read PCI_COMMAND.\n", card->name);
+ deinit_card(card);
+ return -1;
+ }
+ if (!(pci_command & PCI_COMMAND_IO)) {
+ printk("%s: PCI_COMMAND: %04x (???)\n",
+ card->name, pci_command);
+ deinit_card(card);
+ return (-1);
+ }
+ pci_command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ if (pci_write_config_word(card->pcidev, PCI_COMMAND, pci_command)) {
+ printk("%s: can't write PCI_COMMAND.\n", card->name);
+ deinit_card(card);
+ return -1;
+ }
+/*****************************************************************/
+/* G E N E R I C R E S E T */
+/*****************************************************************/
+
+ /* Software reset */
+ writel(SAR_CFG_SWRST, SAR_REG_CFG);
+ mdelay(1);
+ writel(0, SAR_REG_CFG);
+
+ IPRINTK("%s: Software resetted.\n", card->name);


+ return 0;
+}
+
+

+static unsigned long __devinit
+probe_sram(struct idt77252_dev *card)
+{
+ u32 data, addr;
+
+ writel(0, SAR_REG_DR0);
+ writel(SAR_CMD_WRITE_SRAM | (0 << 2), SAR_REG_CMD);
+
+ for (addr = 0x4000; addr < 0x80000; addr += 0x4000) {
+ writel(0xdeadbeef, SAR_REG_DR0);
+ writel(SAR_CMD_WRITE_SRAM | (addr << 2), SAR_REG_CMD);
+
+ writel(SAR_CMD_READ_SRAM | (0 << 2), SAR_REG_CMD);
+ data = readl(SAR_REG_DR0);
+
+ if (data != 0)
+ break;
+ }
+
+ return addr * sizeof(u32);
+}
+
+static int __devinit
+idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
+{
+ static struct idt77252_dev **last = &idt77252_chain;
+ static int index = 0;
+
+ unsigned long membase, srambase;
+ struct idt77252_dev *card;
+ struct atm_dev *dev;
+ ushort revision = 0;


+ int i;
+
+

+ if (pci_read_config_word(pcidev, PCI_REVISION_ID, &revision)) {
+ printk("idt77252-%d: can't read PCI_REVISION_ID\n", index);


+ return -ENODEV;
+ }
+

+ card = kmalloc(sizeof(struct idt77252_dev), GFP_KERNEL);
+ if (!card) {
+ printk("idt77252-%d: can't allocate private data\n", index);
+ return -ENOMEM;
+ }
+ memset(card, 0, sizeof(struct idt77252_dev));
+
+ card->revision = revision;
+ card->index = index;
+ card->pcidev = pcidev;
+ sprintf(card->name, "idt77252-%d", card->index);
+
+ card->tqueue.routine = idt77252_softint;
+ card->tqueue.data = (void *)card;
+
+ membase = pci_resource_start(pcidev, 1);
+ srambase = pci_resource_start(pcidev, 2);
+
+ init_MUTEX(&card->mutex);
+ spin_lock_init(&card->cmd_lock);
+ spin_lock_init(&card->tst_lock);
+
+ card->tst_timer.data = (unsigned long)card;
+ card->tst_timer.function = tst_timer;
+ init_timer(&card->tst_timer);
+
+ /* Do the I/O remapping... */
+ card->membase = (unsigned long) ioremap(membase, 1024);
+ if (!card->membase) {
+ printk("%s: can't ioremap() membase\n", card->name);
+ kfree(card);
+ return -EIO;
+ }
+
+ if (idt77252_preset(card)) {
+ printk("%s: preset failed\n", card->name);
+ iounmap((void *) card->membase);
+ kfree(card);
+ return -EIO;
+ }
+
+ dev = atm_dev_register("idt77252", &idt77252_ops, -1, 0);
+ if (!dev) {
+ printk("%s: can't register atm device\n", card->name);
+ iounmap((void *) card->membase);
+ kfree(card);
+ return -EIO;
+ }
+ dev->dev_data = card;
+ card->atmdev = dev;
+
+#ifdef CONFIG_ATM_IDT77252_USE_SUNI
+ suni_init(dev);
+ if (!dev->phy) {
+ printk("%s: can't init SUNI\n", card->name);
+ deinit_card(card);
+ kfree(card);
+ return -EIO;
+ }
+#endif /* CONFIG_ATM_IDT77252_USE_SUNI */
+
+ card->sramsize = probe_sram(card);
+
+ for (i = 0; i < 4; i++) {
+ card->fbq[i] = (unsigned long)
+ ioremap(srambase | 0x200000 | (i << 18), 4);
+ if (!card->fbq[i]) {
+ printk("%s: can't ioremap() FBQ%d\n", card->name, i);
+ deinit_card(card);
+ kfree(card);
+ return -EIO;
+ }
+ }
+
+ printk("%s: ABR SAR (Rev %c): MEM %08lx SRAM %08lx [%u KB]\n",
+ card->name, ((revision > 1) && (revision < 25)) ?
+ 'A' + revision - 1 : '?', membase, srambase,
+ card->sramsize / 1024);
+
+ if (init_card(dev)) {
+ printk("%s: init_card failed\n", card->name);
+ deinit_card(card);
+ kfree(card);
+ return -EIO;
+ }
+
+ dev->ci_range.vpi_bits = card->vpibits;
+ dev->ci_range.vci_bits = card->vcibits;
+ dev->link_rate = card->link_pcr;
+
+ if (dev->phy->start)
+ dev->phy->start(dev);
+
+ if (idt77252_dev_open(card)) {
+ printk("%s: dev_open failed\n", card->name);
+
+ if (dev->phy->stop)
+ dev->phy->stop(dev);
+ deinit_card(card);
+ kfree(card);
+ return -EIO;
+ }
+
+ *last = card;
+ last = &card->next;
+ index++;
+


+ return 0;
+}
+

+static struct pci_device_id idt77252_pci_tbl[] __devinitdata =
+{
+ { PCI_VENDOR_ID_IDT, PCI_DEVICE_ID_IDT_IDT77252,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0, }
+};
+
+static struct pci_driver idt77252_driver = {
+ name: "idt77252",
+ id_table: idt77252_pci_tbl,
+ probe: idt77252_init_one,
+};
+
+static int __init idt77252_init(void)
+{
+ struct sk_buff *skb;
+
+ printk("%s: at %p\n", __FUNCTION__, idt77252_init);
+
+ if (sizeof(skb->cb) < sizeof(struct atm_skb_data) +
+ sizeof(struct idt77252_skb_prv)) {
+ printk(KERN_ERR "%s: skb->cb is too small (%lu < %lu)\n",
+ __FUNCTION__, (unsigned long) sizeof(skb->cb),
+ (unsigned long) sizeof(struct atm_skb_data) +
+ sizeof(struct idt77252_skb_prv));
+ return -EIO;
+ }
+
+ if (pci_register_driver(&idt77252_driver) > 0)
+ return 0;
+
+ pci_unregister_driver(&idt77252_driver);


+ return -ENODEV;
+}
+

+static void __exit idt77252_exit(void)
+{
+ struct idt77252_dev *card;
+ struct atm_dev *dev;
+
+ pci_unregister_driver(&idt77252_driver);
+
+ while (idt77252_chain) {
+ card = idt77252_chain;
+ dev = card->atmdev;
+ idt77252_chain = card->next;
+
+ if (dev->phy->stop)
+ dev->phy->stop(dev);
+ deinit_card(card);
+ kfree(card);
+ }
+
+ DIPRINTK("idt77252: finished cleanup-module().\n");
+}
+
+module_init(idt77252_init);
+module_exit(idt77252_exit);
+
+EXPORT_NO_SYMBOLS;
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(vpibits, "i");
+MODULE_PARM_DESC(vpibits, "number of VPI bits supported (0, 1, or 2)");
+#ifdef CONFIG_ATM_IDT77252_DEBUG
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "debug bitmap, see drivers/atm/idt77252.h");
+#endif
+
+MODULE_AUTHOR("Eddie C. Dost <e...@atecom.com>");
+MODULE_DESCRIPTION("IDT77252 ABR SAR Driver");
diff -u --recursive --new-file v2.4.14/linux/drivers/atm/idt77252.h linux/drivers/atm/idt77252.h
--- v2.4.14/linux/drivers/atm/idt77252.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/atm/idt77252.h Tue Nov 13 09:19:41 2001
@@ -0,0 +1,818 @@
+/*******************************************************************
+ * ident "$Id: idt77252.h,v 1.2 2001/11/11 08:13:54 ecd Exp $"
+ *
+ * $Author: ecd $
+ * $Date: 2001/11/11 08:13:54 $
+ *
+ * Copyright (c) 2000 ATecoM GmbH
+ *
+ * The author may be reached at e...@atecom.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.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *******************************************************************/
+
+#ifndef _IDT77252_H
+#define _IDT77252_H 1
+
+
+#include <linux/ptrace.h>
+#include <linux/skbuff.h>
+
+
+/*****************************************************************************/
+/* */
+/* Makros */
+/* */
+/*****************************************************************************/
+#define VPCI2VC(card, vpi, vci) \
+ (((vpi) << card->vcibits) | ((vci) & card->vcimask))
+
+/*****************************************************************************/
+/* */
+/* DEBUGGING definitions */
+/* */
+/*****************************************************************************/
+
+#define DBG_RAW_CELL 0x00000400
+#define DBG_TINY 0x00000200
+#define DBG_GENERAL 0x00000100
+#define DBG_XGENERAL 0x00000080
+#define DBG_INIT 0x00000040
+#define DBG_DEINIT 0x00000020
+#define DBG_INTERRUPT 0x00000010
+#define DBG_OPEN_CONN 0x00000008
+#define DBG_CLOSE_CONN 0x00000004
+#define DBG_RX_DATA 0x00000002
+#define DBG_TX_DATA 0x00000001
+
+#ifdef CONFIG_ATM_IDT77252_DEBUG
+
+#define CPRINTK(args...) do { if (debug & DBG_CLOSE_CONN) printk(args); } while(0)
+#define OPRINTK(args...) do { if (debug & DBG_OPEN_CONN) printk(args); } while(0)
+#define IPRINTK(args...) do { if (debug & DBG_INIT) printk(args); } while(0)
+#define INTPRINTK(args...) do { if (debug & DBG_INTERRUPT) printk(args); } while(0)
+#define DIPRINTK(args...) do { if (debug & DBG_DEINIT) printk(args); } while(0)
+#define TXPRINTK(args...) do { if (debug & DBG_TX_DATA) printk(args); } while(0)
+#define RXPRINTK(args...) do { if (debug & DBG_RX_DATA) printk(args); } while(0)
+#define XPRINTK(args...) do { if (debug & DBG_XGENERAL) printk(args); } while(0)
+#define DPRINTK(args...) do { if (debug & DBG_GENERAL) printk(args); } while(0)
+#define NPRINTK(args...) do { if (debug & DBG_TINY) printk(args); } while(0)
+#define RPRINTK(args...) do { if (debug & DBG_RAW_CELL) printk(args); } while(0)
+
+#else
+
+#define CPRINTK(args...) do { } while(0)
+#define OPRINTK(args...) do { } while(0)
+#define IPRINTK(args...) do { } while(0)
+#define INTPRINTK(args...) do { } while(0)
+#define DIPRINTK(args...) do { } while(0)
+#define TXPRINTK(args...) do { } while(0)
+#define RXPRINTK(args...) do { } while(0)
+#define XPRINTK(args...) do { } while(0)
+#define DPRINTK(args...) do { } while(0)
+#define NPRINTK(args...) do { } while(0)
+#define RPRINTK(args...) do { } while(0)
+
+#endif
+
+#define SCHED_UBR0 0
+#define SCHED_UBR 1
+#define SCHED_VBR 2
+#define SCHED_ABR 3
+#define SCHED_CBR 4
+
+#define SCQFULL_TIMEOUT HZ
+
+/*****************************************************************************/
+/* */
+/* Free Buffer Queue Layout */
+/* */
+/*****************************************************************************/
+#define SAR_FB_SIZE_0 (2048 - 256)
+#define SAR_FB_SIZE_1 (4096 - 256)
+#define SAR_FB_SIZE_2 (8192 - 256)
+#define SAR_FB_SIZE_3 (16384 - 256)
+
+#define SAR_FBQ0_LOW 4
+#define SAR_FBQ0_HIGH 8
+#define SAR_FBQ1_LOW 2
+#define SAR_FBQ1_HIGH 4
+#define SAR_FBQ2_LOW 1
+#define SAR_FBQ2_HIGH 2
+#define SAR_FBQ3_LOW 1
+#define SAR_FBQ3_HIGH 2
+
+#if 0
+#define SAR_TST_RESERVED 44 /* Num TST reserved for UBR/ABR/VBR */
+#else
+#define SAR_TST_RESERVED 0 /* Num TST reserved for UBR/ABR/VBR */
+#endif
+
+#define TCT_CBR 0x00000000
+#define TCT_UBR 0x00000000
+#define TCT_VBR 0x40000000
+#define TCT_ABR 0x80000000
+#define TCT_TYPE 0xc0000000
+
+#define TCT_RR 0x20000000
+#define TCT_LMCR 0x08000000
+#define TCT_SCD_MASK 0x0007ffff
+
+#define TCT_TSIF 0x00004000
+#define TCT_HALT 0x80000000
+#define TCT_IDLE 0x40000000
+#define TCT_FLAG_UBR 0x80000000
+
+/*****************************************************************************/
+/* */
+/* Structure describing an IDT77252 */
+/* */
+/*****************************************************************************/
+
+struct scqe
+{
+ u32 word_1;
+ u32 word_2;
+ u32 word_3;
+ u32 word_4;
+};
+
+#define SCQ_ENTRIES 64
+#define SCQ_SIZE (SCQ_ENTRIES * sizeof(struct scqe))
+#define SCQ_MASK (SCQ_SIZE - 1)
+
+struct scq_info
+{
+ struct scqe *base;
+ struct scqe *next;
+ struct scqe *last;
+ dma_addr_t paddr;
+ spinlock_t lock;
+ atomic_t used;
+ unsigned long trans_start;
+ unsigned long scd;
+ spinlock_t skblock;
+ struct sk_buff_head transmit;
+ struct sk_buff_head pending;
+};
+
+struct rx_pool {
+ struct sk_buff *first;
+ struct sk_buff **last;
+ unsigned int len;
+ unsigned int count;
+};
+
+struct aal1 {
+ unsigned int total;
+ unsigned int count;
+ struct sk_buff *data;
+ unsigned char sequence;
+};
+
+struct rate_estimator {
+ struct timer_list timer;
+ unsigned int interval;
+ unsigned int ewma_log;
+ u64 cells;
+ u64 last_cells;
+ long avcps;
+ u32 cps;
+ u32 maxcps;
+};
+
+struct vc_map {
+ unsigned int index;
+ unsigned long flags;
+#define VCF_TX 0
+#define VCF_RX 1
+#define VCF_IDLE 2
+#define VCF_RSV 3
+ unsigned int class;
+ u8 init_er;
+ u8 lacr;
+ u8 max_er;
+ unsigned int ntste;
+ spinlock_t lock;
+ struct atm_vcc *tx_vcc;
+ struct atm_vcc *rx_vcc;
+ struct idt77252_dev *card;
+ struct scq_info *scq; /* To keep track of the SCQ */
+ struct rate_estimator *estimator;
+ int scd_index;
+ union {
+ struct rx_pool rx_pool;
+ struct aal1 aal1;
+ } rcv;
+};
+
+/*****************************************************************************/
+/* */
+/* RCTE - Receive Connection Table Entry */
+/* */
+/*****************************************************************************/
+
+struct rct_entry
+{
+ u32 word_1;
+ u32 buffer_handle;
+ u32 dma_address;
+ u32 aal5_crc32;
+};
+
+/*****************************************************************************/
+/* */
+/* RSQ - Receive Status Queue */
+/* */
+/*****************************************************************************/
+
+#define SAR_RSQE_VALID 0x80000000
+#define SAR_RSQE_IDLE 0x40000000
+#define SAR_RSQE_BUF_MASK 0x00030000
+#define SAR_RSQE_BUF_ASGN 0x00008000
+#define SAR_RSQE_NZGFC 0x00004000
+#define SAR_RSQE_EPDU 0x00002000
+#define SAR_RSQE_BUF_CONT 0x00001000
+#define SAR_RSQE_EFCIE 0x00000800
+#define SAR_RSQE_CLP 0x00000400
+#define SAR_RSQE_CRC 0x00000200
+#define SAR_RSQE_CELLCNT 0x000001FF
+
+
+#define RSQSIZE 8192
+#define RSQ_NUM_ENTRIES (RSQSIZE / 16)
+#define RSQ_ALIGNMENT 8192
+
+struct rsq_entry {
+ u32 word_1;
+ u32 word_2;
+ u32 word_3;
+ u32 word_4;
+};
+
+struct rsq_info {
+ struct rsq_entry *base;
+ struct rsq_entry *next;
+ struct rsq_entry *last;
+ dma_addr_t paddr;
+} rsq_info;
+
+
+/*****************************************************************************/
+/* */
+/* TSQ - Transmit Status Queue */
+/* */
+/*****************************************************************************/
+
+#define SAR_TSQE_INVALID 0x80000000
+#define SAR_TSQE_TIMESTAMP 0x00FFFFFF
+#define SAR_TSQE_TYPE 0x60000000
+#define SAR_TSQE_TYPE_TIMER 0x00000000
+#define SAR_TSQE_TYPE_TSR 0x20000000
+#define SAR_TSQE_TYPE_IDLE 0x40000000
+#define SAR_TSQE_TYPE_TBD_COMP 0x60000000
+
+#define SAR_TSQE_TAG(stat) (((stat) >> 24) & 0x1f)
+
+#define TSQSIZE 8192
+#define TSQ_NUM_ENTRIES 1024
+#define TSQ_ALIGNMENT 8192
+
+struct tsq_entry
+{
+ u32 word_1;
+ u32 word_2;
+};
+
+struct tsq_info
+{
+ struct tsq_entry *base;
+ struct tsq_entry *next;
+ struct tsq_entry *last;
+ dma_addr_t paddr;
+};
+
+struct tst_info
+{
+ struct vc_map *vc;
+ u32 tste;
+};
+
+#define TSTE_MASK 0x601fffff
+
+#define TSTE_OPC_MASK 0x60000000
+#define TSTE_OPC_NULL 0x00000000
+#define TSTE_OPC_CBR 0x20000000
+#define TSTE_OPC_VAR 0x40000000
+#define TSTE_OPC_JMP 0x60000000
+
+#define TSTE_PUSH_IDLE 0x01000000
+#define TSTE_PUSH_ACTIVE 0x02000000
+
+#define TST_SWITCH_DONE 0
+#define TST_SWITCH_PENDING 1
+#define TST_SWITCH_WAIT 2
+
+#define FBQ_SHIFT 9
+#define FBQ_SIZE (1 << FBQ_SHIFT)
+#define FBQ_MASK (FBQ_SIZE - 1)
+
+struct sb_pool
+{
+ unsigned int index;
+ struct sk_buff *skb[FBQ_SIZE];
+};
+
+#define POOL_HANDLE(queue, index) (((queue + 1) << 16) | (index))
+#define POOL_QUEUE(handle) (((handle) >> 16) - 1)
+#define POOL_INDEX(handle) ((handle) & 0xffff)
+
+struct idt77252_dev
+{
+ struct tsq_info tsq; /* Transmit Status Queue */
+ struct rsq_info rsq; /* Receive Status Queue */
+
+ struct pci_dev *pcidev; /* PCI handle (desriptor) */
+ struct atm_dev *atmdev; /* ATM device desriptor */
+
+ unsigned long membase; /* SAR's memory base address */
+ unsigned long srambase; /* SAR's sram base address */
+ unsigned long fbq[4]; /* FBQ fill addresses */
+
+ struct semaphore mutex;
+ spinlock_t cmd_lock; /* for r/w utility/sram */
+
+ unsigned long softstat;
+ unsigned long flags; /* see blow */
+
+ struct tq_struct tqueue;
+
+ unsigned long tct_base; /* TCT base address in SRAM */
+ unsigned long rct_base; /* RCT base address in SRAM */
+ unsigned long rt_base; /* Rate Table base in SRAM */
+ unsigned long scd_base; /* SCD base address in SRAM */
+ unsigned long tst[2]; /* TST base address in SRAM */
+ unsigned long abrst_base; /* ABRST base address in SRAM */
+ unsigned long fifo_base; /* RX FIFO base in SRAM */
+
+ unsigned long irqstat[16];
+
+ unsigned int sramsize; /* SAR's sram size */
+
+ unsigned int tct_size; /* total TCT entries */
+ unsigned int rct_size; /* total RCT entries */
+ unsigned int scd_size; /* length of SCD */
+ unsigned int tst_size; /* total TST entries */
+ unsigned int tst_free; /* free TSTEs in TST */
+ unsigned int abrst_size; /* size of ABRST in words */
+ unsigned int fifo_size; /* size of RX FIFO in words */
+
+ unsigned int vpibits; /* Bits used for VPI index */
+ unsigned int vcibits; /* Bits used for VCI index */
+ unsigned int vcimask; /* Mask for VCI index */
+
+ unsigned int utopia_pcr; /* Utopia Itf's Cell Rate */
+ unsigned int link_pcr; /* PHY's Peek Cell Rate */
+
+ struct vc_map **vcs; /* Open Connections */
+ struct vc_map **scd2vc; /* SCD to Connection map */
+
+ struct tst_info *soft_tst; /* TST to Connection map */
+ unsigned int tst_index; /* Current TST in use */
+ struct timer_list tst_timer;
+ spinlock_t tst_lock;
+ unsigned long tst_state;
+
+ struct sb_pool sbpool[4]; /* Pool of RX skbuffs */
+ struct sk_buff *raw_cell_head; /* Pointer to raw cell queue */
+ u32 *raw_cell_hnd; /* Pointer to RCQ handle */
+ dma_addr_t raw_cell_paddr;
+
+ int index; /* SAR's ID */
+ int revision; /* chip revision */
+
+ char name[16]; /* Device name */
+
+ struct idt77252_dev *next;
+};
+
+
+/* definition for flag field above */
+#define IDT77252_BIT_INIT 1
+#define IDT77252_BIT_INTERRUPT 2
+
+
+#define ATM_CELL_PAYLOAD 48
+
+#define FREEBUF_ALIGNMENT 16
+
+/*****************************************************************************/
+/* */
+/* Makros */
+/* */
+/*****************************************************************************/
+#define ALIGN_ADDRESS(addr, alignment) \
+ ((((u32)(addr)) + (((u32)(alignment))-1)) & ~(((u32)(alignment)) - 1))
+
+
+/*****************************************************************************/
+/* */
+/* ABR SAR Network operation Register */
+/* */
+/*****************************************************************************/
+
+#define SAR_REG_DR0 (card->membase + 0x00)
+#define SAR_REG_DR1 (card->membase + 0x04)
+#define SAR_REG_DR2 (card->membase + 0x08)
+#define SAR_REG_DR3 (card->membase + 0x0C)
+#define SAR_REG_CMD (card->membase + 0x10)
+#define SAR_REG_CFG (card->membase + 0x14)
+#define SAR_REG_STAT (card->membase + 0x18)
+#define SAR_REG_RSQB (card->membase + 0x1C)
+#define SAR_REG_RSQT (card->membase + 0x20)
+#define SAR_REG_RSQH (card->membase + 0x24)
+#define SAR_REG_CDC (card->membase + 0x28)
+#define SAR_REG_VPEC (card->membase + 0x2C)
+#define SAR_REG_ICC (card->membase + 0x30)
+#define SAR_REG_RAWCT (card->membase + 0x34)
+#define SAR_REG_TMR (card->membase + 0x38)
+#define SAR_REG_TSTB (card->membase + 0x3C)
+#define SAR_REG_TSQB (card->membase + 0x40)
+#define SAR_REG_TSQT (card->membase + 0x44)
+#define SAR_REG_TSQH (card->membase + 0x48)
+#define SAR_REG_GP (card->membase + 0x4C)
+#define SAR_REG_VPM (card->membase + 0x50)
+#define SAR_REG_RXFD (card->membase + 0x54)
+#define SAR_REG_RXFT (card->membase + 0x58)
+#define SAR_REG_RXFH (card->membase + 0x5C)
+#define SAR_REG_RAWHND (card->membase + 0x60)
+#define SAR_REG_RXSTAT (card->membase + 0x64)
+#define SAR_REG_ABRSTD (card->membase + 0x68)
+#define SAR_REG_ABRRQ (card->membase + 0x6C)
+#define SAR_REG_VBRRQ (card->membase + 0x70)
+#define SAR_REG_RTBL (card->membase + 0x74)
+#define SAR_REG_MDFCT (card->membase + 0x78)
+#define SAR_REG_TXSTAT (card->membase + 0x7C)
+#define SAR_REG_TCMDQ (card->membase + 0x80)
+#define SAR_REG_IRCP (card->membase + 0x84)
+#define SAR_REG_FBQP0 (card->membase + 0x88)
+#define SAR_REG_FBQP1 (card->membase + 0x8C)
+#define SAR_REG_FBQP2 (card->membase + 0x90)
+#define SAR_REG_FBQP3 (card->membase + 0x94)
+#define SAR_REG_FBQS0 (card->membase + 0x98)
+#define SAR_REG_FBQS1 (card->membase + 0x9C)
+#define SAR_REG_FBQS2 (card->membase + 0xA0)
+#define SAR_REG_FBQS3 (card->membase + 0xA4)
+#define SAR_REG_FBQWP0 (card->membase + 0xA8)
+#define SAR_REG_FBQWP1 (card->membase + 0xAC)
+#define SAR_REG_FBQWP2 (card->membase + 0xB0)
+#define SAR_REG_FBQWP3 (card->membase + 0xB4)
+#define SAR_REG_NOW (card->membase + 0xB8)
+
+
+/*****************************************************************************/
+/* */
+/* Commands */
+/* */
+/*****************************************************************************/
+
+#define SAR_CMD_NO_OPERATION 0x00000000
+#define SAR_CMD_OPENCLOSE_CONNECTION 0x20000000
+#define SAR_CMD_WRITE_SRAM 0x40000000
+#define SAR_CMD_READ_SRAM 0x50000000
+#define SAR_CMD_READ_UTILITY 0x80000000
+#define SAR_CMD_WRITE_UTILITY 0x90000000
+
+#define SAR_CMD_OPEN_CONNECTION (SAR_CMD_OPENCLOSE_CONNECTION | 0x00080000)
+#define SAR_CMD_CLOSE_CONNECTION SAR_CMD_OPENCLOSE_CONNECTION
+
+
+/*****************************************************************************/
+/* */
+/* Configuration Register bits */
+/* */
+/*****************************************************************************/
+
+#define SAR_CFG_SWRST 0x80000000 /* Software reset */
+#define SAR_CFG_LOOP 0x40000000 /* Internal Loopback */
+#define SAR_CFG_RXPTH 0x20000000 /* Receive Path Enable */
+#define SAR_CFG_IDLE_CLP 0x10000000 /* SAR set CLP Bits of Null Cells */
+#define SAR_CFG_TX_FIFO_SIZE_1 0x04000000 /* TX FIFO Size = 1 cell */
+#define SAR_CFG_TX_FIFO_SIZE_2 0x08000000 /* TX FIFO Size = 2 cells */
+#define SAR_CFG_TX_FIFO_SIZE_4 0x0C000000 /* TX FIFO Size = 4 cells */
+#define SAR_CFG_TX_FIFO_SIZE_9 0x00000000 /* TX FIFO Size = 9 cells (full) */
+#define SAR_CFG_NO_IDLE 0x02000000 /* SAR sends no Null Cells */
+#define SAR_CFG_RSVD1 0x01000000 /* Reserved */
+#define SAR_CFG_RXSTQ_SIZE_2k 0x00000000 /* RX Stat Queue Size = 2048 byte */
+#define SAR_CFG_RXSTQ_SIZE_4k 0x00400000 /* RX Stat Queue Size = 4096 byte */
+#define SAR_CFG_RXSTQ_SIZE_8k 0x00800000 /* RX Stat Queue Size = 8192 byte */
+#define SAR_CFG_RXSTQ_SIZE_R 0x00C00000 /* RX Stat Queue Size = reserved */
+#define SAR_CFG_ICAPT 0x00200000 /* accept Invalid Cells */
+#define SAR_CFG_IGGFC 0x00100000 /* Ignore GFC */
+#define SAR_CFG_VPVCS_0 0x00000000 /* VPI/VCI Select bit range */
+#define SAR_CFG_VPVCS_1 0x00040000 /* VPI/VCI Select bit range */
+#define SAR_CFG_VPVCS_2 0x00080000 /* VPI/VCI Select bit range */
+#define SAR_CFG_VPVCS_8 0x000C0000 /* VPI/VCI Select bit range */
+#define SAR_CFG_CNTBL_1k 0x00000000 /* Connection Table Size */
+#define SAR_CFG_CNTBL_4k 0x00010000 /* Connection Table Size */
+#define SAR_CFG_CNTBL_16k 0x00020000 /* Connection Table Size */
+#define SAR_CFG_CNTBL_512 0x00030000 /* Connection Table Size */
+#define SAR_CFG_VPECA 0x00008000 /* VPI/VCI Error Cell Accept */
+#define SAR_CFG_RXINT_NOINT 0x00000000 /* No Interrupt on PDU received */
+#define SAR_CFG_RXINT_NODELAY 0x00001000 /* Interrupt without delay to host*/
+#define SAR_CFG_RXINT_256US 0x00002000 /* Interrupt with delay 256 usec */
+#define SAR_CFG_RXINT_505US 0x00003000 /* Interrupt with delay 505 usec */
+#define SAR_CFG_RXINT_742US 0x00004000 /* Interrupt with delay 742 usec */
+#define SAR_CFG_RAWIE 0x00000800 /* Raw Cell Queue Interrupt Enable*/
+#define SAR_CFG_RQFIE 0x00000400 /* RSQ Almost Full Int Enable */
+#define SAR_CFG_RSVD2 0x00000200 /* Reserved */
+#define SAR_CFG_CACHE 0x00000100 /* DMA on Cache Line Boundary */
+#define SAR_CFG_TMOIE 0x00000080 /* Timer Roll Over Int Enable */
+#define SAR_CFG_FBIE 0x00000040 /* Free Buffer Queue Int Enable */
+#define SAR_CFG_TXEN 0x00000020 /* Transmit Operation Enable */
+#define SAR_CFG_TXINT 0x00000010 /* Transmit status Int Enable */
+#define SAR_CFG_TXUIE 0x00000008 /* Transmit underrun Int Enable */
+#define SAR_CFG_UMODE 0x00000004 /* Utopia Mode Select */
+#define SAR_CFG_TXSFI 0x00000002 /* Transmit status Full Int Enable*/
+#define SAR_CFG_PHYIE 0x00000001 /* PHY Interrupt Enable */
+
+#define SAR_CFG_TX_FIFO_SIZE_MASK 0x0C000000 /* TX FIFO Size Mask */
+#define SAR_CFG_RXSTQSIZE_MASK 0x00C00000
+#define SAR_CFG_CNTBL_MASK 0x00030000
+#define SAR_CFG_RXINT_MASK 0x00007000
+
+
+/*****************************************************************************/
+/* */
+/* Status Register bits */
+/* */
+/*****************************************************************************/
+
+#define SAR_STAT_FRAC_3 0xF0000000 /* Fraction of Free Buffer Queue 3 */
+#define SAR_STAT_FRAC_2 0x0F000000 /* Fraction of Free Buffer Queue 2 */
+#define SAR_STAT_FRAC_1 0x00F00000 /* Fraction of Free Buffer Queue 1 */
+#define SAR_STAT_FRAC_0 0x000F0000 /* Fraction of Free Buffer Queue 0 */
+#define SAR_STAT_TSIF 0x00008000 /* Transmit Status Indicator */
+#define SAR_STAT_TXICP 0x00004000 /* Transmit Status Indicator */
+#define SAR_STAT_RSVD1 0x00002000 /* Reserved */
+#define SAR_STAT_TSQF 0x00001000 /* Transmit Status Queue full */
+#define SAR_STAT_TMROF 0x00000800 /* Timer overflow */
+#define SAR_STAT_PHYI 0x00000400 /* PHY device Interrupt flag */
+#define SAR_STAT_CMDBZ 0x00000200 /* ABR SAR Comand Busy Flag */
+#define SAR_STAT_FBQ3A 0x00000100 /* Free Buffer Queue 3 Attention */
+#define SAR_STAT_FBQ2A 0x00000080 /* Free Buffer Queue 2 Attention */
+#define SAR_STAT_RSQF 0x00000040 /* Receive Status Queue full */
+#define SAR_STAT_EPDU 0x00000020 /* End Of PDU Flag */
+#define SAR_STAT_RAWCF 0x00000010 /* Raw Cell Flag */
+#define SAR_STAT_FBQ1A 0x00000008 /* Free Buffer Queue 1 Attention */
+#define SAR_STAT_FBQ0A 0x00000004 /* Free Buffer Queue 0 Attention */
+#define SAR_STAT_RSQAF 0x00000002 /* Receive Status Queue almost full*/
+#define SAR_STAT_RSVD2 0x00000001 /* Reserved */
+
+
+/*****************************************************************************/
+/* */
+/* General Purpose Register bits */
+/* */
+/*****************************************************************************/
+
+#define SAR_GP_TXNCC_MASK 0xff000000 /* Transmit Negative Credit Count */
+#define SAR_GP_EEDI 0x00010000 /* EEPROM Data In */
+#define SAR_GP_BIGE 0x00008000 /* Big Endian Operation */
+#define SAR_GP_RM_NORMAL 0x00000000 /* Normal handling of RM cells */
+#define SAR_GP_RM_TO_RCQ 0x00002000 /* put RM cells into Raw Cell Queue */
+#define SAR_GP_RM_RSVD 0x00004000 /* Reserved */
+#define SAR_GP_RM_INHIBIT 0x00006000 /* Inhibit update of Connection tab */
+#define SAR_GP_PHY_RESET 0x00000008 /* PHY Reset */
+#define SAR_GP_EESCLK 0x00000004 /* EEPROM SCLK */
+#define SAR_GP_EECS 0x00000002 /* EEPROM Chip Select */
+#define SAR_GP_EEDO 0x00000001 /* EEPROM Data Out */
+
+
+/*****************************************************************************/
+/* */
+/* SAR local SRAM layout for 128k work SRAM */
+/* */
+/*****************************************************************************/
+
+#define SAR_SRAM_SCD_SIZE 12
+#define SAR_SRAM_TCT_SIZE 8
+#define SAR_SRAM_RCT_SIZE 4
+
+#define SAR_SRAM_TCT_128_BASE 0x00000
+#define SAR_SRAM_TCT_128_TOP 0x01fff
+#define SAR_SRAM_RCT_128_BASE 0x02000
+#define SAR_SRAM_RCT_128_TOP 0x02fff
+#define SAR_SRAM_FB0_128_BASE 0x03000
+#define SAR_SRAM_FB0_128_TOP 0x033ff
+#define SAR_SRAM_FB1_128_BASE 0x03400
+#define SAR_SRAM_FB1_128_TOP 0x037ff
+#define SAR_SRAM_FB2_128_BASE 0x03800
+#define SAR_SRAM_FB2_128_TOP 0x03bff
+#define SAR_SRAM_FB3_128_BASE 0x03c00
+#define SAR_SRAM_FB3_128_TOP 0x03fff
+#define SAR_SRAM_SCD_128_BASE 0x04000
+#define SAR_SRAM_SCD_128_TOP 0x07fff
+#define SAR_SRAM_TST1_128_BASE 0x08000
+#define SAR_SRAM_TST1_128_TOP 0x0bfff
+#define SAR_SRAM_TST2_128_BASE 0x0c000
+#define SAR_SRAM_TST2_128_TOP 0x0ffff
+#define SAR_SRAM_ABRSTD_128_BASE 0x10000
+#define SAR_SRAM_ABRSTD_128_TOP 0x13fff
+#define SAR_SRAM_RT_128_BASE 0x14000
+#define SAR_SRAM_RT_128_TOP 0x15fff
+
+#define SAR_SRAM_FIFO_128_BASE 0x18000
+#define SAR_SRAM_FIFO_128_TOP 0x1ffff
+
+
+/*****************************************************************************/
+/* */
+/* SAR local SRAM layout for 32k work SRAM */
+/* */
+/*****************************************************************************/
+
+#define SAR_SRAM_TCT_32_BASE 0x00000
+#define SAR_SRAM_TCT_32_TOP 0x00fff
+#define SAR_SRAM_RCT_32_BASE 0x01000
+#define SAR_SRAM_RCT_32_TOP 0x017ff
+#define SAR_SRAM_FB0_32_BASE 0x01800
+#define SAR_SRAM_FB0_32_TOP 0x01bff
+#define SAR_SRAM_FB1_32_BASE 0x01c00
+#define SAR_SRAM_FB1_32_TOP 0x01fff
+#define SAR_SRAM_FB2_32_BASE 0x02000
+#define SAR_SRAM_FB2_32_TOP 0x023ff
+#define SAR_SRAM_FB3_32_BASE 0x02400
+#define SAR_SRAM_FB3_32_TOP 0x027ff
+#define SAR_SRAM_SCD_32_BASE 0x02800
+#define SAR_SRAM_SCD_32_TOP 0x03fff
+#define SAR_SRAM_TST1_32_BASE 0x04000
+#define SAR_SRAM_TST1_32_TOP 0x04fff
+#define SAR_SRAM_TST2_32_BASE 0x05000
+#define SAR_SRAM_TST2_32_TOP 0x05fff
+#define SAR_SRAM_ABRSTD_32_BASE 0x06000
+#define SAR_SRAM_ABRSTD_32_TOP 0x067ff
+#define SAR_SRAM_RT_32_BASE 0x06800
+#define SAR_SRAM_RT_32_TOP 0x06fff
+#define SAR_SRAM_FIFO_32_BASE 0x07000
+#define SAR_SRAM_FIFO_32_TOP 0x07fff
+
+
+/*****************************************************************************/
+/* */
+/* TSR - Transmit Status Request */
+/* */
+/*****************************************************************************/
+
+#define SAR_TSR_TYPE_TSR 0x80000000
+#define SAR_TSR_TYPE_TBD 0x00000000
+#define SAR_TSR_TSIF 0x20000000
+#define SAR_TSR_TAG_MASK 0x01F00000
+
+
+/*****************************************************************************/
+/* */
+/* TBD - Transmit Buffer Descriptor */
+/* */
+/*****************************************************************************/
+
+#define SAR_TBD_EPDU 0x40000000
+#define SAR_TBD_TSIF 0x20000000
+#define SAR_TBD_OAM 0x10000000
+#define SAR_TBD_AAL0 0x00000000
+#define SAR_TBD_AAL34 0x04000000
+#define SAR_TBD_AAL5 0x08000000
+#define SAR_TBD_GTSI 0x02000000
+#define SAR_TBD_TAG_MASK 0x01F00000
+
+#define SAR_TBD_VPI_MASK 0x0FF00000
+#define SAR_TBD_VCI_MASK 0x000FFFF0
+#define SAR_TBD_VC_MASK (SAR_TBD_VPI_MASK | SAR_TBD_VCI_MASK)
+
+#define SAR_TBD_VPI_SHIFT 20
+#define SAR_TBD_VCI_SHIFT 4
+
+
+/*****************************************************************************/
+/* */
+/* RXFD - Receive FIFO Descriptor */
+/* */
+/*****************************************************************************/
+
+#define SAR_RXFD_SIZE_MASK 0x0F000000
+#define SAR_RXFD_SIZE_512 0x00000000 /* 512 words */
+#define SAR_RXFD_SIZE_1K 0x01000000 /* 1k words */
+#define SAR_RXFD_SIZE_2K 0x02000000 /* 2k words */
+#define SAR_RXFD_SIZE_4K 0x03000000 /* 4k words */
+#define SAR_RXFD_SIZE_8K 0x04000000 /* 8k words */
+#define SAR_RXFD_SIZE_16K 0x05000000 /* 16k words */
+#define SAR_RXFD_SIZE_32K 0x06000000 /* 32k words */
+#define SAR_RXFD_SIZE_64K 0x07000000 /* 64k words */
+#define SAR_RXFD_SIZE_128K 0x08000000 /* 128k words */
+#define SAR_RXFD_SIZE_256K 0x09000000 /* 256k words */
+#define SAR_RXFD_ADDR_MASK 0x001ffc00
+
+
+/*****************************************************************************/
+/* */
+/* ABRSTD - ABR + VBR Schedule Tables */
+/* */
+/*****************************************************************************/
+
+#define SAR_ABRSTD_SIZE_MASK 0x07000000
+#define SAR_ABRSTD_SIZE_512 0x00000000 /* 512 words */
+#define SAR_ABRSTD_SIZE_1K 0x01000000 /* 1k words */
+#define SAR_ABRSTD_SIZE_2K 0x02000000 /* 2k words */
+#define SAR_ABRSTD_SIZE_4K 0x03000000 /* 4k words */
+#define SAR_ABRSTD_SIZE_8K 0x04000000 /* 8k words */
+#define SAR_ABRSTD_SIZE_16K 0x05000000 /* 16k words */
+#define SAR_ABRSTD_ADDR_MASK 0x001ffc00
+
+
+/*****************************************************************************/
+/* */
+/* RCTE - Receive Connection Table Entry */
+/* */
+/*****************************************************************************/
+
+#define SAR_RCTE_IL_MASK 0xE0000000 /* inactivity limit */
+#define SAR_RCTE_IC_MASK 0x1C000000 /* inactivity count */
+#define SAR_RCTE_RSVD 0x02000000 /* reserved */
+#define SAR_RCTE_LCD 0x01000000 /* last cell data */
+#define SAR_RCTE_CI_VC 0x00800000 /* EFCI in previous cell of VC */
+#define SAR_RCTE_FBP_01 0x00000000 /* 1. cell->FBQ0, others->FBQ1 */
+#define SAR_RCTE_FBP_1 0x00200000 /* use FBQ 1 for all cells */
+#define SAR_RCTE_FBP_2 0x00400000 /* use FBQ 2 for all cells */
+#define SAR_RCTE_FBP_3 0x00600000 /* use FBQ 3 for all cells */
+#define SAR_RCTE_NZ_GFC 0x00100000 /* non zero GFC in all cell of VC */
+#define SAR_RCTE_CONNECTOPEN 0x00080000 /* VC is open */
+#define SAR_RCTE_AAL_MASK 0x00070000 /* mask for AAL type field s.b. */
+#define SAR_RCTE_RAWCELLINTEN 0x00008000 /* raw cell interrupt enable */
+#define SAR_RCTE_RXCONCELLADDR 0x00004000 /* RX constant cell address */
+#define SAR_RCTE_BUFFSTAT_MASK 0x00003000 /* buffer status */
+#define SAR_RCTE_EFCI 0x00000800 /* EFCI Congestion flag */
+#define SAR_RCTE_CLP 0x00000400 /* Cell Loss Priority flag */
+#define SAR_RCTE_CRC 0x00000200 /* Recieved CRC Error */
+#define SAR_RCTE_CELLCNT_MASK 0x000001FF /* cell Count */
+
+#define SAR_RCTE_AAL0 0x00000000 /* AAL types for ALL field */
+#define SAR_RCTE_AAL34 0x00010000
+#define SAR_RCTE_AAL5 0x00020000
+#define SAR_RCTE_RCQ 0x00030000
+#define SAR_RCTE_OAM 0x00040000
+
+#define TCMDQ_START 0x01000000
+#define TCMDQ_LACR 0x02000000
+#define TCMDQ_START_LACR 0x03000000
+#define TCMDQ_INIT_ER 0x04000000
+#define TCMDQ_HALT 0x05000000
+
+
+struct idt77252_skb_prv {
+ struct scqe tbd; /* Transmit Buffer Descriptor */
+ dma_addr_t paddr; /* DMA handle */
+ u32 pool; /* sb_pool handle */
+};
+
+#define IDT77252_PRV_TBD(skb) \
+ (((struct idt77252_skb_prv *)(ATM_SKB(skb)+1))->tbd)
+#define IDT77252_PRV_PADDR(skb) \
+ (((struct idt77252_skb_prv *)(ATM_SKB(skb)+1))->paddr)
+#define IDT77252_PRV_POOL(skb) \
+ (((struct idt77252_skb_prv *)(ATM_SKB(skb)+1))->pool)
+
+/*****************************************************************************/
+/* */
+/* PCI related items */
+/* */
+/*****************************************************************************/
+
+#ifndef PCI_VENDOR_ID_IDT
+#define PCI_VENDOR_ID_IDT 0x111D
+#endif /* PCI_VENDOR_ID_IDT */
+
+#ifndef PCI_DEVICE_ID_IDT_IDT77252
+#define PCI_DEVICE_ID_IDT_IDT77252 0x0003
+#endif /* PCI_DEVICE_ID_IDT_IDT772052 */
+
+
+#endif /* !(_IDT77252_H) */
diff -u --recursive --new-file v2.4.14/linux/drivers/atm/idt77252_tables.h linux/drivers/atm/idt77252_tables.h
--- v2.4.14/linux/drivers/atm/idt77252_tables.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/atm/idt77252_tables.h Wed Nov 7 14:39:36 2001
@@ -0,0 +1,780 @@
+/* Do not edit, automatically generated by `./genrtbl'.
+ *
+ * Cell Line Rate: 353207.55 (155520000 bps)
+ */
+
+static unsigned int log_to_rate[] =
+{
+/* 000 */ 0x8d022e27, /* cps = 10.02, nrm = 3, interval = 35264.00 */
+/* 001 */ 0x8d362e11, /* cps = 10.42, nrm = 3, interval = 33856.00 */
+/* 002 */ 0x8d6e2bf8, /* cps = 10.86, nrm = 3, interval = 32512.00 */
+/* 003 */ 0x8da82bcf, /* cps = 11.31, nrm = 3, interval = 31200.00 */
+/* 004 */ 0x8de42ba8, /* cps = 11.78, nrm = 3, interval = 29952.00 */
+/* 005 */ 0x8e242b82, /* cps = 12.28, nrm = 3, interval = 28736.00 */
+/* 006 */ 0x8e662b5e, /* cps = 12.80, nrm = 3, interval = 27584.00 */
+/* 007 */ 0x8eaa2b3c, /* cps = 13.33, nrm = 3, interval = 26496.00 */
+/* 008 */ 0x8ef22b1a, /* cps = 13.89, nrm = 3, interval = 25408.00 */
+/* 009 */ 0x8f3e2afa, /* cps = 14.48, nrm = 3, interval = 24384.00 */
+/* 010 */ 0x8f8a2adc, /* cps = 15.08, nrm = 3, interval = 23424.00 */
+/* 011 */ 0x8fdc2abe, /* cps = 15.72, nrm = 3, interval = 22464.00 */
+/* 012 */ 0x90182aa2, /* cps = 16.38, nrm = 3, interval = 21568.00 */
+/* 013 */ 0x90422a87, /* cps = 17.03, nrm = 3, interval = 20704.00 */
+/* 014 */ 0x90702a6d, /* cps = 17.75, nrm = 3, interval = 19872.00 */
+/* 015 */ 0x90a02a54, /* cps = 18.50, nrm = 3, interval = 19072.00 */
+/* 016 */ 0x90d22a3c, /* cps = 19.28, nrm = 3, interval = 18304.00 */
+/* 017 */ 0x91062a25, /* cps = 20.09, nrm = 3, interval = 17568.00 */
+/* 018 */ 0x913c2a0f, /* cps = 20.94, nrm = 3, interval = 16864.00 */
+/* 019 */ 0x917427f3, /* cps = 21.81, nrm = 3, interval = 16176.00 */
+/* 020 */ 0x91b027ca, /* cps = 22.75, nrm = 3, interval = 15520.00 */
+/* 021 */ 0x91ec27a3, /* cps = 23.69, nrm = 3, interval = 14896.00 */
+/* 022 */ 0x922c277e, /* cps = 24.69, nrm = 3, interval = 14304.00 */
+/* 023 */ 0x926e275a, /* cps = 25.72, nrm = 3, interval = 13728.00 */
+/* 024 */ 0x92b42737, /* cps = 26.81, nrm = 3, interval = 13168.00 */
+/* 025 */ 0x92fc2716, /* cps = 27.94, nrm = 3, interval = 12640.00 */
+/* 026 */ 0x934626f6, /* cps = 29.09, nrm = 3, interval = 12128.00 */
+/* 027 */ 0x939426d8, /* cps = 30.31, nrm = 3, interval = 11648.00 */
+/* 028 */ 0x93e426bb, /* cps = 31.56, nrm = 3, interval = 11184.00 */
+/* 029 */ 0x941e269e, /* cps = 32.94, nrm = 3, interval = 10720.00 */
+/* 030 */ 0x944a2683, /* cps = 34.31, nrm = 3, interval = 10288.00 */
+/* 031 */ 0x9476266a, /* cps = 35.69, nrm = 3, interval = 9888.00 */
+/* 032 */ 0x94a62651, /* cps = 37.19, nrm = 3, interval = 9488.00 */
+/* 033 */ 0x94d82639, /* cps = 38.75, nrm = 3, interval = 9104.00 */
+/* 034 */ 0x950c6622, /* cps = 40.38, nrm = 4, interval = 8736.00 */
+/* 035 */ 0x9544660c, /* cps = 42.12, nrm = 4, interval = 8384.00 */
+/* 036 */ 0x957c63ee, /* cps = 43.88, nrm = 4, interval = 8048.00 */
+/* 037 */ 0x95b663c6, /* cps = 45.69, nrm = 4, interval = 7728.00 */
+/* 038 */ 0x95f4639f, /* cps = 47.62, nrm = 4, interval = 7416.00 */
+/* 039 */ 0x96346379, /* cps = 49.62, nrm = 4, interval = 7112.00 */
+/* 040 */ 0x96766356, /* cps = 51.69, nrm = 4, interval = 6832.00 */
+/* 041 */ 0x96bc6333, /* cps = 53.88, nrm = 4, interval = 6552.00 */
+/* 042 */ 0x97046312, /* cps = 56.12, nrm = 4, interval = 6288.00 */
+/* 043 */ 0x974e62f3, /* cps = 58.44, nrm = 4, interval = 6040.00 */
+/* 044 */ 0x979e62d4, /* cps = 60.94, nrm = 4, interval = 5792.00 */
+/* 045 */ 0x97f062b7, /* cps = 63.50, nrm = 4, interval = 5560.00 */
+/* 046 */ 0x9822629b, /* cps = 66.12, nrm = 4, interval = 5336.00 */
+/* 047 */ 0x984e6280, /* cps = 68.88, nrm = 4, interval = 5120.00 */
+/* 048 */ 0x987e6266, /* cps = 71.88, nrm = 4, interval = 4912.00 */
+/* 049 */ 0x98ac624e, /* cps = 74.75, nrm = 4, interval = 4720.00 */
+/* 050 */ 0x98e06236, /* cps = 78.00, nrm = 4, interval = 4528.00 */
+/* 051 */ 0x9914a21f, /* cps = 81.25, nrm = 8, interval = 4344.00 */
+/* 052 */ 0x994aa209, /* cps = 84.62, nrm = 8, interval = 4168.00 */
+/* 053 */ 0x99829fe9, /* cps = 88.12, nrm = 8, interval = 4004.00 */
+/* 054 */ 0x99be9fc1, /* cps = 91.88, nrm = 8, interval = 3844.00 */
+/* 055 */ 0x99fc9f9a, /* cps = 95.75, nrm = 8, interval = 3688.00 */
+/* 056 */ 0x9a3c9f75, /* cps = 99.75, nrm = 8, interval = 3540.00 */
+/* 057 */ 0x9a809f51, /* cps = 104.00, nrm = 8, interval = 3396.00 */
+/* 058 */ 0x9ac49f2f, /* cps = 108.25, nrm = 8, interval = 3260.00 */
+/* 059 */ 0x9b0e9f0e, /* cps = 112.88, nrm = 8, interval = 3128.00 */
+/* 060 */ 0x9b589eef, /* cps = 117.50, nrm = 8, interval = 3004.00 */
+/* 061 */ 0x9ba69ed1, /* cps = 122.38, nrm = 8, interval = 2884.00 */
+/* 062 */ 0x9bf89eb4, /* cps = 127.50, nrm = 8, interval = 2768.00 */
+/* 063 */ 0x9c269e98, /* cps = 132.75, nrm = 8, interval = 2656.00 */
+/* 064 */ 0x9c549e7d, /* cps = 138.50, nrm = 8, interval = 2548.00 */


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

echo 'End of part 038'
echo 'File patch-2.4.15 is continued in part 039'
echo "039" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:09 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part033

#!/bin/sh -x
# this is part 033 of a 115 - part archive


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

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

+ * task_struct address.


+ */
+ spin_lock(&ctx->ctx_notify_lock);
+

+ ctx->ctx_notify_task = NULL;


+
+ spin_unlock(&ctx->ctx_notify_lock);
+

+ DBprintk((" done for notifier %d in %d\n", task->pid, p->pid));
+ }


+ }
+ read_unlock(&tasklist_lock);
+
X }

X
X #else /* !CONFIG_PERFMON */
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/process.c linux/arch/ia64/kernel/process.c
--- v2.4.14/linux/arch/ia64/kernel/process.c Tue Oct 9 17:06:51 2001
+++ linux/arch/ia64/kernel/process.c Fri Nov 9 14:26:17 2001
@@ -63,7 +63,8 @@
X {
X unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri;
X
- printk("\npsr : %016lx ifs : %016lx ip : [<%016lx>] %s\n",
+ printk("\nPid: %d, comm: %20s\n", current->pid, current->comm);
+ printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s\n",
X regs->cr_ipsr, regs->cr_ifs, ip, print_tainted());
X printk("unat: %016lx pfs : %016lx rsc : %016lx\n",
X regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
@@ -201,7 +202,7 @@
X {
X unsigned long rbs, child_rbs, rbs_size, stack_offset, stack_top, stack_used;
X struct switch_stack *child_stack, *stack;
- extern char ia64_ret_from_clone;
+ extern char ia64_ret_from_clone, ia32_ret_from_clone;
X struct pt_regs *child_ptregs;
X int retval = 0;
X
@@ -250,7 +251,10 @@
X child_ptregs->r12 = (unsigned long) (child_ptregs + 1); /* kernel sp */
X child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */
X }
- child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
+ if (IS_IA32_PROCESS(regs))
+ child_stack->b0 = (unsigned long) &ia32_ret_from_clone;
+ else
+ child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
X child_stack->ar_bspstore = child_rbs + rbs_size;
X
X /* copy parts of thread_struct: */
@@ -285,9 +289,8 @@
X ia32_save_state(p);
X #endif
X #ifdef CONFIG_PERFMON
- p->thread.pfm_pend_notify = 0;
X if (p->thread.pfm_context)
- retval = pfm_inherit(p);
+ retval = pfm_inherit(p, child_ptregs);
X #endif
X return retval;
X }
@@ -441,11 +444,24 @@
X }
X
X #ifdef CONFIG_PERFMON
+/*
+ * By the time we get here, the task is detached from the tasklist. This is important
+ * because it means that no other tasks can ever find it as a notifiied task, therfore
+ * there is no race condition between this code and let's say a pfm_context_create().
+ * Conversely, the pfm_cleanup_notifiers() cannot try to access a task's pfm context if
+ * this other task is in the middle of its own pfm_context_exit() because it would alreayd
+ * be out of the task list. Note that this case is very unlikely between a direct child
+ * and its parents (if it is the notified process) because of the way the exit is notified
+ * via SIGCHLD.
+ */
X void
X release_thread (struct task_struct *task)
X {
X if (task->thread.pfm_context)
X pfm_context_exit(task);
+
+ if (atomic_read(&task->thread.pfm_notifiers_check) > 0)
+ pfm_cleanup_notifiers(task);
X }
X #endif
X
@@ -516,6 +532,29 @@
X }
X
X void
+cpu_halt (void)
+{
+ pal_power_mgmt_info_u_t power_info[8];
+ unsigned long min_power;
+ int i, min_power_state;
+
+ if (ia64_pal_halt_info(power_info) != 0)
+ return;
+
+ min_power_state = 0;
+ min_power = power_info[0].pal_power_mgmt_info_s.power_consumption;
+ for (i = 1; i < 8; ++i)
+ if (power_info[i].pal_power_mgmt_info_s.im
+ && power_info[i].pal_power_mgmt_info_s.power_consumption < min_power) {
+ min_power = power_info[i].pal_power_mgmt_info_s.power_consumption;
+ min_power_state = i;
+ }
+
+ while (1)
+ ia64_pal_halt(min_power_state);
+}
+
+void
X machine_restart (char *restart_cmd)
X {
X (*efi.reset_system)(EFI_RESET_WARM, 0, 0, 0);
@@ -524,6 +563,7 @@
X void
X machine_halt (void)
X {
+ cpu_halt();
X }
X
X void
@@ -531,4 +571,5 @@
X {
X if (pm_power_off)
X pm_power_off();
+ machine_halt();
X }
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/ptrace.c linux/arch/ia64/kernel/ptrace.c
--- v2.4.14/linux/arch/ia64/kernel/ptrace.c Sun Sep 23 11:40:55 2001
+++ linux/arch/ia64/kernel/ptrace.c Wed Nov 21 11:04:18 2001
@@ -2,7 +2,7 @@
X * Kernel support for the ptrace() and syscall tracing interfaces.
X *
X * Copyright (C) 1999-2001 Hewlett-Packard Co
- * Copyright (C) 1999-2001 David Mosberger-Tang <dav...@hpl.hp.com>


+ * David Mosberger-Tang <dav...@hpl.hp.com>
X *

X * Derived from the x86 and Alpha versions. Most of the code in here
X * could actually be factored into a common set of routines.
@@ -794,11 +794,14 @@
X *
X * Make sure the single step bit is not set.
X */
-void ptrace_disable(struct task_struct *child)
+void
+ptrace_disable (struct task_struct *child)
X {
+ struct ia64_psr *child_psr = ia64_psr(ia64_task_regs(child));
+
X /* make sure the single step/take-branch tra bits are not set: */
- ia64_psr(pt)->ss = 0;
- ia64_psr(pt)->tb = 0;
+ child_psr->ss = 0;
+ child_psr->tb = 0;
X
X /* Turn off flag indicating that the KRBS is sync'd with child's VM: */
X child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED;
@@ -809,7 +812,7 @@
X long arg4, long arg5, long arg6, long arg7, long stack)
X {
X struct pt_regs *pt, *regs = (struct pt_regs *) &stack;
- unsigned long flags, urbs_end;
+ unsigned long urbs_end;
X struct task_struct *child;
X struct switch_stack *sw;
X long ret;
@@ -843,16 +846,9 @@


X ret = ptrace_attach(child);
X goto out_tsk;
X }
- ret = -ESRCH;
- if (!(child->ptrace & PT_PTRACED))
- goto out_tsk;

X

- if (child->state != TASK_STOPPED) {
- if (request != PTRACE_KILL)
- goto out_tsk;
- }
-
- if (child->p_pptr != current)
+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
+ if (ret < 0)
X goto out_tsk;

X
X pt = ia64_task_regs(child);
@@ -925,7 +921,7 @@
X child->ptrace &= ~PT_TRACESYS;
X child->exit_code = data;
X
- /* make sure the single step/take-branch tra bits are not set: */
+ /* make sure the single step/taken-branch trap bits are not set: */
X ia64_psr(pt)->ss = 0;
X ia64_psr(pt)->tb = 0;
X
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/sal.c linux/arch/ia64/kernel/sal.c
--- v2.4.14/linux/arch/ia64/kernel/sal.c Thu Jan 4 12:50:17 2001
+++ linux/arch/ia64/kernel/sal.c Fri Nov 9 14:26:17 2001
@@ -1,8 +1,8 @@
X /*
X * System Abstraction Layer (SAL) interface routines.
X *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <dav...@hpl.hp.com>
+ * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
+ * David Mosberger-Tang <dav...@hpl.hp.com>
X * Copyright (C) 1999 VA Linux Systems


X * Copyright (C) 1999 Walt Drummond <drum...@valinux.com>

X */
@@ -18,8 +18,6 @@
X #include <asm/sal.h>
X #include <asm/pal.h>
X
-#define SAL_DEBUG
-
X spinlock_t sal_lock = SPIN_LOCK_UNLOCKED;
X
X static struct {
@@ -122,10 +120,8 @@
X switch (*p) {
X case SAL_DESC_ENTRY_POINT:
X ep = (struct ia64_sal_desc_entry_point *) p;
-#ifdef SAL_DEBUG
- printk("sal[%d] - entry: pal_proc=0x%lx, sal_proc=0x%lx\n",
- i, ep->pal_proc, ep->sal_proc);
-#endif
+ printk("SAL: entry: pal_proc=0x%lx, sal_proc=0x%lx\n",
+ ep->pal_proc, ep->sal_proc);
X ia64_pal_handler_init(__va(ep->pal_proc));
X ia64_sal_handler_init(__va(ep->sal_proc), __va(ep->gp));
X break;
@@ -138,17 +134,12 @@
X #ifdef CONFIG_SMP
X {
X struct ia64_sal_desc_ap_wakeup *ap = (void *) p;
-# ifdef SAL_DEBUG
- printk("sal[%d] - wakeup type %x, 0x%lx\n",
- i, ap->mechanism, ap->vector);
-# endif
+
X switch (ap->mechanism) {
X case IA64_SAL_AP_EXTERNAL_INT:
X ap_wakeup_vector = ap->vector;
-# ifdef SAL_DEBUG
X printk("SAL: AP wakeup using external interrupt "
X "vector 0x%lx\n", ap_wakeup_vector);
-# endif
X break;
X
X default:
@@ -163,21 +154,13 @@
X struct ia64_sal_desc_platform_feature *pf = (void *) p;
X printk("SAL: Platform features ");
X
-#ifdef CONFIG_IA64_HAVE_IRQREDIR
- /*
- * Early versions of SAL say we don't have
- * IRQ redirection, even though we do...
- */
- pf->feature_mask |= (1 << 1);
-#endif
-
X if (pf->feature_mask & (1 << 0))
X printk("BusLock ");
X
X if (pf->feature_mask & (1 << 1)) {
X printk("IRQ_Redirection ");
X #ifdef CONFIG_SMP
- if (no_int_routing)
+ if (no_int_routing)
X smp_int_redirect &= ~SMP_IRQ_REDIRECTION;
X else
X smp_int_redirect |= SMP_IRQ_REDIRECTION;
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/setup.c linux/arch/ia64/kernel/setup.c
--- v2.4.14/linux/arch/ia64/kernel/setup.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/setup.c Tue Nov 13 09:01:16 2001
@@ -2,12 +2,13 @@
X * Architecture-specific setup.
X *


X * Copyright (C) 1998-2001 Hewlett-Packard Co
- * Copyright (C) 1998-2001 David Mosberger-Tang <dav...@hpl.hp.com>
+ * David Mosberger-Tang <dav...@hpl.hp.com>

X * Copyright (C) 1998, 1999, 2001 Stephane Eranian <era...@hpl.hp.com>
X * Copyright (C) 2000, Rohit Seth <rohit...@intel.com>
X * Copyright (C) 1999 VA Linux Systems


X * Copyright (C) 1999 Walt Drummond <drum...@valinux.com>

X *
+ * 11/12/01 D.Mosberger Convert get_cpuinfo() to seq_file based show_cpuinfo().
X * 04/04/00 D.Mosberger renamed cpu_initialized to cpu_online_map
X * 03/31/00 R.Seth cpu_initialized and current->processor fixes
X * 02/04/00 D.Mosberger some more get_cpuinfo fixes...
@@ -23,6 +24,7 @@
X #include <linux/kernel.h>
X #include <linux/reboot.h>
X #include <linux/sched.h>
+#include <linux/seq_file.h>
X #include <linux/string.h>
X #include <linux/threads.h>
X #include <linux/console.h>
@@ -364,61 +366,89 @@
X /*
X * Display cpu info for all cpu's.
X */
-int
-get_cpuinfo (char *buffer)
+static int
+show_cpuinfo (struct seq_file *m, void *v)
X {
X #ifdef CONFIG_SMP
X # define lpj c->loops_per_jiffy
X #else
X # define lpj loops_per_jiffy
X #endif
- char family[32], features[128], *cp, *p = buffer;
- struct cpuinfo_ia64 *c;
- unsigned long mask, cpu;
-
- for (cpu = 0; cpu < smp_num_cpus; ++cpu) {
- c = cpu_data(cpu);
- mask = c->features;
-
- switch (c->family) {
- case 0x07: memcpy(family, "Itanium", 8); break;
- case 0x1f: memcpy(family, "McKinley", 9); break;
- default: sprintf(family, "%u", c->family); break;
- }
+ char family[32], features[128], *cp;
+ struct cpuinfo_ia64 *c = v;
+ unsigned long mask, cpu = c - cpu_data(0);
X
- /* build the feature string: */
- memcpy(features, " standard", 10);
- cp = features;
- if (mask & 1) {
- strcpy(cp, " branchlong");
- cp = strchr(cp, '\0');
- mask &= ~1UL;
- }
- if (mask)
- sprintf(cp, " 0x%lx", mask);
+#ifdef CONFIG_SMP
+ if (!(cpu_online_map & (1 << cpu)))
+ return 0;
+#endif


X
- p += sprintf(p,

- "processor : %lu\n"
- "vendor : %s\n"
- "arch : IA-64\n"
- "family : %s\n"
- "model : %u\n"
- "revision : %u\n"
- "archrev : %u\n"
- "features :%s\n" /* don't change this---it _is_ right! */
- "cpu number : %lu\n"
- "cpu regs : %u\n"
- "cpu MHz : %lu.%06lu\n"
- "itc MHz : %lu.%06lu\n"
- "BogoMIPS : %lu.%02lu\n\n",
- cpu, c->vendor, family, c->model, c->revision, c->archrev, features,
- c->ppn, c->number, c->proc_freq / 1000000, c->proc_freq % 1000000,
- c->itc_freq / 1000000, c->itc_freq % 1000000,
- lpj*HZ/500000, (lpj*HZ/5000) % 100);
- }


- return p - buffer;

+ mask = c->features;
+
+ switch (c->family) {
+ case 0x07: memcpy(family, "Itanium", 8); break;
+ case 0x1f: memcpy(family, "McKinley", 9); break;
+ default: sprintf(family, "%u", c->family); break;
+ }
+
+ /* build the feature string: */
+ memcpy(features, " standard", 10);
+ cp = features;
+ if (mask & 1) {
+ strcpy(cp, " branchlong");
+ cp = strchr(cp, '\0');
+ mask &= ~1UL;
+ }
+ if (mask)
+ sprintf(cp, " 0x%lx", mask);
+
+ seq_printf(m,
+ "processor : %lu\n"
+ "vendor : %s\n"
+ "arch : IA-64\n"
+ "family : %s\n"
+ "model : %u\n"
+ "revision : %u\n"
+ "archrev : %u\n"
+ "features :%s\n" /* don't change this---it _is_ right! */
+ "cpu number : %lu\n"
+ "cpu regs : %u\n"
+ "cpu MHz : %lu.%06lu\n"
+ "itc MHz : %lu.%06lu\n"
+ "BogoMIPS : %lu.%02lu\n\n",
+ cpu, c->vendor, family, c->model, c->revision, c->archrev,
+ features, c->ppn, c->number,
+ c->proc_freq / 1000000, c->proc_freq % 1000000,
+ c->itc_freq / 1000000, c->itc_freq % 1000000,
+ lpj*HZ/500000, (lpj*HZ/5000) % 100);


+ return 0;
+}
+

+static void *
+c_start (struct seq_file *m, loff_t *pos)
+{
+ return *pos < NR_CPUS ? cpu_data(*pos) : NULL;


+}
+
+static void *

+c_next (struct seq_file *m, void *v, loff_t *pos)


+{
+ ++*pos;
+ return c_start(m, pos);
+}
+

+static void
+c_stop (struct seq_file *m, void *v)
+{
X }
X

+struct seq_operations cpuinfo_op = {
+ start: c_start,
+ next: c_next,
+ stop: c_stop,
+ show: show_cpuinfo

+};
+
X void
X identify_cpu (struct cpuinfo_ia64 *c)
X {
@@ -534,10 +564,13 @@
X /*
X * Initialize default control register to defer all speculative faults. The
X * kernel MUST NOT depend on a particular setting of these bits (in other words,
- * the kernel must have recovery code for all speculative accesses).
+ * the kernel must have recovery code for all speculative accesses). Turn on
+ * dcr.lc as per recommendation by the architecture team. Most IA-32 apps
+ * shouldn't be affected by this (moral: keep your ia32 locks aligned and you'll
+ * be fine).
X */
X ia64_set_dcr( IA64_DCR_DM | IA64_DCR_DP | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_DR
- | IA64_DCR_DA | IA64_DCR_DD);
+ | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC);
X #ifndef CONFIG_SMP
X ia64_set_fpu_owner(0);
X #endif
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/sigframe.h linux/arch/ia64/kernel/sigframe.h
--- v2.4.14/linux/arch/ia64/kernel/sigframe.h Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/sigframe.h Fri Nov 9 14:26:17 2001
@@ -1,3 +1,9 @@
+struct sigscratch {
+ unsigned long scratch_unat; /* ar.unat for the general registers saved in pt */
+ unsigned long pad;
+ struct pt_regs pt;
+};
+
X struct sigframe {
X /*
X * Place signal handler args where user-level unwinder can find them easily.
@@ -7,10 +13,11 @@
X unsigned long arg0; /* signum */
X unsigned long arg1; /* siginfo pointer */
X unsigned long arg2; /* sigcontext pointer */
+ /*
+ * End of architected state.
+ */
X
- unsigned long rbs_base; /* base of new register backing store (or NULL) */
X void *handler; /* pointer to the plabel of the signal handler */
-
X struct siginfo info;
X struct sigcontext sc;
X };
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/signal.c linux/arch/ia64/kernel/signal.c
--- v2.4.14/linux/arch/ia64/kernel/signal.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/signal.c Fri Nov 9 14:26:17 2001
@@ -2,7 +2,7 @@
X * Architecture-specific signal handling support.
X *
X * Copyright (C) 1999-2001 Hewlett-Packard Co
- * Copyright (C) 1999-2001 David Mosberger-Tang <dav...@hpl.hp.com>


+ * David Mosberger-Tang <dav...@hpl.hp.com>
X *

X * Derived from i386 and Alpha versions.
X */
@@ -39,12 +39,6 @@
X # define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0])
X #endif
X
-struct sigscratch {
- unsigned long scratch_unat; /* ar.unat for the general registers saved in pt */
- unsigned long pad;
- struct pt_regs pt;
-};
-
X extern long ia64_do_signal (sigset_t *, struct sigscratch *, long); /* forward decl */
X
X long
@@ -55,6 +49,10 @@
X /* XXX: Don't preclude handling different sized sigset_t's. */
X if (sigsetsize != sizeof(sigset_t))
X return -EINVAL;
+
+ if (!access_ok(VERIFY_READ, uset, sigsetsize))
+ return -EFAULT;
+
X if (GET_SIGSET(&set, uset))
X return -EFAULT;
X
@@ -73,15 +71,9 @@
X * pre-set the correct error code here to ensure that the right values
X * get saved in sigcontext by ia64_do_signal.
X */
-#ifdef CONFIG_IA32_SUPPORT
- if (IS_IA32_PROCESS(&scr->pt)) {
- scr->pt.r8 = -EINTR;
- } else
-#endif
- {
- scr->pt.r8 = EINTR;
- scr->pt.r10 = -1;
- }
+ scr->pt.r8 = EINTR;
+ scr->pt.r10 = -1;
+
X while (1) {


X current->state = TASK_INTERRUPTIBLE;
X schedule();

@@ -139,10 +131,9 @@
X struct ia64_psr *psr = ia64_psr(&scr->pt);
X
X __copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16);
- if (!psr->dfh) {
- psr->mfh = 0;
+ psr->mfh = 0; /* drop signal handler's fph contents... */
+ if (!psr->dfh)
X __ia64_load_fpu(current->thread.fph);
- }


X }
X return err;
X }

@@ -380,7 +371,8 @@
X err = __put_user(sig, &frame->arg0);
X err |= __put_user(&frame->info, &frame->arg1);
X err |= __put_user(&frame->sc, &frame->arg2);
- err |= __put_user(new_rbs, &frame->rbs_base);
+ err |= __put_user(new_rbs, &frame->sc.sc_rbs_base);
+ err |= __put_user(0, &frame->sc.sc_loadrs); /* initialize to zero */
X err |= __put_user(ka->sa.sa_handler, &frame->handler);
X
X err |= copy_siginfo_to_user(&frame->info, info);
@@ -460,6 +452,7 @@
X long
X ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
X {
+ struct signal_struct *sig;
X struct k_sigaction *ka;
X siginfo_t info;
X long restart = in_syscall;
@@ -571,8 +564,8 @@
X case SIGSTOP:
X current->state = TASK_STOPPED;
X current->exit_code = signr;
- if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags
- & SA_NOCLDSTOP))
+ sig = current->p_pptr->sig;
+ if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
X notify_parent(current, SIGCHLD);
X schedule();
X continue;
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/smp.c linux/arch/ia64/kernel/smp.c
--- v2.4.14/linux/arch/ia64/kernel/smp.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/smp.c Fri Nov 9 14:26:17 2001
@@ -48,6 +48,7 @@
X #include <asm/sal.h>
X #include <asm/system.h>
X #include <asm/unistd.h>
+#include <asm/mca.h>
X
X /* The 'big kernel lock' */
X spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
@@ -70,20 +71,18 @@
X
X #define IPI_CALL_FUNC 0
X #define IPI_CPU_STOP 1
-#ifndef CONFIG_ITANIUM_PTCG
-# define IPI_FLUSH_TLB 2
-#endif /*!CONFIG_ITANIUM_PTCG */
X
X static void
X stop_this_cpu (void)
X {
+ extern void cpu_halt (void);
X /*
X * Remove this CPU:
X */
X clear_bit(smp_processor_id(), &cpu_online_map);
X max_xtp();
X __cli();
- for (;;);
+ cpu_halt();
X }
X
X void
@@ -136,49 +135,6 @@
X stop_this_cpu();
X break;
X
-#ifndef CONFIG_ITANIUM_PTCG
- case IPI_FLUSH_TLB:
- {
- extern unsigned long flush_start, flush_end, flush_nbits, flush_rid;
- extern atomic_t flush_cpu_count;
- unsigned long saved_rid = ia64_get_rr(flush_start);
- unsigned long end = flush_end;
- unsigned long start = flush_start;
- unsigned long nbits = flush_nbits;
-
- /*
- * Current CPU may be running with different RID so we need to
- * reload the RID of flushed address. Purging the translation
- * also needs ALAT invalidation; we do not need "invala" here
- * since it is done in ia64_leave_kernel.
- */
- ia64_srlz_d();
- if (saved_rid != flush_rid) {
- ia64_set_rr(flush_start, flush_rid);
- ia64_srlz_d();
- }
-
- do {
- /*
- * Purge local TLB entries.
- */
- __asm__ __volatile__ ("ptc.l %0,%1" ::
- "r"(start), "r"(nbits<<2) : "memory");


- start += (1UL << nbits);
- } while (start < end);
-

- ia64_insn_group_barrier();
- ia64_srlz_i(); /* srlz.i implies srlz.d */
-
- if (saved_rid != flush_rid) {
- ia64_set_rr(flush_start, saved_rid);
- ia64_srlz_d();
- }
- atomic_dec(&flush_cpu_count);
- break;
- }
-#endif /* !CONFIG_ITANIUM_PTCG */
-
X default:
X printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which);
X break;
@@ -228,30 +184,6 @@
X platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
X }
X
-#ifndef CONFIG_ITANIUM_PTCG
-
-void
-smp_send_flush_tlb (void)
-{
- send_IPI_allbutself(IPI_FLUSH_TLB);
-}
-
-void
-smp_resend_flush_tlb (void)
-{
- int i;
-
- /*
- * Really need a null IPI but since this rarely should happen & since this code
- * will go away, lets not add one.
- */
- for (i = 0; i < smp_num_cpus; ++i)
- if (i != smp_processor_id())
- smp_send_reschedule(i);
-}
-
-#endif /* !CONFIG_ITANIUM_PTCG */
-
X void
X smp_flush_tlb_all (void)
X {
@@ -277,10 +209,6 @@
X {
X struct call_data_struct data;
X int cpus = 1;
-#if (defined(CONFIG_ITANIUM_B0_SPECIFIC) \
- || defined(CONFIG_ITANIUM_B1_SPECIFIC) || defined(CONFIG_ITANIUM_B2_SPECIFIC))
- unsigned long timeout;
-#endif
X
X if (cpuid == smp_processor_id()) {
X printk(__FUNCTION__" trying to call self\n");
@@ -295,26 +223,15 @@
X atomic_set(&data.finished, 0);
X
X spin_lock_bh(&call_lock);
- call_data = &data;
-
-#if (defined(CONFIG_ITANIUM_B0_SPECIFIC) \
- || defined(CONFIG_ITANIUM_B1_SPECIFIC) || defined(CONFIG_ITANIUM_B2_SPECIFIC))
- resend:
- send_IPI_single(cpuid, IPI_CALL_FUNC);
X
- /* Wait for response */
- timeout = jiffies + HZ;
- while ((atomic_read(&data.started) != cpus) && time_before(jiffies, timeout))
- barrier();
- if (atomic_read(&data.started) != cpus)
- goto resend;
-#else
+ call_data = &data;
+ mb(); /* ensure store to call_data precedes setting of IPI_CALL_FUNC */
X send_IPI_single(cpuid, IPI_CALL_FUNC);
X
X /* Wait for response */
X while (atomic_read(&data.started) != cpus)
X barrier();
-#endif
+
X if (wait)
X while (atomic_read(&data.finished) != cpus)
X barrier();
@@ -348,10 +265,6 @@
X {
X struct call_data_struct data;
X int cpus = smp_num_cpus-1;
-#if (defined(CONFIG_ITANIUM_B0_SPECIFIC) \
- || defined(CONFIG_ITANIUM_B1_SPECIFIC) || defined(CONFIG_ITANIUM_B2_SPECIFIC))
- unsigned long timeout;
-#endif
X
X if (!cpus)
X return 0;
@@ -364,27 +277,14 @@
X atomic_set(&data.finished, 0);
X
X spin_lock_bh(&call_lock);
- call_data = &data;
-
-#if (defined(CONFIG_ITANIUM_B0_SPECIFIC) \
- || defined(CONFIG_ITANIUM_B1_SPECIFIC) || defined(CONFIG_ITANIUM_B2_SPECIFIC))
- resend:
- /* Send a message to all other CPUs and wait for them to respond */
- send_IPI_allbutself(IPI_CALL_FUNC);
X
- /* Wait for response */
- timeout = jiffies + HZ;
- while ((atomic_read(&data.started) != cpus) && time_before(jiffies, timeout))
- barrier();
- if (atomic_read(&data.started) != cpus)
- goto resend;
-#else
+ call_data = &data;
+ mb(); /* ensure store to call_data precedes setting of IPI_CALL_FUNC */
X send_IPI_allbutself(IPI_CALL_FUNC);
X
X /* Wait for response */
X while (atomic_read(&data.started) != cpus)
X barrier();
-#endif
X
X if (wait)
X while (atomic_read(&data.finished) != cpus)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/smpboot.c linux/arch/ia64/kernel/smpboot.c
--- v2.4.14/linux/arch/ia64/kernel/smpboot.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/smpboot.c Wed Nov 21 10:31:09 2001
@@ -33,6 +33,7 @@
X #include <asm/io.h>
X #include <asm/irq.h>
X #include <asm/machvec.h>
+#include <asm/mca.h>


X #include <asm/page.h>
X #include <asm/pgalloc.h>

X #include <asm/pgtable.h>
@@ -42,6 +43,8 @@
X #include <asm/system.h>
X #include <asm/unistd.h>
X
+#define SMP_DEBUG 0
+
X #if SMP_DEBUG
X #define Dprintk(x...) printk(x)
X #else
@@ -310,7 +313,7 @@


X }
X
X
-void __init

+static void __init
X smp_callin (void)
X {
X int cpuid, phys_id;
@@ -324,8 +327,7 @@
X phys_id = hard_smp_processor_id();
X
X if (test_and_set_bit(cpuid, &cpu_online_map)) {
- printk("huh, phys CPU#0x%x, CPU#0x%x already present??\n",
- phys_id, cpuid);
+ printk("huh, phys CPU#0x%x, CPU#0x%x already present??\n", phys_id, cpuid);
X BUG();
X }
X
@@ -341,6 +343,12 @@
X * Get our bogomips.
X */
X ia64_init_itm();
+
+#ifdef CONFIG_IA64_MCA
+ ia64_mca_cmc_vector_setup(); /* Setup vector on AP & enable */


+ ia64_mca_check_errors(); /* For post-failure MCA error logging */
+#endif
+

X #ifdef CONFIG_PERFMON
X perfmon_init_percpu();
X #endif
@@ -364,14 +372,15 @@
X {
X extern int cpu_idle (void);
X
+ Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
X efi_map_pal_code();
X cpu_init();
X smp_callin();
- Dprintk("CPU %d is set to go. \n", smp_processor_id());
+ Dprintk("CPU %d is set to go.\n", smp_processor_id());
X while (!atomic_read(&smp_commenced))
X ;
X
- Dprintk("CPU %d is starting idle. \n", smp_processor_id());
+ Dprintk("CPU %d is starting idle.\n", smp_processor_id());
X return cpu_idle();
X }
X

@@ -409,13 +418,13 @@
X

X idle->processor = cpu;

X ia64_cpu_to_sapicid[cpu] = sapicid;


- idle->has_cpu = 1; /* we schedule the first task manually */
+ idle->cpus_runnable = 1 << cpu; /* we schedule the first task manually */
X
X del_from_runqueue(idle);
X unhash_process(idle);

X init_tasks[cpu] = idle;
X
- Dprintk("Sending Wakeup Vector to AP 0x%x/0x%x.\n", cpu, sapicid);
+ Dprintk("Sending wakeup vector %u to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
X
X platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);
X
@@ -424,7 +433,6 @@
X */
X Dprintk("Waiting on callin_map ...");
X for (timeout = 0; timeout < 100000; timeout++) {
- Dprintk(".");
X if (test_bit(cpu, &cpu_callin_map))
X break; /* It has booted */
X udelay(100);
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/sys_ia64.c linux/arch/ia64/kernel/sys_ia64.c
--- v2.4.14/linux/arch/ia64/kernel/sys_ia64.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/sys_ia64.c Fri Nov 9 14:26:17 2001
@@ -19,24 +19,29 @@
X #include <asm/shmparam.h>
X #include <asm/uaccess.h>
X
-#define COLOR_ALIGN(addr) (((addr) + SHMLBA - 1) & ~(SHMLBA - 1))
-
X unsigned long
X arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len,
X unsigned long pgoff, unsigned long flags)
X {
- struct vm_area_struct * vmm;
X long map_shared = (flags & MAP_SHARED);
+ unsigned long align_mask = PAGE_SIZE - 1;
+ struct vm_area_struct * vmm;
X
X if (len > RGN_MAP_LIMIT)
X return -ENOMEM;
X if (!addr)
X addr = TASK_UNMAPPED_BASE;
X
- if (map_shared)
- addr = COLOR_ALIGN(addr);
- else
- addr = PAGE_ALIGN(addr);
+ if (map_shared && (TASK_SIZE > 0xfffffffful))
+ /*
+ * For 64-bit tasks, align shared segments to 1MB to avoid potential
+ * performance penalty due to virtual aliasing (see ASDM). For 32-bit
+ * tasks, we prefer to avoid exhausting the address space too quickly by
+ * limiting alignment to a single page.
+ */
+ align_mask = SHMLBA - 1;
+
+ addr = (addr + align_mask) & ~align_mask;
X
X for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
X /* At this point: (!vmm || addr < vmm->vm_end). */
@@ -46,9 +51,7 @@
X return -ENOMEM;
X if (!vmm || addr + len <= vmm->vm_start)
X return addr;
- addr = vmm->vm_end;
- if (map_shared)
- addr = COLOR_ALIGN(addr);
+ addr = (vmm->vm_end + align_mask) & ~align_mask;
X }
X }
X
@@ -184,8 +187,10 @@
X if (!file)
X return -EBADF;
X
- if (!file->f_op || !file->f_op->mmap)
- return -ENODEV;
+ if (!file->f_op || !file->f_op->mmap) {
+ addr = -ENODEV;
+ goto out;


+ }
X }
X
X /*

@@ -194,22 +199,26 @@
X */
X len = PAGE_ALIGN(len);
X if (len == 0)
- return addr;
+ goto out;
X
X /* don't permit mappings into unmapped space or the virtual page table of a region: */
X roff = rgn_offset(addr);
- if ((len | roff | (roff + len)) >= RGN_MAP_LIMIT)
- return -EINVAL;
+ if ((len | roff | (roff + len)) >= RGN_MAP_LIMIT) {
+ addr = -EINVAL;
+ goto out;
+ }
X
X /* don't permit mappings that would cross a region boundary: */
- if (rgn_index(addr) != rgn_index(addr + len))
- return -EINVAL;
+ if (rgn_index(addr) != rgn_index(addr + len)) {
+ addr = -EINVAL;
+ goto out;
+ }
X
X down_write(&current->mm->mmap_sem);
X addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);


X up_write(&current->mm->mmap_sem);
X

- if (file)
+out: if (file)
X fput(file);
X return addr;
X }
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/time.c linux/arch/ia64/kernel/time.c
--- v2.4.14/linux/arch/ia64/kernel/time.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/time.c Fri Nov 9 14:26:17 2001
@@ -145,6 +145,9 @@
X tv->tv_usec = usec;
X }
X
+/* XXX there should be a cleaner way for declaring an alias... */
+asm (".global get_fast_time; get_fast_time = do_gettimeofday");
+
X static void
X timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
X {
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/traps.c linux/arch/ia64/kernel/traps.c
--- v2.4.14/linux/arch/ia64/kernel/traps.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/traps.c Fri Nov 9 14:26:17 2001
@@ -1,20 +1,19 @@
X /*
X * Architecture-specific trap handling.
X *


- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <dav...@hpl.hp.com>

+ * Copyright (C) 1998-2001 Hewlett-Packard Co


+ * David Mosberger-Tang <dav...@hpl.hp.com>
X *

X * 05/12/00 grao <gouth...@intel.com> : added isr in siginfo for SIGFPE


X */
X
X /*

- * The fpu_fault() handler needs to be able to access and update all
- * floating point registers. Those saved in pt_regs can be accessed
- * through that structure, but those not saved, will be accessed
- * directly. To make this work, we need to ensure that the compiler
- * does not end up using a preserved floating point register on its
- * own. The following achieves this by declaring preserved registers
- * that are not marked as "fixed" as global register variables.
+ * fp_emulate() needs to be able to access and update all floating point registers. Those
+ * saved in pt_regs can be accessed through that structure, but those not saved, will be
+ * accessed directly. To make this work, we need to ensure that the compiler does not end
+ * up using a preserved floating point register on its own. The following achieves this
+ * by declaring preserved registers that are not marked as "fixed" as global register
+ * variables.
X */
X register double f2 asm ("f2"); register double f3 asm ("f3");
X register double f4 asm ("f4"); register double f5 asm ("f5");
@@ -33,13 +32,17 @@
X #include <linux/kernel.h>
X #include <linux/init.h>
X #include <linux/sched.h>
+#include <linux/vt_kern.h> /* For unblank_screen() */
X
+#include <asm/hardirq.h>
X #include <asm/ia32.h>
X #include <asm/processor.h>
X #include <asm/uaccess.h>
X
X #include <asm/fpswa.h>
X
+extern spinlock_t timerlist_lock;
+
X static fpswa_interface_t *fpswa_interface;
X
X void __init
@@ -51,30 +54,74 @@
X fpswa_interface = __va(ia64_boot_param->fpswa);
X }
X
+/*
+ * Unlock any spinlocks which will prevent us from getting the message out (timerlist_lock
+ * is acquired through the console unblank code)
+ */
X void
-die_if_kernel (char *str, struct pt_regs *regs, long err)
+bust_spinlocks (int yes)
X {
- if (user_mode(regs)) {
-#if 0
- /* XXX for debugging only */
- printk ("!!die_if_kernel: %s(%d): %s %ld\n",
- current->comm, current->pid, str, err);
- show_regs(regs);
+ spin_lock_init(&timerlist_lock);
+ if (yes) {
+ oops_in_progress = 1;
+#ifdef CONFIG_SMP
+ global_irq_lock = 0; /* Many serial drivers do __global_cli() */
X #endif
- return;
+ } else {
+ int loglevel_save = console_loglevel;
+#ifdef CONFIG_VT
+ unblank_screen();
+#endif
+ oops_in_progress = 0;
+ /*
+ * OK, the message is on the console. Now we call printk() without
+ * oops_in_progress set so that printk will give klogd a poke. Hold onto
+ * your hats...
+ */
+ console_loglevel = 15; /* NMI oopser may have shut the console up */
+ printk(" ");
+ console_loglevel = loglevel_save;
X }
+}
X
- printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err);
-
- show_regs(regs);
+void
+die (const char *str, struct pt_regs *regs, long err)
+{
+ static struct {
+ spinlock_t lock;
+ int lock_owner;
+ int lock_owner_depth;
+ } die = {
+ lock: SPIN_LOCK_UNLOCKED,
+ lock_owner: -1,
+ lock_owner_depth: 0
+ };
X
- if (current->thread.flags & IA64_KERNEL_DEATH) {
- printk("die_if_kernel recursion detected.\n");
- sti();
- while (1);
+ if (die.lock_owner != smp_processor_id()) {
+ console_verbose();
+ spin_lock_irq(&die.lock);
+ die.lock_owner = smp_processor_id();
+ die.lock_owner_depth = 0;
+ bust_spinlocks(1);
X }
- current->thread.flags |= IA64_KERNEL_DEATH;
- do_exit(SIGSEGV);
+
+ if (++die.lock_owner_depth < 3) {
+ printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err);
+ show_regs(regs);
+ } else
+ printk(KERN_ERR "Recursive die() failure, output suppressed\n");
+
+ bust_spinlocks(0);
+ die.lock_owner = -1;
+ spin_unlock_irq(&die.lock);
+ do_exit(SIGSEGV);
+}
+
+void
+die_if_kernel (char *str, struct pt_regs *regs, long err)
+{
+ if (!user_mode(regs))
+ die(str, regs, err);
X }
X
X void
@@ -169,14 +216,12 @@
X }
X
X /*
- * disabled_fph_fault() is called when a user-level process attempts
- * to access one of the registers f32..f127 when it doesn't own the
- * fp-high register partition. When this happens, we save the current
- * fph partition in the task_struct of the fpu-owner (if necessary)
- * and then load the fp-high partition of the current task (if
- * necessary). Note that the kernel has access to fph by the time we
- * get here, as the IVT's "Diabled FP-Register" handler takes care of
- * clearing psr.dfh.
+ * disabled_fph_fault() is called when a user-level process attempts to access f32..f127
+ * and it doesn't own the fp-high register partition. When this happens, we save the
+ * current fph partition in the task_struct of the fpu-owner (if necessary) and then load
+ * the fp-high partition of the current task (if necessary). Note that the kernel has
+ * access to fph by the time we get here, as the IVT's "Disabled FP-Register" handler takes
+ * care of clearing psr.dfh.


X */
X static inline void

X disabled_fph_fault (struct pt_regs *regs)
@@ -277,7 +322,7 @@
X
X if (jiffies - last_time > 5*HZ)
X fpu_swa_count = 0;
- if (++fpu_swa_count < 5) {
+ if ((++fpu_swa_count < 5) && !(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) {
X last_time = jiffies;
X printk(KERN_WARNING "%s(%d): floating-point assist fault at ip %016lx\n",
X current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri);
@@ -478,12 +523,12 @@
X case 32: /* fp fault */
X case 33: /* fp trap */
X result = handle_fpu_swa((vector == 32) ? 1 : 0, regs, isr);
- if (result < 0) {
+ if ((result < 0) || (current->thread.flags & IA64_THREAD_FPEMU_SIGFPE)) {
X siginfo.si_signo = SIGFPE;
X siginfo.si_errno = 0;
X siginfo.si_code = FPE_FLTINV;
X siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
- force_sig(SIGFPE, current);
+ force_sig_info(SIGFPE, &siginfo, current);
X }
X return;
X
@@ -510,6 +555,10 @@
X break;
X
X case 46:
+#ifdef CONFIG_IA32_SUPPORT
+ if (ia32_intercept(regs, isr) == 0)
+ return;
+#endif
X printk("Unexpected IA-32 intercept trap (Trap 46)\n");
X printk(" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n",
X regs->cr_iip, ifa, isr, iim);
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/unaligned.c linux/arch/ia64/kernel/unaligned.c
--- v2.4.14/linux/arch/ia64/kernel/unaligned.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/unaligned.c Fri Nov 9 14:26:17 2001
@@ -5,6 +5,8 @@
X * Copyright (C) 1999-2000 Stephane Eranian <era...@hpl.hp.com>
X * Copyright (C) 2001 David Mosberger-Tang <dav...@hpl.hp.com>
X *
+ * 2001/10/11 Fix unaligned access to rotating registers in s/w pipelined loops.
+ * 2001/08/13 Correct size of extended floats (float_fsz) from 16 to 10 bytes.
X * 2001/01/17 Add support emulation of unaligned kernel accesses.
X */
X #include <linux/kernel.h>
@@ -282,9 +284,19 @@
X unsigned long rnats, nat_mask;
X unsigned long on_kbs;
X long sof = (regs->cr_ifs) & 0x7f;
+ long sor = 8 * ((regs->cr_ifs >> 14) & 0xf);
+ long rrb_gr = (regs->cr_ifs >> 18) & 0x7f;
+ long ridx;
+
+ if ((r1 - 32) > sor)
+ ridx = -sof + (r1 - 32);
+ else if ((r1 - 32) < (sor - rrb_gr))
+ ridx = -sof + (r1 - 32) + rrb_gr;
+ else
+ ridx = -sof + (r1 - 32) - (sor - rrb_gr);
X
- DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld\n",
- r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f);
+ DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n",
+ r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx);
X
X if ((r1 - 32) >= sof) {
X /* this should never happen, as the "rsvd register fault" has higher priority */
@@ -293,7 +305,7 @@
X }
X
X on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore);
- addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + (r1 - 32));
+ addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, ridx);
X if (addr >= kbs) {
X /* the register is on the kernel backing store: easy... */
X rnat_addr = ia64_rse_rnat_addr(addr);
@@ -318,12 +330,12 @@
X return;
X }
X
- bspstore = (unsigned long *) regs->ar_bspstore;
+ bspstore = (unsigned long *)regs->ar_bspstore;
X ubs_end = ia64_rse_skip_regs(bspstore, on_kbs);
X bsp = ia64_rse_skip_regs(ubs_end, -sof);
- addr = ia64_rse_skip_regs(bsp, r1 - 32);
+ addr = ia64_rse_skip_regs(bsp, ridx + sof);
X
- DPRINT("ubs_end=%p bsp=%p addr=%px\n", (void *) ubs_end, (void *) bsp, (void *) addr);
+ DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr);
X
X ia64_poke(current, sw, (unsigned long) ubs_end, (unsigned long) addr, val);
X
@@ -353,9 +365,19 @@
X unsigned long rnats, nat_mask;
X unsigned long on_kbs;
X long sof = (regs->cr_ifs) & 0x7f;
+ long sor = 8 * ((regs->cr_ifs >> 14) & 0xf);
+ long rrb_gr = (regs->cr_ifs >> 18) & 0x7f;
+ long ridx;
+
+ if ((r1 - 32) > sor)
+ ridx = -sof + (r1 - 32);
+ else if ((r1 - 32) < (sor - rrb_gr))
+ ridx = -sof + (r1 - 32) + rrb_gr;
+ else
+ ridx = -sof + (r1 - 32) - (sor - rrb_gr);
X
- DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld\n",
- r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f);
+ DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n",
+ r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx);
X
X if ((r1 - 32) >= sof) {
X /* this should never happen, as the "rsvd register fault" has higher priority */
@@ -364,7 +386,7 @@
X }
X
X on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore);
- addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + (r1 - 32));
+ addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, ridx);
X if (addr >= kbs) {
X /* the register is on the kernel backing store: easy... */
X *val = *addr;
@@ -390,7 +412,7 @@
X bspstore = (unsigned long *)regs->ar_bspstore;
X ubs_end = ia64_rse_skip_regs(bspstore, on_kbs);
X bsp = ia64_rse_skip_regs(ubs_end, -sof);
- addr = ia64_rse_skip_regs(bsp, r1 - 32);
+ addr = ia64_rse_skip_regs(bsp, ridx + sof);
X
X DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr);
X
@@ -908,7 +930,7 @@
X * floating point operations sizes in bytes
X */
X static const unsigned char float_fsz[4]={
- 16, /* extended precision (e) */
+ 10, /* extended precision (e) */
X 8, /* integer (8) */
X 4, /* single precision (s) */
X 8 /* double precision (d) */
@@ -978,11 +1000,11 @@
X unsigned long len = float_fsz[ld.x6_sz];
X
X /*
- * fr0 & fr1 don't need to be checked because Illegal Instruction
- * faults have higher priority than unaligned faults.
+ * fr0 & fr1 don't need to be checked because Illegal Instruction faults have
+ * higher priority than unaligned faults.
X *
- * r0 cannot be found as the base as it would never generate an
- * unaligned reference.
+ * r0 cannot be found as the base as it would never generate an unaligned
+ * reference.


X */
X
X /*

@@ -996,8 +1018,10 @@
X * invalidate the ALAT entry and execute updates, if any.
X */
X if (ld.x6_op != 0x2) {
- /* this assumes little-endian byte-order: */
-
+ /*
+ * This assumes little-endian byte-order. Note that there is no "ldfpe"
+ * instruction:
+ */
X if (copy_from_user(&fpr_init[0], (void *) ifa, len)
X || copy_from_user(&fpr_init[1], (void *) (ifa + len), len))
X return -1;
@@ -1337,7 +1361,7 @@
X
X /*
X * IMPORTANT:
- * Notice that the swictch statement DOES not cover all possible instructions
+ * Notice that the switch statement DOES not cover all possible instructions
X * that DO generate unaligned references. This is made on purpose because for some
X * instructions it DOES NOT make sense to try and emulate the access. Sometimes it
X * is WRONG to try and emulate. Here is a list of instruction we don't emulate i.e.,
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/unwind.c linux/arch/ia64/kernel/unwind.c
--- v2.4.14/linux/arch/ia64/kernel/unwind.c Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/unwind.c Fri Nov 9 14:26:17 2001
@@ -504,7 +504,7 @@


X return 0;
X }
X

-inline int
+int
X unw_access_pr (struct unw_frame_info *info, unsigned long *val, int write)
X {
X unsigned long *addr;
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/lib/clear_page.S linux/arch/ia64/lib/clear_page.S
--- v2.4.14/linux/arch/ia64/lib/clear_page.S Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/lib/clear_page.S Fri Nov 9 14:26:17 2001
@@ -47,5 +47,5 @@
X br.cloop.dptk.few 1b
X ;;
X mov ar.lc = r2 // restore lc


- br.ret.sptk.few rp
+ br.ret.sptk.many rp

X END(clear_page)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/lib/clear_user.S linux/arch/ia64/lib/clear_user.S
--- v2.4.14/linux/arch/ia64/lib/clear_user.S Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/lib/clear_user.S Fri Nov 9 14:26:17 2001
@@ -8,7 +8,7 @@
X * r8: number of bytes that didn't get cleared due to a fault
X *
X * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
- * Copyright (C) 1999 Stephane Eranian <era...@hpl.hp.com>
+ * Stephane Eranian <era...@hpl.hp.com>


X */
X
X #include <asm/asmmacro.h>

@@ -62,11 +62,11 @@


X ;; // avoid WAW on CFM

X adds tmp=-1,len // br.ctop is repeat/until

X mov ret0=len // return value is length at this point
-(p6) br.ret.spnt.few rp
+(p6) br.ret.spnt.many rp
X ;;
X cmp.lt p6,p0=16,len // if len > 16 then long memset


X mov ar.lc=tmp // initialize lc for small count

-(p6) br.cond.dptk.few long_do_clear
+(p6) br.cond.dptk .long_do_clear
X ;; // WAR on ar.lc
X //
X // worst case 16 iterations, avg 8 iterations
@@ -79,7 +79,7 @@
X 1:
X EX( .Lexit1, st1 [buf]=r0,1 )
X adds len=-1,len // countdown length using len
- br.cloop.dptk.few 1b
+ br.cloop.dptk 1b


X ;; // avoid RAW on ar.lc

X //
X // .Lexit4: comes from byte by byte loop
@@ -87,7 +87,7 @@
X .Lexit1:
X mov ret0=len // faster than using ar.lc
X mov ar.lc=saved_lc
- br.ret.sptk.few rp // end of short clear_user
+ br.ret.sptk.many rp // end of short clear_user
X
X
X //
@@ -98,7 +98,7 @@
X // instead of ret0 is due to the fact that the exception code
X // changes the values of r8.
X //
-long_do_clear:
+.long_do_clear:
X tbit.nz p6,p0=buf,0 // odd alignment (for long_do_clear)
X ;;
X EX( .Lexit3, (p6) st1 [buf]=r0,1 ) // 1-byte aligned
@@ -119,7 +119,7 @@


X ;;
X cmp.eq p6,p0=r0,cnt
X adds tmp=-1,cnt
-(p6) br.cond.dpnt.few .dotail // we have less than 16 bytes left
+(p6) br.cond.dpnt .dotail // we have less than 16 bytes left
X ;;
X adds buf2=8,buf // setup second base pointer
X mov ar.lc=tmp

@@ -148,7 +148,7 @@
X ;; // needed to get len correct when error
X st8 [buf2]=r0,16
X adds len=-16,len
- br.cloop.dptk.few 2b
+ br.cloop.dptk 2b
X ;;
X mov ar.lc=saved_lc
X //
@@ -178,7 +178,7 @@
X ;;
X EX( .Lexit2, (p7) st1 [buf]=r0 ) // only 1 byte left
X mov ret0=r0 // success
- br.ret.dptk.few rp // end of most likely path
+ br.ret.sptk.many rp // end of most likely path
X
X //
X // Outlined error handling code
@@ -205,5 +205,5 @@
X .Lexit3:
X mov ret0=len
X mov ar.lc=saved_lc
- br.ret.dptk.few rp
+ br.ret.sptk.many rp
X END(__do_clear_user)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/lib/copy_page.S linux/arch/ia64/lib/copy_page.S
--- v2.4.14/linux/arch/ia64/lib/copy_page.S Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/lib/copy_page.S Fri Nov 9 14:26:17 2001
@@ -90,5 +90,5 @@
X mov pr=saved_pr,0xffffffffffff0000 // restore predicates
X mov ar.pfs=saved_pfs
X mov ar.lc=saved_lc


- br.ret.sptk.few rp
+ br.ret.sptk.many rp

X END(copy_page)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/lib/copy_user.S linux/arch/ia64/lib/copy_user.S
--- v2.4.14/linux/arch/ia64/lib/copy_user.S Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/lib/copy_user.S Fri Nov 9 14:26:17 2001
@@ -19,8 +19,8 @@
X * ret0 0 in case of success. The number of bytes NOT copied in
X * case of error.


X *
- * Copyright (C) 2000 Hewlett-Packard Co
- * Copyright (C) 2000 Stephane Eranian <era...@hpl.hp.com>
+ * Copyright (C) 2000-2001 Hewlett-Packard Co
+ * Stephane Eranian <era...@hpl.hp.com>
X *

X * Fixme:
X * - handle the case where we have more than 16 bytes and the alignment
@@ -85,7 +85,7 @@
X cmp.eq p8,p0=r0,len // check for zero length
X .save ar.lc, saved_lc
X mov saved_lc=ar.lc // preserve ar.lc (slow)
-(p8) br.ret.spnt.few rp // empty mempcy()
+(p8) br.ret.spnt.many rp // empty mempcy()
X ;;
X add enddst=dst,len // first byte after end of source
X add endsrc=src,len // first byte after end of destination
@@ -103,26 +103,26 @@
X cmp.lt p10,p7=COPY_BREAK,len // if len > COPY_BREAK then long copy
X
X xor tmp=src,dst // same alignment test prepare
-(p10) br.cond.dptk.few long_copy_user
+(p10) br.cond.dptk .long_copy_user
X ;; // RAW pr.rot/p16 ?
X //
X // Now we do the byte by byte loop with software pipeline
X //
X // p7 is necessarily false by now
X 1:
- EX(failure_in_pipe1,(p16) ld1 val1[0]=[src1],1)
- EX(failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
+ EX(.failure_in_pipe1,(p16) ld1 val1[0]=[src1],1)
+ EX(.failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
X br.ctop.dptk.few 1b
X ;;
X mov ar.lc=saved_lc
X mov pr=saved_pr,0xffffffffffff0000
X mov ar.pfs=saved_pfs // restore ar.ec
- br.ret.sptk.few rp // end of short memcpy
+ br.ret.sptk.many rp // end of short memcpy
X
X //
X // Not 8-byte aligned
X //
-diff_align_copy_user:
+.diff_align_copy_user:
X // At this point we know we have more than 16 bytes to copy
X // and also that src and dest do _not_ have the same alignment.
X and src2=0x7,src1 // src offset
@@ -153,7 +153,7 @@
X // We know src1 is not 8-byte aligned in this case.
X //
X cmp.eq p14,p15=r0,dst2
-(p15) br.cond.spnt.few 1f
+(p15) br.cond.spnt 1f
X ;;
X sub t1=8,src2
X mov t2=src2


@@ -163,7 +163,7 @@
X ;;

X sub lshift=64,rshift
X ;;
- br.cond.spnt.few word_copy_user
+ br.cond.spnt .word_copy_user
X ;;
X 1:
X cmp.leu p14,p15=src2,dst2
@@ -192,15 +192,15 @@
X mov ar.lc=cnt
X ;;
X 2:
- EX(failure_in_pipe2,(p16) ld1 val1[0]=[src1],1)
- EX(failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
+ EX(.failure_in_pipe2,(p16) ld1 val1[0]=[src1],1)
+ EX(.failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
X br.ctop.dptk.few 2b
X ;;
X clrrrb
X ;;
-word_copy_user:
+.word_copy_user:
X cmp.gtu p9,p0=16,len1
-(p9) br.cond.spnt.few 4f // if (16 > len1) skip 8-byte copy
+(p9) br.cond.spnt 4f // if (16 > len1) skip 8-byte copy
X ;;
X shr.u cnt=len1,3 // number of 64-bit words
X ;;
@@ -232,24 +232,24 @@
X #define EPI_1 p[PIPE_DEPTH-2]
X #define SWITCH(pred, shift) cmp.eq pred,p0=shift,rshift
X #define CASE(pred, shift) \
- (pred) br.cond.spnt.few copy_user_bit##shift
+ (pred) br.cond.spnt .copy_user_bit##shift
X #define BODY(rshift) \
-copy_user_bit##rshift: \
+.copy_user_bit##rshift: \
X 1: \
- EX(failure_out,(EPI) st8 [dst1]=tmp,8); \
+ EX(.failure_out,(EPI) st8 [dst1]=tmp,8); \
X (EPI_1) shrp tmp=val1[PIPE_DEPTH-3],val1[PIPE_DEPTH-2],rshift; \
X EX(3f,(p16) ld8 val1[0]=[src1],8); \
- br.ctop.dptk.few 1b; \
+ br.ctop.dptk 1b; \
X ;; \
- br.cond.sptk.few .diff_align_do_tail; \
+ br.cond.sptk.many .diff_align_do_tail; \
X 2: \
X (EPI) st8 [dst1]=tmp,8; \
X (EPI_1) shrp tmp=val1[PIPE_DEPTH-3],val1[PIPE_DEPTH-2],rshift; \
X 3: \
X (p16) mov val1[0]=r0; \
- br.ctop.dptk.few 2b; \
+ br.ctop.dptk 2b; \
X ;; \
- br.cond.sptk.few failure_in2
+ br.cond.sptk.many .failure_in2
X
X //
X // Since the instruction 'shrp' requires a fixed 128-bit value
@@ -301,25 +301,25 @@
X mov ar.lc=len1
X ;;
X 5:
- EX(failure_in_pipe1,(p16) ld1 val1[0]=[src1],1)
- EX(failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
+ EX(.failure_in_pipe1,(p16) ld1 val1[0]=[src1],1)
+ EX(.failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
X br.ctop.dptk.few 5b
X ;;
X mov ar.lc=saved_lc


X mov pr=saved_pr,0xffffffffffff0000
X mov ar.pfs=saved_pfs

- br.ret.dptk.few rp
+ br.ret.sptk.many rp
X
X //
X // Beginning of long mempcy (i.e. > 16 bytes)
X //
-long_copy_user:
+.long_copy_user:
X tbit.nz p6,p7=src1,0 // odd alignement
X and tmp=7,tmp
X ;;
X cmp.eq p10,p8=r0,tmp
X mov len1=len // copy because of rotation
-(p8) br.cond.dpnt.few diff_align_copy_user
+(p8) br.cond.dpnt .diff_align_copy_user
X ;;
X // At this point we know we have more than 16 bytes to copy
X // and also that both src and dest have the same alignment
@@ -327,11 +327,11 @@
X // forward slowly until we reach 16byte alignment: no need to
X // worry about reaching the end of buffer.
X //
- EX(failure_in1,(p6) ld1 val1[0]=[src1],1) // 1-byte aligned
+ EX(.failure_in1,(p6) ld1 val1[0]=[src1],1) // 1-byte aligned
X (p6) adds len1=-1,len1;;
X tbit.nz p7,p0=src1,1
X ;;
- EX(failure_in1,(p7) ld2 val1[1]=[src1],2) // 2-byte aligned
+ EX(.failure_in1,(p7) ld2 val1[1]=[src1],2) // 2-byte aligned
X (p7) adds len1=-2,len1;;
X tbit.nz p8,p0=src1,2
X ;;
@@ -339,28 +339,28 @@
X // Stop bit not required after ld4 because if we fail on ld4
X // we have never executed the ld1, therefore st1 is not executed.
X //
- EX(failure_in1,(p8) ld4 val2[0]=[src1],4) // 4-byte aligned
+ EX(.failure_in1,(p8) ld4 val2[0]=[src1],4) // 4-byte aligned
X ;;
- EX(failure_out,(p6) st1 [dst1]=val1[0],1)
+ EX(.failure_out,(p6) st1 [dst1]=val1[0],1)
X tbit.nz p9,p0=src1,3
X ;;
X //
X // Stop bit not required after ld8 because if we fail on ld8
X // we have never executed the ld2, therefore st2 is not executed.
X //
- EX(failure_in1,(p9) ld8 val2[1]=[src1],8) // 8-byte aligned
- EX(failure_out,(p7) st2 [dst1]=val1[1],2)
+ EX(.failure_in1,(p9) ld8 val2[1]=[src1],8) // 8-byte aligned
+ EX(.failure_out,(p7) st2 [dst1]=val1[1],2)
X (p8) adds len1=-4,len1
X ;;
- EX(failure_out, (p8) st4 [dst1]=val2[0],4)
+ EX(.failure_out, (p8) st4 [dst1]=val2[0],4)
X (p9) adds len1=-8,len1;;
X shr.u cnt=len1,4 // number of 128-bit (2x64bit) words
X ;;
- EX(failure_out, (p9) st8 [dst1]=val2[1],8)
+ EX(.failure_out, (p9) st8 [dst1]=val2[1],8)
X tbit.nz p6,p0=len1,3
X cmp.eq p7,p0=r0,cnt
X adds tmp=-1,cnt // br.ctop is repeat/until
-(p7) br.cond.dpnt.few .dotail // we have less than 16 bytes left
+(p7) br.cond.dpnt .dotail // we have less than 16 bytes left
X ;;
X adds src2=8,src1
X adds dst2=8,dst1
@@ -370,12 +370,12 @@
X // 16bytes/iteration
X //
X 2:
- EX(failure_in3,(p16) ld8 val1[0]=[src1],16)
+ EX(.failure_in3,(p16) ld8 val1[0]=[src1],16)
X (p16) ld8 val2[0]=[src2],16
X
- EX(failure_out, (EPI) st8 [dst1]=val1[PIPE_DEPTH-1],16)
+ EX(.failure_out, (EPI) st8 [dst1]=val1[PIPE_DEPTH-1],16)
X (EPI) st8 [dst2]=val2[PIPE_DEPTH-1],16
- br.ctop.dptk.few 2b
+ br.ctop.dptk 2b
X ;; // RAW on src1 when fall through from loop
X //
X // Tail correction based on len only
@@ -384,29 +384,28 @@
X // is 16 byte aligned AND we have less than 16 bytes to copy.
X //
X .dotail:
- EX(failure_in1,(p6) ld8 val1[0]=[src1],8) // at least 8 bytes
+ EX(.failure_in1,(p6) ld8 val1[0]=[src1],8) // at least 8 bytes
X tbit.nz p7,p0=len1,2
X ;;
- EX(failure_in1,(p7) ld4 val1[1]=[src1],4) // at least 4 bytes
+ EX(.failure_in1,(p7) ld4 val1[1]=[src1],4) // at least 4 bytes
X tbit.nz p8,p0=len1,1
X ;;
- EX(failure_in1,(p8) ld2 val2[0]=[src1],2) // at least 2 bytes
+ EX(.failure_in1,(p8) ld2 val2[0]=[src1],2) // at least 2 bytes
X tbit.nz p9,p0=len1,0
X ;;
- EX(failure_out, (p6) st8 [dst1]=val1[0],8)
+ EX(.failure_out, (p6) st8 [dst1]=val1[0],8)
X ;;
- EX(failure_in1,(p9) ld1 val2[1]=[src1]) // only 1 byte left
+ EX(.failure_in1,(p9) ld1 val2[1]=[src1]) // only 1 byte left
X mov ar.lc=saved_lc
X ;;
- EX(failure_out,(p7) st4 [dst1]=val1[1],4)
+ EX(.failure_out,(p7) st4 [dst1]=val1[1],4)
X mov pr=saved_pr,0xffffffffffff0000
X ;;
- EX(failure_out, (p8) st2 [dst1]=val2[0],2)
+ EX(.failure_out, (p8) st2 [dst1]=val2[0],2)
X mov ar.pfs=saved_pfs
X ;;
- EX(failure_out, (p9) st1 [dst1]=val2[1])
- br.ret.dptk.few rp
-
+ EX(.failure_out, (p9) st1 [dst1]=val2[1])


+ br.ret.sptk.many rp
X
X

X //
@@ -433,32 +432,32 @@
X // pipeline going. We can't really do this inline because
X // p16 is always reset to 1 when lc > 0.
X //
-failure_in_pipe1:
+.failure_in_pipe1:
X sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied
X 1:
X (p16) mov val1[0]=r0
X (EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1
- br.ctop.dptk.few 1b
+ br.ctop.dptk 1b
X ;;
X mov pr=saved_pr,0xffffffffffff0000


X mov ar.lc=saved_lc
X mov ar.pfs=saved_pfs

- br.ret.dptk.few rp
+ br.ret.sptk.many rp
X
X //
X // This is the case where the byte by byte copy fails on the load
X // when we copy the head. We need to finish the pipeline and copy
X // zeros for the rest of the destination. Since this happens
X // at the top we still need to fill the body and tail.
-failure_in_pipe2:
+.failure_in_pipe2:
X sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied
X 2:
X (p16) mov val1[0]=r0
X (EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1
- br.ctop.dptk.few 2b
+ br.ctop.dptk 2b
X ;;
X sub len=enddst,dst1,1 // precompute len
- br.cond.dptk.few failure_in1bis
+ br.cond.dptk.many .failure_in1bis
X ;;
X
X //
@@ -533,9 +532,7 @@
X // This means that we are in a situation similar the a fault in the
X // head part. That's nice!
X //
-failure_in1:
-// sub ret0=enddst,dst1 // number of bytes to zero, i.e. not copied
-// sub len=enddst,dst1,1
+.failure_in1:
X sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied
X sub len=endsrc,src1,1
X //
@@ -546,18 +543,17 @@
X // calling side.
X //
X ;;
-failure_in1bis: // from (failure_in3)
+.failure_in1bis: // from (.failure_in3)
X mov ar.lc=len // Continue with a stupid byte store.
X ;;
X 5:
X st1 [dst1]=r0,1
- br.cloop.dptk.few 5b
+ br.cloop.dptk 5b
X ;;
-skip_loop:
X mov pr=saved_pr,0xffffffffffff0000


X mov ar.lc=saved_lc
X mov ar.pfs=saved_pfs

- br.ret.dptk.few rp
+ br.ret.sptk.many rp
X
X //
X // Here we simply restart the loop but instead
@@ -569,7 +565,7 @@
X // we MUST use src1/endsrc here and not dst1/enddst because
X // of the pipeline effect.
X //
-failure_in3:
+.failure_in3:
X sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied
X ;;
X 2:
@@ -577,36 +573,36 @@
X (p16) mov val2[0]=r0
X (EPI) st8 [dst1]=val1[PIPE_DEPTH-1],16
X (EPI) st8 [dst2]=val2[PIPE_DEPTH-1],16
- br.ctop.dptk.few 2b
+ br.ctop.dptk 2b
X ;;
X cmp.ne p6,p0=dst1,enddst // Do we need to finish the tail ?
X sub len=enddst,dst1,1 // precompute len
-(p6) br.cond.dptk.few failure_in1bis
+(p6) br.cond.dptk .failure_in1bis
X ;;
X mov pr=saved_pr,0xffffffffffff0000


X mov ar.lc=saved_lc
X mov ar.pfs=saved_pfs

- br.ret.dptk.few rp
+ br.ret.sptk.many rp
X
-failure_in2:
+.failure_in2:
X sub ret0=endsrc,src1
X cmp.ne p6,p0=dst1,enddst // Do we need to finish the tail ?
X sub len=enddst,dst1,1 // precompute len
-(p6) br.cond.dptk.few failure_in1bis
+(p6) br.cond.dptk .failure_in1bis
X ;;
X mov pr=saved_pr,0xffffffffffff0000


X mov ar.lc=saved_lc
X mov ar.pfs=saved_pfs

- br.ret.dptk.few rp
+ br.ret.sptk.many rp
X
X //
X // handling of failures on stores: that's the easy part
X //
-failure_out:
+.failure_out:
X sub ret0=enddst,dst1
X mov pr=saved_pr,0xffffffffffff0000
X mov ar.lc=saved_lc
X
X mov ar.pfs=saved_pfs
- br.ret.dptk.few rp
+ br.ret.sptk.many rp
X END(__copy_user)
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/lib/do_csum.S linux/arch/ia64/lib/do_csum.S
--- v2.4.14/linux/arch/ia64/lib/do_csum.S Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/lib/do_csum.S Fri Nov 9 14:26:17 2001
@@ -16,7 +16,6 @@
X * back-to-back 8-byte words per loop. Clean up the initialization
X * for the loop. Support the cases where load latency = 1 or 2.
X * Set CONFIG_IA64_LOAD_LATENCY to 1 or 2 (default).
- *


X */
X
X #include <asm/asmmacro.h>

@@ -130,7 +129,7 @@


X ;; // avoid WAW on CFM

X mov tmp3=0x7 // a temporary mask/value
X add tmp1=buf,len // last byte's address
-(p6) br.ret.spnt.few rp // return if true (hope we can avoid that)
+(p6) br.ret.spnt.many rp // return if true (hope we can avoid that)
X
X and firstoff=7,buf // how many bytes off for first1 element
X tbit.nz p15,p0=buf,0 // is buf an odd address ?
@@ -181,9 +180,9 @@
X cmp.ltu p6,p0=result1[0],word1[0] // check the carry


X ;;
X (p6) adds result1[0]=1,result1[0]

-(p8) br.cond.dptk.few do_csum_exit // if (within an 8-byte word)
+(p8) br.cond.dptk .do_csum_exit // if (within an 8-byte word)
X ;;
-(p11) br.cond.dptk.few do_csum16 // if (count is even)
+(p11) br.cond.dptk .do_csum16 // if (count is even)
X ;;
X // Here count is odd.
X ld8 word1[1]=[first1],8 // load an 8-byte word
@@ -196,14 +195,14 @@


X ;;
X (p6) adds result1[0]=1,result1[0]
X ;;

-(p9) br.cond.sptk.few do_csum_exit // if (count == 1) exit
+(p9) br.cond.sptk .do_csum_exit // if (count == 1) exit
X // Fall through to caluculate the checksum, feeding result1[0] as
X // the initial value in result1[0].
X ;;
X //
X // Calculate the checksum loading two 8-byte words per loop.
X //
-do_csum16:
+.do_csum16:
X mov saved_lc=ar.lc


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

echo 'End of part 033'
echo 'File patch-2.4.15 is continued in part 034'
echo "034" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:13 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part037

#!/bin/sh -x
# this is part 037 of a 115 - part archive


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

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

+ skb->len, PCI_DMA_TODEVICE);
+ return error;


+}
+
+static unsigned long

+get_free_scd(struct idt77252_dev *card, struct vc_map *vc)
+{
+ int i;
+
+ for (i = 0; i < card->scd_size; i++) {
+ if (!card->scd2vc[i]) {
+ card->scd2vc[i] = vc;
+ vc->scd_index = i;
+ return card->scd_base + i * SAR_SRAM_SCD_SIZE;
+ }
+ }


+ return 0;
+}
+
+static void

+fill_scd(struct idt77252_dev *card, struct scq_info *scq, int class)
+{
+ write_sram(card, scq->scd, scq->paddr);
+ write_sram(card, scq->scd + 1, 0x00000000);
+ write_sram(card, scq->scd + 2, 0xffffffff);
+ write_sram(card, scq->scd + 3, 0x00000000);
+}
+
+static void
+clear_scd(struct idt77252_dev *card, struct scq_info *scq, int class)
+{
+ return;


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

+/* RSQ Handling */
+/* */
+/*****************************************************************************/
+
+static int
+init_rsq(struct idt77252_dev *card)
+{
+ struct rsq_entry *rsqe;
+
+ card->rsq.base = pci_alloc_consistent(card->pcidev, RSQSIZE,
+ &card->rsq.paddr);
+ if (card->rsq.base == NULL) {
+ printk("%s: can't allocate RSQ.\n", card->name);
+ return -1;
+ }
+ memset(card->rsq.base, 0, RSQSIZE);
+
+ card->rsq.last = card->rsq.base + RSQ_NUM_ENTRIES - 1;
+ card->rsq.next = card->rsq.last;
+ for (rsqe = card->rsq.base; rsqe <= card->rsq.last; rsqe++)
+ rsqe->word_4 = 0;
+
+ writel((unsigned long) card->rsq.last - (unsigned long) card->rsq.base,
+ SAR_REG_RSQH);
+ writel(card->rsq.paddr, SAR_REG_RSQB);
+
+ IPRINTK("%s: RSQ base at 0x%lx (0x%x).\n", card->name,
+ (unsigned long) card->rsq.base,
+ readl(SAR_REG_RSQB));
+ IPRINTK("%s: RSQ head = 0x%x, base = 0x%x, tail = 0x%x.\n",
+ card->name,
+ readl(SAR_REG_RSQH),
+ readl(SAR_REG_RSQB),
+ readl(SAR_REG_RSQT));
+


+ return 0;
+}
+
+static void

+deinit_rsq(struct idt77252_dev *card)
+{
+ pci_free_consistent(card->pcidev, RSQSIZE,
+ card->rsq.base, card->rsq.paddr);
+}
+
+static void
+dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
+{
+ struct atm_vcc *vcc;
+ struct sk_buff *skb;
+ struct rx_pool *rpp;
+ struct vc_map *vc;
+ u32 header, vpi, vci;
+ u32 stat;
+ int i;
+
+ stat = le32_to_cpu(rsqe->word_4);
+
+ if (stat & SAR_RSQE_IDLE) {
+ RXPRINTK("%s: message about inactive connection.\n",
+ card->name);
+ return;
+ }
+
+ skb = sb_pool_skb(card, le32_to_cpu(rsqe->word_2));
+ if (skb == NULL) {
+ printk("%s: NULL skb in %s, rsqe: %08x %08x %08x %08x\n",
+ card->name, __FUNCTION__,
+ le32_to_cpu(rsqe->word_1), le32_to_cpu(rsqe->word_2),
+ le32_to_cpu(rsqe->word_3), le32_to_cpu(rsqe->word_4));
+ return;
+ }
+
+ header = le32_to_cpu(rsqe->word_1);
+ vpi = (header >> 16) & 0x00ff;
+ vci = (header >> 0) & 0xffff;
+
+ RXPRINTK("%s: SDU for %d.%d received in buffer 0x%p (data 0x%p).\n",
+ card->name, vpi, vci, skb, skb->data);
+
+ if ((vpi >= (1 << card->vpibits)) || (vci != (vci & card->vcimask))) {
+ printk("%s: SDU received for out-of-range vc %u.%u\n",
+ card->name, vpi, vci);
+ recycle_rx_skb(card, skb);
+ return;
+ }
+
+ vc = card->vcs[VPCI2VC(card, vpi, vci)];
+ if (!vc || !test_bit(VCF_RX, &vc->flags)) {
+ printk("%s: SDU received on non RX vc %u.%u\n",
+ card->name, vpi, vci);
+ recycle_rx_skb(card, skb);
+ return;
+ }
+
+ vcc = vc->rx_vcc;
+
+ pci_dma_sync_single(card->pcidev, IDT77252_PRV_PADDR(skb),
+ skb->end - skb->data, PCI_DMA_FROMDEVICE);
+
+ if ((vcc->qos.aal == ATM_AAL0) ||
+ (vcc->qos.aal == ATM_AAL34)) {
+ struct sk_buff *sb;
+ unsigned char *cell;
+ u32 aal0;
+
+ cell = skb->data;
+ for (i = (stat & SAR_RSQE_CELLCNT); i; i--) {
+ if ((sb = dev_alloc_skb(64)) == NULL) {
+ printk("%s: Can't allocate buffers for aal0.\n",
+ card->name);
+ atomic_add(i, &vcc->stats->rx_drop);
+ break;
+ }
+ if (!atm_charge(vcc, sb->truesize)) {
+ RXPRINTK("%s: atm_charge() dropped aal0 packets.\n",
+ card->name);
+ atomic_add(i - 1, &vcc->stats->rx_drop);
+ dev_kfree_skb(sb);
+ break;
+ }
+ aal0 = (vpi << ATM_HDR_VPI_SHIFT) |
+ (vci << ATM_HDR_VCI_SHIFT);
+ aal0 |= (stat & SAR_RSQE_EPDU) ? 0x00000002 : 0;
+ aal0 |= (stat & SAR_RSQE_CLP) ? 0x00000001 : 0;
+
+ *((u32 *) sb->data) = aal0;
+ skb_put(sb, sizeof(u32));
+ memcpy(skb_put(sb, ATM_CELL_PAYLOAD),
+ cell, ATM_CELL_PAYLOAD);
+
+ ATM_SKB(sb)->vcc = vcc;
+ sb->stamp = xtime;
+ vcc->push(vcc, sb);
+ atomic_inc(&vcc->stats->rx);
+
+ cell += ATM_CELL_PAYLOAD;
+ }
+
+ recycle_rx_skb(card, skb);
+ return;
+ }
+ if (vcc->qos.aal != ATM_AAL5) {
+ printk("%s: Unexpected AAL type in dequeue_rx(): %d.\n",
+ card->name, vcc->qos.aal);
+ recycle_rx_skb(card, skb);
+ return;
+ }
+ skb->len = (stat & SAR_RSQE_CELLCNT) * ATM_CELL_PAYLOAD;
+
+ rpp = &vc->rcv.rx_pool;
+
+ rpp->len += skb->len;
+ if (!rpp->count++)
+ rpp->first = skb;
+ *rpp->last = skb;
+ rpp->last = &skb->next;
+
+ if (stat & SAR_RSQE_EPDU) {
+ unsigned char *l1l2;


+ unsigned int len;
+

+ l1l2 = (unsigned char *) ((unsigned long) skb->data + skb->len - 6);
+
+ len = (l1l2[0] << 8) | l1l2[1];
+ len = len ? len : 0x10000;
+
+ RXPRINTK("%s: PDU has %d bytes.\n", card->name, len);
+
+ if ((len + 8 > rpp->len) || (len + (47 + 8) < rpp->len)) {
+ RXPRINTK("%s: AAL5 PDU size mismatch: %d != %d. "
+ "(CDC: %08x)\n",
+ card->name, len, rpp->len, readl(SAR_REG_CDC));
+ recycle_rx_pool_skb(card, rpp);
+ atomic_inc(&vcc->stats->rx_err);
+ return;
+ }
+ if (stat & SAR_RSQE_CRC) {
+ RXPRINTK("%s: AAL5 CRC error.\n", card->name);
+ recycle_rx_pool_skb(card, rpp);
+ atomic_inc(&vcc->stats->rx_err);
+ return;
+ }
+ if (rpp->count > 1) {
+ struct sk_buff *sb;
+
+ skb = dev_alloc_skb(rpp->len);
+ if (!skb) {
+ RXPRINTK("%s: Can't alloc RX skb.\n",
+ card->name);
+ recycle_rx_pool_skb(card, rpp);
+ atomic_inc(&vcc->stats->rx_err);
+ return;
+ }
+ if (!atm_charge(vcc, skb->truesize)) {
+ recycle_rx_pool_skb(card, rpp);
+ dev_kfree_skb(skb);
+ return;
+ }
+ sb = rpp->first;
+ for (i = 0; i < rpp->count; i++) {
+ memcpy(skb_put(skb, sb->len),
+ sb->data, sb->len);
+ sb = sb->next;
+ }
+
+ recycle_rx_pool_skb(card, rpp);
+
+ skb_trim(skb, len);
+ ATM_SKB(skb)->vcc = vcc;
+ skb->stamp = xtime;
+
+ vcc->push(vcc, skb);
+ atomic_inc(&vcc->stats->rx);
+
+ return;
+ }
+
+ skb->next = NULL;
+ flush_rx_pool(card, rpp);
+
+ if (!atm_charge(vcc, skb->truesize)) {
+ recycle_rx_skb(card, skb);
+ return;
+ }
+
+ pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb),
+ skb->end - skb->data, PCI_DMA_FROMDEVICE);
+ sb_pool_remove(card, skb);
+
+ skb_trim(skb, len);
+ ATM_SKB(skb)->vcc = vcc;
+ skb->stamp = xtime;
+
+ vcc->push(vcc, skb);
+ atomic_inc(&vcc->stats->rx);
+
+ if (skb->truesize > SAR_FB_SIZE_3)
+ add_rx_skb(card, 3, SAR_FB_SIZE_3, 1);
+ else if (skb->truesize > SAR_FB_SIZE_2)
+ add_rx_skb(card, 2, SAR_FB_SIZE_2, 1);
+ else if (skb->truesize > SAR_FB_SIZE_1)
+ add_rx_skb(card, 1, SAR_FB_SIZE_1, 1);
+ else
+ add_rx_skb(card, 0, SAR_FB_SIZE_0, 1);


+ return;
+ }
+}
+

+static void
+idt77252_rx(struct idt77252_dev *card)
+{
+ struct rsq_entry *rsqe;
+
+ if (card->rsq.next == card->rsq.last)
+ rsqe = card->rsq.base;
+ else
+ rsqe = card->rsq.next + 1;
+
+ if (!(le32_to_cpu(rsqe->word_4) & SAR_RSQE_VALID)) {
+ RXPRINTK("%s: no entry in RSQ.\n", card->name);
+ return;
+ }
+
+ do {
+ dequeue_rx(card, rsqe);
+ rsqe->word_4 = 0;
+ card->rsq.next = rsqe;
+ if (card->rsq.next == card->rsq.last)
+ rsqe = card->rsq.base;
+ else
+ rsqe = card->rsq.next + 1;
+ } while (le32_to_cpu(rsqe->word_4) & SAR_RSQE_VALID);
+
+ writel((unsigned long) card->rsq.next - (unsigned long) card->rsq.base,
+ SAR_REG_RSQH);
+}
+
+static void
+idt77252_rx_raw(struct idt77252_dev *card)
+{
+ struct sk_buff *queue;
+ u32 head, tail;
+ struct atm_vcc *vcc;
+ struct vc_map *vc;
+ struct sk_buff *sb;
+
+ if (card->raw_cell_head == NULL) {
+ u32 handle = le32_to_cpu(*(card->raw_cell_hnd + 1));
+ card->raw_cell_head = sb_pool_skb(card, handle);
+ }
+
+ queue = card->raw_cell_head;
+ if (!queue)
+ return;
+
+ head = IDT77252_PRV_PADDR(queue) + (queue->data - queue->head - 16);
+ tail = readl(SAR_REG_RAWCT);
+
+ pci_dma_sync_single(card->pcidev, IDT77252_PRV_PADDR(queue),
+ queue->end - queue->head - 16, PCI_DMA_FROMDEVICE);
+
+ while (head != tail) {
+ unsigned int vpi, vci, pti;
+ u32 header;
+
+ header = le32_to_cpu(*(u32 *) &queue->data[0]);
+
+ vpi = (header & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT;
+ vci = (header & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT;
+ pti = (header & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT;
+
+#ifdef CONFIG_ATM_IDT77252_DEBUG
+ if (debug & DBG_RAW_CELL) {
+ int i;
+
+ printk("%s: raw cell %x.%02x.%04x.%x.%x\n",
+ card->name, (header >> 28) & 0x000f,
+ (header >> 20) & 0x00ff,
+ (header >> 4) & 0xffff,
+ (header >> 1) & 0x0007,
+ (header >> 0) & 0x0001);
+ for (i = 16; i < 64; i++)
+ printk(" %02x", queue->data[i]);


+ printk("\n");
+ }

+#endif
+
+ if (vpi >= (1<<card->vpibits) || vci >= (1<<card->vcibits)) {
+ RPRINTK("%s: SDU received for out-of-range vc %u.%u\n",
+ card->name, vpi, vci);
+ goto drop;
+ }
+
+ vc = card->vcs[VPCI2VC(card, vpi, vci)];
+ if (!vc || !test_bit(VCF_RX, &vc->flags)) {
+ RPRINTK("%s: SDU received on non RX vc %u.%u\n",
+ card->name, vpi, vci);
+ goto drop;
+ }
+
+ vcc = vc->rx_vcc;
+
+ if (vcc->qos.aal != ATM_AAL0) {
+ RPRINTK("%s: raw cell for non AAL0 vc %u.%u\n",
+ card->name, vpi, vci);
+ atomic_inc(&vcc->stats->rx_drop);
+ goto drop;
+ }
+
+ if ((sb = dev_alloc_skb(64)) == NULL) {
+ printk("%s: Can't allocate buffers for AAL0.\n",
+ card->name);
+ atomic_inc(&vcc->stats->rx_err);
+ goto drop;
+ }
+
+ if ((vcc->sk != NULL) && !atm_charge(vcc, sb->truesize)) {
+ RXPRINTK("%s: atm_charge() dropped AAL0 packets.\n",
+ card->name);
+ dev_kfree_skb(sb);
+ goto drop;
+ }
+
+ *((u32 *) sb->data) = header;
+ skb_put(sb, sizeof(u32));
+ memcpy(skb_put(sb, ATM_CELL_PAYLOAD), &(queue->data[16]),
+ ATM_CELL_PAYLOAD);
+
+ ATM_SKB(sb)->vcc = vcc;
+ sb->stamp = xtime;
+ vcc->push(vcc, sb);
+ atomic_inc(&vcc->stats->rx);
+
+drop:
+ skb_pull(queue, 64);
+
+ head = IDT77252_PRV_PADDR(queue)
+ + (queue->data - queue->head - 16);
+
+ if (queue->len < 128) {
+ struct sk_buff *next;
+ u32 handle;
+
+ head = le32_to_cpu(*(u32 *) &queue->data[0]);
+ handle = le32_to_cpu(*(u32 *) &queue->data[4]);
+
+ next = sb_pool_skb(card, handle);
+ recycle_rx_skb(card, queue);
+
+ if (next) {
+ card->raw_cell_head = next;
+ queue = card->raw_cell_head;
+ pci_dma_sync_single(card->pcidev,
+ IDT77252_PRV_PADDR(queue),
+ queue->end - queue->data,
+ PCI_DMA_FROMDEVICE);
+ } else {
+ card->raw_cell_head = NULL;
+ printk("%s: raw cell queue overrun\n",
+ card->name);
+ break;
+ }
+ }
+ }


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

+/* TSQ Handling */
+/* */
+/*****************************************************************************/
+
+static int
+init_tsq(struct idt77252_dev *card)
+{
+ struct tsq_entry *tsqe;
+
+ card->tsq.base = pci_alloc_consistent(card->pcidev, RSQSIZE,
+ &card->tsq.paddr);
+ if (card->tsq.base == NULL) {
+ printk("%s: can't allocate TSQ.\n", card->name);
+ return -1;
+ }
+ memset(card->tsq.base, 0, TSQSIZE);
+
+ card->tsq.last = card->tsq.base + TSQ_NUM_ENTRIES - 1;
+ card->tsq.next = card->tsq.last;
+ for (tsqe = card->tsq.base; tsqe <= card->tsq.last; tsqe++)
+ tsqe->word_2 = cpu_to_le32(SAR_TSQE_INVALID);
+
+ writel(card->tsq.paddr, SAR_REG_TSQB);
+ writel((unsigned long) card->tsq.next - (unsigned long) card->tsq.base,
+ SAR_REG_TSQH);
+


+ return 0;
+}
+
+static void

+deinit_tsq(struct idt77252_dev *card)
+{
+ pci_free_consistent(card->pcidev, TSQSIZE,
+ card->tsq.base, card->tsq.paddr);
+}
+
+static void
+idt77252_tx(struct idt77252_dev *card)
+{
+ struct tsq_entry *tsqe;
+ unsigned int vpi, vci;
+ struct vc_map *vc;
+ u32 conn, stat;
+
+ if (card->tsq.next == card->tsq.last)
+ tsqe = card->tsq.base;
+ else
+ tsqe = card->tsq.next + 1;
+
+ TXPRINTK("idt77252_tx: tsq %p: base %p, next %p, last %p\n", tsqe,
+ card->tsq.base, card->tsq.next, card->tsq.last);
+ TXPRINTK("idt77252_tx: tsqb %08x, tsqt %08x, tsqh %08x, \n",
+ readl(SAR_REG_TSQB),
+ readl(SAR_REG_TSQT),
+ readl(SAR_REG_TSQH));
+
+ stat = le32_to_cpu(tsqe->word_2);
+
+ if (stat & SAR_TSQE_INVALID)
+ return;
+
+ do {
+ TXPRINTK("tsqe: 0x%p [0x%08x 0x%08x]\n", tsqe,
+ le32_to_cpu(tsqe->word_1),
+ le32_to_cpu(tsqe->word_2));
+
+ switch (stat & SAR_TSQE_TYPE) {
+ case SAR_TSQE_TYPE_TIMER:
+ TXPRINTK("%s: Timer RollOver detected.\n", card->name);
+ break;
+
+ case SAR_TSQE_TYPE_IDLE:
+
+ conn = le32_to_cpu(tsqe->word_1);
+
+ if (SAR_TSQE_TAG(stat) == 0x10) {
+#ifdef NOTDEF
+ printk("%s: Connection %d halted.\n",
+ card->name,
+ le32_to_cpu(tsqe->word_1) & 0x1fff);
+#endif
+ break;
+ }
+
+ vc = card->vcs[conn & 0x1fff];
+ if (!vc) {
+ printk("%s: could not find VC from conn %d\n",
+ card->name, conn & 0x1fff);
+ break;
+ }
+
+ printk("%s: Connection %d IDLE.\n",
+ card->name, vc->index);
+
+ set_bit(VCF_IDLE, &vc->flags);
+ break;
+
+ case SAR_TSQE_TYPE_TSR:
+
+ conn = le32_to_cpu(tsqe->word_1);
+
+ vc = card->vcs[conn & 0x1fff];
+ if (!vc) {
+ printk("%s: no VC at index %d\n",
+ card->name,
+ le32_to_cpu(tsqe->word_1) & 0x1fff);
+ break;
+ }
+
+ drain_scq(card, vc);
+ break;
+
+ case SAR_TSQE_TYPE_TBD_COMP:
+
+ conn = le32_to_cpu(tsqe->word_1);
+
+ vpi = (conn >> SAR_TBD_VPI_SHIFT) & 0x00ff;
+ vci = (conn >> SAR_TBD_VCI_SHIFT) & 0xffff;
+
+ if (vpi >= (1 << card->vpibits) ||
+ vci >= (1 << card->vcibits)) {
+ printk("%s: TBD complete: "
+ "out of range VPI.VCI %u.%u\n",
+ card->name, vpi, vci);
+ break;
+ }
+
+ vc = card->vcs[VPCI2VC(card, vpi, vci)];
+ if (!vc) {
+ printk("%s: TBD complete: "
+ "no VC at VPI.VCI %u.%u\n",
+ card->name, vpi, vci);
+ break;
+ }
+
+ drain_scq(card, vc);
+ break;
+ }
+
+ tsqe->word_2 = cpu_to_le32(SAR_TSQE_INVALID);
+
+ card->tsq.next = tsqe;
+ if (card->tsq.next == card->tsq.last)
+ tsqe = card->tsq.base;
+ else
+ tsqe = card->tsq.next + 1;
+
+ TXPRINTK("tsqe: %p: base %p, next %p, last %p\n", tsqe,
+ card->tsq.base, card->tsq.next, card->tsq.last);
+
+ stat = le32_to_cpu(tsqe->word_2);
+
+ } while (!(stat & SAR_TSQE_INVALID));
+
+ writel((unsigned long)card->tsq.next - (unsigned long)card->tsq.base,
+ SAR_REG_TSQH);
+
+ XPRINTK("idt77252_tx-after writel%d: TSQ head = 0x%x, tail = 0x%x, next = 0x%p.\n",
+ card->index, readl(SAR_REG_TSQH),
+ readl(SAR_REG_TSQT), card->tsq.next);


+}
+
+
+static void

+tst_timer(unsigned long data)
+{
+ struct idt77252_dev *card = (struct idt77252_dev *)data;
+ unsigned long base, idle, jump;
+ unsigned long flags;
+ u32 pc;
+ int e;
+
+ spin_lock_irqsave(&card->tst_lock, flags);
+
+ base = card->tst[card->tst_index];
+ idle = card->tst[card->tst_index ^ 1];
+
+ if (test_bit(TST_SWITCH_WAIT, &card->tst_state)) {
+ jump = base + card->tst_size - 2;
+
+ pc = readl(SAR_REG_NOW) >> 2;
+ if ((pc ^ idle) & ~(card->tst_size - 1)) {
+ mod_timer(&card->tst_timer, jiffies + 1);


+ goto out;
+ }
+

+ clear_bit(TST_SWITCH_WAIT, &card->tst_state);
+
+ card->tst_index ^= 1;
+ write_sram(card, jump, TSTE_OPC_JMP | (base << 2));
+
+ base = card->tst[card->tst_index];
+ idle = card->tst[card->tst_index ^ 1];
+
+ for (e = 0; e < card->tst_size - 2; e++) {
+ if (card->soft_tst[e].tste & TSTE_PUSH_IDLE) {
+ write_sram(card, idle + e,
+ card->soft_tst[e].tste & TSTE_MASK);
+ card->soft_tst[e].tste &= ~(TSTE_PUSH_IDLE);
+ }
+ }
+ }
+
+ if (test_and_clear_bit(TST_SWITCH_PENDING, &card->tst_state)) {
+
+ for (e = 0; e < card->tst_size - 2; e++) {
+ if (card->soft_tst[e].tste & TSTE_PUSH_ACTIVE) {
+ write_sram(card, idle + e,
+ card->soft_tst[e].tste & TSTE_MASK);
+ card->soft_tst[e].tste &= ~(TSTE_PUSH_ACTIVE);
+ card->soft_tst[e].tste |= TSTE_PUSH_IDLE;
+ }
+ }
+
+ jump = base + card->tst_size - 2;
+
+ write_sram(card, jump, TSTE_OPC_NULL);
+ set_bit(TST_SWITCH_WAIT, &card->tst_state);
+
+ mod_timer(&card->tst_timer, jiffies + 1);
+ }
+
+out:
+ spin_unlock_irqrestore(&card->tst_lock, flags);
+}
+
+static int
+__fill_tst(struct idt77252_dev *card, struct vc_map *vc,
+ int n, unsigned int opc)
+{
+ unsigned long cl, avail;
+ unsigned long idle;
+ int e, r;
+ u32 data;
+
+ avail = card->tst_size - 2;
+ for (e = 0; e < avail; e++) {
+ if (card->soft_tst[e].vc == NULL)
+ break;
+ }
+ if (e >= avail) {
+ printk("%s: No free TST entries found\n", card->name);
+ return -1;
+ }
+
+ NPRINTK("%s: conn %d: first TST entry at %d.\n",
+ card->name, vc ? vc->index : -1, e);
+
+ r = n;
+ cl = avail;
+ data = opc & TSTE_OPC_MASK;
+ if (vc && (opc != TSTE_OPC_NULL))
+ data = opc | vc->index;
+
+ idle = card->tst[card->tst_index ^ 1];
+
+ /*
+ * Fill Soft TST.
+ */
+ while (r > 0) {
+ if ((cl >= avail) && (card->soft_tst[e].vc == NULL)) {
+ if (vc)
+ card->soft_tst[e].vc = vc;
+ else
+ card->soft_tst[e].vc = (void *)-1;
+
+ card->soft_tst[e].tste = data;
+ if (timer_pending(&card->tst_timer))
+ card->soft_tst[e].tste |= TSTE_PUSH_ACTIVE;
+ else {
+ write_sram(card, idle + e, data);
+ card->soft_tst[e].tste |= TSTE_PUSH_IDLE;
+ }
+
+ cl -= card->tst_size;
+ r--;
+ }
+
+ if (++e == avail)
+ e = 0;
+ cl += n;
+ }
+


+ return 0;
+}
+

+static int
+fill_tst(struct idt77252_dev *card, struct vc_map *vc, int n, unsigned int opc)
+{
+ unsigned long flags;
+ int res;
+
+ spin_lock_irqsave(&card->tst_lock, flags);
+
+ res = __fill_tst(card, vc, n, opc);
+
+ set_bit(TST_SWITCH_PENDING, &card->tst_state);
+ if (!timer_pending(&card->tst_timer))
+ mod_timer(&card->tst_timer, jiffies + 1);
+
+ spin_unlock_irqrestore(&card->tst_lock, flags);
+ return res;
+}
+
+static int
+__clear_tst(struct idt77252_dev *card, struct vc_map *vc)
+{
+ unsigned long idle;
+ int e;
+
+ idle = card->tst[card->tst_index ^ 1];
+
+ for (e = 0; e < card->tst_size - 2; e++) {
+ if (card->soft_tst[e].vc == vc) {
+ card->soft_tst[e].vc = NULL;
+
+ card->soft_tst[e].tste = TSTE_OPC_VAR;
+ if (timer_pending(&card->tst_timer))
+ card->soft_tst[e].tste |= TSTE_PUSH_ACTIVE;
+ else {
+ write_sram(card, idle + e, TSTE_OPC_VAR);
+ card->soft_tst[e].tste |= TSTE_PUSH_IDLE;
+ }
+ }
+ }
+


+ return 0;
+}
+

+static int
+clear_tst(struct idt77252_dev *card, struct vc_map *vc)
+{
+ unsigned long flags;
+ int res;
+
+ spin_lock_irqsave(&card->tst_lock, flags);
+
+ res = __clear_tst(card, vc);
+
+ set_bit(TST_SWITCH_PENDING, &card->tst_state);
+ if (!timer_pending(&card->tst_timer))
+ mod_timer(&card->tst_timer, jiffies + 1);
+
+ spin_unlock_irqrestore(&card->tst_lock, flags);
+ return res;
+}
+
+static int
+change_tst(struct idt77252_dev *card, struct vc_map *vc,
+ int n, unsigned int opc)
+{
+ unsigned long flags;
+ int res;
+
+ spin_lock_irqsave(&card->tst_lock, flags);
+
+ __clear_tst(card, vc);
+ res = __fill_tst(card, vc, n, opc);
+
+ set_bit(TST_SWITCH_PENDING, &card->tst_state);
+ if (!timer_pending(&card->tst_timer))
+ mod_timer(&card->tst_timer, jiffies + 1);
+
+ spin_unlock_irqrestore(&card->tst_lock, flags);
+ return res;


+}
+
+
+static int

+set_tct(struct idt77252_dev *card, struct vc_map *vc)
+{
+ unsigned long tct;
+
+ tct = (unsigned long) (card->tct_base + vc->index * SAR_SRAM_TCT_SIZE);
+
+ switch (vc->class) {
+ case SCHED_CBR:
+ OPRINTK("%s: writing TCT at 0x%lx, SCD 0x%lx.\n",
+ card->name, tct, vc->scq->scd);
+
+ write_sram(card, tct + 0, TCT_CBR | vc->scq->scd);
+ write_sram(card, tct + 1, 0);
+ write_sram(card, tct + 2, 0);
+ write_sram(card, tct + 3, 0);
+ write_sram(card, tct + 4, 0);
+ write_sram(card, tct + 5, 0);
+ write_sram(card, tct + 6, 0);
+ write_sram(card, tct + 7, 0);
+ break;
+
+ case SCHED_UBR:
+ OPRINTK("%s: writing TCT at 0x%lx, SCD 0x%lx.\n",
+ card->name, tct, vc->scq->scd);
+
+ write_sram(card, tct + 0, TCT_UBR | vc->scq->scd);
+ write_sram(card, tct + 1, 0);
+ write_sram(card, tct + 2, TCT_TSIF);
+ write_sram(card, tct + 3, TCT_HALT | TCT_IDLE);
+ write_sram(card, tct + 4, 0);
+ write_sram(card, tct + 5, vc->init_er);
+ write_sram(card, tct + 6, 0);
+ write_sram(card, tct + 7, TCT_FLAG_UBR);
+ break;
+
+ case SCHED_VBR:
+ case SCHED_ABR:
+ default:
+ return -ENOSYS;
+ }
+


+ return 0;
+}
+

+/*****************************************************************************/
+/* */
+/* FBQ Handling */
+/* */
+/*****************************************************************************/
+
+static __inline__ int
+idt77252_fbq_level(struct idt77252_dev *card, int queue)
+{
+ return (readl(SAR_REG_STAT) >> (16 + (queue << 2))) & 0x0f;
+}
+
+static __inline__ int
+idt77252_fbq_full(struct idt77252_dev *card, int queue)
+{
+ return (readl(SAR_REG_STAT) >> (16 + (queue << 2))) == 0x0f;
+}
+
+static int
+push_rx_skb(struct idt77252_dev *card, struct sk_buff *skb, int queue)
+{
+ unsigned long flags;
+ u32 handle;
+ u32 addr;
+
+ skb->data = skb->tail = skb->head;
+ skb->len = 0;
+
+ skb_reserve(skb, 16);
+
+ switch (queue) {
+ case 0:
+ skb_put(skb, SAR_FB_SIZE_0);
+ break;
+ case 1:
+ skb_put(skb, SAR_FB_SIZE_1);


+ break;
+ case 2:

+ skb_put(skb, SAR_FB_SIZE_2);
+ break;
+ case 3:
+ skb_put(skb, SAR_FB_SIZE_3);
+ break;
+ default:
+ dev_kfree_skb(skb);


+ return -1;
+ }
+

+ if (idt77252_fbq_full(card, queue))
+ return -1;
+
+ memset(&skb->data[(skb->len & ~(0x3f)) - 64], 0, 2 * sizeof(u32));
+
+ handle = IDT77252_PRV_POOL(skb);
+ addr = IDT77252_PRV_PADDR(skb);
+
+ spin_lock_irqsave(&card->cmd_lock, flags);
+ writel(handle, card->fbq[queue]);
+ writel(addr, card->fbq[queue]);
+ spin_unlock_irqrestore(&card->cmd_lock, flags);
+


+ return 0;
+}
+
+static void

+add_rx_skb(struct idt77252_dev *card, int queue,
+ unsigned int size, unsigned int count)
+{
+ struct sk_buff *skb;
+ dma_addr_t paddr;
+ u32 handle;
+
+ while (count--) {
+ skb = dev_alloc_skb(size);
+ if (!skb)
+ return;
+
+ if (sb_pool_add(card, skb, queue)) {
+ printk("%s: SB POOL full\n", __FUNCTION__);
+ goto outfree;
+ }
+
+ paddr = pci_map_single(card->pcidev, skb->data,
+ skb->end - skb->data,
+ PCI_DMA_FROMDEVICE);
+ IDT77252_PRV_PADDR(skb) = paddr;
+
+ if (push_rx_skb(card, skb, queue)) {
+ printk("%s: FB QUEUE full\n", __FUNCTION__);
+ goto outunmap;
+ }
+ }
+
+ return;
+
+outunmap:
+ pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb),
+ skb->end - skb->data, PCI_DMA_FROMDEVICE);
+
+ handle = IDT77252_PRV_POOL(skb);
+ card->sbpool[POOL_QUEUE(handle)].skb[POOL_INDEX(handle)] = NULL;
+
+outfree:
+ dev_kfree_skb(skb);


+}
+
+
+static void

+recycle_rx_skb(struct idt77252_dev *card, struct sk_buff *skb)
+{
+ u32 handle = IDT77252_PRV_POOL(skb);
+ int err;
+
+ err = push_rx_skb(card, skb, POOL_QUEUE(handle));
+ if (err) {
+ pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb),
+ skb->end - skb->data, PCI_DMA_FROMDEVICE);
+ sb_pool_remove(card, skb);
+ dev_kfree_skb(skb);


+ }
+}
+
+static void

+flush_rx_pool(struct idt77252_dev *card, struct rx_pool *rpp)
+{
+ rpp->len = 0;
+ rpp->count = 0;
+ rpp->first = NULL;
+ rpp->last = &rpp->first;
+}
+
+static void
+recycle_rx_pool_skb(struct idt77252_dev *card, struct rx_pool *rpp)
+{
+ struct sk_buff *skb, *next;
+ int i;
+
+ skb = rpp->first;
+ for (i = 0; i < rpp->count; i++) {
+ next = skb->next;
+ skb->next = NULL;
+ recycle_rx_skb(card, skb);
+ skb = next;
+ }
+ flush_rx_pool(card, rpp);


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

+/* ATM Interface */
+/* */
+/*****************************************************************************/
+
+static void
+idt77252_phy_put(struct atm_dev *dev, unsigned char value, unsigned long addr)
+{
+ write_utility(dev->dev_data, 0x100 + (addr & 0x1ff), value);


+}
+
+static unsigned char

+idt77252_phy_get(struct atm_dev *dev, unsigned long addr)
+{
+ return read_utility(dev->dev_data, 0x100 + (addr & 0x1ff));
+}
+
+static int
+idt77252_send_skb(struct atm_vcc *vcc, struct sk_buff *skb, int oam)
+{
+ struct atm_dev *dev = vcc->dev;


+ struct idt77252_dev *card = dev->dev_data;

+ struct vc_map *vc = vcc->dev_data;
+ int err;
+
+ if (vc == NULL) {
+ printk("%s: NULL connection in send().\n", card->name);
+ atomic_inc(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+ if (!test_bit(VCF_TX, &vc->flags)) {
+ printk("%s: Trying to transmit on a non-tx VC.\n", card->name);
+ atomic_inc(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);


+ return -EINVAL;
+ }
+

+ switch (vcc->qos.aal) {
+ case ATM_AAL0:
+ case ATM_AAL1:
+ case ATM_AAL5:
+ break;
+ default:
+ printk("%s: Unsupported AAL: %d\n", card->name, vcc->qos.aal);
+ atomic_inc(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);


+ return -EINVAL;
+ }
+

+ if (ATM_SKB(skb)->iovcnt != 0) {
+ printk("%s: No scatter-gather yet.\n", card->name);
+ atomic_inc(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+ ATM_SKB(skb)->vcc = vcc;
+
+ err = queue_skb(card, vc, skb, oam);
+ if (err) {
+ atomic_inc(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);


+ return err;
+ }
+

+ return 0;
+}
+

+int
+idt77252_send(struct atm_vcc *vcc, struct sk_buff *skb)
+{
+ return idt77252_send_skb(vcc, skb, 0);
+}
+
+static int
+idt77252_send_oam(struct atm_vcc *vcc, void *cell, int flags)
+{
+ struct atm_dev *dev = vcc->dev;


+ struct idt77252_dev *card = dev->dev_data;

+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(64);
+ if (!skb) {
+ printk("%s: Out of memory in send_oam().\n", card->name);
+ atomic_inc(&vcc->stats->tx_err);
+ return -ENOMEM;
+ }
+ atomic_add(skb->truesize + ATM_PDU_OVHD, &vcc->tx_inuse);
+ ATM_SKB(skb)->iovcnt = 0;
+
+ memcpy(skb_put(skb, 52), cell, 52);
+
+ return idt77252_send_skb(vcc, skb, 1);
+}
+
+static __inline__ unsigned int
+idt77252_fls(unsigned int x)
+{
+ int r = 1;
+
+ if (x == 0)
+ return 0;
+ if (x & 0xffff0000) {
+ x >>= 16;
+ r += 16;
+ }
+ if (x & 0xff00) {
+ x >>= 8;
+ r += 8;
+ }
+ if (x & 0xf0) {
+ x >>= 4;
+ r += 4;
+ }
+ if (x & 0xc) {
+ x >>= 2;
+ r += 2;
+ }
+ if (x & 0x2)
+ r += 1;
+ return r;
+}
+
+static u16
+idt77252_int_to_atmfp(unsigned int rate)
+{
+ u16 m, e;
+
+ if (rate == 0)
+ return 0;
+ e = idt77252_fls(rate) - 1;
+ if (e < 9)
+ m = (rate - (1 << e)) << (9 - e);
+ else if (e == 9)
+ m = (rate - (1 << e));
+ else /* e > 9 */
+ m = (rate - (1 << e)) >> (e - 9);
+ return 0x4000 | (e << 9) | m;
+}
+
+static u8
+idt77252_rate_logindex(struct idt77252_dev *card, int pcr)
+{
+ u16 afp;
+
+ afp = idt77252_int_to_atmfp(pcr < 0 ? -pcr : pcr);
+ if (pcr < 0)
+ return rate_to_log[(afp >> 5) & 0x1ff];
+ return rate_to_log[((afp >> 5) + 1) & 0x1ff];
+}
+
+static void
+idt77252_est_timer(unsigned long data)
+{
+ struct vc_map *vc = (struct vc_map *)data;
+ struct idt77252_dev *card = vc->card;
+ struct rate_estimator *est;
+ unsigned long flags;
+ u32 rate, cps;
+ u64 ncells;
+ u8 lacr;
+
+ spin_lock_irqsave(&vc->lock, flags);
+ est = vc->estimator;
+ if (!est)
+ goto out;
+
+ ncells = est->cells;
+
+ rate = ((u32)(ncells - est->last_cells)) << (7 - est->interval);
+ est->last_cells = ncells;
+ est->avcps += ((long)rate - (long)est->avcps) >> est->ewma_log;
+ est->cps = (est->avcps + 0x1f) >> 5;
+
+ cps = est->cps;
+ if (cps < (est->maxcps >> 4))
+ cps = est->maxcps >> 4;
+
+ lacr = idt77252_rate_logindex(card, cps);
+ if (lacr > vc->max_er)
+ lacr = vc->max_er;
+
+ if (lacr != vc->lacr) {
+ vc->lacr = lacr;
+ writel(TCMDQ_LACR|(vc->lacr << 16)|vc->index, SAR_REG_TCMDQ);
+ }
+
+ est->timer.expires = jiffies + ((HZ / 4) << est->interval);
+ add_timer(&est->timer);
+
+out:
+ spin_unlock_irqrestore(&vc->lock, flags);
+}
+
+static struct rate_estimator *
+idt77252_init_est(struct vc_map *vc, int pcr)
+{
+ struct rate_estimator *est;
+
+ est = kmalloc(sizeof(struct rate_estimator), GFP_KERNEL);
+ if (!est)
+ return NULL;
+ memset(est, 0, sizeof(*est));
+
+ est->maxcps = pcr < 0 ? -pcr : pcr;
+ est->cps = est->maxcps;
+ est->avcps = est->cps << 5;
+
+ est->interval = 2; /* XXX: make this configurable */
+ est->ewma_log = 2; /* XXX: make this configurable */
+ est->timer.data = (unsigned long)vc;
+ est->timer.function = idt77252_est_timer;
+ init_timer(&est->timer);
+
+ est->timer.expires = jiffies + ((HZ / 4) << est->interval);
+ add_timer(&est->timer);
+
+ return est;
+}
+
+static int
+idt77252_init_cbr(struct idt77252_dev *card, struct vc_map *vc,
+ struct atm_vcc *vcc, struct atm_qos *qos)
+{
+ int tst_free, tst_used, tst_entries;


+ unsigned long tmpl, modl;

+ int tcr, tcra;
+
+ if ((qos->txtp.max_pcr == 0) &&
+ (qos->txtp.pcr == 0) && (qos->txtp.min_pcr == 0)) {
+ printk("%s: trying to open a CBR VC with cell rate = 0\n",
+ card->name);


+ return -EINVAL;
+ }
+

+ tst_used = 0;
+ tst_free = card->tst_free;
+ if (test_bit(VCF_TX, &vc->flags))
+ tst_used = vc->ntste;
+ tst_free += tst_used;
+
+ tcr = atm_pcr_goal(&qos->txtp);
+ tcra = tcr >= 0 ? tcr : -tcr;
+
+ TXPRINTK("%s: CBR target cell rate = %d\n", card->name, tcra);
+
+ tmpl = (unsigned long) tcra * ((unsigned long) card->tst_size - 2);


+ modl = tmpl % (unsigned long)card->utopia_pcr;
+

+ tst_entries = (int) (tmpl / card->utopia_pcr);
+ if (tcr > 0) {
+ if (modl > 0)
+ tst_entries++;
+ } else if (tcr == 0) {
+ tst_entries = tst_free - SAR_TST_RESERVED;
+ if (tst_entries <= 0) {
+ printk("%s: no CBR bandwidth free.\n", card->name);
+ return -ENOSR;
+ }
+ }
+
+ if (tst_entries == 0) {
+ printk("%s: selected CBR bandwidth < granularity.\n",
+ card->name);


+ return -EINVAL;
+ }
+

+ if (tst_entries > (tst_free - SAR_TST_RESERVED)) {
+ printk("%s: not enough CBR bandwidth free.\n", card->name);
+ return -ENOSR;
+ }
+
+ vc->ntste = tst_entries;
+
+ card->tst_free = tst_free - tst_entries;
+ if (test_bit(VCF_TX, &vc->flags)) {
+ if (tst_used == tst_entries)
+ return 0;
+
+ OPRINTK("%s: modify %d -> %d entries in TST.\n",
+ card->name, tst_used, tst_entries);
+ change_tst(card, vc, tst_entries, TSTE_OPC_CBR);


+ return 0;
+ }
+

+ OPRINTK("%s: setting %d entries in TST.\n", card->name, tst_entries);
+ fill_tst(card, vc, tst_entries, TSTE_OPC_CBR);


+ return 0;
+}
+

+static int
+idt77252_init_ubr(struct idt77252_dev *card, struct vc_map *vc,
+ struct atm_vcc *vcc, struct atm_qos *qos)
+{
+ unsigned long flags;
+ int tcr;
+
+ spin_lock_irqsave(&vc->lock, flags);
+ if (vc->estimator) {
+ del_timer(&vc->estimator->timer);
+ kfree(vc->estimator);
+ vc->estimator = NULL;
+ }
+ spin_unlock_irqrestore(&vc->lock, flags);
+
+ tcr = atm_pcr_goal(&qos->txtp);
+ if (tcr == 0)
+ tcr = card->link_pcr;
+
+ vc->estimator = idt77252_init_est(vc, tcr);
+
+ vc->class = SCHED_UBR;
+ vc->init_er = idt77252_rate_logindex(card, tcr);
+ vc->lacr = vc->init_er;
+ if (tcr < 0)
+ vc->max_er = vc->init_er;
+ else
+ vc->max_er = 0xff;
+


+ return 0;
+}
+

+static int
+idt77252_init_tx(struct idt77252_dev *card, struct vc_map *vc,
+ struct atm_vcc *vcc, struct atm_qos *qos)
+{
+ int error;
+
+ if (test_bit(VCF_TX, &vc->flags))
+ return -EBUSY;
+
+ switch (qos->txtp.traffic_class) {
+ case ATM_CBR:
+ vc->class = SCHED_CBR;
+ break;
+
+ case ATM_UBR:
+ vc->class = SCHED_UBR;
+ break;
+
+ case ATM_VBR:
+ case ATM_ABR:
+ default:
+ return -EPROTONOSUPPORT;
+ }
+
+ vc->scq = alloc_scq(card, vc->class);
+ if (!vc->scq) {
+ printk("%s: can't get SCQ.\n", card->name);
+ return -ENOMEM;
+ }
+
+ vc->scq->scd = get_free_scd(card, vc);
+ if (vc->scq->scd == 0) {
+ printk("%s: no SCD available.\n", card->name);
+ free_scq(card, vc->scq);


+ return -ENOMEM;
+ }
+

+ fill_scd(card, vc->scq, vc->class);
+
+ if (set_tct(card, vc)) {
+ printk("%s: class %d not supported.\n",
+ card->name, qos->txtp.traffic_class);
+
+ card->scd2vc[vc->scd_index] = NULL;
+ free_scq(card, vc->scq);
+ return -EPROTONOSUPPORT;
+ }
+
+ switch (vc->class) {
+ case SCHED_CBR:
+ error = idt77252_init_cbr(card, vc, vcc, qos);
+ if (error) {
+ card->scd2vc[vc->scd_index] = NULL;
+ free_scq(card, vc->scq);
+ return error;
+ }
+
+ clear_bit(VCF_IDLE, &vc->flags);
+ writel(TCMDQ_START | vc->index, SAR_REG_TCMDQ);
+ break;
+
+ case SCHED_UBR:
+ error = idt77252_init_ubr(card, vc, vcc, qos);
+ if (error) {
+ card->scd2vc[vc->scd_index] = NULL;
+ free_scq(card, vc->scq);
+ return error;
+ }
+
+ set_bit(VCF_IDLE, &vc->flags);
+ break;
+ }
+
+ vc->tx_vcc = vcc;
+ set_bit(VCF_TX, &vc->flags);


+ return 0;
+}
+

+static int
+idt77252_init_rx(struct idt77252_dev *card, struct vc_map *vc,
+ struct atm_vcc *vcc, struct atm_qos *qos)
+{
+ unsigned long flags;
+ unsigned long addr;
+ u32 rcte = 0;
+
+ if (test_bit(VCF_RX, &vc->flags))
+ return -EBUSY;
+
+ vc->rx_vcc = vcc;
+ set_bit(VCF_RX, &vc->flags);
+
+ if ((vcc->vci == 3) || (vcc->vci == 4))
+ return 0;
+
+ flush_rx_pool(card, &vc->rcv.rx_pool);
+
+ rcte |= SAR_RCTE_CONNECTOPEN;
+ rcte |= SAR_RCTE_RAWCELLINTEN;
+
+ switch (qos->aal) {
+ case ATM_AAL0:
+ rcte |= SAR_RCTE_RCQ;
+ break;
+ case ATM_AAL1:
+ rcte |= SAR_RCTE_OAM; /* Let SAR drop Video */
+ break;
+ case ATM_AAL34:
+ rcte |= SAR_RCTE_AAL34;
+ break;
+ case ATM_AAL5:
+ rcte |= SAR_RCTE_AAL5;
+ break;
+ default:
+ rcte |= SAR_RCTE_RCQ;
+ break;
+ }
+
+ if (qos->aal != ATM_AAL5)
+ rcte |= SAR_RCTE_FBP_1;
+ else if (qos->rxtp.max_sdu > SAR_FB_SIZE_2)
+ rcte |= SAR_RCTE_FBP_3;
+ else if (qos->rxtp.max_sdu > SAR_FB_SIZE_1)
+ rcte |= SAR_RCTE_FBP_2;
+ else if (qos->rxtp.max_sdu > SAR_FB_SIZE_0)
+ rcte |= SAR_RCTE_FBP_1;
+ else
+ rcte |= SAR_RCTE_FBP_01;
+
+ addr = card->rct_base + (vc->index << 2);
+
+ OPRINTK("%s: writing RCT at 0x%lx\n", card->name, addr);
+ write_sram(card, addr, rcte);
+
+ spin_lock_irqsave(&card->cmd_lock, flags);
+ writel(SAR_CMD_OPEN_CONNECTION | (addr << 2), SAR_REG_CMD);
+ waitfor_idle(card);
+ spin_unlock_irqrestore(&card->cmd_lock, flags);
+


+ return 0;
+}
+

+static int
+idt77252_find_vcc(struct atm_vcc *vcc, short *vpi, int *vci)
+{
+ struct atm_vcc *walk;
+
+ if (*vpi == ATM_VPI_ANY) {
+ *vpi = 0;
+ walk = vcc->dev->vccs;
+ while (walk) {
+ if ((walk->vci == *vci) && (walk->vpi == *vpi)) {
+ (*vpi)++;
+ walk = vcc->dev->vccs;
+ continue;
+ }
+ walk = walk->next;
+ }
+ }
+
+ if (*vci == ATM_VCI_ANY) {
+ *vci = ATM_NOT_RSV_VCI;
+ walk = vcc->dev->vccs;
+ while (walk) {
+ if ((walk->vci == *vci) && (walk->vpi == *vpi)) {
+ (*vci)++;
+ walk = vcc->dev->vccs;
+ continue;
+ }
+ walk = walk->next;
+ }
+ }
+


+ return 0;
+}
+

+static int
+idt77252_open(struct atm_vcc *vcc, short vpi, int vci)
+{
+ struct atm_dev *dev = vcc->dev;


+ struct idt77252_dev *card = dev->dev_data;

+ struct vc_map *vc;
+ unsigned int index;
+ unsigned int inuse;
+ int error;
+
+ idt77252_find_vcc(vcc, &vpi, &vci);
+
+ if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
+ return 0;
+
+ if (vpi >= (1 << card->vpibits)) {
+ printk("%s: unsupported VPI: %d\n", card->name, vpi);


+ return -EINVAL;
+ }
+

+ if (vci >= (1 << card->vcibits)) {
+ printk("%s: unsupported VCI: %d\n", card->name, vci);


+ return -EINVAL;
+ }
+

+ vcc->vpi = vpi;
+ vcc->vci = vci;
+ set_bit(ATM_VF_ADDR, &vcc->flags);
+
+ down(&card->mutex);
+
+ OPRINTK("%s: opening vpi.vci: %d.%d\n", card->name, vpi, vci);
+
+ switch (vcc->qos.aal) {
+ case ATM_AAL0:
+ case ATM_AAL1:
+ case ATM_AAL5:
+ break;
+ default:
+ printk("%s: Unsupported AAL: %d\n", card->name, vcc->qos.aal);
+ up(&card->mutex);
+ return -EPROTONOSUPPORT;
+ }
+
+ index = VPCI2VC(card, vpi, vci);
+ if (!card->vcs[index]) {
+ card->vcs[index] = kmalloc(sizeof(struct vc_map), GFP_KERNEL);
+ if (!card->vcs[index]) {
+ printk("%s: can't alloc vc in open()\n", card->name);
+ up(&card->mutex);
+ return -ENOMEM;
+ }
+ memset(card->vcs[index], 0, sizeof(struct vc_map));
+
+ card->vcs[index]->card = card;
+ card->vcs[index]->index = index;
+
+ spin_lock_init(&card->vcs[index]->lock);
+ }
+ vc = card->vcs[index];
+
+ vcc->dev_data = vc;
+
+ IPRINTK("%s: idt77252_open: vc = %d (%d.%d) %s/%s (max RX SDU: %u)\n",
+ card->name, vc->index, vcc->vpi, vcc->vci,
+ vcc->qos.rxtp.traffic_class != ATM_NONE ? "rx" : "--",
+ vcc->qos.txtp.traffic_class != ATM_NONE ? "tx" : "--",
+ vcc->qos.rxtp.max_sdu);
+
+ inuse = 0;
+ if (vcc->qos.txtp.traffic_class != ATM_NONE &&
+ test_bit(VCF_TX, &vc->flags))
+ inuse = 1;
+ if (vcc->qos.rxtp.traffic_class != ATM_NONE &&
+ test_bit(VCF_RX, &vc->flags))
+ inuse += 2;
+
+ if (inuse) {
+ printk("%s: %s vci already in use.\n", card->name,
+ inuse == 1 ? "tx" : inuse == 2 ? "rx" : "tx and rx");
+ up(&card->mutex);
+ return -EADDRINUSE;
+ }
+
+ if (vcc->qos.txtp.traffic_class != ATM_NONE) {
+ error = idt77252_init_tx(card, vc, vcc, &vcc->qos);
+ if (error) {
+ up(&card->mutex);
+ return error;
+ }
+ }
+
+ if (vcc->qos.rxtp.traffic_class != ATM_NONE) {
+ error = idt77252_init_rx(card, vc, vcc, &vcc->qos);
+ if (error) {
+ up(&card->mutex);
+ return error;
+ }
+ }
+
+ set_bit(ATM_VF_READY, &vcc->flags);
+ MOD_INC_USE_COUNT;
+
+ up(&card->mutex);


+ return 0;
+}
+
+static void

+idt77252_close(struct atm_vcc *vcc)
+{
+ struct atm_dev *dev = vcc->dev;


+ struct idt77252_dev *card = dev->dev_data;

+ struct vc_map *vc = vcc->dev_data;
+ unsigned long flags;
+ unsigned long addr;
+ int timeout;
+
+ down(&card->mutex);
+
+ IPRINTK("%s: idt77252_close: vc = %d (%d.%d)\n",
+ card->name, vc->index, vcc->vpi, vcc->vci);
+
+ clear_bit(ATM_VF_READY, &vcc->flags);
+
+ if (vcc->qos.rxtp.traffic_class != ATM_NONE) {
+
+ spin_lock_irqsave(&vc->lock, flags);
+ clear_bit(VCF_RX, &vc->flags);
+ vc->rx_vcc = NULL;
+ spin_unlock_irqrestore(&vc->lock, flags);
+
+ if ((vcc->vci == 3) || (vcc->vci == 4))
+ goto done;
+
+ addr = card->rct_base + vc->index * SAR_SRAM_RCT_SIZE;
+
+ spin_lock_irqsave(&card->cmd_lock, flags);
+ writel(SAR_CMD_CLOSE_CONNECTION | (addr << 2), SAR_REG_CMD);
+ waitfor_idle(card);
+ spin_unlock_irqrestore(&card->cmd_lock, flags);
+
+ if (vc->rcv.rx_pool.count) {
+ DPRINTK("%s: closing a VC with pending rx buffers.\n",
+ card->name);
+
+ recycle_rx_pool_skb(card, &vc->rcv.rx_pool);
+ }
+ }
+
+done:
+ if (vcc->qos.txtp.traffic_class != ATM_NONE) {
+
+ spin_lock_irqsave(&vc->lock, flags);
+ clear_bit(VCF_TX, &vc->flags);
+ clear_bit(VCF_IDLE, &vc->flags);
+ clear_bit(VCF_RSV, &vc->flags);
+ vc->tx_vcc = NULL;
+
+ if (vc->estimator) {
+ del_timer(&vc->estimator->timer);
+ kfree(vc->estimator);
+ vc->estimator = NULL;
+ }
+ spin_unlock_irqrestore(&vc->lock, flags);
+
+ timeout = 5 * HZ;
+ while (atomic_read(&vc->scq->used) > 0) {
+ timeout = schedule_timeout(timeout);
+ if (!timeout)
+ break;
+ }
+ if (!timeout)
+ printk("%s: SCQ drain timeout: %u used\n",
+ card->name, atomic_read(&vc->scq->used));
+
+ writel(TCMDQ_HALT | vc->index, SAR_REG_TCMDQ);
+ clear_scd(card, vc->scq, vc->class);
+
+ if (vc->class == SCHED_CBR) {
+ clear_tst(card, vc);
+ card->tst_free += vc->ntste;
+ vc->ntste = 0;
+ }
+
+ card->scd2vc[vc->scd_index] = NULL;
+ free_scq(card, vc->scq);
+ }
+
+ MOD_DEC_USE_COUNT;
+ up(&card->mutex);
+}
+
+static int
+idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags)
+{
+ struct atm_dev *dev = vcc->dev;


+ struct idt77252_dev *card = dev->dev_data;

+ struct vc_map *vc = vcc->dev_data;
+ int error = 0;
+
+ down(&card->mutex);
+
+ if (qos->txtp.traffic_class != ATM_NONE) {
+ if (!test_bit(VCF_TX, &vc->flags)) {
+ error = idt77252_init_tx(card, vc, vcc, qos);
+ if (error)
+ goto out;
+ } else {
+ switch (qos->txtp.traffic_class) {
+ case ATM_CBR:
+ error = idt77252_init_cbr(card, vc, vcc, qos);
+ if (error)
+ goto out;
+ break;
+
+ case ATM_UBR:
+ error = idt77252_init_ubr(card, vc, vcc, qos);
+ if (error)
+ goto out;
+
+ if (!test_bit(VCF_IDLE, &vc->flags)) {
+ writel(TCMDQ_LACR | (vc->lacr << 16) |
+ vc->index, SAR_REG_TCMDQ);
+ }
+ break;
+
+ case ATM_VBR:
+ case ATM_ABR:
+ error = -EOPNOTSUPP;


+ goto out;
+ }
+ }
+ }

+
+ if ((qos->rxtp.traffic_class != ATM_NONE) &&
+ !test_bit(VCF_RX, &vc->flags)) {
+ error = idt77252_init_rx(card, vc, vcc, qos);
+ if (error)
+ goto out;
+ }
+
+ memcpy(&vcc->qos, qos, sizeof(struct atm_qos));
+
+ set_bit(ATM_VF_HASQOS, &vcc->flags);
+
+out:
+ up(&card->mutex);
+ return error;
+}
+
+static int
+idt77252_proc_read(struct atm_dev *dev, loff_t * pos, char *page)


+{
+ struct idt77252_dev *card = dev->dev_data;

+ int i, left;
+
+ left = (int) *pos;
+ if (!left--)
+ return sprintf(page, "IDT77252 Interrupts:\n");
+ if (!left--)
+ return sprintf(page, "TSIF: %lu\n", card->irqstat[15]);
+ if (!left--)
+ return sprintf(page, "TXICP: %lu\n", card->irqstat[14]);
+ if (!left--)
+ return sprintf(page, "TSQF: %lu\n", card->irqstat[12]);
+ if (!left--)
+ return sprintf(page, "TMROF: %lu\n", card->irqstat[11]);
+ if (!left--)
+ return sprintf(page, "PHYI: %lu\n", card->irqstat[10]);
+ if (!left--)
+ return sprintf(page, "FBQ3A: %lu\n", card->irqstat[8]);
+ if (!left--)
+ return sprintf(page, "FBQ2A: %lu\n", card->irqstat[7]);
+ if (!left--)
+ return sprintf(page, "RSQF: %lu\n", card->irqstat[6]);
+ if (!left--)
+ return sprintf(page, "EPDU: %lu\n", card->irqstat[5]);
+ if (!left--)
+ return sprintf(page, "RAWCF: %lu\n", card->irqstat[4]);
+ if (!left--)
+ return sprintf(page, "FBQ1A: %lu\n", card->irqstat[3]);
+ if (!left--)
+ return sprintf(page, "FBQ0A: %lu\n", card->irqstat[2]);
+ if (!left--)
+ return sprintf(page, "RSQAF: %lu\n", card->irqstat[1]);
+ if (!left--)
+ return sprintf(page, "IDT77252 Transmit Connection Table:\n");
+
+ for (i = 0; i < card->tct_size; i++) {
+ unsigned long tct;
+ struct atm_vcc *vcc;
+ struct vc_map *vc;
+ char *p;
+
+ vc = card->vcs[i];
+ if (!vc)
+ continue;
+
+ vcc = NULL;
+ if (vc->tx_vcc)
+ vcc = vc->tx_vcc;
+ if (!vcc)
+ continue;
+ if (left--)
+ continue;
+
+ p = page;
+ p += sprintf(p, " %4u: %u.%u: ", i, vcc->vpi, vcc->vci);
+ tct = (unsigned long) (card->tct_base + i * SAR_SRAM_TCT_SIZE);
+
+ for (i = 0; i < 8; i++)
+ p += sprintf(p, " %08x", read_sram(card, tct + i));
+ p += sprintf(p, "\n");
+ return p - page;
+ }


+ return 0;
+}
+

+/*****************************************************************************/
+/* */
+/* Interrupt handler */
+/* */
+/*****************************************************************************/
+
+static void
+idt77252_collect_stat(struct idt77252_dev *card)
+{
+ u32 cdc, vpec, icc;
+
+ cdc = readl(SAR_REG_CDC);
+ vpec = readl(SAR_REG_VPEC);
+ icc = readl(SAR_REG_ICC);
+
+#ifdef NOTDEF
+ printk("%s:", card->name);
+
+ if (cdc & 0x7f0000) {
+ char *s = "";
+
+ printk(" [");
+ if (cdc & (1 << 22)) {
+ printk("%sRM ID", s);
+ s = " | ";
+ }
+ if (cdc & (1 << 21)) {
+ printk("%sCON TAB", s);
+ s = " | ";
+ }
+ if (cdc & (1 << 20)) {
+ printk("%sNO FB", s);
+ s = " | ";
+ }
+ if (cdc & (1 << 19)) {
+ printk("%sOAM CRC", s);
+ s = " | ";
+ }
+ if (cdc & (1 << 18)) {
+ printk("%sRM CRC", s);
+ s = " | ";
+ }
+ if (cdc & (1 << 17)) {
+ printk("%sRM FIFO", s);
+ s = " | ";
+ }
+ if (cdc & (1 << 16)) {
+ printk("%sRX FIFO", s);
+ s = " | ";
+ }
+ printk("]");
+ }
+
+ printk(" CDC %04x, VPEC %04x, ICC: %04x\n",
+ cdc & 0xffff, vpec & 0xffff, icc & 0xffff);
+#endif
+}
+
+static void
+idt77252_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
+{
+ struct idt77252_dev *card = dev_id;
+ u32 stat;
+
+ stat = readl(SAR_REG_STAT) & 0xffff;
+ if (!stat) /* no interrupt for us */
+ return;
+
+ if (test_and_set_bit(IDT77252_BIT_INTERRUPT, &card->flags)) {
+ printk("%s: Re-entering irq_handler()\n", card->name);


+ goto out;
+ }
+

+ writel(stat, SAR_REG_STAT); /* reset interrupt */
+
+ if (stat & SAR_STAT_TSIF) { /* entry written to TSQ */
+ INTPRINTK("%s: TSIF\n", card->name);
+ card->irqstat[15]++;
+ idt77252_tx(card);
+ }
+ if (stat & SAR_STAT_TXICP) { /* Incomplete CS-PDU has */
+ INTPRINTK("%s: TXICP\n", card->name);
+ card->irqstat[14]++;
+#ifdef CONFIG_ATM_IDT77252_DEBUG
+ idt77252_tx_dump(card);
+#endif
+ }
+ if (stat & SAR_STAT_TSQF) { /* TSQ 7/8 full */
+ INTPRINTK("%s: TSQF\n", card->name);
+ card->irqstat[12]++;
+ idt77252_tx(card);
+ }
+ if (stat & SAR_STAT_TMROF) { /* Timer overflow */
+ INTPRINTK("%s: TMROF\n", card->name);
+ card->irqstat[11]++;
+ idt77252_collect_stat(card);
+ }
+
+ if (stat & SAR_STAT_EPDU) { /* Got complete CS-PDU */
+ INTPRINTK("%s: EPDU\n", card->name);
+ card->irqstat[5]++;
+ idt77252_rx(card);
+ }
+ if (stat & SAR_STAT_RSQAF) { /* RSQ is 7/8 full */
+ INTPRINTK("%s: RSQAF\n", card->name);
+ card->irqstat[1]++;
+ idt77252_rx(card);
+ }
+ if (stat & SAR_STAT_RSQF) { /* RSQ is full */
+ INTPRINTK("%s: RSQF\n", card->name);
+ card->irqstat[6]++;
+ idt77252_rx(card);
+ }
+ if (stat & SAR_STAT_RAWCF) { /* Raw cell received */
+ INTPRINTK("%s: RAWCF\n", card->name);
+ card->irqstat[4]++;
+ idt77252_rx_raw(card);
+ }
+
+ if (stat & SAR_STAT_PHYI) { /* PHY device interrupt */
+ INTPRINTK("%s: PHYI", card->name);
+ card->irqstat[10]++;
+ if (card->atmdev->phy && card->atmdev->phy->interrupt)
+ card->atmdev->phy->interrupt(card->atmdev);
+ }
+
+ if (stat & (SAR_STAT_FBQ0A | SAR_STAT_FBQ1A |
+ SAR_STAT_FBQ2A | SAR_STAT_FBQ3A)) {
+
+ writel(readl(SAR_REG_CFG) & ~(SAR_CFG_FBIE), SAR_REG_CFG);
+
+ INTPRINTK("%s: FBQA: %04x\n", card->name, stat);
+
+ if (stat & SAR_STAT_FBQ0A)
+ card->irqstat[2]++;
+ if (stat & SAR_STAT_FBQ1A)
+ card->irqstat[3]++;
+ if (stat & SAR_STAT_FBQ2A)
+ card->irqstat[7]++;
+ if (stat & SAR_STAT_FBQ3A)
+ card->irqstat[8]++;
+
+ queue_task(&card->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+ }
+
+out:
+ clear_bit(IDT77252_BIT_INTERRUPT, &card->flags);
+}
+
+static void
+idt77252_softint(void *dev_id)
+{
+ struct idt77252_dev *card = dev_id;
+ u32 stat;
+ int done;
+
+ for (done = 1; ; done = 1) {
+ stat = readl(SAR_REG_STAT) >> 16;
+
+ if ((stat & 0x0f) < SAR_FBQ0_HIGH) {
+ add_rx_skb(card, 0, SAR_FB_SIZE_0, 32);
+ done = 0;
+ }
+
+ stat >>= 4;
+ if ((stat & 0x0f) < SAR_FBQ1_HIGH) {
+ add_rx_skb(card, 1, SAR_FB_SIZE_1, 32);
+ done = 0;
+ }
+
+ stat >>= 4;
+ if ((stat & 0x0f) < SAR_FBQ2_HIGH) {
+ add_rx_skb(card, 2, SAR_FB_SIZE_2, 32);
+ done = 0;
+ }
+
+ stat >>= 4;
+ if ((stat & 0x0f) < SAR_FBQ3_HIGH) {
+ add_rx_skb(card, 3, SAR_FB_SIZE_3, 32);
+ done = 0;
+ }
+
+ if (done)
+ break;
+ }
+
+ writel(readl(SAR_REG_CFG) | SAR_CFG_FBIE, SAR_REG_CFG);


+}
+
+
+static int

+open_card_oam(struct idt77252_dev *card)
+{
+ unsigned long flags;
+ unsigned long addr;
+ struct vc_map *vc;
+ int vpi, vci;
+ int index;
+ u32 rcte;
+
+ for (vpi = 0; vpi < (1 << card->vpibits); vpi++) {
+ for (vci = 3; vci < 5; vci++) {
+ index = VPCI2VC(card, vpi, vci);
+
+ vc = kmalloc(sizeof(struct vc_map), GFP_KERNEL);
+ if (!vc) {
+ printk("%s: can't alloc vc\n", card->name);
+ return -ENOMEM;
+ }
+ memset(vc, 0, sizeof(struct vc_map));
+
+ vc->index = index;
+ card->vcs[index] = vc;
+
+ flush_rx_pool(card, &vc->rcv.rx_pool);
+
+ rcte = SAR_RCTE_CONNECTOPEN |
+ SAR_RCTE_RAWCELLINTEN |
+ SAR_RCTE_RCQ |
+ SAR_RCTE_FBP_1;
+
+ addr = card->rct_base + (vc->index << 2);
+ write_sram(card, addr, rcte);
+
+ spin_lock_irqsave(&card->cmd_lock, flags);
+ writel(SAR_CMD_OPEN_CONNECTION | (addr << 2),
+ SAR_REG_CMD);
+ waitfor_idle(card);
+ spin_unlock_irqrestore(&card->cmd_lock, flags);
+ }
+ }
+


+ return 0;
+}
+
+static void

+close_card_oam(struct idt77252_dev *card)
+{
+ unsigned long flags;
+ unsigned long addr;
+ struct vc_map *vc;
+ int vpi, vci;
+ int index;
+
+ for (vpi = 0; vpi < (1 << card->vpibits); vpi++) {
+ for (vci = 3; vci < 5; vci++) {
+ index = VPCI2VC(card, vpi, vci);
+ vc = card->vcs[index];
+
+ addr = card->rct_base + vc->index * SAR_SRAM_RCT_SIZE;
+
+ spin_lock_irqsave(&card->cmd_lock, flags);
+ writel(SAR_CMD_CLOSE_CONNECTION | (addr << 2),
+ SAR_REG_CMD);
+ waitfor_idle(card);
+ spin_unlock_irqrestore(&card->cmd_lock, flags);
+
+ if (vc->rcv.rx_pool.count) {
+ DPRINTK("%s: closing a VC "
+ "with pending rx buffers.\n",
+ card->name);
+
+ recycle_rx_pool_skb(card, &vc->rcv.rx_pool);
+ }
+ }


+ }
+}
+
+static int

+open_card_ubr0(struct idt77252_dev *card)


+{
+ struct vc_map *vc;
+

+ vc = kmalloc(sizeof(struct vc_map), GFP_KERNEL);
+ if (!vc) {
+ printk("%s: can't alloc vc\n", card->name);
+ return -ENOMEM;
+ }
+ memset(vc, 0, sizeof(struct vc_map));
+ card->vcs[0] = vc;
+ vc->class = SCHED_UBR0;
+
+ vc->scq = alloc_scq(card, vc->class);
+ if (!vc->scq) {
+ printk("%s: can't get SCQ.\n", card->name);
+ return -ENOMEM;
+ }
+
+ card->scd2vc[0] = vc;
+ vc->scd_index = 0;
+ vc->scq->scd = card->scd_base;
+
+ fill_scd(card, vc->scq, vc->class);
+
+ write_sram(card, card->tct_base + 0, TCT_UBR | card->scd_base);
+ write_sram(card, card->tct_base + 1, 0);
+ write_sram(card, card->tct_base + 2, 0);
+ write_sram(card, card->tct_base + 3, 0);
+ write_sram(card, card->tct_base + 4, 0);
+ write_sram(card, card->tct_base + 5, 0);
+ write_sram(card, card->tct_base + 6, 0);
+ write_sram(card, card->tct_base + 7, TCT_FLAG_UBR);
+
+ clear_bit(VCF_IDLE, &vc->flags);
+ writel(TCMDQ_START | 0, SAR_REG_TCMDQ);


+ return 0;
+}
+

+static int
+idt77252_dev_open(struct idt77252_dev *card)
+{
+ u32 conf;
+
+ if (!test_bit(IDT77252_BIT_INIT, &card->flags)) {
+ printk("%s: SAR not yet initialized.\n", card->name);
+ return -1;
+ }
+
+ conf = SAR_CFG_RXPTH| /* enable receive path */
+ SAR_RX_DELAY | /* interrupt on complete PDU */
+ SAR_CFG_RAWIE | /* interrupt enable on raw cells */
+ SAR_CFG_RQFIE | /* interrupt on RSQ almost full */
+ SAR_CFG_TMOIE | /* interrupt on timer overflow */
+ SAR_CFG_FBIE | /* interrupt on low free buffers */
+ SAR_CFG_TXEN | /* transmit operation enable */
+ SAR_CFG_TXINT | /* interrupt on transmit status */
+ SAR_CFG_TXUIE | /* interrupt on transmit underrun */
+ SAR_CFG_TXSFI | /* interrupt on TSQ almost full */
+ SAR_CFG_PHYIE /* enable PHY interrupts */
+ ;
+
+#ifdef CONFIG_ATM_IDT77252_RCV_ALL
+ /* Test RAW cell receive. */
+ conf |= SAR_CFG_VPECA;
+#endif


+
+ writel(readl(SAR_REG_CFG) | conf, SAR_REG_CFG);
+

+ if (open_card_oam(card)) {
+ printk("%s: Error initializing OAM.\n", card->name);
+ return -1;
+ }
+
+ if (open_card_ubr0(card)) {
+ printk("%s: Error initializing UBR0.\n", card->name);


+ return -1;
+ }
+

+ IPRINTK("%s: opened IDT77252 ABR SAR.\n", card->name);


+ return 0;
+}
+

+void
+idt77252_dev_close(struct atm_dev *dev)


+{
+ struct idt77252_dev *card = dev->dev_data;

+ u32 conf;
+
+ close_card_oam(card);
+
+ conf = SAR_CFG_RXPTH | /* enable receive path */
+ SAR_RX_DELAY | /* interrupt on complete PDU */
+ SAR_CFG_RAWIE | /* interrupt enable on raw cells */
+ SAR_CFG_RQFIE | /* interrupt on RSQ almost full */
+ SAR_CFG_TMOIE | /* interrupt on timer overflow */
+ SAR_CFG_FBIE | /* interrupt on low free buffers */
+ SAR_CFG_TXEN | /* transmit operation enable */
+ SAR_CFG_TXINT | /* interrupt on transmit status */
+ SAR_CFG_TXUIE | /* interrupt on xmit underrun */
+ SAR_CFG_TXSFI /* interrupt on TSQ almost full */
+ ;
+
+ writel(readl(SAR_REG_CFG) & ~(conf), SAR_REG_CFG);
+
+ DIPRINTK("%s: closed IDT77252 ABR SAR.\n", card->name);
+}
+
+
+/*****************************************************************************/
+/* */
+/* Initialisation and Deinitialization of IDT77252 */


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

+static void
+deinit_card(struct idt77252_dev *card)


+{
+ struct sk_buff *skb;

+ int i, j;
+

+ if (!test_bit(IDT77252_BIT_INIT, &card->flags)) {
+ printk("%s: SAR not yet initialized.\n", card->name);
+ return;
+ }
+ DIPRINTK("idt77252: deinitialize card %u\n", card->index);
+
+ writel(0, SAR_REG_CFG);
+
+ if (card->atmdev)
+ atm_dev_deregister(card->atmdev);
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < FBQ_SIZE; j++) {
+ skb = card->sbpool[i].skb[j];
+ if (skb) {
+ pci_unmap_single(card->pcidev,
+ IDT77252_PRV_PADDR(skb),
+ skb->end - skb->data,
+ PCI_DMA_FROMDEVICE);
+ card->sbpool[i].skb[j] = NULL;
+ dev_kfree_skb(skb);
+ }
+ }
+ }
+
+ if (card->soft_tst)
+ vfree(card->soft_tst);
+
+ if (card->scd2vc)
+ vfree(card->scd2vc);
+
+ if (card->vcs)
+ vfree(card->vcs);
+
+ if (card->raw_cell_hnd) {
+ pci_free_consistent(card->pcidev, 2 * sizeof(u32),
+ card->raw_cell_hnd, card->raw_cell_paddr);
+ }
+
+ if (card->rsq.base) {
+ DIPRINTK("%s: Release RSQ ...\n", card->name);
+ deinit_rsq(card);
+ }
+
+ if (card->tsq.base) {
+ DIPRINTK("%s: Release TSQ ...\n", card->name);
+ deinit_tsq(card);
+ }
+
+ DIPRINTK("idt77252: Release IRQ.\n");
+ free_irq(card->pcidev->irq, card);
+
+ for (i = 0; i < 4; i++) {
+ if (card->fbq[i])
+ iounmap((void *) card->fbq[i]);
+ }
+
+ if (card->membase)


+ iounmap((void *) card->membase);
+

+ clear_bit(IDT77252_BIT_INIT, &card->flags);
+ DIPRINTK("%s: Card deinitialized.\n", card->name);
+}
+
+
+static int __devinit
+init_sram(struct idt77252_dev *card)
+{
+ int i;
+
+ for (i = 0; i < card->sramsize; i += 4)
+ write_sram(card, (i >> 2), 0);
+
+ /* set SRAM layout for THIS card */


+ if (card->sramsize == (512 * 1024)) {

+ card->tct_base = SAR_SRAM_TCT_128_BASE;
+ card->tct_size = (SAR_SRAM_TCT_128_TOP - card->tct_base + 1)
+ / SAR_SRAM_TCT_SIZE;
+ card->rct_base = SAR_SRAM_RCT_128_BASE;
+ card->rct_size = (SAR_SRAM_RCT_128_TOP - card->rct_base + 1)
+ / SAR_SRAM_RCT_SIZE;
+ card->rt_base = SAR_SRAM_RT_128_BASE;
+ card->scd_base = SAR_SRAM_SCD_128_BASE;
+ card->scd_size = (SAR_SRAM_SCD_128_TOP - card->scd_base + 1)
+ / SAR_SRAM_SCD_SIZE;
+ card->tst[0] = SAR_SRAM_TST1_128_BASE;
+ card->tst[1] = SAR_SRAM_TST2_128_BASE;
+ card->tst_size = SAR_SRAM_TST1_128_TOP - card->tst[0] + 1;
+ card->abrst_base = SAR_SRAM_ABRSTD_128_BASE;
+ card->abrst_size = SAR_ABRSTD_SIZE_8K;
+ card->fifo_base = SAR_SRAM_FIFO_128_BASE;
+ card->fifo_size = SAR_RXFD_SIZE_32K;
+ } else {
+ card->tct_base = SAR_SRAM_TCT_32_BASE;
+ card->tct_size = (SAR_SRAM_TCT_32_TOP - card->tct_base + 1)
+ / SAR_SRAM_TCT_SIZE;
+ card->rct_base = SAR_SRAM_RCT_32_BASE;
+ card->rct_size = (SAR_SRAM_RCT_32_TOP - card->rct_base + 1)
+ / SAR_SRAM_RCT_SIZE;
+ card->rt_base = SAR_SRAM_RT_32_BASE;
+ card->scd_base = SAR_SRAM_SCD_32_BASE;
+ card->scd_size = (SAR_SRAM_SCD_32_TOP - card->scd_base + 1)
+ / SAR_SRAM_SCD_SIZE;
+ card->tst[0] = SAR_SRAM_TST1_32_BASE;
+ card->tst[1] = SAR_SRAM_TST2_32_BASE;
+ card->tst_size = (SAR_SRAM_TST1_32_TOP - card->tst[0] + 1);
+ card->abrst_base = SAR_SRAM_ABRSTD_32_BASE;
+ card->abrst_size = SAR_ABRSTD_SIZE_1K;
+ card->fifo_base = SAR_SRAM_FIFO_32_BASE;
+ card->fifo_size = SAR_RXFD_SIZE_4K;
+ }
+
+ /* Initialize TCT */
+ for (i = 0; i < card->tct_size; i++) {
+ write_sram(card, i * SAR_SRAM_TCT_SIZE + 0, 0);
+ write_sram(card, i * SAR_SRAM_TCT_SIZE + 1, 0);
+ write_sram(card, i * SAR_SRAM_TCT_SIZE + 2, 0);
+ write_sram(card, i * SAR_SRAM_TCT_SIZE + 3, 0);
+ write_sram(card, i * SAR_SRAM_TCT_SIZE + 4, 0);
+ write_sram(card, i * SAR_SRAM_TCT_SIZE + 5, 0);
+ write_sram(card, i * SAR_SRAM_TCT_SIZE + 6, 0);
+ write_sram(card, i * SAR_SRAM_TCT_SIZE + 7, 0);
+ }
+
+ /* Initialize RCT */
+ for (i = 0; i < card->rct_size; i++) {
+ write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE,
+ (u32) SAR_RCTE_RAWCELLINTEN);
+ write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE + 1,
+ (u32) 0);
+ write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE + 2,
+ (u32) 0);
+ write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE + 3,
+ (u32) 0xffffffff);
+ }
+
+ writel((SAR_FBQ0_LOW << 28) | 0x00000000 | 0x00000000 |
+ (SAR_FB_SIZE_0 / 48), SAR_REG_FBQS0);
+ writel((SAR_FBQ1_LOW << 28) | 0x00000000 | 0x00000000 |
+ (SAR_FB_SIZE_1 / 48), SAR_REG_FBQS1);
+ writel((SAR_FBQ2_LOW << 28) | 0x00000000 | 0x00000000 |
+ (SAR_FB_SIZE_2 / 48), SAR_REG_FBQS2);


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

echo 'End of part 037'
echo 'File patch-2.4.15 is continued in part 038'
echo "038" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:21 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part045

#!/bin/sh -x
# this is part 045 of a 115 - part archive


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

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

+ * details.


+ *
+ * You should have received a copy of the GNU General Public License

+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gr...@kroah.com>


+ *
+ */
+

+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/pci.h>
+#include "cpqphp.h"
+
+
+
+static struct proc_dir_entry *ctrl_proc_root;
+
+/* A few routines that create proc entries for the hot plug controller */
+
+static int read_ctrl (char *buf, char **start, off_t offset, int len, int *eof, void *data)
+{
+ struct controller *ctrl = (struct controller *)data;
+ char * out = buf;
+ int index;
+ struct pci_resource *res;
+
+ if (offset > 0) return 0; /* no partial requests */
+ len = 0;
+ *eof = 1;
+
+ out += sprintf(out, "hot plug ctrl Info Page\n");
+ out += sprintf(out, "bus = %d, device = %d, function = %d\n",ctrl->bus,
+ ctrl->device, ctrl->function);
+ out += sprintf(out, "Free resources: memory\n");
+ index = 11;
+ res = ctrl->mem_head;
+ while (res && index--) {
+ out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+ res = res->next;
+ }
+ out += sprintf(out, "Free resources: prefetchable memory\n");
+ index = 11;
+ res = ctrl->p_mem_head;
+ while (res && index--) {
+ out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+ res = res->next;
+ }
+ out += sprintf(out, "Free resources: IO\n");
+ index = 11;
+ res = ctrl->io_head;
+ while (res && index--) {
+ out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+ res = res->next;
+ }
+ out += sprintf(out, "Free resources: bus numbers\n");
+ index = 11;
+ res = ctrl->bus_head;
+ while (res && index--) {
+ out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+ res = res->next;
+ }
+
+ *start = buf;
+ len = out-buf;
+
+ return len;
+}
+
+static int read_dev (char *buf, char **start, off_t offset, int len, int *eof, void *data)
+{
+ struct controller *ctrl = (struct controller *)data;
+ char * out = buf;
+ int index;
+ struct pci_resource *res;
+ struct pci_func *new_slot;
+ struct slot *slot;
+
+ if (offset > 0) return 0; /* no partial requests */
+ len = 0;
+ *eof = 1;
+
+ out += sprintf(out, "hot plug ctrl Info Page\n");
+ out += sprintf(out, "bus = %d, device = %d, function = %d\n",ctrl->bus,
+ ctrl->device, ctrl->function);
+
+ slot=ctrl->slot;
+
+ while (slot) {
+ new_slot = cpqhp_slot_find(slot->bus, slot->device, 0);
+ out += sprintf(out, "assigned resources: memory\n");
+ index = 11;
+ res = new_slot->mem_head;
+ while (res && index--) {
+ out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+ res = res->next;
+ }
+ out += sprintf(out, "assigned resources: prefetchable memory\n");
+ index = 11;
+ res = new_slot->p_mem_head;
+ while (res && index--) {
+ out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+ res = res->next;
+ }
+ out += sprintf(out, "assigned resources: IO\n");
+ index = 11;
+ res = new_slot->io_head;
+ while (res && index--) {
+ out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+ res = res->next;
+ }
+ out += sprintf(out, "assigned resources: bus numbers\n");
+ index = 11;
+ res = new_slot->bus_head;
+ while (res && index--) {
+ out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+ res = res->next;
+ }
+ slot=slot->next;
+ }
+
+ *start = buf;
+ len = out-buf;
+
+ return len;
+}
+
+int cpqhp_proc_create_ctrl (struct controller *ctrl)
+{
+ strcpy(ctrl->proc_name, "hpca");
+ ctrl->proc_name[3] = 'a' + ctrl->bus;
+
+ ctrl->proc_entry = create_proc_entry(ctrl->proc_name, S_IFREG | S_IRUGO, ctrl_proc_root);
+ ctrl->proc_entry->data = ctrl;
+ ctrl->proc_entry->read_proc = &read_ctrl;
+
+ strcpy(ctrl->proc_name2, "slot_a");
+ ctrl->proc_name2[5] = 'a' + ctrl->bus;
+ ctrl->proc_entry2 = create_proc_entry(ctrl->proc_name2, S_IFREG | S_IRUGO, ctrl_proc_root);
+ ctrl->proc_entry2->data = ctrl;
+ ctrl->proc_entry2->read_proc = &read_dev;


+
+ return 0;
+}
+

+int cpqhp_proc_remove_ctrl (struct controller *ctrl)
+{
+ if (ctrl->proc_entry)
+ remove_proc_entry(ctrl->proc_name, ctrl_proc_root);
+ if (ctrl->proc_entry2)
+ remove_proc_entry(ctrl->proc_name2, ctrl_proc_root);


+
+ return 0;
+}
+

+int cpqhp_proc_init_ctrl (void)
+{
+ ctrl_proc_root = proc_mkdir("driver/hpc", NULL);
+ if (!ctrl_proc_root)
+ return -ENOMEM;
+ ctrl_proc_root->owner = THIS_MODULE;


+ return 0;
+}
+

+int cpqhp_proc_destroy_ctrl (void)
+{
+ remove_proc_entry("hpc", proc_root_driver);


+ return 0;
+}
+

diff -u --recursive --new-file v2.4.14/linux/drivers/hotplug/pci_hotplug.h linux/drivers/hotplug/pci_hotplug.h
--- v2.4.14/linux/drivers/hotplug/pci_hotplug.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/hotplug/pci_hotplug.h Fri Nov 9 14:01:22 2001
@@ -0,0 +1,160 @@
+/*
+ * PCI HotPlug Core Functions
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (gr...@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.


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

+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.


+ *
+ * You should have received a copy of the GNU General Public License

+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gr...@kroah.com>
+ *
+ */
+#ifndef _PCI_HOTPLUG_H
+#define _PCI_HOTPLUG_H
+
+
+struct hotplug_slot;
+struct hotplug_slot_core;
+
+/**
+ * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use
+ * @owner: The module owner of this structure
+ * @enable_slot: Called when the user wants to enable a specific pci slot
+ * @disable_slot: Called when the user wants to disable a specific pci slot
+ * @set_attention_status: Called to set the specific slot's attention LED to
+ * the specified value
+ * @hardware_test: Called to run a specified hardware test on the specified
+ * slot.
+ * @get_power_status: Called to get the current power status of a slot.
+ * If this field is NULL, the value passed in the struct hotplug_slot_info
+ * will be used when this value is requested by a user.
+ * @get_attention_status: Called to get the current attention status of a slot.
+ * If this field is NULL, the value passed in the struct hotplug_slot_info
+ * will be used when this value is requested by a user.
+ * @get_latch_status: Called to get the current latch status of a slot.
+ * If this field is NULL, the value passed in the struct hotplug_slot_info
+ * will be used when this value is requested by a user.
+ * @get_adapter_present: Called to get see if an adapter is present in the slot or not.
+ * If this field is NULL, the value passed in the struct hotplug_slot_info
+ * will be used when this value is requested by a user.
+ *
+ * The table of function pointers that is passed to the hotplug pci core by a
+ * hotplug pci driver. These functions are called by the hotplug pci core when
+ * the user wants to do something to a specific slot (query it for information,
+ * set an LED, enable / disable power, etc.)
+ */
+struct hotplug_slot_ops {
+ struct module *owner;
+ int (*enable_slot) (struct hotplug_slot *slot);
+ int (*disable_slot) (struct hotplug_slot *slot);
+ int (*set_attention_status) (struct hotplug_slot *slot, u8 value);
+ int (*hardware_test) (struct hotplug_slot *slot, u32 value);
+ int (*get_power_status) (struct hotplug_slot *slot, u8 *value);
+ int (*get_attention_status) (struct hotplug_slot *slot, u8 *value);
+ int (*get_latch_status) (struct hotplug_slot *slot, u8 *value);
+ int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value);
+};
+
+/**
+ * struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot
+ * @power: if power is enabled or not (1/0)
+ * @attention_status: if the attention light is enabled or not (1/0)
+ * @latch_status: if the latch (if any) is open or closed (1/0)
+ * @adapter_present: if there is a pci board present in the slot or not (1/0)
+ *
+ * Used to notify the hotplug pci core of the status of a specific slot.
+ */
+struct hotplug_slot_info {
+ u8 power_status;
+ u8 attention_status;
+ u8 latch_status;
+ u8 adapter_status;
+};
+
+/**
+ * struct hotplug_slot - used to register a physical slot with the hotplug pci core
+ * @name: the name of the slot being registered. This string must
+ * be unique amoung slots registered on this system.
+ * @ops: pointer to the &struct hotplug_slot_ops to be used for this slot
+ * @info: pointer to the &struct hotplug_slot_info for the inital values for
+ * this slot.
+ * @private: used by the hotplug pci controller driver to store whatever it
+ * needs.
+ */
+struct hotplug_slot {
+ char *name;
+ struct hotplug_slot_ops *ops;
+ struct hotplug_slot_info *info;
+ void *private;
+
+ /* Variables below this are for use only by the hotplug pci core. */
+ struct list_head slot_list;
+ struct hotplug_slot_core *core_priv;
+};
+
+extern int pci_hp_register (struct hotplug_slot *slot);
+extern int pci_hp_deregister (struct hotplug_slot *slot);
+extern int pci_hp_change_slot_info (const char *name,
+ struct hotplug_slot_info *info);
+
+struct pci_dev_wrapped {
+ struct pci_dev *dev;
+ void *data;
+};
+
+struct pci_bus_wrapped {
+ struct pci_bus *bus;
+ void *data;
+};
+
+struct pci_visit {
+ int (* pre_visit_pci_bus) (struct pci_bus_wrapped *,
+ struct pci_dev_wrapped *);
+ int (* post_visit_pci_bus) (struct pci_bus_wrapped *,
+ struct pci_dev_wrapped *);
+
+ int (* pre_visit_pci_dev) (struct pci_dev_wrapped *,
+ struct pci_bus_wrapped *);
+ int (* visit_pci_dev) (struct pci_dev_wrapped *,
+ struct pci_bus_wrapped *);
+ int (* post_visit_pci_dev) (struct pci_dev_wrapped *,
+ struct pci_bus_wrapped *);
+};
+
+extern int pci_visit_dev (struct pci_visit *fn,
+ struct pci_dev_wrapped *wrapped_dev,
+ struct pci_bus_wrapped *wrapped_parent);
+
+extern int pci_read_config_byte_nodev (struct pci_ops *ops, u8 bus, u8 device,
+ u8 function, int where, u8 *val);
+extern int pci_read_config_word_nodev (struct pci_ops *ops, u8 bus, u8 device,
+ u8 function, int where, u16 *val);
+extern int pci_read_config_dword_nodev (struct pci_ops *ops, u8 bus, u8 device,
+ u8 function, int where, u32 *val);
+
+extern int pci_write_config_byte_nodev (struct pci_ops *ops, u8 bus, u8 device,
+ u8 function, int where, u8 val);
+extern int pci_write_config_word_nodev (struct pci_ops *ops, u8 bus, u8 device,
+ u8 function, int where, u16 val);
+extern int pci_write_config_dword_nodev (struct pci_ops *ops, u8 bus, u8 device,
+ u8 function, int where, u32 val);
+
+
+#endif
+
diff -u --recursive --new-file v2.4.14/linux/drivers/hotplug/pci_hotplug_core.c linux/drivers/hotplug/pci_hotplug_core.c
--- v2.4.14/linux/drivers/hotplug/pci_hotplug_core.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/hotplug/pci_hotplug_core.c Wed Nov 21 09:59:11 2001
@@ -0,0 +1,1135 @@
+/*
+ * PCI HotPlug Controller Core
+ *
+ * Copyright (c) 2001 Greg Kroah-Hartman (gr...@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.


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

+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.


+ *
+ * You should have received a copy of the GNU General Public License

+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gr...@kroah.com>


+ *
+ */
+

+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+#include "pci_hotplug.h"
+
+
+#if !defined(CONFIG_HOTPLUG_PCI_MODULE)
+ #define MY_NAME "pci_hotplug"
+#else
+ #define MY_NAME THIS_MODULE->name
+#endif
+
+#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: "__FUNCTION__": " fmt , MY_NAME , ## arg); } while (0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
+
+
+/* local variables */
+static int debug;
+
+#define DRIVER_VERSION "0.3"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <gr...@kroah.com>"
+#define DRIVER_DESC "PCI Hot Plug PCI Core"
+
+
+//////////////////////////////////////////////////////////////////
+
+/* Random magic number */
+#define PCIHPFS_MAGIC 0x52454541
+
+struct hotplug_slot_core {
+ struct dentry *dir_dentry;
+ struct dentry *power_dentry;
+ struct dentry *attention_dentry;
+ struct dentry *latch_dentry;
+ struct dentry *adapter_dentry;
+ struct dentry *test_dentry;
+};
+
+static struct super_operations pcihpfs_ops;
+static struct address_space_operations pcihpfs_aops;
+static struct file_operations pcihpfs_dir_operations;
+static struct file_operations default_file_operations;
+static struct inode_operations pcihpfs_dir_inode_operations;
+static struct vfsmount *pcihpfs_mount; /* one of the mounts of our fs for reference counting */
+static int pcihpfs_mount_count; /* times we have mounted our fs */
+static spinlock_t mount_lock; /* protects our mount_count */
+static spinlock_t list_lock;
+
+LIST_HEAD(pci_hotplug_slot_list);
+
+
+static int pcihpfs_statfs (struct super_block *sb, struct statfs *buf)
+{
+ buf->f_type = PCIHPFS_MAGIC;
+ buf->f_bsize = PAGE_CACHE_SIZE;
+ buf->f_namelen = 255;


+ return 0;
+}
+

+static struct dentry *pcihpfs_lookup (struct inode *dir, struct dentry *dentry)
+{
+ d_add(dentry, NULL);


+ return NULL;
+}
+

+static struct inode *pcihpfs_get_inode (struct super_block *sb, int mode, int dev)
+{
+ struct inode *inode = new_inode(sb);
+
+ if (inode) {
+ inode->i_mode = mode;
+ inode->i_uid = current->fsuid;
+ inode->i_gid = current->fsgid;
+ inode->i_blksize = PAGE_CACHE_SIZE;
+ inode->i_blocks = 0;
+ inode->i_rdev = NODEV;
+ inode->i_mapping->a_ops = &pcihpfs_aops;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ switch (mode & S_IFMT) {
+ default:
+ init_special_inode(inode, mode, dev);
+ break;
+ case S_IFREG:
+ inode->i_fop = &default_file_operations;
+ break;
+ case S_IFDIR:
+ inode->i_op = &pcihpfs_dir_inode_operations;
+ inode->i_fop = &pcihpfs_dir_operations;
+ break;
+ }
+ }
+ return inode;
+}
+
+static int pcihpfs_mknod (struct inode *dir, struct dentry *dentry, int mode, int dev)
+{
+ struct inode *inode = pcihpfs_get_inode(dir->i_sb, mode, dev);
+ int error = -ENOSPC;
+
+ if (inode) {
+ d_instantiate(dentry, inode);
+ dget(dentry);
+ error = 0;
+ }


+ return error;
+}
+

+static int pcihpfs_mkdir (struct inode *dir, struct dentry *dentry, int mode)
+{
+ return pcihpfs_mknod (dir, dentry, mode | S_IFDIR, 0);
+}
+
+static int pcihpfs_create (struct inode *dir, struct dentry *dentry, int mode)
+{
+ return pcihpfs_mknod (dir, dentry, mode | S_IFREG, 0);
+}
+
+static int pcihpfs_link (struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry)
+{
+ struct inode *inode = old_dentry->d_inode;
+
+ if(S_ISDIR(inode->i_mode))
+ return -EPERM;
+
+ inode->i_nlink++;
+ atomic_inc(&inode->i_count);
+ dget(dentry);
+ d_instantiate(dentry, inode);


+ return 0;
+}
+

+static inline int pcihpfs_positive (struct dentry *dentry)
+{
+ return dentry->d_inode && !d_unhashed(dentry);
+}
+
+static int pcihpfs_empty (struct dentry *dentry)
+{
+ struct list_head *list;
+
+ spin_lock(&dcache_lock);
+
+ list_for_each(list, &dentry->d_subdirs) {
+ struct dentry *de = list_entry(list, struct dentry, d_child);
+ if (pcihpfs_positive(de)) {
+ spin_unlock(&dcache_lock);


+ return 0;
+ }
+ }
+

+ spin_unlock(&dcache_lock);


+ return 1;
+}
+

+static int pcihpfs_unlink (struct inode *dir, struct dentry *dentry)
+{
+ int error = -ENOTEMPTY;
+
+ if (pcihpfs_empty(dentry)) {
+ struct inode *inode = dentry->d_inode;
+
+ inode->i_nlink--;
+ dput(dentry);
+ error = 0;
+ }


+ return error;
+}
+

+static int pcihpfs_rename (struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+{
+ int error = -ENOTEMPTY;
+
+ if (pcihpfs_empty(new_dentry)) {
+ struct inode *inode = new_dentry->d_inode;
+ if (inode) {
+ inode->i_nlink--;
+ dput(new_dentry);
+ }
+ error = 0;
+ }
+ return error;
+}
+
+#define pcihpfs_rmdir pcihpfs_unlink
+
+/* default file operations */
+static ssize_t default_read_file (struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+ dbg ("\n");


+ return 0;
+}
+

+static ssize_t default_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+ dbg ("\n");
+ return count;
+}
+
+static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
+{
+ loff_t retval = -EINVAL;
+
+ switch(orig) {
+ case 0:
+ if (offset > 0) {
+ file->f_pos = offset;
+ retval = file->f_pos;
+ }

+ break;
+ case 1:

+ if ((offset + file->f_pos) > 0) {
+ file->f_pos += offset;
+ retval = file->f_pos;
+ }
+ break;
+ default:
+ break;
+ }


+ return retval;
+}
+

+static int default_open (struct inode *inode, struct file *filp)
+{
+ if (inode->u.generic_ip)
+ filp->private_data = inode->u.generic_ip;


+
+ return 0;
+}
+

+static int default_sync_file (struct file *file, struct dentry *dentry, int datasync)


+{
+ return 0;
+}
+

+static struct address_space_operations pcihpfs_aops = {
+};
+
+static struct file_operations pcihpfs_dir_operations = {
+ read: generic_read_dir,
+ readdir: dcache_readdir,
+ fsync: default_sync_file,
+};
+
+static struct file_operations default_file_operations = {
+ read: default_read_file,
+ write: default_write_file,
+ open: default_open,
+ llseek: default_file_lseek,
+ fsync: default_sync_file,
+ mmap: generic_file_mmap,
+};
+
+/* file ops for the "power" files */
+static ssize_t power_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
+static ssize_t power_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos);
+static struct file_operations power_file_operations = {
+ read: power_read_file,
+ write: power_write_file,
+ open: default_open,
+ llseek: default_file_lseek,
+ fsync: default_sync_file,
+ mmap: generic_file_mmap,
+};
+
+/* file ops for the "attention" files */
+static ssize_t attention_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
+static ssize_t attention_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos);
+static struct file_operations attention_file_operations = {
+ read: attention_read_file,
+ write: attention_write_file,
+ open: default_open,
+ llseek: default_file_lseek,
+ fsync: default_sync_file,
+ mmap: generic_file_mmap,
+};
+
+/* file ops for the "latch" files */
+static ssize_t latch_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
+static struct file_operations latch_file_operations = {
+ read: latch_read_file,
+ write: default_write_file,
+ open: default_open,
+ llseek: default_file_lseek,
+ fsync: default_sync_file,
+ mmap: generic_file_mmap,
+};
+
+/* file ops for the "presence" files */
+static ssize_t presence_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
+static struct file_operations presence_file_operations = {
+ read: presence_read_file,
+ write: default_write_file,
+ open: default_open,
+ llseek: default_file_lseek,
+ fsync: default_sync_file,
+ mmap: generic_file_mmap,
+};
+
+/* file ops for the "test" files */
+static ssize_t test_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos);
+static struct file_operations test_file_operations = {
+ read: default_read_file,
+ write: test_write_file,
+ open: default_open,
+ llseek: default_file_lseek,
+ fsync: default_sync_file,
+ mmap: generic_file_mmap,
+};
+
+static struct inode_operations pcihpfs_dir_inode_operations = {
+ create: pcihpfs_create,
+ lookup: pcihpfs_lookup,
+ link: pcihpfs_link,
+ unlink: pcihpfs_unlink,
+ mkdir: pcihpfs_mkdir,
+ rmdir: pcihpfs_rmdir,
+ mknod: pcihpfs_mknod,
+ rename: pcihpfs_rename,
+};
+
+static struct super_operations pcihpfs_ops = {
+ statfs: pcihpfs_statfs,
+ put_inode: force_delete,
+};
+
+static struct super_block *pcihpfs_read_super (struct super_block *sb, void *data, int silent)
+{
+ struct inode *inode;
+ struct dentry *root;
+
+ sb->s_blocksize = PAGE_CACHE_SIZE;
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+ sb->s_magic = PCIHPFS_MAGIC;
+ sb->s_op = &pcihpfs_ops;
+ inode = pcihpfs_get_inode(sb, S_IFDIR | 0755, 0);
+
+ if (!inode) {
+ dbg("%s: could not get inode!\n",__FUNCTION__);


+ return NULL;
+ }
+

+ root = d_alloc_root(inode);
+ if (!root) {
+ dbg("%s: could not get root dentry!\n",__FUNCTION__);
+ iput(inode);
+ return NULL;
+ }
+ sb->s_root = root;
+ return sb;
+}
+
+static DECLARE_FSTYPE(pcihpfs_fs_type, "pcihpfs", pcihpfs_read_super, FS_SINGLE | FS_LITTER);
+
+static int get_mount (void)
+{
+ struct vfsmount *mnt;
+
+ spin_lock (&mount_lock);
+ if (pcihpfs_mount) {
+ mntget(pcihpfs_mount);
+ ++pcihpfs_mount_count;
+ spin_unlock (&mount_lock);
+ goto go_ahead;
+ }
+
+ spin_unlock (&mount_lock);
+ mnt = kern_mount (&pcihpfs_fs_type);
+ if (IS_ERR(mnt)) {
+ err ("could not mount the fs...erroring out!\n");
+ return -ENODEV;
+ }
+ spin_lock (&mount_lock);
+ if (!pcihpfs_mount) {
+ pcihpfs_mount = mnt;
+ ++pcihpfs_mount_count;
+ spin_unlock (&mount_lock);
+ goto go_ahead;
+ }
+ mntget(pcihpfs_mount);
+ ++pcihpfs_mount_count;
+ spin_unlock (&mount_lock);
+ mntput(mnt);
+
+go_ahead:
+ dbg("pcihpfs_mount_count = %d\n", pcihpfs_mount_count);


+ return 0;
+}
+

+static void remove_mount (void)
+{
+ struct vfsmount *mnt;
+
+ spin_lock (&mount_lock);
+ mnt = pcihpfs_mount;
+ --pcihpfs_mount_count;
+ if (!pcihpfs_mount_count)
+ pcihpfs_mount = NULL;
+
+ spin_unlock (&mount_lock);
+ mntput(mnt);
+ dbg("pcihpfs_mount_count = %d\n", pcihpfs_mount_count);
+}
+
+
+/**
+ * pcihpfs_create_by_name - create a file, given a name
+ * @name: name of file
+ * @mode: type of file
+ * @parent: dentry of directory to create it in
+ * @dentry: resulting dentry of file
+ *
+ * There is a bit of overhead in creating a file - basically, we
+ * have to hash the name of the file, then look it up. This will
+ * prevent files of the same name.
+ * We then call the proper vfs_ function to take care of all the
+ * file creation details.
+ * This function handles both regular files and directories.
+ */
+static int pcihpfs_create_by_name (const char *name, mode_t mode,
+ struct dentry *parent, struct dentry **dentry)
+{
+ struct dentry *d = NULL;
+ struct qstr qstr;
+ int error;
+
+ /* If the parent is not specified, we create it in the root.
+ * We need the root dentry to do this, which is in the super
+ * block. A pointer to that is in the struct vfsmount that we
+ * have around.
+ */
+ if (!parent ) {
+ if (pcihpfs_mount && pcihpfs_mount->mnt_sb) {
+ parent = pcihpfs_mount->mnt_sb->s_root;
+ }
+ }
+
+ if (!parent) {
+ dbg("Ah! can not find a parent!\n");


+ return -EFAULT;
+ }
+

+ *dentry = NULL;
+ qstr.name = name;
+ qstr.len = strlen(name);
+ qstr.hash = full_name_hash(name,qstr.len);
+
+ parent = dget(parent);
+
+ down(&parent->d_inode->i_sem);
+
+ d = lookup_hash(&qstr,parent);
+
+ error = PTR_ERR(d);
+ if (!IS_ERR(d)) {
+ switch(mode & S_IFMT) {
+ case 0:
+ case S_IFREG:
+ error = vfs_create(parent->d_inode,d,mode);
+ break;
+ case S_IFDIR:
+ error = vfs_mkdir(parent->d_inode,d,mode);
+ break;
+ default:
+ err("cannot create special files\n");
+ }
+ *dentry = d;
+ }
+ up(&parent->d_inode->i_sem);
+
+ dput(parent);


+ return error;
+}
+

+static struct dentry *fs_create_file (const char *name, mode_t mode,
+ struct dentry *parent, void *data,
+ struct file_operations *fops)
+{
+ struct dentry *dentry;
+ int error;
+
+ dbg("creating file '%s'\n",name);
+
+ error = pcihpfs_create_by_name(name,mode,parent,&dentry);
+ if (error) {
+ dentry = NULL;
+ } else {
+ if (dentry->d_inode) {
+ if (data)
+ dentry->d_inode->u.generic_ip = data;
+ if (fops)
+ dentry->d_inode->i_fop = fops;
+ }
+ }
+
+ return dentry;
+}
+
+static void fs_remove_file (struct dentry *dentry)
+{
+ struct dentry *parent = dentry->d_parent;
+
+ if (!parent || !parent->d_inode)
+ return;
+
+ down(&parent->d_inode->i_sem);
+ if (pcihpfs_positive(dentry)) {
+ if (dentry->d_inode) {
+ if (S_ISDIR(dentry->d_inode->i_mode))
+ vfs_rmdir(parent->d_inode,dentry);
+ else
+ vfs_unlink(parent->d_inode,dentry);
+ }
+
+ dput(dentry);
+ }
+ up(&parent->d_inode->i_sem);
+}
+
+#define GET_STATUS(name) \
+static int get_##name##_status (struct hotplug_slot *slot, u8 *value) \
+{ \
+ struct hotplug_slot_ops *ops = slot->ops; \
+ int retval = 0; \
+ if (ops->owner) \
+ __MOD_INC_USE_COUNT(ops->owner); \
+ if (ops->get_##name##_status) \
+ retval = ops->get_##name##_status (slot, value); \
+ else \
+ *value = slot->info->name##_status; \
+ if (ops->owner) \
+ __MOD_DEC_USE_COUNT(ops->owner); \


+ return retval; \
+}
+

+GET_STATUS(power)
+GET_STATUS(attention)
+GET_STATUS(latch)
+GET_STATUS(adapter)
+
+static ssize_t power_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
+{
+ struct hotplug_slot *slot = file->private_data;
+ unsigned char *page;
+ int retval;
+ int len;
+ u8 value;
+
+ dbg(" count = %d, offset = %lld\n", count, *offset);
+
+ if (*offset < 0)
+ return -EINVAL;
+ if (count <= 0)
+ return 0;
+ if (*offset != 0)
+ return 0;
+
+ if (slot == NULL) {
+ dbg("slot == NULL???\n");


+ return -ENODEV;
+ }
+

+ page = (unsigned char *)__get_free_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+
+ retval = get_power_status (slot, &value);
+ if (retval)
+ goto exit;
+ len = sprintf (page, "%d\n", value);
+
+ if (copy_to_user (buf, page, len)) {
+ retval = -EFAULT;
+ goto exit;
+ }
+ *offset += len;
+ retval = len;
+
+exit:
+ free_page((unsigned long)page);


+ return retval;
+}
+

+static ssize_t power_write_file (struct file *file, const char *ubuff, size_t count, loff_t *offset)
+{
+ struct hotplug_slot *slot = file->private_data;
+ char *buff;
+ unsigned long lpower;
+ u8 power;
+ int retval = 0;
+
+ if (*offset < 0)
+ return -EINVAL;
+ if (count <= 0)
+ return 0;
+ if (*offset != 0)
+ return 0;
+
+ if (slot == NULL) {
+ dbg("slot == NULL???\n");


+ return -ENODEV;
+ }
+

+ buff = kmalloc (count + 1, GFP_KERNEL);
+ if (!buff)
+ return -ENOMEM;
+ memset (buff, 0x00, count + 1);
+
+ if (copy_from_user ((void *)buff, (void *)ubuff, count)) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ lpower = simple_strtoul (buff, NULL, 10);
+ power = (u8)(lpower & 0xff);
+ dbg ("power = %d\n", power);
+
+ switch (power) {
+ case 0:
+ if (!slot->ops->disable_slot)
+ break;
+ if (slot->ops->owner)
+ __MOD_INC_USE_COUNT(slot->ops->owner);
+ retval = slot->ops->disable_slot(slot);
+ if (slot->ops->owner)
+ __MOD_DEC_USE_COUNT(slot->ops->owner);
+ break;
+
+ case 1:
+ if (!slot->ops->enable_slot)
+ break;
+ if (slot->ops->owner)
+ __MOD_INC_USE_COUNT(slot->ops->owner);
+ retval = slot->ops->enable_slot(slot);
+ if (slot->ops->owner)
+ __MOD_DEC_USE_COUNT(slot->ops->owner);


+ break;
+
+ default:

+ err ("Illegal value specified for power\n");


+ retval = -EFAULT;
+ }

+
+exit:
+ kfree (buff);
+
+ if (retval)
+ return retval;
+ return count;
+}
+
+static ssize_t attention_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
+{
+ struct hotplug_slot *slot = file->private_data;
+ unsigned char *page;
+ int retval;
+ int len;
+ u8 value;
+
+ dbg("count = %d, offset = %lld\n", count, *offset);
+
+ if (*offset < 0)
+ return -EINVAL;
+ if (count <= 0)
+ return 0;
+ if (*offset != 0)
+ return 0;
+
+ if (slot == NULL) {
+ dbg("slot == NULL???\n");


+ return -ENODEV;
+ }
+

+ page = (unsigned char *)__get_free_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+
+ retval = get_attention_status (slot, &value);
+ if (retval)
+ goto exit;
+ len = sprintf (page, "%d\n", value);
+
+ if (copy_to_user (buf, page, len)) {
+ retval = -EFAULT;
+ goto exit;
+ }
+ *offset += len;
+ retval = len;
+
+exit:
+ free_page((unsigned long)page);


+ return retval;
+}
+

+static ssize_t attention_write_file (struct file *file, const char *ubuff, size_t count, loff_t *offset)
+{
+ struct hotplug_slot *slot = file->private_data;
+ char *buff;
+ unsigned long lattention;
+ u8 attention;
+ int retval = 0;
+
+ if (*offset < 0)
+ return -EINVAL;
+ if (count <= 0)
+ return 0;
+ if (*offset != 0)
+ return 0;
+
+ if (slot == NULL) {
+ dbg("slot == NULL???\n");


+ return -ENODEV;
+ }
+

+ buff = kmalloc (count + 1, GFP_KERNEL);
+ if (!buff)
+ return -ENOMEM;
+ memset (buff, 0x00, count + 1);
+
+ if (copy_from_user ((void *)buff, (void *)ubuff, count)) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ lattention = simple_strtoul (buff, NULL, 10);
+ attention = (u8)(lattention & 0xff);
+ dbg (" - attention = %d\n", attention);
+
+ if (slot->ops->set_attention_status) {
+ if (slot->ops->owner)
+ __MOD_INC_USE_COUNT(slot->ops->owner);
+ retval = slot->ops->set_attention_status(slot, attention);
+ if (slot->ops->owner)
+ __MOD_DEC_USE_COUNT(slot->ops->owner);
+ }
+
+exit:
+ kfree (buff);
+
+ if (retval)
+ return retval;
+ return count;
+}
+
+static ssize_t latch_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
+{
+ struct hotplug_slot *slot = file->private_data;
+ unsigned char *page;
+ int retval;
+ int len;
+ u8 value;
+
+ dbg("count = %d, offset = %lld\n", count, *offset);
+
+ if (*offset < 0)
+ return -EINVAL;
+ if (count <= 0)
+ return 0;
+ if (*offset != 0)
+ return 0;
+
+ if (slot == NULL) {
+ dbg("slot == NULL???\n");


+ return -ENODEV;
+ }
+

+ page = (unsigned char *)__get_free_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+
+ retval = get_latch_status (slot, &value);
+ if (retval)
+ goto exit;
+ len = sprintf (page, "%d\n", value);
+
+ if (copy_to_user (buf, page, len)) {
+ retval = -EFAULT;
+ goto exit;
+ }
+ *offset += len;
+ retval = len;
+
+exit:
+ free_page((unsigned long)page);


+ return retval;
+}
+
+

+static ssize_t presence_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
+{
+ struct hotplug_slot *slot = file->private_data;
+ unsigned char *page;
+ int retval;
+ int len;
+ u8 value;
+
+ dbg("count = %d, offset = %lld\n", count, *offset);
+
+ if (*offset < 0)
+ return -EINVAL;
+ if (count <= 0)
+ return 0;
+ if (*offset != 0)
+ return 0;
+
+ if (slot == NULL) {
+ dbg("slot == NULL???\n");


+ return -ENODEV;
+ }
+

+ page = (unsigned char *)__get_free_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+
+ retval = get_adapter_status (slot, &value);
+ if (retval)
+ goto exit;
+ len = sprintf (page, "%d\n", value);
+
+ if (copy_to_user (buf, page, len)) {
+ retval = -EFAULT;
+ goto exit;
+ }
+ *offset += len;
+ retval = len;
+
+exit:
+ free_page((unsigned long)page);


+ return retval;
+}
+

+static ssize_t test_write_file (struct file *file, const char *ubuff, size_t count, loff_t *offset)
+{
+ struct hotplug_slot *slot = file->private_data;
+ char *buff;
+ unsigned long ltest;
+ u32 test;
+ int retval = 0;
+
+ if (*offset < 0)
+ return -EINVAL;
+ if (count <= 0)
+ return 0;
+ if (*offset != 0)
+ return 0;
+
+ if (slot == NULL) {
+ dbg("slot == NULL???\n");


+ return -ENODEV;
+ }
+

+ buff = kmalloc (count + 1, GFP_KERNEL);
+ if (!buff)
+ return -ENOMEM;
+ memset (buff, 0x00, count + 1);
+
+ if (copy_from_user ((void *)buff, (void *)ubuff, count)) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ ltest = simple_strtoul (buff, NULL, 10);
+ test = (u32)(ltest & 0xffffffff);
+ dbg ("test = %d\n", test);
+
+ if (slot->ops->hardware_test) {
+ if (slot->ops->owner)
+ __MOD_INC_USE_COUNT(slot->ops->owner);
+ retval = slot->ops->hardware_test(slot, test);
+ if (slot->ops->owner)
+ __MOD_DEC_USE_COUNT(slot->ops->owner);
+ }
+
+exit:
+ kfree (buff);
+
+ if (retval)
+ return retval;
+ return count;
+}
+
+static int fs_add_slot (struct hotplug_slot *slot)
+{
+ struct hotplug_slot_core *core = slot->core_priv;
+ int result;
+
+ result = get_mount();
+ if (result)
+ return result;
+
+ core->dir_dentry = fs_create_file (slot->name,
+ S_IFDIR | S_IXUGO | S_IRUGO,
+ NULL, NULL, NULL);
+ if (core->dir_dentry != NULL) {
+ core->power_dentry = fs_create_file ("power",
+ S_IFREG | S_IRUGO | S_IWUSR,
+ core->dir_dentry, slot,
+ &power_file_operations);
+
+ core->attention_dentry = fs_create_file ("attention",
+ S_IFREG | S_IRUGO | S_IWUSR,
+ core->dir_dentry, slot,
+ &attention_file_operations);
+
+ core->latch_dentry = fs_create_file ("latch",
+ S_IFREG | S_IRUGO,
+ core->dir_dentry, slot,
+ &latch_file_operations);
+
+ core->adapter_dentry = fs_create_file ("adapter",
+ S_IFREG | S_IRUGO,
+ core->dir_dentry, slot,
+ &presence_file_operations);
+
+ core->test_dentry = fs_create_file ("test",
+ S_IFREG | S_IRUGO | S_IWUSR,
+ core->dir_dentry, slot,
+ &test_file_operations);


+ }
+ return 0;
+}
+

+static void fs_remove_slot (struct hotplug_slot *slot)
+{
+ struct hotplug_slot_core *core = slot->core_priv;
+
+ if (core->dir_dentry) {
+ if (core->power_dentry)
+ fs_remove_file (core->power_dentry);
+ if (core->attention_dentry)
+ fs_remove_file (core->attention_dentry);
+ if (core->latch_dentry)
+ fs_remove_file (core->latch_dentry);
+ if (core->adapter_dentry)
+ fs_remove_file (core->adapter_dentry);
+ if (core->test_dentry)
+ fs_remove_file (core->test_dentry);
+ fs_remove_file (core->dir_dentry);
+ }
+
+ remove_mount();
+}
+
+static struct hotplug_slot *get_slot_from_name (const char *name)
+{
+ struct hotplug_slot *slot;
+ struct list_head *tmp;
+
+ list_for_each (tmp, &pci_hotplug_slot_list) {
+ slot = list_entry (tmp, struct hotplug_slot, slot_list);
+ if (strcmp(slot->name, name) == 0)
+ return slot;


+ }
+ return NULL;
+}
+

+/**
+ * pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem
+ * @slot: pointer to the &struct hotplug_slot to register
+ *
+ * Registers a hotplug slot with the pci hotplug subsystem, which will allow
+ * userspace interaction to the slot.
+ *
+ * Returns 0 if successful, anything else for an error.
+ */
+int pci_hp_register (struct hotplug_slot *slot)
+{
+ struct hotplug_slot_core *core;
+ int result;
+
+ if (slot == NULL)
+ return -ENODEV;
+ if ((slot->info == NULL) || (slot->ops == NULL))
+ return -EFAULT;
+
+ core = kmalloc (sizeof (struct hotplug_slot_core), GFP_KERNEL);
+ if (!core)
+ return -ENOMEM;
+
+ /* make sure we have not already registered this slot */
+ spin_lock (&list_lock);
+ if (get_slot_from_name (slot->name) != NULL) {
+ spin_unlock (&list_lock);
+ kfree (core);


+ return -EFAULT;
+ }
+

+ slot->core_priv = core;
+
+ list_add (&slot->slot_list, &pci_hotplug_slot_list);
+ spin_unlock (&list_lock);
+
+ result = fs_add_slot (slot);
+ dbg ("Added slot %s to the list\n", slot->name);


+ return result;
+}
+

+/**
+ * pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem
+ * @slot: pointer to the &struct hotplug_slot to deregister
+ *
+ * The @slot must have been registered with the pci hotplug subsystem
+ * previously with a call to pci_hp_register().
+ *
+ * Returns 0 if successful, anything else for an error.
+ */
+int pci_hp_deregister (struct hotplug_slot *slot)
+{
+ struct hotplug_slot *temp;
+
+ if (slot == NULL)
+ return -ENODEV;
+
+ /* make sure we have this slot in our list before trying to delete it */
+ spin_lock (&list_lock);
+ temp = get_slot_from_name (slot->name);
+ if (temp != slot) {
+ spin_unlock (&list_lock);


+ return -ENODEV;
+ }
+

+ list_del (&slot->slot_list);
+ spin_unlock (&list_lock);
+
+ fs_remove_slot (slot);
+ kfree(slot->core_priv);
+ dbg ("Removed slot %s from the list\n", slot->name);


+ return 0;
+}
+

+/**
+ * pci_hp_change_slot_info - changes the slot's information structure in the core
+ * @name: the name of the slot whose info has changed
+ * @info: pointer to the info copy into the slot's info structure
+ *
+ * A slot with @name must have been registered with the pci
+ * hotplug subsystem previously with a call to pci_hp_register().
+ *
+ * Returns 0 if successful, anything else for an error.
+ */
+int pci_hp_change_slot_info (const char *name, struct hotplug_slot_info *info)
+{
+ struct hotplug_slot *temp;
+
+ if (info == NULL)
+ return -ENODEV;
+
+ spin_lock (&list_lock);
+ temp = get_slot_from_name (name);
+ if (temp == NULL) {
+ spin_unlock (&list_lock);


+ return -ENODEV;
+ }
+

+ memcpy (temp->info, info, sizeof (struct hotplug_slot_info));
+ spin_unlock (&list_lock);


+ return 0;
+}
+

+static int __init pci_hotplug_init (void)
+{
+ int result;
+
+ spin_lock_init(&mount_lock);
+ spin_lock_init(&list_lock);
+
+ dbg("registering filesystem.\n");
+ result = register_filesystem(&pcihpfs_fs_type);
+ if (result) {
+ err("register_filesystem failed with %d\n", result);
+ goto exit;
+ }
+
+ info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
+
+exit:
+ return result;
+}
+
+static void __exit pci_hotplug_exit (void)
+{
+ unregister_filesystem(&pcihpfs_fs_type);
+}
+
+module_init(pci_hotplug_init);
+module_exit(pci_hotplug_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+
+EXPORT_SYMBOL_GPL(pci_hp_register);
+EXPORT_SYMBOL_GPL(pci_hp_deregister);
+EXPORT_SYMBOL_GPL(pci_hp_change_slot_info);
+
diff -u --recursive --new-file v2.4.14/linux/drivers/hotplug/pci_hotplug_util.c linux/drivers/hotplug/pci_hotplug_util.c
--- v2.4.14/linux/drivers/hotplug/pci_hotplug_util.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/hotplug/pci_hotplug_util.c Fri Nov 9 14:01:22 2001
@@ -0,0 +1,403 @@
+/*
+ * PCI HotPlug Utility functions
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (gr...@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.


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

+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.


+ *
+ * You should have received a copy of the GNU General Public License

+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gr...@kroah.com>


+ *
+ */
+

+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include "pci_hotplug.h"
+
+
+#if !defined(CONFIG_HOTPLUG_PCI_MODULE)
+ #define MY_NAME "pci_hotplug"
+#else
+ #define MY_NAME THIS_MODULE->name
+#endif
+
+#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: "__FUNCTION__": " fmt , MY_NAME , ## arg); } while (0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
+
+
+/* local variables */
+static int debug;
+
+
+static int build_dev (struct pci_ops *ops, u8 bus, u8 slot, u8 function, struct pci_dev **pci_dev)
+{
+ struct pci_dev *my_dev;
+ struct pci_bus *my_bus;
+
+ /* Some validity checks. */
+ if ((function > 7) ||
+ (slot > 31) ||
+ (pci_dev == NULL) ||
+ (ops == NULL))
+ return -ENODEV;
+
+ my_dev = kmalloc (sizeof (struct pci_dev), GFP_KERNEL);
+ if (!my_dev)
+ return -ENOMEM;
+ my_bus = kmalloc (sizeof (struct pci_bus), GFP_KERNEL);
+ if (!my_bus) {
+ kfree (my_dev);
+ return -ENOMEM;
+ }
+ memset(my_dev, 0, sizeof(struct pci_dev));
+ memset(my_bus, 0, sizeof(struct pci_bus));
+
+ my_bus->number = bus;
+ my_bus->ops = ops;
+ my_dev->devfn = PCI_DEVFN(slot, function);
+ my_dev->bus = my_bus;
+ *pci_dev = my_dev;


+ return 0;
+}
+

+/**
+ * pci_read_config_byte_nodev - read a byte from a pci device
+ * @ops: pointer to a &struct pci_ops that will be used to read from the pci device
+ * @bus: the bus of the pci device to read from
+ * @slot: the pci slot number of the pci device to read from
+ * @function: the function of the pci device to read from
+ * @where: the location on the pci address space to read from
+ * @value: pointer to where to place the data read
+ *
+ * Like pci_read_config_byte() but works for pci devices that do not have a
+ * pci_dev structure set up yet.
+ * Returns 0 on success.
+ */
+int pci_read_config_byte_nodev (struct pci_ops *ops, u8 bus, u8 slot, u8 function, int where, u8 *value)
+{
+ struct pci_dev *dev = NULL;
+ int result;
+
+ dbg("%p, %d, %d, %d, %d, %p\n", ops, bus, slot, function, where, value);
+ dev = pci_find_slot(bus, PCI_DEVFN(slot, function));
+ if (dev) {
+ dbg("using native pci_dev\n");
+ return pci_read_config_byte (dev, where, value);
+ }
+
+ result = build_dev (ops, bus, slot, function, &dev);
+ if (result)
+ return result;
+ result = pci_read_config_byte(dev, where, value);
+ kfree (dev->bus);
+ kfree (dev);


+ return result;
+}
+

+/**
+ * pci_read_config_word_nodev - read a word from a pci device
+ * @ops: pointer to a &struct pci_ops that will be used to read from the pci device
+ * @bus: the bus of the pci device to read from
+ * @slot: the pci slot number of the pci device to read from
+ * @function: the function of the pci device to read from
+ * @where: the location on the pci address space to read from
+ * @value: pointer to where to place the data read
+ *
+ * Like pci_read_config_word() but works for pci devices that do not have a
+ * pci_dev structure set up yet.
+ * Returns 0 on success.
+ */
+int pci_read_config_word_nodev (struct pci_ops *ops, u8 bus, u8 slot, u8 function, int where, u16 *value)
+{
+ struct pci_dev *dev = NULL;
+ int result;
+
+ dbg("%p, %d, %d, %d, %d, %p\n", ops, bus, slot, function, where, value);
+ dev = pci_find_slot(bus, PCI_DEVFN(slot, function));
+ if (dev) {
+ dbg("using native pci_dev\n");
+ return pci_read_config_word (dev, where, value);
+ }
+
+ result = build_dev (ops, bus, slot, function, &dev);
+ if (result)
+ return result;
+ result = pci_read_config_word(dev, where, value);
+ kfree (dev->bus);
+ kfree (dev);


+ return result;
+}
+

+/**
+ * pci_read_config_dword_nodev - read a dword from a pci device
+ * @ops: pointer to a &struct pci_ops that will be used to read from the pci
+ * device
+ * @bus: the bus of the pci device to read from
+ * @slot: the pci slot number of the pci device to read from
+ * @function: the function of the pci device to read from
+ * @where: the location on the pci address space to read from
+ * @value: pointer to where to place the data read
+ *
+ * Like pci_read_config_dword() but works for pci devices that do not have a
+ * pci_dev structure set up yet.
+ * Returns 0 on success.
+ */
+int pci_read_config_dword_nodev (struct pci_ops *ops, u8 bus, u8 slot, u8 function, int where, u32 *value)
+{
+ struct pci_dev *dev = NULL;
+ int result;
+
+ dbg("%p, %d, %d, %d, %d, %p\n", ops, bus, slot, function, where, value);
+ dev = pci_find_slot(bus, PCI_DEVFN(slot, function));
+ if (dev) {
+ dbg("using native pci_dev\n");
+ return pci_read_config_dword (dev, where, value);
+ }
+
+ result = build_dev (ops, bus, slot, function, &dev);
+ if (result)
+ return result;
+ result = pci_read_config_dword(dev, where, value);
+ kfree (dev->bus);
+ kfree (dev);


+ return result;
+}
+

+/**
+ * pci_write_config_byte_nodev - write a byte to a pci device
+ * @ops: pointer to a &struct pci_ops that will be used to write to the pci
+ * device
+ * @bus: the bus of the pci device to write to
+ * @slot: the pci slot number of the pci device to write to
+ * @function: the function of the pci device to write to
+ * @where: the location on the pci address space to write to
+ * @value: the value to write to the pci device
+ *
+ * Like pci_write_config_byte() but works for pci devices that do not have a
+ * pci_dev structure set up yet.
+ * Returns 0 on success.
+ */
+int pci_write_config_byte_nodev (struct pci_ops *ops, u8 bus, u8 slot, u8 function, int where, u8 value)
+{
+ struct pci_dev *dev = NULL;
+ int result;
+
+ dbg("%p, %d, %d, %d, %d, %d\n", ops, bus, slot, function, where, value);
+ dev = pci_find_slot(bus, PCI_DEVFN(slot, function));
+ if (dev) {
+ dbg("using native pci_dev\n");
+ return pci_write_config_byte (dev, where, value);
+ }
+
+ result = build_dev (ops, bus, slot, function, &dev);
+ if (result)
+ return result;
+ result = pci_write_config_byte(dev, where, value);
+ kfree (dev->bus);
+ kfree (dev);


+ return result;
+}
+

+/**
+ * pci_write_config_word_nodev - write a word to a pci device
+ * @ops: pointer to a &struct pci_ops that will be used to write to the pci
+ * device
+ * @bus: the bus of the pci device to write to
+ * @slot: the pci slot number of the pci device to write to
+ * @function: the function of the pci device to write to
+ * @where: the location on the pci address space to write to
+ * @value: the value to write to the pci device
+ *
+ * Like pci_write_config_word() but works for pci devices that do not have a
+ * pci_dev structure set up yet.
+ * Returns 0 on success.
+ */
+int pci_write_config_word_nodev (struct pci_ops *ops, u8 bus, u8 slot, u8 function, int where, u16 value)
+{
+ struct pci_dev *dev = NULL;
+ int result;
+
+ dbg("%p, %d, %d, %d, %d, %d\n", ops, bus, slot, function, where, value);
+ dev = pci_find_slot(bus, PCI_DEVFN(slot, function));
+ if (dev) {
+ dbg("using native pci_dev\n");
+ return pci_write_config_word (dev, where, value);
+ }
+
+ result = build_dev (ops, bus, slot, function, &dev);
+ if (result)
+ return result;
+ result = pci_write_config_word(dev, where, value);
+ kfree (dev->bus);
+ kfree (dev);


+ return result;
+}
+

+/**
+ * pci_write_config_dword_nodev - write a dword to a pci device
+ * @ops: pointer to a &struct pci_ops that will be used to write to the pci
+ * device
+ * @bus: the bus of the pci device to write to
+ * @slot: the pci slot number of the pci device to write to
+ * @function: the function of the pci device to write to
+ * @where: the location on the pci address space to write to
+ * @value: the value to write to the pci device
+ *
+ * Like pci_write_config_dword() but works for pci devices that do not have a
+ * pci_dev structure set up yet.
+ * Returns 0 on success.
+ */
+int pci_write_config_dword_nodev (struct pci_ops *ops, u8 bus, u8 slot, u8 function, int where, u32 value)
+{
+ struct pci_dev *dev = NULL;
+ int result;
+
+ dbg("%p, %d, %d, %d, %d, %d\n", ops, bus, slot, function, where, value);
+ dev = pci_find_slot(bus, PCI_DEVFN(slot, function));
+ if (dev) {
+ dbg("using native pci_dev\n");
+ return pci_write_config_dword (dev, where, value);
+ }
+
+ result = build_dev (ops, bus, slot, function, &dev);
+ if (result)
+ return result;
+ result = pci_write_config_dword(dev, where, value);
+ kfree (dev->bus);
+ kfree (dev);
+ return result;
+}
+
+/*
+ * This is code that scans the pci buses.
+ * Every bus and every function is presented to a custom
+ * function that can act upon it.
+ */
+
+static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_parent)
+{
+ struct list_head *ln;
+ struct pci_dev *dev;
+ struct pci_dev_wrapped wrapped_dev;
+ int result = 0;
+
+ dbg("scanning bus %02x\n", wrapped_bus->bus->number);
+
+ if (fn->pre_visit_pci_bus) {
+ result = fn->pre_visit_pci_bus(wrapped_bus, wrapped_parent);
+ if (result)


+ return result;
+ }
+

+ ln = wrapped_bus->bus->devices.next;
+ while (ln != &wrapped_bus->bus->devices) {
+ dev = pci_dev_b(ln);
+ ln = ln->next;
+
+ memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
+ wrapped_dev.dev = dev;
+
+ result = pci_visit_dev(fn, &wrapped_dev, wrapped_bus);
+ if (result)


+ return result;
+ }
+

+ if (fn->post_visit_pci_bus)
+ result = fn->post_visit_pci_bus(wrapped_bus, wrapped_parent);
+
+ return result;
+}
+
+
+static int pci_visit_bridge (struct pci_visit * fn, struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_parent)
+{
+ struct pci_bus *bus = wrapped_dev->dev->subordinate;
+ struct pci_bus_wrapped wrapped_bus;
+ int result;
+
+ memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
+ wrapped_bus.bus = bus;
+
+ dbg("scanning bridge %02x, %02x\n", wrapped_dev->dev->devfn >> 3,
+ wrapped_dev->dev->devfn & 0x7);
+
+ if (fn->visit_pci_dev) {
+ result = fn->visit_pci_dev(wrapped_dev, wrapped_parent);
+ if (result)


+ return result;
+ }
+

+ result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev);


+ return result;
+}
+
+

+int pci_visit_dev (struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_parent)
+{
+ struct pci_dev* dev = wrapped_dev ? wrapped_dev->dev : NULL;
+ int result = 0;
+
+ if (!dev)
+ return 0;
+
+ if (fn->pre_visit_pci_dev) {
+ result = fn->pre_visit_pci_dev(wrapped_dev, wrapped_parent);
+ if (result)


+ return result;
+ }
+

+ switch (dev->class >> 8) {
+ case PCI_CLASS_BRIDGE_PCI:
+ result = pci_visit_bridge(fn, wrapped_dev,
+ wrapped_parent);
+ if (result)
+ return result;
+ break;
+ default:
+ dbg("scanning device %02x, %02x\n",
+ PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+ if (fn->visit_pci_dev) {
+ result = fn->visit_pci_dev (wrapped_dev,
+ wrapped_parent);
+ if (result)
+ return result;
+ }
+ }
+
+ if (fn->post_visit_pci_dev)
+ result = fn->post_visit_pci_dev(wrapped_dev, wrapped_parent);
+
+ return result;
+}
+
+
+EXPORT_SYMBOL(pci_visit_dev);
+EXPORT_SYMBOL(pci_read_config_byte_nodev);
+EXPORT_SYMBOL(pci_read_config_word_nodev);
+EXPORT_SYMBOL(pci_read_config_dword_nodev);
+EXPORT_SYMBOL(pci_write_config_byte_nodev);
+EXPORT_SYMBOL(pci_write_config_word_nodev);
+EXPORT_SYMBOL(pci_write_config_dword_nodev);
+
diff -u --recursive --new-file v2.4.14/linux/drivers/i2c/i2c-core.c linux/drivers/i2c/i2c-core.c
--- v2.4.14/linux/drivers/i2c/i2c-core.c Tue Oct 23 22:48:50 2001
+++ linux/drivers/i2c/i2c-core.c Mon Nov 5 18:15:40 2001
@@ -1284,7 +1284,7 @@
X #ifdef CONFIG_I2C_ALGOBIT
X extern int i2c_algo_bit_init(void);
X #endif
-#ifdef CONFIG_I2C_CONFIG_I2C_PHILIPSPAR
+#ifdef CONFIG_I2C_PHILIPSPAR
X extern int i2c_bitlp_init(void);
X #endif
X #ifdef CONFIG_I2C_ELV
diff -u --recursive --new-file v2.4.14/linux/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c
--- v2.4.14/linux/drivers/ide/ide-disk.c Tue Oct 23 22:48:51 2001
+++ linux/drivers/ide/ide-disk.c Tue Nov 20 21:35:28 2001
@@ -690,7 +690,7 @@
X ide_add_setting(drive, "multcount", id ? SETTING_RW : SETTING_READ, HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, TYPE_BYTE, 0, id ? id->max_multsect : 0, 1, 2, &drive->mult_count, set_multcount);
X ide_add_setting(drive, "nowerr", SETTING_RW, HDIO_GET_NOWERR, HDIO_SET_NOWERR, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr);
X ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL);
- ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL);
+ ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, 4096, PAGE_SIZE, 1024, &max_readahead[major][minor], NULL);
X ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL);
X ide_add_setting(drive, "lun", SETTING_RW, -1, -1, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL);
X ide_add_setting(drive, "failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL);
diff -u --recursive --new-file v2.4.14/linux/drivers/ide/ide-geometry.c linux/drivers/ide/ide-geometry.c
--- v2.4.14/linux/drivers/ide/ide-geometry.c Thu Jan 4 12:50:17 2001
+++ linux/drivers/ide/ide-geometry.c Fri Nov 9 14:23:34 2001
@@ -71,8 +71,8 @@
X drive->sect = drive->bios_sect = sect;
X drive->ctl = *(BIOS+8);
X } else {
- printk("hd%d: C/H/S=%d/%d/%d from BIOS ignored\n",
- unit, cyl, head, sect);
+ printk("hd%c: C/H/S=%d/%d/%d from BIOS ignored\n",
+ unit+'a', cyl, head, sect);
X }
X }
X
diff -u --recursive --new-file v2.4.14/linux/drivers/ide/pdc202xx.c linux/drivers/ide/pdc202xx.c
--- v2.4.14/linux/drivers/ide/pdc202xx.c Mon Nov 5 15:55:30 2001
+++ linux/drivers/ide/pdc202xx.c Wed Nov 14 11:44:03 2001
@@ -230,6 +230,7 @@
X "QUANTUM FIREBALLP KA6.4",
X "QUANTUM FIREBALLP LM20.4",
X "QUANTUM FIREBALLP KX20.5",
+ "QUANTUM FIREBALLP KX27.3",
X "QUANTUM FIREBALLP LM20.5",
X NULL
X };
diff -u --recursive --new-file v2.4.14/linux/drivers/ide/pdcraid.c linux/drivers/ide/pdcraid.c
--- v2.4.14/linux/drivers/ide/pdcraid.c Tue Oct 23 22:48:51 2001
+++ linux/drivers/ide/pdcraid.c Tue Nov 13 09:19:41 2001
@@ -12,9 +12,7 @@
X
X Authors: Arjan van de Ven <arj...@redhat.com>
X
-
-
-
+ Based on work done by Søren Schmidt for FreeBSD
X
X */
X
@@ -54,6 +52,12 @@
X {IDE2_MAJOR, 64, -1 },
X {IDE3_MAJOR, 0, -1 },
X {IDE3_MAJOR, 64, -1 },
+ {IDE4_MAJOR, 0, -1 },
+ {IDE4_MAJOR, 64, -1 },
+ {IDE5_MAJOR, 0, -1 },
+ {IDE5_MAJOR, 64, -1 },
+ {IDE6_MAJOR, 0, -1 },
+ {IDE6_MAJOR, 64, -1 },
X };
X
X
@@ -96,9 +100,7 @@
X static int pdcraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
X {
X unsigned int minor;
- unsigned long sectors,*larg;
-
-
+ unsigned long sectors;
X
X if (!inode || !inode->i_rdev)
X return -EINVAL;
@@ -279,10 +281,6 @@
X * Let the main block layer submit the IO and resolve recursion:
X */
X return 1;
-
- outerr:
- buffer_IO_error(bh);
- return 0;
X }
X
X static int pdcraid1_write_request(request_queue_t *q, int rw, struct buffer_head * bh)
@@ -547,17 +545,10 @@
X
X static __init int pdcraid_init_one(int device,int raidlevel)
X {
- request_queue_t *q;
- int i,count;
+ int i, count;
X
- probedisk(0, device, raidlevel);
- probedisk(1, device, raidlevel);
- probedisk(2, device, raidlevel);
- probedisk(3, device, raidlevel);
- probedisk(4, device, raidlevel);
- probedisk(5, device, raidlevel);
- probedisk(6, device, raidlevel);
- probedisk(7, device, raidlevel);
+ for (i=0; i<14; i++)
+ probedisk(i, device, raidlevel);
X
X if (raidlevel==0)
X fill_cutoff(device);
@@ -585,10 +576,9 @@
X
X static __init int pdcraid_init(void)
X {
- int i,retval,device,count=0;
+ int retval, device, count = 0;
X
X do {
-
X cookie = 0;
X device=ataraid_get_device(&pdcraid0_ops);
X if (device<0)
diff -u --recursive --new-file v2.4.14/linux/drivers/ieee1394/ieee1394_syms.c linux/drivers/ieee1394/ieee1394_syms.c
--- v2.4.14/linux/drivers/ieee1394/ieee1394_syms.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/ieee1394/ieee1394_syms.c Sun Nov 11 10:09:32 2001
@@ -84,4 +84,5 @@
X EXPORT_SYMBOL(hpsb_register_protocol);
X EXPORT_SYMBOL(hpsb_unregister_protocol);
X EXPORT_SYMBOL(hpsb_release_unit_directory);
+
X MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/ieee1394/pcilynx.c linux/drivers/ieee1394/pcilynx.c
--- v2.4.14/linux/drivers/ieee1394/pcilynx.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/ieee1394/pcilynx.c Sun Nov 11 10:20:21 2001


@@ -1637,8 +1637,8 @@
X

X static void __exit pcilynx_cleanup(void)
X {
+ pci_unregister_driver(&lynx_pcidriver);
X hpsb_unregister_lowlevel(&lynx_template);
- pci_unregister_driver(&lynx_pcidriver);
X PRINT_G(KERN_INFO, "removed " PCILYNX_DRIVER_NAME " module");
X }
X
diff -u --recursive --new-file v2.4.14/linux/drivers/isdn/eicon/eicon_idi.c linux/drivers/isdn/eicon/eicon_idi.c
--- v2.4.14/linux/drivers/isdn/eicon/eicon_idi.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/isdn/eicon/eicon_idi.c Fri Nov 9 13:41:41 2001
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.c,v 1.41.6.3 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_idi.c,v 1.41.6.4 2001/11/06 20:58:29 kai Exp $
X *
X * ISDN lowlevel-module for Eicon active cards.
X * IDI interface
@@ -25,7 +25,7 @@
X
X #undef EICON_FULL_SERVICE_OKTETT
X
-char *eicon_idi_revision = "$Revision: 1.41.6.3 $";
+char *eicon_idi_revision = "$Revision: 1.41.6.4 $";
X
X eicon_manifbuf *manbuf;
X
@@ -3119,8 +3119,8 @@


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

echo 'End of part 045'
echo 'File patch-2.4.15 is continued in part 046'
echo "046" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:12 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part036

#!/bin/sh -x
# this is part 036 of a 115 - part archive


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

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

X
X probe_interrupts:


+ for (i = 0; i < PROMINTR_MAX; i++)
+ dev->irqs[i] = PCI_IRQ_NONE;
+
X len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
X if ((len == -1) || (len == 0)) {
X dev->num_irqs = 0;

diff -u --recursive --new-file v2.4.14/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.4.14/linux/arch/sparc64/kernel/ioctl32.c Mon Nov 5 15:55:27 2001
+++ linux/arch/sparc64/kernel/ioctl32.c Tue Nov 13 09:16:05 2001
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.127 2001/11/01 23:54:19 davem Exp $
+/* $Id: ioctl32.c,v 1.132 2001/11/07 05:56:19 davem Exp $
X * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
X *
X * Copyright (C) 1997-2000 Jakub Jelinek (ja...@redhat.com)
@@ -71,6 +71,7 @@
X #include <asm/audioio.h>
X #include <linux/ethtool.h>
X #include <linux/mii.h>
+#include <linux/if_bonding.h>
X #include <asm/display7seg.h>
X #include <asm/watchdog.h>
X #include <asm/module.h>
@@ -456,6 +457,7 @@
X __kernel_caddr_t32 ifcbuf;
X };
X
+#ifdef CONFIG_NET
X static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
X {
X struct net_device *dev;
@@ -474,6 +476,7 @@
X err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32));
X return (err ? -EFAULT : 0);
X }
+#endif
X
X static inline int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
X {
@@ -564,9 +567,25 @@
X }
X switch (ethcmd) {
X case ETHTOOL_GDRVINFO: len = sizeof(struct ethtool_drvinfo); break;
+ case ETHTOOL_GMSGLVL:
+ case ETHTOOL_SMSGLVL:
+ case ETHTOOL_GLINK:
+ case ETHTOOL_NWAY_RST: len = sizeof(struct ethtool_value); break;
+ case ETHTOOL_GREGS: {
+ struct ethtool_regs *regaddr = (struct ethtool_regs *)A(data);
+ /* darned variable size arguments */
+ if (get_user(len, (u32 *)&regaddr->len)) {
+ err = -EFAULT;
+ goto out;
+ }
+ len += sizeof(struct ethtool_regs);
+ break;
+ }
X case ETHTOOL_GSET:
- case ETHTOOL_SSET:
- default: len = sizeof(struct ethtool_cmd); break;
+ case ETHTOOL_SSET: len = sizeof(struct ethtool_cmd); break;
+ default:
+ err = -EOPNOTSUPP;
+ goto out;
X }
X
X if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) {
@@ -592,6 +611,58 @@


X return err;
X }
X

+static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg)
+{
+ struct ifreq ifr;
+ mm_segment_t old_fs;
+ int err, len;
+ u32 data;
+
+ if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
+ return -EFAULT;
+ ifr.ifr_data = (__kernel_caddr_t)get_free_page(GFP_KERNEL);
+ if (!ifr.ifr_data)
+ return -EAGAIN;
+
+ switch (cmd) {
+ case SIOCBONDENSLAVE:
+ case SIOCBONDRELEASE:
+ case SIOCBONDSETHWADDR:
+ case SIOCBONDCHANGEACTIVE:
+ len = IFNAMSIZ * sizeof(char);
+ break;
+ case SIOCBONDSLAVEINFOQUERY:
+ len = sizeof(struct ifslave);
+ break;
+ case SIOCBONDINFOQUERY:
+ len = sizeof(struct ifbond);
+ break;
+ default:
+ err = -EINVAL;


+ goto out;
+ };
+

+ __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
+ if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) {
+ err = -EFAULT;


+ goto out;
+ }
+

+ old_fs = get_fs();
+ set_fs (KERNEL_DS);
+ err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
+ set_fs (old_fs);
+ if (!err) {
+ len = copy_to_user((char *)A(data), ifr.ifr_data, len);
+ if (len)


+ err = -EFAULT;
+ }
+

+out:
+ free_page((unsigned long)ifr.ifr_data);


+ return err;
+}
+

X static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg)
X {
X struct ifreq ifr;
@@ -4455,7 +4526,9 @@
X /* And these ioctls need translation */
X HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob)
X HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob)
+#ifdef CONFIG_NET
X HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
+#endif
X HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
X HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc)
X HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc)
@@ -4488,6 +4561,12 @@
X HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc)
X HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc)
X HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl)
+HANDLE_IOCTL(SIOCBONDENSLAVE, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDRELEASE, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDSETHWADDR, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDSLAVEINFOQUERY, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDINFOQUERY, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDCHANGEACTIVE, bond_ioctl)
X HANDLE_IOCTL(SIOCADDRT, routing_ioctl)
X HANDLE_IOCTL(SIOCDELRT, routing_ioctl)
X /* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */
diff -u --recursive --new-file v2.4.14/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c
--- v2.4.14/linux/arch/sparc64/kernel/irq.c Tue Jul 3 17:08:19 2001
+++ linux/arch/sparc64/kernel/irq.c Tue Nov 13 09:16:05 2001
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.101 2001/06/04 06:50:18 ecd Exp $
+/* $Id: irq.c,v 1.109 2001/11/12 22:22:37 davem Exp $
X * irq.c: UltraSparc IRQ handling/init/registry.
X *
X * Copyright (C) 1997 David S. Miller (da...@caip.rutgers.edu)
@@ -14,9 +14,10 @@
X #include <linux/mm.h>
X #include <linux/interrupt.h>
X #include <linux/slab.h>
-#include <linux/random.h> /* XXX ADD add_foo_randomness() calls... -DaveM */
+#include <linux/random.h>
X #include <linux/init.h>
X #include <linux/delay.h>
+#include <linux/proc_fs.h>
X
X #include <asm/ptrace.h>
X #include <asm/processor.h>
@@ -32,10 +33,7 @@
X #include <asm/hardirq.h>
X #include <asm/softirq.h>
X #include <asm/starfire.h>
-
-/* Internal flag, should not be visible elsewhere at all. */
-#define SA_IMAP_MASKED 0x100
-#define SA_DMA_SYNC 0x200
+#include <asm/uaccess.h>
X
X #ifdef CONFIG_SMP
X static void distribute_irqs(void);
@@ -64,7 +62,7 @@
X #endif
X
X #ifdef CONFIG_PCI
-/* This is a table of physical addresses used to deal with SA_DMA_SYNC.
+/* This is a table of physical addresses used to deal with IBF_DMA_SYNC.
X * It is used for PCI only to synchronize DMA transfers with IRQ delivery
X * for devices behind busses other than APB on Sabre systems.
X *
@@ -89,6 +87,23 @@
X NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
X };
X
+static void register_irq_proc (unsigned int irq);
+
+/*
+ * Upper 2b of irqaction->flags holds the ino.
+ * irqaction->mask holds the smp affinity information.
+ */
+#define put_ino_in_irqaction(action, irq) \
+ action->flags &= 0xffffffffffffUL; \
+ if (__bucket(irq) == &pil0_dummy_bucket) \
+ action->flags |= 0xdeadUL << 48; \
+ else \
+ action->flags |= __irq_ino(irq) << 48;
+#define get_ino_in_irqaction(action) (action->flags >> 48)
+
+#define put_smpaff_in_irqaction(action, smpaff) (action)->mask = (smpaff)
+#define get_smpaff_in_irqaction(action) ((action)->mask)
+
X int get_irq_list(char *buf)
X {
X int i, len = 0;
@@ -108,13 +123,11 @@
X len += sprintf(buf + len, "%10u ",
X kstat.irqs[cpu_logical_map(j)][i]);
X #endif
- len += sprintf(buf + len, "%c %s",
- (action->flags & SA_INTERRUPT) ? '+' : ' ',
- action->name);
+ len += sprintf(buf + len, " %s:%lx", action->name, \
+ get_ino_in_irqaction(action));
X for(action = action->next; action; action = action->next) {
- len += sprintf(buf+len, ",%s %s",
- (action->flags & SA_INTERRUPT) ? " +" : "",
- action->name);
+ len += sprintf(buf+len, ", %s:%lx", action->name, \
+ get_ino_in_irqaction(action));
X }
X len += sprintf(buf + len, "\n");
X }
@@ -286,23 +299,18 @@
X if(!handler)
X return -EINVAL;
X
- if (!bucket->pil)
- irqflags &= ~SA_IMAP_MASKED;
- else {
- irqflags |= SA_IMAP_MASKED;
- if (bucket->flags & IBF_PCI) {
- /*
- * PCI IRQs should never use SA_INTERRUPT.
- */
- irqflags &= ~(SA_INTERRUPT);
-
- /*
- * Check wether we _should_ use DMA Write Sync
- * (for devices behind bridges behind APB).
- */
- if (bucket->flags & IBF_DMA_SYNC)
- irqflags |= SA_DMA_SYNC;
- }
+ if ((bucket != &pil0_dummy_bucket) && (irqflags & SA_SAMPLE_RANDOM)) {
+ /*
+ * This function might sleep, we want to call it first,
+ * outside of the atomic block. In SA_STATIC_ALLOC case,
+ * random driver's kmalloc will fail, but it is safe.
+ * If already initialized, random driver will not reinit.
+ * Yes, this might clear the entropy pool if the wrong
+ * driver is attempted to be loaded, without actually
+ * installing a new handler, but is this really a problem,
+ * only the sysadmin is able to do this.
+ */
+ rand_initialize_irq(irq);
X }
X
X save_and_cli(flags);
@@ -316,12 +324,6 @@
X restore_flags(flags);
X return -EBUSY;
X }
- if((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
- printk("Attempt to mix fast and slow interrupts on IRQ%d "
- "denied\n", bucket->pil);
- restore_flags(flags);
- return -EBUSY;
- }
X action = NULL; /* Or else! */
X }
X
@@ -344,7 +346,7 @@
X return -ENOMEM;
X }
X
- if ((irqflags & SA_IMAP_MASKED) == 0) {
+ if (bucket == &pil0_dummy_bucket) {
X bucket->irq_info = action;
X bucket->flags |= IBF_ACTIVE;
X } else {
@@ -405,12 +407,13 @@
X bucket->pending = 0;
X }
X
- action->mask = (unsigned long) bucket;
X action->handler = handler;
X action->flags = irqflags;
X action->name = name;
X action->next = NULL;
X action->dev_id = dev_id;
+ put_ino_in_irqaction(action, irq);
+ put_smpaff_in_irqaction(action, 0);
X
X if(tmp)
X tmp->next = action;
@@ -425,6 +428,8 @@
X set_softint(1 << bucket->pil);
X }
X restore_flags(flags);
+ if ((bucket != &pil0_dummy_bucket) && (!(irqflags & SA_STATIC_ALLOC)))
+ register_irq_proc(__irq_ino(irq));
X
X #ifdef CONFIG_SMP
X distribute_irqs();
@@ -492,7 +497,7 @@
X else
X *(bucket->pil + irq_action) = action->next;
X
- if(action->flags & SA_IMAP_MASKED) {
+ if (bucket != &pil0_dummy_bucket) {
X unsigned long imap = bucket->imap;
X void **vector, *orig;
X int ent;
@@ -716,36 +721,80 @@
X /* Tune this... */
X #define FORWARD_VOLUME 12
X
-void handler_irq(int irq, struct pt_regs *regs)
-{
- struct ino_bucket *bp, *nbp;
- int cpu = smp_processor_id();
X #ifdef CONFIG_SMP
- int should_forward = (this_is_starfire == 0 &&
- irq < 10 &&
- current->pid != 0);
- unsigned int buddy = 0;
+
+static inline void redirect_intr(int cpu, struct ino_bucket *bp)
+{
+ /* Ok, here is what is going on:
+ * 1) Retargeting IRQs on Starfire is very
+ * expensive so just forget about it on them.
+ * 2) Moving around very high priority interrupts
+ * is a losing game.
+ * 3) If the current cpu is idle, interrupts are
+ * useful work, so keep them here. But do not
+ * pass to our neighbour if he is not very idle.
+ * 4) If sysadmin explicitly asks for directed intrs,
+ * Just Do It.
+ */
+ struct irqaction *ap = bp->irq_info;
+ unsigned long cpu_mask = get_smpaff_in_irqaction(ap);
+ unsigned int buddy, ticks;
+
+ if (cpu_mask == 0)
+ cpu_mask = ~0UL;
+
+ if (this_is_starfire != 0 ||
+ bp->pil >= 10 || current->pid == 0)
+ goto out;
X
X /* 'cpu' is the MID (ie. UPAID), calculate the MID
X * of our buddy.
X */
- if (should_forward != 0) {
- buddy = cpu_number_map(cpu) + 1;
+ buddy = cpu_number_map(cpu) + 1;
+ if (buddy >= NR_CPUS ||
+ cpu_logical_map(buddy) == -1)
+ buddy = 0;
+
+ ticks = 0;
+ while ((cpu_mask & (1UL << buddy)) == 0) {
+ buddy++;
X if (buddy >= NR_CPUS ||
- (buddy = cpu_logical_map(buddy)) == -1)
+ cpu_logical_map(buddy) == -1)
X buddy = cpu_logical_map(0);
+ if (++ticks > NR_CPUS) {
+ put_smpaff_in_irqaction(ap, 0);


+ goto out;
+ }
+ }

X
- /* Voo-doo programming. */
- if (cpu_data[buddy].idle_volume < FORWARD_VOLUME)
- should_forward = 0;
+ if (buddy == cpu_number_map(cpu))
+ goto out;
+
+ buddy = cpu_logical_map(buddy);
+
+ /* Voo-doo programming. */
+ if (cpu_data[buddy].idle_volume < FORWARD_VOLUME)
+ goto out;
+
+ /* This just so happens to be correct on Cheetah
+ * at the moment.
+ */
+ buddy <<= 26;
+
+ /* Push it to our buddy. */
+ upa_writel(buddy | IMAP_VALID, bp->imap);
+
+out:
+ return;
+}
X
- /* This just so happens to be correct on Cheetah
- * at the moment.
- */
- buddy <<= 26;
- }
X #endif
X
+void handler_irq(int irq, struct pt_regs *regs)
+{
+ struct ino_bucket *bp, *nbp;
+ int cpu = smp_processor_id();
+
X #ifndef CONFIG_SMP
X /*
X * Check for TICK_INT on level 14 softint.
@@ -765,6 +814,8 @@
X clear_softint(clr_mask);
X }
X #else
+ int should_forward = 1;
+
X clear_softint(1 << irq);
X #endif
X
@@ -781,6 +832,7 @@
X #endif
X for ( ; bp != NULL; bp = nbp) {
X unsigned char flags = bp->flags;
+ unsigned char random = 0;
X
X nbp = __bucket(bp->irq_chain);
X bp->irq_chain = 0;
@@ -795,34 +847,30 @@
X if ((flags & IBF_MULTI) == 0) {
X struct irqaction *ap = bp->irq_info;
X ap->handler(__irq(bp), ap->dev_id, regs);
+ random |= ap->flags & SA_SAMPLE_RANDOM;
X } else {
X void **vector = (void **)bp->irq_info;
X int ent;
X for (ent = 0; ent < 4; ent++) {
X struct irqaction *ap = vector[ent];
- if (ap != NULL)
+ if (ap != NULL) {
X ap->handler(__irq(bp), ap->dev_id, regs);
+ random |= ap->flags & SA_SAMPLE_RANDOM;
+ }
X }
X }
X /* Only the dummy bucket lacks IMAP/ICLR. */
X if (bp->pil != 0) {
X #ifdef CONFIG_SMP
- /* Ok, here is what is going on:
- * 1) Retargeting IRQs on Starfire is very
- * expensive so just forget about it on them.
- * 2) Moving around very high priority interrupts
- * is a losing game.
- * 3) If the current cpu is idle, interrupts are
- * useful work, so keep them here. But do not
- * pass to our neighbour if he is not very idle.
- */
- if (should_forward != 0) {
- /* Push it to our buddy. */
+ if (should_forward) {
+ redirect_intr(cpu, bp);
X should_forward = 0;
- upa_writel(buddy | IMAP_VALID, bp->imap);
X }
X #endif
X upa_writel(ICLR_IDLE, bp->iclr);
+ /* Test and add entropy */
+ if (random)
+ add_interrupt_randomness(irq);
X }
X } else
X bp->pending = 1;
@@ -843,7 +891,7 @@
X kstat.irqs[cpu][irq]++;
X
X *(irq_work(cpu, irq)) = 0;
- bucket = (struct ino_bucket *)action->mask;
+ bucket = get_ino_in_irqaction(action) + ivector_table;
X
X floppy_interrupt(irq, dev_cookie, regs);
X upa_writel(ICLR_IDLE, bucket->iclr);
@@ -896,10 +944,6 @@
X return -EINVAL;
X }
X
- /* Only IMAP style interrupts can be registered as fast. */
- if(bucket->pil == 0)
- return -EINVAL;
-
X if(!handler)
X return -EINVAL;
X
@@ -918,6 +962,10 @@
X return -EBUSY;
X }
X
+ /*
+ * We do not check for SA_SAMPLE_RANDOM in this path. Neither do we
+ * support smp intr affinity in this path.
+ */
X save_and_cli(flags);
X if(irqflags & SA_STATIC_ALLOC) {
X if(static_irq_count < MAX_STATIC_ALLOC)
@@ -938,12 +986,13 @@
X bucket->irq_info = action;
X bucket->flags |= IBF_ACTIVE;
X
- action->mask = (unsigned long) bucket;
X action->handler = handler;
- action->flags = irqflags | SA_IMAP_MASKED;
+ action->flags = irqflags;
X action->dev_id = NULL;
X action->name = name;
X action->next = NULL;
+ put_ino_in_irqaction(action, irq);
+ put_smpaff_in_irqaction(action, 0);
X
X *(bucket->pil + irq_action) = action;
X enable_irq(irq);
@@ -993,7 +1042,7 @@
X #endif
X
X /* Register IRQ handler. */
- err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, (SA_INTERRUPT | SA_STATIC_ALLOC),
+ err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, SA_STATIC_ALLOC,
X "timer", NULL);
X
X if(err) {
@@ -1079,14 +1128,10 @@
X #ifdef CONFIG_SMP
X static int retarget_one_irq(struct irqaction *p, int goal_cpu)
X {
- struct ino_bucket *bucket = __bucket(p->mask);
+ struct ino_bucket *bucket = get_ino_in_irqaction(p) + ivector_table;
X unsigned long imap = bucket->imap;
X unsigned int tid;
X
- /* Never change this, it causes problems on Ex000 systems. */
- if (bucket->pil == 12)
- return goal_cpu;
-
X if (tlb_type == cheetah) {
X tid = __cpu_logical_map[goal_cpu] << 26;
X tid &= IMAP_AID_SAFARI;
@@ -1114,11 +1159,16 @@
X
X save_and_cli(flags);
X cpu = 0;
- for(level = 0; level < NR_IRQS; level++) {
+
+ /*
+ * Skip the timer at [0], and very rare error/power intrs at [15].
+ * Also level [12], it causes problems on Ex000 systems.
+ */
+ for(level = 1; level < NR_IRQS; level++) {
X struct irqaction *p = irq_action[level];
+ if (level == 12) continue;
X while(p) {
- if(p->flags & SA_IMAP_MASKED)
- cpu = retarget_one_irq(p, cpu);
+ cpu = retarget_one_irq(p, cpu);
X p = p->next;
X }
X }
@@ -1228,7 +1278,173 @@
X : "g1");
X }
X
-void init_irq_proc(void)
+static struct proc_dir_entry * root_irq_dir;
+static struct proc_dir_entry * irq_dir [NUM_IVECS];
+
+#ifdef CONFIG_SMP
+
+#define HEX_DIGITS 16
+
+static unsigned int parse_hex_value (const char *buffer,
+ unsigned long count, unsigned long *ret)
X {
- /* For now, nothing... */
+ unsigned char hexnum [HEX_DIGITS];
+ unsigned long value;
+ int i;
+
+ if (!count)
+ return -EINVAL;
+ if (count > HEX_DIGITS)
+ count = HEX_DIGITS;
+ if (copy_from_user(hexnum, buffer, count))
+ return -EFAULT;
+
+ /*
+ * Parse the first 8 characters as a hex string, any non-hex char
+ * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
+ */
+ value = 0;
+
+ for (i = 0; i < count; i++) {
+ unsigned int c = hexnum[i];
+
+ switch (c) {
+ case '0' ... '9': c -= '0'; break;
+ case 'a' ... 'f': c -= 'a'-10; break;
+ case 'A' ... 'F': c -= 'A'-10; break;
+ default:
+ goto out;
+ }
+ value = (value << 4) | c;
+ }
+out:
+ *ret = value;
+ return 0;
X }
+
+static unsigned long hw_to_logical(unsigned long mask)
+{
+ unsigned long new_mask = 0UL;
+ int i;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ if (mask & (1UL << i)) {
+ int logical = cpu_number_map(i);
+
+ new_mask |= (1UL << logical);
+ }
+ }
+
+ return new_mask;
+}
+
+static unsigned long logical_to_hw(unsigned long mask)
+{
+ unsigned long new_mask = 0UL;
+ int i;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ if (mask & (1UL << i)) {
+ int hw = cpu_logical_map(i);
+
+ new_mask |= (1UL << hw);
+ }
+ }
+
+ return new_mask;
+}


+
+static int irq_affinity_read_proc (char *page, char **start, off_t off,

+ int count, int *eof, void *data)
+{
+ struct ino_bucket *bp = ivector_table + (long)data;
+ struct irqaction *ap = bp->irq_info;
+ unsigned long mask = get_smpaff_in_irqaction(ap);
+
+ mask = logical_to_hw(mask);


+
+ if (count < HEX_DIGITS+1)
+ return -EINVAL;

+ return sprintf (page, "%016lx\n", mask == 0 ? ~0UL : mask);
+}
+
+static inline void set_intr_affinity(int irq, unsigned long hw_aff)
+{
+ struct ino_bucket *bp = ivector_table + irq;
+ unsigned long aff = hw_to_logical(hw_aff);
+
+ /*
+ * Users specify affinity in terms of cpu ids, which is what
+ * is displayed via /proc/cpuinfo. As soon as we do this,
+ * handler_irq() might see and take action.
+ */
+ put_smpaff_in_irqaction((struct irqaction *)bp->irq_info, aff);
+
+ /* Migration is simply done by the next cpu to service this
+ * interrupt.
+ */
+}
+
+static int irq_affinity_write_proc (struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ int irq = (long) data, full_count = count, err;
+ unsigned long new_value;
+
+ err = parse_hex_value(buffer, count, &new_value);
+
+ /*
+ * Do not allow disabling IRQs completely - it's a too easy
+ * way to make the system unusable accidentally :-) At least
+ * one online CPU still has to be targeted.
+ */
+ new_value &= cpu_online_map;
+ if (!new_value)
+ return -EINVAL;
+
+ set_intr_affinity(irq, new_value);
+
+ return full_count;
+}
+
+#endif
+
+#define MAX_NAMELEN 10
+
+static void register_irq_proc (unsigned int irq)
+{
+ char name [MAX_NAMELEN];
+
+ if (!root_irq_dir || irq_dir[irq])
+ return;
+
+ memset(name, 0, MAX_NAMELEN);
+ sprintf(name, "%x", irq);
+
+ /* create /proc/irq/1234 */
+ irq_dir[irq] = proc_mkdir(name, root_irq_dir);
+
+#ifdef CONFIG_SMP
+ /* XXX SMP affinity not supported on starfire yet. */
+ if (this_is_starfire == 0) {


+ struct proc_dir_entry *entry;
+
+ /* create /proc/irq/1234/smp_affinity */
+ entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
+
+ if (entry) {
+ entry->nlink = 1;
+ entry->data = (void *)(long)irq;
+ entry->read_proc = irq_affinity_read_proc;
+ entry->write_proc = irq_affinity_write_proc;
+ }

+ }
+#endif
+}
+
+void init_irq_proc (void)
+{
+ /* create /proc/irq */
+ root_irq_dir = proc_mkdir("irq", 0);
+}
+
diff -u --recursive --new-file v2.4.14/linux/arch/sparc64/kernel/isa.c linux/arch/sparc64/kernel/isa.c
--- v2.4.14/linux/arch/sparc64/kernel/isa.c Wed May 16 10:31:27 2001
+++ linux/arch/sparc64/kernel/isa.c Tue Nov 13 09:16:05 2001
@@ -74,7 +74,7 @@
X irq_prop = prom_getintdefault(isa_dev->prom_node,
X "interrupts", -1);
X if (irq_prop <= 0) {
- isa_dev->irq = 0;
+ isa_dev->irq = PCI_IRQ_NONE;
X } else {
X int i;
X
@@ -85,7 +85,7 @@
X int ino = grover_irq_table[i].pci_ino;
X
X if (ino == 0) {
- isa_dev->irq = 0;
+ isa_dev->irq = PCI_IRQ_NONE;
X } else {
X pbm = isa_dev->bus->parent;
X pcic = pbm->parent;
diff -u --recursive --new-file v2.4.14/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- v2.4.14/linux/arch/sparc64/kernel/setup.c Mon Nov 5 15:55:27 2001
+++ linux/arch/sparc64/kernel/setup.c Tue Nov 13 09:16:05 2001
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.70 2001/10/25 18:48:03 davem Exp $
+/* $Id: setup.c,v 1.71 2001/11/13 00:49:28 davem Exp $
X * linux/arch/sparc64/kernel/setup.c
X *
X * Copyright (C) 1995,1996 David S. Miller (da...@caip.rutgers.edu)


@@ -20,6 +20,7 @@
X #include <linux/delay.h>
X #include <linux/config.h>
X #include <linux/fs.h>
+#include <linux/seq_file.h>
X #include <linux/kdev_t.h>
X #include <linux/major.h>
X #include <linux/string.h>

@@ -606,54 +607,77 @@


X extern char *sparc_cpu_type[];
X extern char *sparc_fpu_type[];
X

-extern int smp_info(char *);
-extern int smp_bogo(char *);
-extern int mmu_info(char *);
+extern void smp_info(struct seq_file *);
+extern void smp_bogo(struct seq_file *);
+extern void mmu_info(struct seq_file *);
X
X #ifndef CONFIG_SMP
X unsigned long up_clock_tick;
X #endif


X
-int get_cpuinfo(char *buffer)
+static int show_cpuinfo(struct seq_file *m, void *__unused)
X {

- int cpuid=smp_processor_id();
- int len;
+ int cpuid = smp_processor_id();


X
- len = sprintf(buffer,

- "cpu\t\t: %s\n"


- "fpu\t\t: %s\n"

- "promlib\t\t: Version 3 Revision %d\n"
- "prom\t\t: %d.%d.%d\n"
- "type\t\t: sun4u\n"


- "ncpus probed\t: %d\n"
- "ncpus active\t: %d\n"
+ seq_printf(m,
+ "cpu\t\t: %s\n"
+ "fpu\t\t: %s\n"

+ "promlib\t\t: Version 3 Revision %d\n"
+ "prom\t\t: %d.%d.%d\n"
+ "type\t\t: sun4u\n"


+ "ncpus probed\t: %d\n"
+ "ncpus active\t: %d\n"
X #ifndef CONFIG_SMP

- "Cpu0Bogo\t: %lu.%02lu\n"
- "Cpu0ClkTck\t: %016lx\n"
+ "Cpu0Bogo\t: %lu.%02lu\n"
+ "Cpu0ClkTck\t: %016lx\n"
X #endif
- ,
- sparc_cpu_type[cpuid],
- sparc_fpu_type[cpuid],
- prom_rev, prom_prev >> 16, (prom_prev >> 8) & 0xff, prom_prev & 0xff,


- linux_num_cpus, smp_num_cpus
+ ,

+ sparc_cpu_type[cpuid],
+ sparc_fpu_type[cpuid],
+ prom_rev,
+ prom_prev >> 16,
+ (prom_prev >> 8) & 0xff,
+ prom_prev & 0xff,


+ linux_num_cpus,
+ smp_num_cpus
X #ifndef CONFIG_SMP

- , loops_per_jiffy/(500000/HZ), (loops_per_jiffy/(5000/HZ)) % 100,
- up_clock_tick
+ , loops_per_jiffy/(500000/HZ),
+ (loops_per_jiffy/(5000/HZ)) % 100,
+ up_clock_tick


X #endif
- );
+ );

X #ifdef CONFIG_SMP
- len += smp_bogo(buffer + len);
+ smp_bogo(m);


X #endif
- len += mmu_info(buffer + len);
+ mmu_info(m);
X #ifdef CONFIG_SMP
- len += smp_info(buffer + len);
+ smp_info(m);
X #endif

-#undef ZS_LOG
-#ifdef ZS_LOG
- {
- extern int zs_dumplog(char *);
- len += zs_dumplog(buffer + len);
- }
-#endif


- return len;
+ return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ /* The pointer we are returning is arbitrary,
+ * it just has to be non-NULL and not IS_ERR
+ * in the success case.
+ */
+ return *pos == 0 ? &c_start : NULL;

X }


+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return c_start(m, pos);
+}

+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+struct seq_operations cpuinfo_op = {
+ start: c_start,
+ next: c_next,
+ stop: c_stop,
+ show: show_cpuinfo,
+};

diff -u --recursive --new-file v2.4.14/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
--- v2.4.14/linux/arch/sparc64/kernel/smp.c Mon Nov 5 15:55:27 2001
+++ linux/arch/sparc64/kernel/smp.c Wed Nov 21 10:31:09 2001
@@ -15,6 +15,8 @@
X #include <linux/delay.h>
X #include <linux/init.h>
X #include <linux/spinlock.h>


+#include <linux/fs.h>
+#include <linux/seq_file.h>
X

X #include <asm/head.h>
X #include <asm/ptrace.h>
@@ -68,31 +70,30 @@
X
X __setup("maxcpus=", maxcpus);


X
-int smp_info(char *buf)
+void smp_info(struct seq_file *m)
X {

- int len = 7, i;
+ int i;
X
- strcpy(buf, "State:\n");


- for (i = 0; i < NR_CPUS; i++)

+ seq_printf(m, "State:\n");


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

X if (cpu_present_map & (1UL << i))


- len += sprintf(buf + len,

- "CPU%d:\t\tonline\n", i);


- return len;
+ seq_printf(m,

+ "CPU%d:\t\tonline\n", i);
+ }
X }
X
-int smp_bogo(char *buf)
+void smp_bogo(struct seq_file *m)


X {
- int len = 0, i;
+ int i;
X

X for (i = 0; i < NR_CPUS; i++)
X if (cpu_present_map & (1UL << i))


- len += sprintf(buf + len,

- "Cpu%dBogo\t: %lu.%02lu\n"
- "Cpu%dClkTck\t: %016lx\n",
- i, cpu_data[i].udelay_val / (500000/HZ),
- (cpu_data[i].udelay_val / (5000/HZ)) % 100,
- i, cpu_data[i].clock_tick);


- return len;
+ seq_printf(m,
+ "Cpu%dBogo\t: %lu.%02lu\n"

+ "Cpu%dClkTck\t: %016lx\n",
+ i, cpu_data[i].udelay_val / (500000/HZ),
+ (cpu_data[i].udelay_val / (5000/HZ)) % 100,
+ i, cpu_data[i].clock_tick);
X }
X
X void __init smp_store_cpu_info(int id)
@@ -275,7 +276,7 @@
X init_tasks[cpucount] = p;


X
X p->processor = i;
- p->has_cpu = 1; /* we schedule the first task manually */
+ p->cpus_runnable = 1 << i; /* we schedule the first task manually */
X

X del_from_runqueue(p);
X unhash_process(p);
@@ -559,19 +560,30 @@
X
X smp_cross_call(&xcall_call_function,
X 0, (u64) &data, 0);
- if (wait) {
- while (atomic_read(&data.finished) != cpus)
- barrier();
- }
+ /*
+ * Wait for other cpus to complete function or at
+ * least snap the call data.
+ */
+ while (atomic_read(&data.finished) != cpus)
+ barrier();
X

X return 0;
X }
X

X void smp_call_function_client(struct call_data_struct *call_data)
X {
- call_data->func(call_data->info);
- if (call_data->wait)
+ void (*func) (void *info) = call_data->func;
+ void *info = call_data->info;
+
+ if (call_data->wait) {
+ /* let initiator proceed only after completion */
+ func(info);
X atomic_inc(&call_data->finished);
+ } else {
+ /* let initiator proceed after getting data */
+ atomic_inc(&call_data->finished);
+ func(info);
+ }
X }
X
X extern unsigned long xcall_flush_tlb_page;
diff -u --recursive --new-file v2.4.14/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- v2.4.14/linux/arch/sparc64/mm/init.c Mon Nov 5 15:55:27 2001
+++ linux/arch/sparc64/mm/init.c Tue Nov 13 09:16:05 2001
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.199 2001/10/25 18:48:03 davem Exp $
+/* $Id: init.c,v 1.202 2001/11/13 00:49:28 davem Exp $
X * arch/sparc64/mm/init.c
X *
X * Copyright (C) 1996-1999 David S. Miller (da...@caip.rutgers.edu)
@@ -16,6 +16,9 @@
X #include <linux/blk.h>
X #include <linux/swap.h>
X #include <linux/swapctl.h>
+#include <linux/pagemap.h>


+#include <linux/fs.h>
+#include <linux/seq_file.h>
X

X #include <asm/head.h>
X #include <asm/system.h>
@@ -249,27 +252,23 @@
X show_buffers();
X }
X
-int mmu_info(char *buf)
+void mmu_info(struct seq_file *m)
X {
- int len;
-
X if (tlb_type == cheetah)
- len = sprintf(buf, "MMU Type\t: Cheetah\n");
+ seq_printf(m, "MMU Type\t: Cheetah\n");
X else if (tlb_type == spitfire)
- len = sprintf(buf, "MMU Type\t: Spitfire\n");
+ seq_printf(m, "MMU Type\t: Spitfire\n");
X else
- len = sprintf(buf, "MMU Type\t: ???\n");
+ seq_printf(m, "MMU Type\t: ???\n");
X
X #ifdef DCFLUSH_DEBUG
- len += sprintf(buf + len, "DCPageFlushes\t: %d\n",
- atomic_read(&dcpage_flushes));
+ seq_printf(m, "DCPageFlushes\t: %d\n",
+ atomic_read(&dcpage_flushes));
X #ifdef CONFIG_SMP
- len += sprintf(buf + len, "DCPageFlushesXC\t: %d\n",
- atomic_read(&dcpage_flushes_xcall));
+ seq_printf(m, "DCPageFlushesXC\t: %d\n",
+ atomic_read(&dcpage_flushes_xcall));


X #endif /* CONFIG_SMP */

X #endif /* DCFLUSH_DEBUG */
-
- return len;
X }
X
X struct linux_prom_translation {
@@ -1400,7 +1399,7 @@
X if (second_alias_page)
X spitfire_flush_dtlb_nucleus_page(second_alias_page);
X
- flush_tlb_all();
+ __flush_tlb_all();
X
X {
X unsigned long zones_size[MAX_NR_ZONES];
diff -u --recursive --new-file v2.4.14/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S
--- v2.4.14/linux/arch/sparc64/mm/ultra.S Mon Nov 5 15:55:27 2001
+++ linux/arch/sparc64/mm/ultra.S Tue Nov 13 09:16:05 2001
@@ -1,4 +1,4 @@
-/* $Id: ultra.S,v 1.67 2001/10/23 14:28:20 davem Exp $
+/* $Id: ultra.S,v 1.68 2001/11/09 14:59:19 davem Exp $
X * ultra.S: Don't expand these all over the place...
X *
X * Copyright (C) 1997, 2000 David S. Miller (da...@redhat.com)
@@ -316,9 +316,9 @@
X sethi %hi(PAGE_SIZE), %o4
X 1: subcc %o4, (1 << 5), %o4
X stxa %g0, [%o0 + %o4] ASI_DCACHE_INVALIDATE
- membar #Sync
X bne,pt %icc, 1b
X nop
+ membar #Sync
X /* I-cache flush never needed on Cheetah, see callers. */
X retl
X nop
@@ -509,9 +509,9 @@
X sethi %hi(PAGE_SIZE), %g3
X 1: subcc %g3, (1 << 5), %g3
X stxa %g0, [%g1 + %g3] ASI_DCACHE_INVALIDATE
- membar #Sync
X bne,pt %icc, 1b
X nop
+ membar #Sync
X retry
X nop
X
diff -u --recursive --new-file v2.4.14/linux/drivers/Makefile linux/drivers/Makefile
--- v2.4.14/linux/drivers/Makefile Tue Oct 23 22:48:50 2001
+++ linux/drivers/Makefile Sun Nov 11 10:09:32 2001
@@ -10,7 +10,7 @@
X message/i2o message/fusion scsi md ieee1394 pnp isdn atm \
X fc4 net/hamradio i2c acpi bluetooth
X
-subdir-y := parport char block net sound misc media cdrom
+subdir-y := parport char block net sound misc media cdrom hotplug
X subdir-m := $(subdir-y)
X
X
@@ -48,4 +48,3 @@
X subdir-$(CONFIG_BLUEZ) += bluetooth
X
X include $(TOPDIR)/Rules.make
-
diff -u --recursive --new-file v2.4.14/linux/drivers/acpi/os.c linux/drivers/acpi/os.c
--- v2.4.14/linux/drivers/acpi/os.c Mon Nov 5 15:55:28 2001
+++ linux/drivers/acpi/os.c Fri Nov 9 13:39:25 2001
@@ -189,11 +189,6 @@
X return AE_ERROR;
X }
X
- if ((unsigned long) phys < virt_to_phys(high_memory)) {
- *virt = phys_to_virt((unsigned long) phys);
- return AE_OK;
- }
-
X *virt = ioremap((unsigned long) phys, size);
X if (!*virt)
X return AE_ERROR;
@@ -204,8 +199,7 @@
X void
X acpi_os_unmap_memory(void *virt, u32 size)
X {
- if (virt >= high_memory)
- iounmap(virt);
+ iounmap(virt);
X }
X
X acpi_status
diff -u --recursive --new-file v2.4.14/linux/drivers/acpi/ospm/processor/pr_osl.c linux/drivers/acpi/ospm/processor/pr_osl.c
--- v2.4.14/linux/drivers/acpi/ospm/processor/pr_osl.c Mon Nov 5 15:55:28 2001
+++ linux/drivers/acpi/ospm/processor/pr_osl.c Fri Nov 9 13:58:02 2001
@@ -143,7 +143,7 @@
X PR_CONTEXT *processor)
X {
X u32 i = 0;
- struct proc_dir_entry *proc_entry = NULL;
+ struct proc_dir_entry *proc_entry = NULL, *proc;
X char processor_uid[16];
X
X if (!processor) {
@@ -165,15 +165,18 @@
X sprintf(processor_uid, "%d", processor->uid);
X
X proc_entry = proc_mkdir(processor_uid, pr_proc_root);
- if (!proc_entry) {
+ if (!proc_entry)
X return(AE_ERROR);
- }
X
- create_proc_read_entry(PR_PROC_STATUS, S_IFREG | S_IRUGO,
- proc_entry, pr_osl_proc_read_status, (void*)processor);
+ proc = create_proc_read_entry(PR_PROC_STATUS, S_IFREG | S_IRUGO,
+ proc_entry, pr_osl_proc_read_status, (void*)processor);
+ if (!proc_entry)
+ return(AE_ERROR);
X
- create_proc_read_entry(PR_PROC_INFO, S_IFREG | S_IRUGO,
- proc_entry, pr_osl_proc_read_info, (void*)processor);
+ proc = create_proc_read_entry(PR_PROC_INFO, S_IFREG | S_IRUGO,
+ proc_entry, pr_osl_proc_read_info, (void*)processor);
+ if (!proc_entry)
+ return(AE_ERROR);
X
X return(AE_OK);
X }
diff -u --recursive --new-file v2.4.14/linux/drivers/atm/Config.in linux/drivers/atm/Config.in
--- v2.4.14/linux/drivers/atm/Config.in Mon Nov 5 15:55:28 2001
+++ linux/drivers/atm/Config.in Tue Nov 13 09:19:41 2001
@@ -40,6 +40,12 @@
X bool ' Use suni PHY driver (155Mbps)' CONFIG_ATM_NICSTAR_USE_SUNI
X bool ' Use IDT77015 PHY driver (25Mbps)' CONFIG_ATM_NICSTAR_USE_IDT77105
X fi
+ tristate 'IDT 77252 (NICStAR II)' CONFIG_ATM_IDT77252
+ if [ "$CONFIG_ATM_IDT77252" != "n" ]; then
+ bool ' Enable debugging messages' CONFIG_ATM_IDT77252_DEBUG
+ bool ' Receive ALL cells in raw queue' CONFIG_ATM_IDT77252_RCV_ALL
+ define_bool CONFIG_ATM_IDT77252_USE_SUNI y
+ fi
X tristate 'Madge Ambassador (Collage PCI 155 Server)' CONFIG_ATM_AMBASSADOR
X if [ "$CONFIG_ATM_AMBASSADOR" != "n" ]; then
X bool ' Enable debugging messages' CONFIG_ATM_AMBASSADOR_DEBUG
diff -u --recursive --new-file v2.4.14/linux/drivers/atm/Makefile linux/drivers/atm/Makefile
--- v2.4.14/linux/drivers/atm/Makefile Mon Nov 5 15:55:28 2001
+++ linux/drivers/atm/Makefile Wed Nov 7 14:39:36 2001
@@ -12,6 +12,7 @@
X obj-$(CONFIG_ATM_ENI) += eni.o suni.o
X obj-$(CONFIG_ATM_ZATM) += zatm.o uPD98402.o
X obj-$(CONFIG_ATM_NICSTAR) += nicstar.o
+obj-$(CONFIG_ATM_IDT77252) += idt77252.o
X
X ifeq ($(CONFIG_ATM_NICSTAR_USE_SUNI),y)
X obj-$(CONFIG_ATM_NICSTAR) += suni.o
@@ -19,6 +20,10 @@
X
X ifeq ($(CONFIG_ATM_NICSTAR_USE_IDT77105),y)
X obj-$(CONFIG_ATM_NICSTAR) += idt77105.o
+endif
+
+ifeq ($(CONFIG_ATM_IDT77252_USE_SUNI),y)
+ obj-$(CONFIG_ATM_IDT77252) += suni.o
X endif
X
X obj-$(CONFIG_ATM_HORIZON) += horizon.o
diff -u --recursive --new-file v2.4.14/linux/drivers/atm/eni.c linux/drivers/atm/eni.c
--- v2.4.14/linux/drivers/atm/eni.c Sun Sep 23 11:40:57 2001
+++ linux/drivers/atm/eni.c Fri Nov 9 13:41:42 2001
@@ -2266,7 +2266,7 @@
X }
X dev = atm_dev_register(DEV_LABEL,&ops,-1,NULL);
X if (!dev) goto out2;
- pci_dev->driver_data = dev;
+ pci_set_drvdata(pci_dev, dev);
X eni_dev->pci_dev = pci_dev;
X ENI_DEV(dev) = eni_dev;
X eni_dev->asic = ent->driver_data;
diff -u --recursive --new-file v2.4.14/linux/drivers/atm/firestream.c linux/drivers/atm/firestream.c
--- v2.4.14/linux/drivers/atm/firestream.c Sun Sep 23 11:40:57 2001
+++ linux/drivers/atm/firestream.c Fri Nov 9 13:58:03 2001
@@ -912,6 +912,9 @@
X if (IS_FS50(dev)) {
X /* Increment the channel numer: take a free one next time. */
X for (to=33;to;to--, dev->channo++) {
+ /* We only have 32 channels */
+ if (dev->channo >= 32)
+ dev->channo = 0;
X /* If we need to do RX, AND the RX is inuse, try the next */
X if (DO_DIRECTION(rxtp) && dev->atm_vccs[dev->channo])
X continue;
@@ -1226,7 +1229,7 @@
X {
X func_enter ();
X func_exit ();
- return 0;
+ return -ENOIOCTLCMD;
X }
X
X
diff -u --recursive --new-file v2.4.14/linux/drivers/atm/idt77252.c linux/drivers/atm/idt77252.c
--- v2.4.14/linux/drivers/atm/idt77252.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/atm/idt77252.c Tue Nov 20 15:46:21 2001
@@ -0,0 +1,3908 @@
+/*******************************************************************
+ * ident "$Id: idt77252.c,v 1.2 2001/11/11 08:13:54 ecd Exp $"


+ *
+ * $Author: ecd $
+ * $Date: 2001/11/11 08:13:54 $

+ *
+ * Copyright (c) 2000 ATecoM GmbH
+ *


+ * The author may be reached at e...@atecom.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.
+ *


+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *******************************************************************/
+static char const rcsid[] =
+"$Id: idt77252.c,v 1.2 2001/11/11 08:13:54 ecd Exp $";
+
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <linux/skbuff.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/netdevice.h>
+#include <linux/atmdev.h>
+#include <linux/atm.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/wait.h>
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+#include <asm/byteorder.h>
+
+#ifdef CONFIG_ATM_IDT77252_USE_SUNI
+#include "suni.h"


+#endif /* CONFIG_ATM_IDT77252_USE_SUNI */
+
+

+#include "idt77252.h"
+#include "idt77252_tables.h"
+
+static unsigned int vpibits = 1;
+
+
+#define CONFIG_ATM_IDT77252_SEND_IDLE 1
+
+
+/*
+ * Debug HACKs.
+ */
+#define DEBUG_MODULE 1
+#undef HAVE_EEPROM /* does not work, yet. */
+
+#ifdef CONFIG_ATM_IDT77252_DEBUG
+static unsigned long debug = DBG_GENERAL;
+#endif
+
+
+#define SAR_RX_DELAY (SAR_CFG_RXINT_NODELAY)
+
+
+/*
+ * SCQ Handling.
+ */
+static struct scq_info *alloc_scq(struct idt77252_dev *, int);
+static void free_scq(struct idt77252_dev *, struct scq_info *);
+static int queue_skb(struct idt77252_dev *, struct vc_map *,
+ struct sk_buff *, int oam);
+static void drain_scq(struct idt77252_dev *, struct vc_map *);
+static unsigned long get_free_scd(struct idt77252_dev *, struct vc_map *);
+static void fill_scd(struct idt77252_dev *, struct scq_info *, int);
+
+/*
+ * FBQ Handling.
+ */
+static int push_rx_skb(struct idt77252_dev *,
+ struct sk_buff *, int queue);
+static void recycle_rx_skb(struct idt77252_dev *, struct sk_buff *);
+static void flush_rx_pool(struct idt77252_dev *, struct rx_pool *);
+static void recycle_rx_pool_skb(struct idt77252_dev *,
+ struct rx_pool *);
+static void add_rx_skb(struct idt77252_dev *, int queue,


+ unsigned int size, unsigned int count);
+

+/*
+ * RSQ Handling.
+ */
+static int init_rsq(struct idt77252_dev *);
+static void deinit_rsq(struct idt77252_dev *);
+static void idt77252_rx(struct idt77252_dev *);
+
+/*
+ * TSQ handling.
+ */
+static int init_tsq(struct idt77252_dev *);
+static void deinit_tsq(struct idt77252_dev *);
+static void idt77252_tx(struct idt77252_dev *);
+
+
+/*
+ * ATM Interface.
+ */
+static void idt77252_dev_close(struct atm_dev *dev);
+static int idt77252_open(struct atm_vcc *vcc, short vpi, int vci);
+static void idt77252_close(struct atm_vcc *vcc);
+static int idt77252_send(struct atm_vcc *vcc, struct sk_buff *skb);
+static int idt77252_send_oam(struct atm_vcc *vcc, void *cell,
+ int flags);
+static void idt77252_phy_put(struct atm_dev *dev, unsigned char value,
+ unsigned long addr);
+static unsigned char idt77252_phy_get(struct atm_dev *dev, unsigned long addr);
+static int idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos,
+ int flags);
+static int idt77252_proc_read(struct atm_dev *dev, loff_t * pos,
+ char *page);
+static void idt77252_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs);
+static void idt77252_softint(void *dev_id);
+
+
+static struct atmdev_ops idt77252_ops =
+{
+ dev_close: idt77252_dev_close,
+ open: idt77252_open,
+ close: idt77252_close,
+ send: idt77252_send,
+ send_oam: idt77252_send_oam,
+ phy_put: idt77252_phy_put,
+ phy_get: idt77252_phy_get,
+ change_qos: idt77252_change_qos,
+ proc_read: idt77252_proc_read
+};
+
+static struct idt77252_dev *idt77252_chain = NULL;
+static unsigned int idt77252_sram_write_errors = 0;
+
+/*****************************************************************************/
+/* */
+/* I/O and Utility Bus */


+/* */
+/*****************************************************************************/
+
+static void

+waitfor_idle(struct idt77252_dev *card)
+{
+ u32 stat;
+
+ stat = readl(SAR_REG_STAT);
+ while (stat & SAR_STAT_CMDBZ)
+ stat = readl(SAR_REG_STAT);
+}
+
+static u32
+read_sram(struct idt77252_dev *card, unsigned long addr)
+{
+ unsigned long flags;
+ u32 value;


+
+ spin_lock_irqsave(&card->cmd_lock, flags);

+ writel(SAR_CMD_READ_SRAM | (addr << 2), SAR_REG_CMD);
+ waitfor_idle(card);
+ value = readl(SAR_REG_DR0);
+ spin_unlock_irqrestore(&card->cmd_lock, flags);
+ return value;
+}
+
+static void
+write_sram(struct idt77252_dev *card, unsigned long addr, u32 value)
+{
+ unsigned long flags;
+
+ if ((idt77252_sram_write_errors == 0) &&
+ (((addr > card->tst[0] + card->tst_size - 2) &&
+ (addr < card->tst[0] + card->tst_size)) ||
+ ((addr > card->tst[1] + card->tst_size - 2) &&
+ (addr < card->tst[1] + card->tst_size)))) {
+ printk("%s: ERROR: TST JMP section at %08lx written: %08x\n",
+ card->name, addr, value);
+ }


+
+ spin_lock_irqsave(&card->cmd_lock, flags);

+ writel(value, SAR_REG_DR0);
+ writel(SAR_CMD_WRITE_SRAM | (addr << 2), SAR_REG_CMD);


+ waitfor_idle(card);
+ spin_unlock_irqrestore(&card->cmd_lock, flags);
+}
+

+static u8
+read_utility(void *dev, unsigned long ubus_addr)
+{
+ struct idt77252_dev *card = dev;
+ unsigned long flags;
+ u8 value;
+
+ if (!card) {
+ printk("Error: No such device.\n");


+ return -1;
+ }
+

+ spin_lock_irqsave(&card->cmd_lock, flags);
+ writel(SAR_CMD_READ_UTILITY + ubus_addr, SAR_REG_CMD);
+ waitfor_idle(card);
+ value = readl(SAR_REG_DR0);
+ spin_unlock_irqrestore(&card->cmd_lock, flags);
+ return value;
+}
+
+static void
+write_utility(void *dev, unsigned long ubus_addr, u8 value)
+{
+ struct idt77252_dev *card = dev;


+ unsigned long flags;
+

+ if (!card) {
+ printk("Error: No such device.\n");
+ return;
+ }
+
+ spin_lock_irqsave(&card->cmd_lock, flags);
+ writel((u32) value, SAR_REG_DR0);
+ writel(SAR_CMD_WRITE_UTILITY + ubus_addr, SAR_REG_CMD);


+ waitfor_idle(card);
+ spin_unlock_irqrestore(&card->cmd_lock, flags);
+}
+

+#ifdef HAVE_EEPROM
+static u32 rdsrtab[] =
+{
+ SAR_GP_EECS | SAR_GP_EESCLK,
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ SAR_GP_EEDO,
+ SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ SAR_GP_EEDO,
+ SAR_GP_EESCLK | SAR_GP_EEDO /* 1 */
+};
+
+static u32 wrentab[] =
+{
+ SAR_GP_EECS | SAR_GP_EESCLK,
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ SAR_GP_EEDO,
+ SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
+ SAR_GP_EEDO,
+ SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK /* 0 */
+};
+
+static u32 rdtab[] =
+{
+ SAR_GP_EECS | SAR_GP_EESCLK,
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ SAR_GP_EEDO,
+ SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
+ SAR_GP_EEDO,
+ SAR_GP_EESCLK | SAR_GP_EEDO /* 1 */
+};
+
+static u32 wrtab[] =
+{
+ SAR_GP_EECS | SAR_GP_EESCLK,
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ 0,
+ SAR_GP_EESCLK, /* 0 */
+ SAR_GP_EEDO,
+ SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
+ 0,
+ SAR_GP_EESCLK /* 0 */
+};
+
+static u32 clktab[] =
+{
+ 0,
+ SAR_GP_EESCLK,
+ 0,
+ SAR_GP_EESCLK,
+ 0,
+ SAR_GP_EESCLK,
+ 0,
+ SAR_GP_EESCLK,
+ 0,
+ SAR_GP_EESCLK,
+ 0,
+ SAR_GP_EESCLK,
+ 0,
+ SAR_GP_EESCLK,
+ 0,
+ SAR_GP_EESCLK,
+ 0
+};
+
+static u32
+idt77252_read_gp(struct idt77252_dev *card)
+{
+ u32 gp;
+
+ gp = readl(SAR_REG_GP);
+#if 0
+ printk("RD: %s\n", gp & SAR_GP_EEDI ? "1" : "0");
+#endif
+ return gp;
+}
+
+static void
+idt77252_write_gp(struct idt77252_dev *card, u32 value)


+{
+ unsigned long flags;
+

+#if 0
+ printk("WR: %s %s %s\n", value & SAR_GP_EECS ? " " : "/CS",
+ value & SAR_GP_EESCLK ? "HIGH" : "LOW ",
+ value & SAR_GP_EEDO ? "1" : "0");
+#endif


+
+ spin_lock_irqsave(&card->cmd_lock, flags);

+ waitfor_idle(card);
+ writel(value, SAR_REG_GP);


+ spin_unlock_irqrestore(&card->cmd_lock, flags);
+}
+

+static u8
+idt77252_eeprom_read_status(struct idt77252_dev *card)
+{
+ u8 byte;
+ u32 gp;


+ int i, j;
+

+ gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
+
+ for (i = 0; i < sizeof(rdsrtab)/sizeof(rdsrtab[0]); i++) {
+ idt77252_write_gp(card, gp | rdsrtab[i]);
+ udelay(5);
+ }
+ idt77252_write_gp(card, gp | SAR_GP_EECS);
+ udelay(5);
+
+ byte = 0;
+ for (i = 0, j = 0; i < 8; i++) {
+ byte <<= 1;
+
+ idt77252_write_gp(card, gp | clktab[j++]);
+ udelay(5);
+
+ byte |= idt77252_read_gp(card) & SAR_GP_EEDI ? 1 : 0;
+
+ idt77252_write_gp(card, gp | clktab[j++]);
+ udelay(5);
+ }
+ idt77252_write_gp(card, gp | SAR_GP_EECS);
+ udelay(5);
+
+ return byte;
+}
+
+static u8
+idt77252_eeprom_read_byte(struct idt77252_dev *card, u8 offset)
+{
+ u8 byte;
+ u32 gp;


+ int i, j;
+

+ gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
+
+ for (i = 0; i < sizeof(rdtab)/sizeof(rdtab[0]); i++) {
+ idt77252_write_gp(card, gp | rdtab[i]);
+ udelay(5);
+ }
+ idt77252_write_gp(card, gp | SAR_GP_EECS);
+ udelay(5);
+
+ for (i = 0, j = 0; i < 8; i++) {
+ idt77252_write_gp(card, gp | clktab[j++] |
+ (offset & 1 ? SAR_GP_EEDO : 0));
+ udelay(5);
+
+ idt77252_write_gp(card, gp | clktab[j++] |
+ (offset & 1 ? SAR_GP_EEDO : 0));
+ udelay(5);
+
+ offset >>= 1;
+ }
+ idt77252_write_gp(card, gp | SAR_GP_EECS);
+ udelay(5);
+
+ byte = 0;
+ for (i = 0, j = 0; i < 8; i++) {
+ byte <<= 1;
+
+ idt77252_write_gp(card, gp | clktab[j++]);
+ udelay(5);
+
+ byte |= idt77252_read_gp(card) & SAR_GP_EEDI ? 1 : 0;
+
+ idt77252_write_gp(card, gp | clktab[j++]);
+ udelay(5);
+ }
+ idt77252_write_gp(card, gp | SAR_GP_EECS);
+ udelay(5);
+
+ return byte;
+}
+
+static void
+idt77252_eeprom_write_byte(struct idt77252_dev *card, u8 offset, u8 data)
+{
+ u32 gp;


+ int i, j;
+

+ gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
+
+ for (i = 0; i < sizeof(wrentab)/sizeof(wrentab[0]); i++) {
+ idt77252_write_gp(card, gp | wrentab[i]);
+ udelay(5);
+ }
+ idt77252_write_gp(card, gp | SAR_GP_EECS);
+ udelay(5);
+
+ for (i = 0; i < sizeof(wrtab)/sizeof(wrtab[0]); i++) {
+ idt77252_write_gp(card, gp | wrtab[i]);
+ udelay(5);
+ }
+ idt77252_write_gp(card, gp | SAR_GP_EECS);
+ udelay(5);
+
+ for (i = 0, j = 0; i < 8; i++) {
+ idt77252_write_gp(card, gp | clktab[j++] |
+ (offset & 1 ? SAR_GP_EEDO : 0));
+ udelay(5);
+
+ idt77252_write_gp(card, gp | clktab[j++] |
+ (offset & 1 ? SAR_GP_EEDO : 0));
+ udelay(5);
+
+ offset >>= 1;
+ }
+ idt77252_write_gp(card, gp | SAR_GP_EECS);
+ udelay(5);
+
+ for (i = 0, j = 0; i < 8; i++) {
+ idt77252_write_gp(card, gp | clktab[j++] |
+ (data & 1 ? SAR_GP_EEDO : 0));
+ udelay(5);
+
+ idt77252_write_gp(card, gp | clktab[j++] |
+ (data & 1 ? SAR_GP_EEDO : 0));
+ udelay(5);
+
+ data >>= 1;
+ }
+ idt77252_write_gp(card, gp | SAR_GP_EECS);
+ udelay(5);
+}
+
+static void
+idt77252_eeprom_init(struct idt77252_dev *card)
+{
+ u32 gp;
+
+ gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
+
+ idt77252_write_gp(card, gp | SAR_GP_EECS | SAR_GP_EESCLK);
+ udelay(5);
+ idt77252_write_gp(card, gp | SAR_GP_EECS);
+ udelay(5);
+ idt77252_write_gp(card, gp | SAR_GP_EECS | SAR_GP_EESCLK);
+ udelay(5);
+ idt77252_write_gp(card, gp | SAR_GP_EECS);
+ udelay(5);
+}


+#endif /* HAVE_EEPROM */
+
+

+#ifdef CONFIG_ATM_IDT77252_DEBUG
+static void
+dump_tct(struct idt77252_dev *card, int index)


+{
+ unsigned long tct;

+ int i;
+
+ tct = (unsigned long) (card->tct_base + index * SAR_SRAM_TCT_SIZE);
+
+ printk("%s: TCT %x:", card->name, index);
+ for (i = 0; i < 8; i++) {
+ printk(" %08x", read_sram(card, tct + i));
+ }


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

+static void
+idt77252_tx_dump(struct idt77252_dev *card)
+{


+ struct atm_vcc *vcc;
+ struct vc_map *vc;

+ int i;
+
+ printk("%s\n", __FUNCTION__);
+ for (i = 0; i < card->tct_size; i++) {


+ vc = card->vcs[i];
+ if (!vc)
+ continue;
+
+ vcc = NULL;

+ if (vc->rx_vcc)


+ vcc = vc->rx_vcc;

+ else if (vc->tx_vcc)


+ vcc = vc->tx_vcc;
+
+ if (!vcc)
+ continue;
+

+ printk("%s: Connection %d:\n", card->name, vc->index);
+ dump_tct(card, vc->index);
+ }
+}
+#endif


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

+/* SCQ Handling */


+/* */
+/*****************************************************************************/
+
+static int

+sb_pool_add(struct idt77252_dev *card, struct sk_buff *skb, int queue)
+{
+ struct sb_pool *pool = &card->sbpool[queue];
+ int index;
+
+ index = pool->index;
+ while (pool->skb[index]) {
+ index = (index + 1) & FBQ_MASK;
+ if (index == pool->index)


+ return -ENOBUFS;
+ }
+

+ pool->skb[index] = skb;
+ IDT77252_PRV_POOL(skb) = POOL_HANDLE(queue, index);
+
+ pool->index = (index + 1) & FBQ_MASK;


+ return 0;
+}
+
+static void

+sb_pool_remove(struct idt77252_dev *card, struct sk_buff *skb)
+{
+ unsigned int queue, index;
+ u32 handle;
+
+ handle = IDT77252_PRV_POOL(skb);
+
+ queue = POOL_QUEUE(handle);
+ if (queue > 3)
+ return;
+
+ index = POOL_INDEX(handle);
+ if (index > FBQ_SIZE - 1)
+ return;
+
+ card->sbpool[queue].skb[index] = NULL;
+}
+
+static struct sk_buff *
+sb_pool_skb(struct idt77252_dev *card, u32 handle)
+{
+ unsigned int queue, index;
+
+ queue = POOL_QUEUE(handle);
+ if (queue > 3)
+ return NULL;
+
+ index = POOL_INDEX(handle);
+ if (index > FBQ_SIZE - 1)
+ return NULL;
+
+ return card->sbpool[queue].skb[index];
+}
+
+static struct scq_info *
+alloc_scq(struct idt77252_dev *card, int class)
+{
+ struct scq_info *scq;
+
+ scq = (struct scq_info *) kmalloc(sizeof(struct scq_info), GFP_KERNEL);
+ if (!scq)
+ return NULL;
+ memset(scq, 0, sizeof(struct scq_info));
+
+ scq->base = pci_alloc_consistent(card->pcidev, SCQ_SIZE,
+ &scq->paddr);
+ if (scq->base == NULL) {
+ kfree(scq);
+ return NULL;
+ }
+ memset(scq->base, 0, SCQ_SIZE);
+
+ scq->next = scq->base;
+ scq->last = scq->base + (SCQ_ENTRIES - 1);
+ atomic_set(&scq->used, 0);
+
+ spin_lock_init(&scq->lock);
+ spin_lock_init(&scq->skblock);
+
+ skb_queue_head_init(&scq->transmit);
+ skb_queue_head_init(&scq->pending);
+
+ TXPRINTK("idt77252: SCQ: base 0x%p, next 0x%p, last 0x%p, paddr %08x\n",
+ scq->base, scq->next, scq->last, scq->paddr);
+
+ return scq;
+}
+
+static void
+free_scq(struct idt77252_dev *card, struct scq_info *scq)


+{
+ struct sk_buff *skb;

+ struct atm_vcc *vcc;
+
+ pci_free_consistent(card->pcidev, SCQ_SIZE,
+ scq->base, scq->paddr);
+
+ while ((skb = skb_dequeue(&scq->transmit))) {
+ pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb),
+ skb->len, PCI_DMA_TODEVICE);
+
+ vcc = ATM_SKB(skb)->vcc;
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb(skb);
+ }
+
+ while ((skb = skb_dequeue(&scq->pending))) {
+ pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb),
+ skb->len, PCI_DMA_TODEVICE);
+
+ vcc = ATM_SKB(skb)->vcc;
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb(skb);
+ }
+
+ kfree(scq);


+}
+
+
+static int

+push_on_scq(struct idt77252_dev *card, struct vc_map *vc, struct sk_buff *skb)
+{
+ struct scq_info *scq = vc->scq;
+ unsigned long flags;
+ struct scqe *tbd;
+ int entries;
+
+ TXPRINTK("%s: SCQ: next 0x%p\n", card->name, scq->next);
+
+ atomic_inc(&scq->used);
+ entries = atomic_read(&scq->used);
+ if (entries > (SCQ_ENTRIES - 1)) {
+ atomic_dec(&scq->used);


+ goto out;
+ }
+

+ skb_queue_tail(&scq->transmit, skb);


+
+ spin_lock_irqsave(&vc->lock, flags);
+ if (vc->estimator) {

+ struct atm_vcc *vcc = vc->tx_vcc;
+
+ vc->estimator->cells += (skb->len + 47) / 48;
+ if (atomic_read(&vcc->tx_inuse) > (vcc->sk->sndbuf >> 1)) {
+ u32 cps = vc->estimator->maxcps;
+
+ vc->estimator->cps = cps;
+ vc->estimator->avcps = cps << 5;
+ if (vc->lacr < vc->init_er) {


+ vc->lacr = vc->init_er;

+ writel(TCMDQ_LACR | (vc->lacr << 16) |
+ vc->index, SAR_REG_TCMDQ);
+ }
+ }

+ }
+ spin_unlock_irqrestore(&vc->lock, flags);
+

+ tbd = &IDT77252_PRV_TBD(skb);
+
+ spin_lock_irqsave(&scq->lock, flags);
+ scq->next->word_1 = cpu_to_le32(tbd->word_1 |
+ SAR_TBD_TSIF | SAR_TBD_GTSI);
+ scq->next->word_2 = cpu_to_le32(tbd->word_2);
+ scq->next->word_3 = cpu_to_le32(tbd->word_3);
+ scq->next->word_4 = cpu_to_le32(tbd->word_4);
+
+ if (scq->next == scq->last)
+ scq->next = scq->base;
+ else
+ scq->next++;


+
+ write_sram(card, scq->scd,

+ scq->paddr +
+ (u32)((unsigned long)scq->next - (unsigned long)scq->base));
+ spin_unlock_irqrestore(&scq->lock, flags);
+
+ scq->trans_start = jiffies;
+
+ if (test_and_clear_bit(VCF_IDLE, &vc->flags)) {
+ writel(TCMDQ_START_LACR | (vc->lacr << 16) | vc->index,
+ SAR_REG_TCMDQ);
+ }
+
+ TXPRINTK("%d entries in SCQ used (push).\n", atomic_read(&scq->used));
+
+ XPRINTK("%s: SCQ (after push %2d) head = 0x%x, next = 0x%p.\n",
+ card->name, atomic_read(&scq->used),
+ read_sram(card, scq->scd + 1), scq->next);


+
+ return 0;
+

+out:
+ if (jiffies - scq->trans_start > HZ) {
+ printk("%s: Error pushing TBD for %d.%d\n",
+ card->name, vc->tx_vcc->vpi, vc->tx_vcc->vci);


+#ifdef CONFIG_ATM_IDT77252_DEBUG
+ idt77252_tx_dump(card);
+#endif

+ scq->trans_start = jiffies;
+ }
+
+ return -ENOBUFS;


+}
+
+
+static void

+drain_scq(struct idt77252_dev *card, struct vc_map *vc)
+{
+ struct scq_info *scq = vc->scq;
+ struct sk_buff *skb;
+ struct atm_vcc *vcc;
+
+ TXPRINTK("%s: SCQ (before drain %2d) next = 0x%p.\n",
+ card->name, atomic_read(&scq->used), scq->next);
+
+ skb = skb_dequeue(&scq->transmit);
+ if (skb) {
+ TXPRINTK("%s: freeing skb at %p.\n", card->name, skb);


+
+ pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb),

+ skb->len, PCI_DMA_TODEVICE);
+
+ vcc = ATM_SKB(skb)->vcc;
+
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb(skb);
+
+ atomic_inc(&vcc->stats->tx);
+ }
+
+ atomic_dec(&scq->used);
+
+ spin_lock(&scq->skblock);
+ while ((skb = skb_dequeue(&scq->pending))) {
+ if (push_on_scq(card, vc, skb)) {
+ skb_queue_head(&vc->scq->pending, skb);
+ break;
+ }
+ }
+ spin_unlock(&scq->skblock);
+}
+
+static int
+queue_skb(struct idt77252_dev *card, struct vc_map *vc,
+ struct sk_buff *skb, int oam)
+{
+ struct atm_vcc *vcc;
+ struct scqe *tbd;
+ unsigned long flags;
+ int error;
+ int aal;
+
+ if (skb->len == 0) {
+ printk("%s: invalid skb->len (%d)\n", card->name, skb->len);


+ return -EINVAL;
+ }
+

+ TXPRINTK("%s: Sending %d bytes of data.\n",
+ card->name, skb->len);
+
+ tbd = &IDT77252_PRV_TBD(skb);
+ vcc = ATM_SKB(skb)->vcc;
+
+ IDT77252_PRV_PADDR(skb) = pci_map_single(card->pcidev, skb->data,
+ skb->len, PCI_DMA_TODEVICE);
+
+ error = -EINVAL;
+
+ if (oam) {
+ if (skb->len != 52)
+ goto errout;
+
+ tbd->word_1 = SAR_TBD_OAM | ATM_CELL_PAYLOAD | SAR_TBD_EPDU;
+ tbd->word_2 = IDT77252_PRV_PADDR(skb) + 4;
+ tbd->word_3 = 0x00000000;
+ tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
+ (skb->data[2] << 8) | (skb->data[3] << 0);
+
+ if (test_bit(VCF_RSV, &vc->flags))
+ vc = card->vcs[0];
+


+ goto done;
+ }
+

+ if (test_bit(VCF_RSV, &vc->flags)) {
+ printk("%s: Trying to transmit on reserved VC\n", card->name);
+ goto errout;
+ }
+
+ aal = vcc->qos.aal;
+
+ switch (aal) {
+ case ATM_AAL0:
+ case ATM_AAL34:
+ if (skb->len > 52)
+ goto errout;
+
+ if (aal == ATM_AAL0)
+ tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL0 |
+ ATM_CELL_PAYLOAD;
+ else
+ tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL34 |
+ ATM_CELL_PAYLOAD;
+
+ tbd->word_2 = IDT77252_PRV_PADDR(skb) + 4;
+ tbd->word_3 = 0x00000000;
+ tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
+ (skb->data[2] << 8) | (skb->data[3] << 0);
+ break;
+
+ case ATM_AAL5:
+ tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL5 | skb->len;
+ tbd->word_2 = IDT77252_PRV_PADDR(skb);
+ tbd->word_3 = skb->len;
+ tbd->word_4 = (vcc->vpi << SAR_TBD_VPI_SHIFT) |
+ (vcc->vci << SAR_TBD_VCI_SHIFT);
+ break;
+
+ case ATM_AAL1:
+ case ATM_AAL2:
+ default:
+ printk("%s: Traffic type not supported.\n", card->name);
+ error = -EPROTONOSUPPORT;
+ goto errout;
+ }
+
+done:
+ spin_lock_irqsave(&vc->scq->skblock, flags);
+ skb_queue_tail(&vc->scq->pending, skb);
+
+ while ((skb = skb_dequeue(&vc->scq->pending))) {
+ if (push_on_scq(card, vc, skb)) {
+ skb_queue_head(&vc->scq->pending, skb);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&vc->scq->skblock, flags);


+
+ return 0;
+

+errout:
+ pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb),


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

echo 'End of part 036'
echo 'File patch-2.4.15 is continued in part 037'
echo "037" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:23 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part047

#!/bin/sh -x
# this is part 047 of a 115 - part archive


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

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

- out:
+out:


X return err;
X }
X

X int lvm_snapshot_alloc(lv_t * lv_snap)
X {
- int err, blocksize, max_sectors;
+ int ret, max_sectors;
X
- err = alloc_kiovec(1, &lv_snap->lv_iobuf);
- if (err)
- goto out;
+ /* allocate kiovec to do chunk io */
+ ret = alloc_kiovec(1, &lv_snap->lv_iobuf);
+ if (ret) goto out;
X
- blocksize = lvm_blocksizes[MINOR(lv_snap->lv_dev)];
X max_sectors = KIO_MAX_SECTORS << (PAGE_SHIFT-9);
X
- err = lvm_snapshot_alloc_iobuf_pages(lv_snap->lv_iobuf, max_sectors);
- if (err)
- goto out_free_kiovec;
-
- err = lvm_snapshot_alloc_hash_table(lv_snap);
- if (err)
- goto out_free_kiovec;
+ ret = lvm_snapshot_alloc_iobuf_pages(lv_snap->lv_iobuf, max_sectors);
+ if (ret) goto out_free_kiovec;
X
+ /* allocate kiovec to do exception table io */
+ ret = alloc_kiovec(1, &lv_snap->lv_COW_table_iobuf);
+ if (ret) goto out_free_kiovec;
X
- lv_snap->lv_COW_table_page = alloc_page(GFP_KERNEL);
- if (!lv_snap->lv_COW_table_page)
- goto out_free_kiovec;
+ ret = lvm_snapshot_alloc_iobuf_pages(lv_snap->lv_COW_table_iobuf,
+ PAGE_SIZE/SECTOR_SIZE);
+ if (ret) goto out_free_both_kiovecs;
X
- out:
- return err;
+ ret = lvm_snapshot_alloc_hash_table(lv_snap);
+ if (ret) goto out_free_both_kiovecs;
+
+
+out:
+ return ret;
+
+out_free_both_kiovecs:
+ unmap_kiobuf(lv_snap->lv_COW_table_iobuf);
+ free_kiovec(1, &lv_snap->lv_COW_table_iobuf);
+ lv_snap->lv_COW_table_iobuf = NULL;
X
- out_free_kiovec:
+out_free_kiovec:
X unmap_kiobuf(lv_snap->lv_iobuf);
X free_kiovec(1, &lv_snap->lv_iobuf);
- vfree(lv_snap->lv_snapshot_hash_table);
+ lv_snap->lv_iobuf = NULL;
+ if (lv_snap->lv_snapshot_hash_table != NULL)
+ vfree(lv_snap->lv_snapshot_hash_table);
X lv_snap->lv_snapshot_hash_table = NULL;
X goto out;
X }
X
X void lvm_snapshot_release(lv_t * lv)
X {
+ int nbhs = KIO_MAX_SECTORS;
+
X if (lv->lv_block_exception)
X {
X vfree(lv->lv_block_exception);
@@ -580,9 +562,126 @@
X free_kiovec(1, &lv->lv_iobuf);
X lv->lv_iobuf = NULL;
X }
- if (lv->lv_COW_table_page)
+ if (lv->lv_COW_table_iobuf)
X {
- free_page((ulong)lv->lv_COW_table_page);
- lv->lv_COW_table_page = NULL;
+ kiobuf_wait_for_io(lv->lv_COW_table_iobuf);
+ unmap_kiobuf(lv->lv_COW_table_iobuf);
+ free_kiovec(1, &lv->lv_COW_table_iobuf);
+ lv->lv_COW_table_iobuf = NULL;
X }
X }
+
+
+static int _write_COW_table_block(vg_t *vg, lv_t *lv_snap,
+ int idx, const char **reason) {
+ int blksize_snap;
+ int end_of_table;
+ int idx_COW_table;
+ uint pvn;
+ ulong snap_pe_start, COW_table_sector_offset,
+ COW_entries_per_pe, COW_chunks_per_pe, COW_entries_per_block;
+ ulong blocks[1];
+ kdev_t snap_phys_dev;
+ lv_block_exception_t *be;
+ struct kiobuf * COW_table_iobuf = lv_snap->lv_COW_table_iobuf;
+ lv_COW_table_disk_t * lv_COW_table =
+ ( lv_COW_table_disk_t *) page_address(lv_snap->lv_COW_table_iobuf->maplist[0]);
+
+ COW_chunks_per_pe = LVM_GET_COW_TABLE_CHUNKS_PER_PE(vg, lv_snap);
+ COW_entries_per_pe = LVM_GET_COW_TABLE_ENTRIES_PER_PE(vg, lv_snap);
+
+ /* get physical addresse of destination chunk */
+ snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new;
+ snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size;
+
+ blksize_snap = lvm_get_blksize(snap_phys_dev);
+
+ COW_entries_per_block = blksize_snap / sizeof(lv_COW_table_disk_t);
+ idx_COW_table = idx % COW_entries_per_pe % COW_entries_per_block;
+
+ if ( idx_COW_table == 0) memset(lv_COW_table, 0, blksize_snap);
+
+ /* sector offset into the on disk COW table */
+ COW_table_sector_offset = (idx % COW_entries_per_pe) / (SECTOR_SIZE / sizeof(lv_COW_table_disk_t));
+
+ /* COW table block to write next */
+ blocks[0] = (snap_pe_start + COW_table_sector_offset) >> (blksize_snap >> 10);
+
+ /* store new COW_table entry */
+ be = lv_snap->lv_block_exception + idx;
+ if(_pv_get_number(vg, be->rdev_org, &pvn))
+ goto fail_pv_get_number;
+
+ lv_COW_table[idx_COW_table].pv_org_number = cpu_to_le64(pvn);
+ lv_COW_table[idx_COW_table].pv_org_rsector =
+ cpu_to_le64(be->rsector_org);
+ if(_pv_get_number(vg, snap_phys_dev, &pvn))
+ goto fail_pv_get_number;
+
+ lv_COW_table[idx_COW_table].pv_snap_number = cpu_to_le64(pvn);
+ lv_COW_table[idx_COW_table].pv_snap_rsector =
+ cpu_to_le64(be->rsector_new);
+
+ COW_table_iobuf->length = blksize_snap;
+
+ if (brw_kiovec(WRITE, 1, &COW_table_iobuf, snap_phys_dev,
+ blocks, blksize_snap) != blksize_snap)
+ goto fail_raw_write;
+
+ /* initialization of next COW exception table block with zeroes */
+ end_of_table = idx % COW_entries_per_pe == COW_entries_per_pe - 1;
+ if (idx_COW_table % COW_entries_per_block == COW_entries_per_block - 1 || end_of_table)
+ {
+ /* don't go beyond the end */
+ if (idx + 1 >= lv_snap->lv_remap_end) goto out;
+
+ memset(lv_COW_table, 0, blksize_snap);
+
+ if (end_of_table)
+ {
+ idx++;
+ snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new;
+ snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size;
+ blksize_snap = lvm_get_blksize(snap_phys_dev);
+ blocks[0] = snap_pe_start >> (blksize_snap >> 10);
+ } else blocks[0]++;
+
+ if (brw_kiovec(WRITE, 1, &COW_table_iobuf, snap_phys_dev,
+ blocks, blksize_snap) !=
+ blksize_snap)
+ goto fail_raw_write;
+ }
+
+ out:
+ return 0;
+
+ fail_raw_write:
+ *reason = "write error";
+ return 1;
+
+ fail_pv_get_number:
+ *reason = "_pv_get_number failed";
+ return 1;
+}
+
+/*
+ * FIXME_1.2
+ * This function is a bit of a hack; we need to ensure that the
+ * snapshot is never made active again, because it will surely be
+ * corrupt. At the moment we do not have access to the LVM metadata
+ * from within the kernel. So we set the first exception to point to
+ * sector 1 (which will always be within the metadata, and as such
+ * invalid). User land tools will check for this when they are asked
+ * to activate the snapshot and prevent this from happening.
+ */
+
+static void _disable_snapshot(vg_t *vg, lv_t *lv) {
+ const char *err;
+ lv->lv_block_exception[0].rsector_org = LVM_SNAPSHOT_DROPPED_SECTOR;
+ if(_write_COW_table_block(vg, lv, 0, &err) < 0) {
+ printk(KERN_ERR "%s -- couldn't disable snapshot: %s\n",
+ lvm_name, err);
+ }
+}
+
+MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/md/lvm-snap.h linux/drivers/md/lvm-snap.h
--- v2.4.14/linux/drivers/md/lvm-snap.h Sun Jan 28 16:11:20 2001
+++ linux/drivers/md/lvm-snap.h Wed Dec 31 16:00:00 1969
@@ -1,47 +0,0 @@
-/*
- * kernel/lvm-snap.h
- *
- * Copyright (C) 2001 Sistina Software
- *
- *
- * LVM driver is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * LVM driver 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 GNU CC; see the file COPYING. If not, write to
- * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- */
-
-/*
- * Changelog
- *
- * 05/01/2001:Joe Thornber - Factored this file out of lvm.c
- *
- */
-
-#ifndef LVM_SNAP_H
-#define LVM_SNAP_H
-
-/* external snapshot calls */
-extern inline int lvm_get_blksize(kdev_t);
-extern int lvm_snapshot_alloc(lv_t *);
-extern void lvm_snapshot_fill_COW_page(vg_t *, lv_t *);
-extern int lvm_snapshot_COW(kdev_t, ulong, ulong, ulong, lv_t *);
-extern int lvm_snapshot_remap_block(kdev_t *, ulong *, ulong, lv_t *);
-extern void lvm_snapshot_release(lv_t *);
-extern int lvm_write_COW_table_block(vg_t *, lv_t *);
-extern inline void lvm_hash_link(lv_block_exception_t *,
- kdev_t, ulong, lv_t *);
-extern int lvm_snapshot_alloc_hash_table(lv_t *);
-extern void lvm_drop_snapshot(lv_t *, const char *);
-
-#endif
diff -u --recursive --new-file v2.4.14/linux/drivers/md/lvm.c linux/drivers/md/lvm.c
--- v2.4.14/linux/drivers/md/lvm.c Mon Nov 5 15:55:30 2001
+++ linux/drivers/md/lvm.c Mon Nov 19 09:56:04 2001
@@ -147,25 +147,51 @@
X * 08/01/2001 - Removed conditional compiles related to PROC_FS,
X * procfs is always supported now. (JT)
X * 12/01/2001 - avoided flushing logical volume in case of shrinking
- * because of unecessary overhead in case of heavy updates
+ * because of unnecessary overhead in case of heavy updates
+ * 25/01/2001 - Allow RO open of an inactive LV so it can be reactivated.
+ * 31/01/2001 - If you try and BMAP a snapshot you now get an -EPERM
+ * 01/02/2001 - factored __remap_snapshot out of lvm_map
+ * 12/02/2001 - move devfs code to create VG before LVs
+ * 14/02/2001 - tidied device defines for blk.h
+ * - tidied debug statements
+ * - more lvm_map tidying
+ * 14/02/2001 - bug: vg[] member not set back to NULL if activation fails
+ * 28/02/2001 - introduced the P_DEV macro and changed some internel
+ * functions to be static [AD]
+ * 28/02/2001 - factored lvm_get_snapshot_use_rate out of blk_ioctl [AD]
+ * - fixed user address accessing bug in lvm_do_lv_create()
+ * where the check for an existing LV takes place right at
+ * the beginning
+ * 01/03/2001 - Add VG_CREATE_OLD for IOP 10 compatibility
+ * 02/03/2001 - Don't destroy usermode pointers in lv_t structures duing LV_
+ * STATUS_BYxxx and remove redundant lv_t variables from same.
+ * 05/03/2001 - restore copying pe_t array in lvm_do_lv_status_byname. For
+ * lvdisplay -v (PC)
+ * - restore copying pe_t array in lvm_do_lv_status_byindex (HM)
+ * - added copying pe_t array in lvm_do_lv_status_bydev (HM)
+ * - enhanced lvm_do_lv_status_by{name,index,dev} to be capable
+ * to copy the lv_block_exception_t array to userspace (HM)
+ * 08/03/2001 - factored lvm_do_pv_flush out of lvm_chr_ioctl [HM]
+ * 09/03/2001 - Added _lock_open_count to ensure we only drop the lock
+ * when the locking process closes.
X * 05/04/2001 - lvm_map bugs: don't use b_blocknr/b_dev in lvm_map, it
X * destroys stacking devices. call b_end_io on failed maps.
X * (Jens Axboe)
+ * - Defer writes to an extent that is being moved [JT + AD]
+ * 28/05/2001 - implemented missing BLKSSZGET ioctl [AD]
X *
X */
X
X
-static char *lvm_version = "LVM version 0.9.1_beta2 by Heinz Mauelshagen (18/01/2001)\n";
-static char *lvm_short_version = "version 0.9.1_beta2 (18/01/2001)";
-
-#define MAJOR_NR LVM_BLK_MAJOR
-#define DEVICE_OFF(device)
+#define MAJOR_NR LVM_BLK_MAJOR
+#define DEVICE_OFF(device)
+#define LOCAL_END_REQUEST
X
X /* lvm_do_lv_create calls fsync_dev_lockfs()/unlockfs() */
X /* #define LVM_VFS_ENHANCEMENT */
X
X #include <linux/config.h>
-#include <linux/version.h>
+
X #include <linux/module.h>
X
X #include <linux/kernel.h>
@@ -180,6 +206,7 @@
X #include <linux/blkdev.h>
X #include <linux/genhd.h>
X #include <linux/locks.h>
+#include <linux/devfs_fs_kernel.h>
X #include <linux/smp_lock.h>
X #include <asm/ioctl.h>
X #include <asm/segment.h>
@@ -195,38 +222,16 @@
X #include <linux/errno.h>
X #include <linux/lvm.h>
X
-#include "lvm-snap.h"
+#include "lvm-internal.h"
X
-#define LVM_CORRECT_READ_AHEAD(a) \
-do { \
- if ((a) < LVM_MIN_READ_AHEAD || \
- (a) > LVM_MAX_READ_AHEAD) \
- (a) = LVM_DEFAULT_READ_AHEAD; \
- read_ahead[MAJOR_NR] = (a); \
-} while(0)
+#define LVM_CORRECT_READ_AHEAD( a) \
+ if ( a < LVM_MIN_READ_AHEAD || \
+ a > LVM_MAX_READ_AHEAD) a = LVM_MAX_READ_AHEAD;
X
X #ifndef WRITEA
X # define WRITEA WRITE
X #endif
X
-/* debug macros */
-#ifdef DEBUG_IOCTL
-#define P_IOCTL(fmt, args...) printk(KERN_DEBUG "lvm ioctl: " fmt, ## args)
-#else
-#define P_IOCTL(fmt, args...)
-#endif
-
-#ifdef DEBUG_MAP
-#define P_MAP(fmt, args...) printk(KERN_DEBUG "lvm map: " fmt, ## args)
-#else
-#define P_MAP(fmt, args...)
-#endif
-
-#ifdef DEBUG_KFREE
-#define P_KFREE(fmt, args...) printk(KERN_DEBUG "lvm kfree: " fmt, ## args)
-#else
-#define P_KFREE(fmt, args...)
-#endif
X
X /*
X * External function prototypes
@@ -236,27 +241,14 @@
X static int lvm_blk_ioctl(struct inode *, struct file *, uint, ulong);
X static int lvm_blk_open(struct inode *, struct file *);
X
-static int lvm_chr_open(struct inode *, struct file *);
-
-static int lvm_chr_close(struct inode *, struct file *);
X static int lvm_blk_close(struct inode *, struct file *);
+static int lvm_get_snapshot_use_rate(lv_t *lv_ptr, void *arg);
X static int lvm_user_bmap(struct inode *, struct lv_bmap *);
X
+static int lvm_chr_open(struct inode *, struct file *);
+static int lvm_chr_close(struct inode *, struct file *);
X static int lvm_chr_ioctl(struct inode *, struct file *, uint, ulong);
X
-int lvm_proc_read_vg_info(char *, char **, off_t, int, int *, void *);
-int lvm_proc_read_lv_info(char *, char **, off_t, int, int *, void *);
-int lvm_proc_read_pv_info(char *, char **, off_t, int, int *, void *);
-static int lvm_proc_get_global_info(char *, char **, off_t, int, int *, void *);
-
-void lvm_do_create_devfs_entry_of_vg ( vg_t *);
-
-void lvm_do_create_proc_entry_of_vg ( vg_t *);
-void lvm_do_remove_proc_entry_of_vg ( vg_t *);
-void lvm_do_create_proc_entry_of_lv ( vg_t *, lv_t *);
-void lvm_do_remove_proc_entry_of_lv ( vg_t *, lv_t *);
-void lvm_do_create_proc_entry_of_pv ( vg_t *, pv_t *);
-void lvm_do_remove_proc_entry_of_pv ( vg_t *, pv_t *);
X
X /* End external function prototypes */
X
@@ -288,34 +280,41 @@
X
X static int lvm_do_pv_change(vg_t*, void*);
X static int lvm_do_pv_status(vg_t *, void *);
+static int lvm_do_pv_flush(void *);
X
-static int lvm_do_vg_create(int, void *);
+static int lvm_do_vg_create(void *, int minor);
X static int lvm_do_vg_extend(vg_t *, void *);
X static int lvm_do_vg_reduce(vg_t *, void *);
X static int lvm_do_vg_rename(vg_t *, void *);
X static int lvm_do_vg_remove(int);
X static void lvm_geninit(struct gendisk *);
-static char *lvm_show_uuid ( char *);
+static void __update_hardsectsize(lv_t *lv);
+
+
+static void _queue_io(struct buffer_head *bh, int rw);
+static struct buffer_head *_dequeue_io(void);
+static void _flush_io(struct buffer_head *bh);
+
+static int _open_pv(pv_t *pv);
+static void _close_pv(pv_t *pv);
+
+static unsigned long _sectors_to_k(unsigned long sect);
+
X #ifdef LVM_HD_NAME
X void lvm_hd_name(char *, int);
X #endif
X /* END Internal function prototypes */
X
X
-/* volume group descriptor area pointers */
-static vg_t *vg[ABS_MAX_VG];
+/* variables */
+char *lvm_version = "LVM version "LVM_RELEASE_NAME"("LVM_RELEASE_DATE")";
+ushort lvm_iop_version = LVM_DRIVER_IOP_VERSION;
+int loadtime = 0;
+const char *const lvm_name = LVM_NAME;
X
-static devfs_handle_t lvm_devfs_handle;
-static devfs_handle_t vg_devfs_handle[MAX_VG];
-static devfs_handle_t ch_devfs_handle[MAX_VG];
-static devfs_handle_t lv_devfs_handle[MAX_LV];
-
-static pv_t *pvp = NULL;
-static lv_t *lvp = NULL;
-static pe_t *pep = NULL;
-static pe_t *pep1 = NULL;
-static char *basename = NULL;
X
+/* volume group descriptor area pointers */
+vg_t *vg[ABS_MAX_VG];
X
X /* map from block minor number to VG and LV numbers */
X typedef struct {
@@ -327,9 +326,8 @@
X
X /* Request structures (lvm_chr_ioctl()) */
X static pv_change_req_t pv_change_req;
-static pv_flush_req_t pv_flush_req;
X static pv_status_req_t pv_status_req;
-static pe_lock_req_t pe_lock_req;
+volatile static pe_lock_req_t pe_lock_req;
X static le_remap_req_t le_remap_req;
X static lv_req_t lv_req;
X
@@ -339,33 +337,27 @@
X
X static char pv_name[NAME_LEN];
X /* static char rootvg[NAME_LEN] = { 0, }; */
-const char *const lvm_name = LVM_NAME;
X static int lock = 0;
-static int loadtime = 0;
+static int _lock_open_count = 0;
X static uint vg_count = 0;
X static long lvm_chr_open_count = 0;
-static ushort lvm_iop_version = LVM_DRIVER_IOP_VERSION;
X static DECLARE_WAIT_QUEUE_HEAD(lvm_wait);
-static DECLARE_WAIT_QUEUE_HEAD(lvm_map_wait);
X
X static spinlock_t lvm_lock = SPIN_LOCK_UNLOCKED;
X static spinlock_t lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;
X
-static struct proc_dir_entry *lvm_proc_dir = NULL;
-static struct proc_dir_entry *lvm_proc_vg_subdir = NULL;
-struct proc_dir_entry *pde = NULL;
+static struct buffer_head *_pe_requests;
+static DECLARE_RWSEM(_pe_lock);
X
-static struct file_operations lvm_chr_fops =
-{
- owner: THIS_MODULE,
+
+struct file_operations lvm_chr_fops = {
X open: lvm_chr_open,
X release: lvm_chr_close,
X ioctl: lvm_chr_ioctl,
X };
X
-
X /* block device operations structure needed for 2.3.38? and above */
-static struct block_device_operations lvm_blk_dops =
+struct block_device_operations lvm_blk_dops =
X {
X owner: THIS_MODULE,
X open: lvm_blk_open,
@@ -376,10 +368,10 @@
X
X /* gendisk structures */
X static struct hd_struct lvm_hd_struct[MAX_LV];
-static int lvm_blocksizes[MAX_LV] =
-{0,};
-static int lvm_size[MAX_LV] =
-{0,};
+static int lvm_blocksizes[MAX_LV];
+static int lvm_hardsectsizes[MAX_LV];
+static int lvm_size[MAX_LV];
+
X static struct gendisk lvm_gendisk =
X {
X major: MAJOR_NR,
@@ -396,30 +388,24 @@
X */
X int lvm_init(void)
X {
- if (register_chrdev(LVM_CHAR_MAJOR, lvm_name, &lvm_chr_fops) < 0) {
- printk(KERN_ERR "%s -- register_chrdev failed\n", lvm_name);
+ if (devfs_register_chrdev(LVM_CHAR_MAJOR,
+ lvm_name, &lvm_chr_fops) < 0) {
+ printk(KERN_ERR "%s -- devfs_register_chrdev failed\n",
+ lvm_name);
X return -EIO;
X }
- if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0)
+
+ if (devfs_register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0)
X {
- printk("%s -- register_blkdev failed\n", lvm_name);
- if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
- printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name);
+ printk("%s -- devfs_register_blkdev failed\n", lvm_name);
+ if (devfs_unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
+ printk(KERN_ERR
+ "%s -- devfs_unregister_chrdev failed\n",
+ lvm_name);


X return -EIO;
X }
X

- lvm_devfs_handle = devfs_register(
- 0 , "lvm", 0, 0, LVM_CHAR_MAJOR,
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
- &lvm_chr_fops, NULL);
-
- lvm_proc_dir = create_proc_entry (LVM_DIR, S_IFDIR, &proc_root);
- if (lvm_proc_dir != NULL) {
- lvm_proc_vg_subdir = create_proc_entry (LVM_VG_SUBDIR, S_IFDIR, lvm_proc_dir);
- pde = create_proc_entry(LVM_GLOBAL, S_IFREG, lvm_proc_dir);
- if ( pde != NULL) pde->read_proc = &lvm_proc_get_global_info;
- }
-
+ lvm_init_fs();
X lvm_init_vars();
X lvm_geninit(&lvm_gendisk);
X
@@ -433,20 +419,19 @@
X blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_make_request_fn);
X
X
+ /* initialise the pe lock */
+ pe_lock_req.lock = UNLOCK_PE;
+
X /* optional read root VGDA */
X /*
X if ( *rootvg != 0) vg_read_with_pv_and_lv ( rootvg, &vg);
X */
X
- printk(KERN_INFO
- "%s%s -- "
X #ifdef MODULE
- "Module"
+ printk(KERN_INFO "%s module loaded\n", lvm_version);
X #else
- "Driver"
+ printk(KERN_INFO "%s\n", lvm_version);
X #endif
- " successfully initialized\n",
- lvm_version, lvm_name);
X
X return 0;
X } /* lvm_init() */
@@ -457,15 +442,12 @@
X */
X static void lvm_cleanup(void)
X {
- devfs_unregister (lvm_devfs_handle);
-
- if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) {
- printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name);
- }
- if (unregister_blkdev(MAJOR_NR, lvm_name) < 0) {
- printk(KERN_ERR "%s -- unregister_blkdev failed\n", lvm_name);
- }
-
+ if (devfs_unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
+ printk(KERN_ERR "%s -- devfs_unregister_chrdev failed\n",
+ lvm_name);
+ if (devfs_unregister_blkdev(MAJOR_NR, lvm_name) < 0)
+ printk(KERN_ERR "%s -- devfs_unregister_blkdev failed\n",
+ lvm_name);
X
X del_gendisk(&lvm_gendisk);
X
@@ -473,25 +455,25 @@
X blksize_size[MAJOR_NR] = NULL;
X hardsect_size[MAJOR_NR] = NULL;
X
- remove_proc_entry(LVM_GLOBAL, lvm_proc_dir);
- remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir);
- remove_proc_entry(LVM_DIR, &proc_root);
-
X #ifdef LVM_HD_NAME
X /* reference from linux/drivers/block/genhd.c */
X lvm_hd_name_ptr = NULL;
X #endif
X
+ /* unregister with procfs and devfs */
+ lvm_fin_fs();
+
+#ifdef MODULE
X printk(KERN_INFO "%s -- Module successfully deactivated\n", lvm_name);
+#endif
X
X return;
X } /* lvm_cleanup() */
X
-
X /*
X * support function to initialize lvm variables
X */
-void __init lvm_init_vars(void)
+static void __init lvm_init_vars(void)
X {
X int v;
X
@@ -500,8 +482,8 @@
X lvm_lock = lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;
X
X pe_lock_req.lock = UNLOCK_PE;
- pe_lock_req.data.lv_dev = \
- pe_lock_req.data.pv_dev = \
+ pe_lock_req.data.lv_dev = 0;
+ pe_lock_req.data.pv_dev = 0;
X pe_lock_req.data.pv_offset = 0;
X
X /* Initialize VG pointers */
@@ -524,19 +506,18 @@
X *
X ********************************************************************/
X
+#define MODE_TO_STR(mode) (mode) & FMODE_READ ? "READ" : "", \
+ (mode) & FMODE_WRITE ? "WRITE" : ""
+
X /*
X * character device open routine
X */
-static int lvm_chr_open(struct inode *inode,
- struct file *file)
+static int lvm_chr_open(struct inode *inode, struct file *file)
X {
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = MINOR(inode->i_rdev);
X
-#ifdef DEBUG
- printk(KERN_DEBUG
- "%s -- lvm_chr_open MINOR: %d VG#: %d mode: 0x%X lock: %d\n",
- lvm_name, minor, VG_CHR(minor), file->f_mode, lock);
-#endif
+ P_DEV("chr_open MINOR: %d VG#: %d mode: %s%s lock: %d\n",
+ minor, VG_CHR(minor), MODE_TO_STR(file->f_mode), lock);
X
X /* super user validation */
X if (!capable(CAP_SYS_ADMIN)) return -EACCES;
@@ -544,8 +525,15 @@
X /* Group special file open */
X if (VG_CHR(minor) > MAX_VG) return -ENXIO;
X
+ spin_lock(&lvm_lock);
+ if(lock == current->pid)
+ _lock_open_count++;
+ spin_unlock(&lvm_lock);
+
X lvm_chr_open_count++;
X
+ MOD_INC_USE_COUNT;
+
X return 0;
X } /* lvm_chr_open() */
X
@@ -558,7 +546,7 @@
X *
X */
X static int lvm_chr_ioctl(struct inode *inode, struct file *file,
- uint command, ulong a)
+ uint command, ulong a)
X {
X int minor = MINOR(inode->i_rdev);
X uint extendable, l, v;
@@ -569,9 +557,8 @@
X /* otherwise cc will complain about unused variables */
X (void) lvm_lock;
X
- P_IOCTL("%s -- lvm_chr_ioctl: command: 0x%X MINOR: %d "
- "VG#: %d mode: 0x%X\n",
- lvm_name, command, minor, VG_CHR(minor), file->f_mode);
+ P_IOCTL("chr MINOR: %d command: 0x%X arg: %p VG#: %d mode: %s%s\n",
+ minor, command, arg, VG_CHR(minor), MODE_TO_STR(file->f_mode));
X
X #ifdef LVM_TOTAL_RESET
X if (lvm_reset_spindown > 0) return -EACCES;
@@ -619,9 +606,13 @@
X physical volume (move's done in user space's pvmove) */
X return lvm_do_pe_lock_unlock(vg_ptr,arg);
X
- case VG_CREATE:
+ case VG_CREATE_OLD:
X /* create a VGDA */
- return lvm_do_vg_create(minor, arg);
+ return lvm_do_vg_create(arg, minor);
+
+ case VG_CREATE:
+ /* create a VGDA, assume VG number is filled in */
+ return lvm_do_vg_create(arg, -1);
X
X case VG_EXTEND:
X /* extend a volume group */
@@ -672,7 +663,7 @@
X
X
X case VG_STATUS_GET_NAMELIST:
- /* get volume group count */
+ /* get volume group names */
X for (l = v = 0; v < ABS_MAX_VG; v++) {
X if (vg[v] != NULL) {
X if (copy_to_user(arg + l * NAME_LEN,
@@ -727,6 +718,7 @@
X
X
X case LV_STATUS_BYDEV:
+ /* get status of a logical volume by device */
X return lvm_do_lv_status_bydev(vg_ptr, arg);
X
X
@@ -742,18 +734,12 @@
X
X case PV_FLUSH:
X /* physical volume buffer flush/invalidate */
- if (copy_from_user(&pv_flush_req, arg,
- sizeof(pv_flush_req)) != 0)
- return -EFAULT;
-
- fsync_dev(pv_flush_req.pv_dev);
- invalidate_buffers(pv_flush_req.pv_dev);
- return 0;
+ return lvm_do_pv_flush(arg);
X
X
X default:
X printk(KERN_WARNING
- "%s -- lvm_chr_ioctl: unknown command %x\n",
+ "%s -- lvm_chr_ioctl: unknown command 0x%x\n",
X lvm_name, command);
X return -EINVAL;
X }
@@ -767,11 +753,8 @@
X */
X static int lvm_chr_close(struct inode *inode, struct file *file)
X {
-#ifdef DEBUG
- int minor = MINOR(inode->i_rdev);
- printk(KERN_DEBUG
- "%s -- lvm_chr_close VG#: %d\n", lvm_name, VG_CHR(minor));
-#endif
+ P_DEV("chr_close MINOR: %d VG#: %d\n",
+ MINOR(inode->i_rdev), VG_CHR(MINOR(inode->i_rdev)));
X
X #ifdef LVM_TOTAL_RESET
X if (lvm_reset_spindown > 0) {
@@ -781,10 +764,19 @@
X #endif
X
X if (lvm_chr_open_count > 0) lvm_chr_open_count--;
- if (lock == current->pid) {
- lock = 0; /* release lock */
- wake_up_interruptible(&lvm_wait);
+
+ spin_lock(&lvm_lock);
+ if(lock == current->pid) {
+ if(!_lock_open_count) {
+ P_DEV("chr_close: unlocking LVM for pid %d\n", lock);
+ lock = 0;
+ wake_up_interruptible(&lvm_wait);
+ } else
+ _lock_open_count--;
X }
+ spin_unlock(&lvm_lock);
+
+ MOD_DEC_USE_COUNT;
X
X return 0;
X } /* lvm_chr_close() */
@@ -806,11 +798,8 @@
X lv_t *lv_ptr;
X vg_t *vg_ptr = vg[VG_BLK(minor)];
X
-#ifdef DEBUG_LVM_BLK_OPEN
- printk(KERN_DEBUG
- "%s -- lvm_blk_open MINOR: %d VG#: %d LV#: %d mode: 0x%X\n",
- lvm_name, minor, VG_BLK(minor), LV_BLK(minor), file->f_mode);
-#endif
+ P_DEV("blk_open MINOR: %d VG#: %d LV#: %d mode: %s%s\n",
+ minor, VG_BLK(minor), LV_BLK(minor), MODE_TO_STR(file->f_mode));
X
X #ifdef LVM_TOTAL_RESET
X if (lvm_reset_spindown > 0)
@@ -827,8 +816,12 @@
X if (lv_ptr->lv_status & LV_SPINDOWN) return -EPERM;
X
X /* Check inactive LV and open for read/write */
- if (!(lv_ptr->lv_status & LV_ACTIVE))
- return -EPERM;
+ /* We need to be able to "read" an inactive LV
+ to re-activate it again */
+ if ((file->f_mode & FMODE_WRITE) &&
+ (!(lv_ptr->lv_status & LV_ACTIVE)))
+ return -EPERM;
+
X if (!(lv_ptr->lv_access & LV_WRITE) &&
X (file->f_mode & FMODE_WRITE))
X return -EACCES;
@@ -838,12 +831,9 @@
X if (lv_ptr->lv_open == 0) vg_ptr->lv_open++;
X lv_ptr->lv_open++;
X
-#ifdef DEBUG_LVM_BLK_OPEN
- printk(KERN_DEBUG
- "%s -- lvm_blk_open MINOR: %d VG#: %d LV#: %d size: %d\n",
- lvm_name, minor, VG_BLK(minor), LV_BLK(minor),
- lv_ptr->lv_size);
-#endif
+ MOD_INC_USE_COUNT;
+
+ P_DEV("blk_open OK, LV size %d\n", lv_ptr->lv_size);


X
X return 0;
X }

@@ -863,16 +853,18 @@
X void *arg = (void *) a;
X struct hd_geometry *hd = (struct hd_geometry *) a;
X
- P_IOCTL("%s -- lvm_blk_ioctl MINOR: %d command: 0x%X arg: %X "
- "VG#: %dl LV#: %d\n",
- lvm_name, minor, command, (ulong) arg,
- VG_BLK(minor), LV_BLK(minor));
+ P_IOCTL("blk MINOR: %d command: 0x%X arg: %p VG#: %d LV#: %d "
+ "mode: %s%s\n", minor, command, arg, VG_BLK(minor),
+ LV_BLK(minor), MODE_TO_STR(file->f_mode));
X
X switch (command) {
+ case BLKSSZGET:
+ /* get block device sector size as needed e.g. by fdisk */
+ return put_user(get_hardsect_size(inode->i_rdev), (int *) arg);
+
X case BLKGETSIZE:
X /* return device size */
- P_IOCTL("%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n",
- lvm_name, lv_ptr->lv_size);
+ P_IOCTL("BLKGETSIZE: %u\n", lv_ptr->lv_size);
X if (put_user(lv_ptr->lv_size, (unsigned long *)arg))
X return -EFAULT;
X break;
@@ -887,7 +879,7 @@
X /* flush buffer cache */
X if (!capable(CAP_SYS_ADMIN)) return -EACCES;
X
- P_IOCTL("%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name);
+ P_IOCTL("BLKFLSBUF\n");
X
X fsync_dev(inode->i_rdev);
X invalidate_buffers(inode->i_rdev);
@@ -898,20 +890,19 @@
X /* set read ahead for block device */
X if (!capable(CAP_SYS_ADMIN)) return -EACCES;
X
- P_IOCTL("%s -- lvm_blk_ioctl -- BLKRASET: %d sectors for %02X:%02X\n",
- lvm_name, (long) arg, MAJOR(inode->i_rdev), minor);
+ P_IOCTL("BLKRASET: %ld sectors for %s\n",
+ (long) arg, kdevname(inode->i_rdev));
X
X if ((long) arg < LVM_MIN_READ_AHEAD ||
X (long) arg > LVM_MAX_READ_AHEAD)
X return -EINVAL;
X lv_ptr->lv_read_ahead = (long) arg;
- read_ahead[MAJOR_NR] = lv_ptr->lv_read_ahead;
X break;
X
X
X case BLKRAGET:
X /* get current read ahead setting */
- P_IOCTL("%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name);
+ P_IOCTL("BLKRAGET %d\n", lv_ptr->lv_read_ahead);
X if (put_user(lv_ptr->lv_read_ahead, (long *)arg))
X return -EFAULT;
X break;
@@ -937,10 +928,10 @@
X copy_to_user((long *) &hd->start, &start,
X sizeof(start)) != 0)
X return -EFAULT;
- }
X
- P_IOCTL("%s -- lvm_blk_ioctl -- cylinders: %d\n",
- lvm_name, lv_ptr->lv_size / heads / sectors);
+ P_IOCTL("%s -- lvm_blk_ioctl -- cylinders: %d\n",
+ lvm_name, cylinders);
+ }
X break;
X
X
@@ -964,13 +955,12 @@
X break;
X
X case LV_BMAP:
- /* turn logical block into (dev_t, block). non privileged. */
- /* don't bmap a snapshot, since the mapping can change */
- if (lv_ptr->lv_access & LV_SNAPSHOT)
+ /* turn logical block into (dev_t, block). non privileged. */
+ /* don't bmap a snapshot, since the mapping can change */
+ if(lv_ptr->lv_access & LV_SNAPSHOT)
X return -EPERM;
X
X return lvm_user_bmap(inode, (struct lv_bmap *) arg);
- break;
X
X case LV_SET_ALLOCATION:
X /* set allocation flags of a logical volume */
@@ -979,40 +969,11 @@
X break;
X
X case LV_SNAPSHOT_USE_RATE:
- if (!(lv_ptr->lv_access & LV_SNAPSHOT)) return -EPERM;
- {
- lv_snapshot_use_rate_req_t lv_snapshot_use_rate_req;
-
- if (copy_from_user(&lv_snapshot_use_rate_req, arg,
- sizeof(lv_snapshot_use_rate_req_t)))
- return -EFAULT;
- if (lv_snapshot_use_rate_req.rate < 0 ||
- lv_snapshot_use_rate_req.rate > 100) return -EFAULT;
-
- switch (lv_snapshot_use_rate_req.block)
- {
- case 0:
- lv_ptr->lv_snapshot_use_rate = lv_snapshot_use_rate_req.rate;
- if (lv_ptr->lv_remap_ptr * 100 / lv_ptr->lv_remap_end < lv_ptr->lv_snapshot_use_rate)
- interruptible_sleep_on (&lv_ptr->lv_snapshot_wait);
- break;
-
- case O_NONBLOCK:
- break;
-
- default:
- return -EFAULT;
- }
- lv_snapshot_use_rate_req.rate = lv_ptr->lv_remap_ptr * 100 / lv_ptr->lv_remap_end;
- if (copy_to_user(arg, &lv_snapshot_use_rate_req,
- sizeof(lv_snapshot_use_rate_req_t)))
- return -EFAULT;
- }
- break;
+ return lvm_get_snapshot_use_rate(lv_ptr, arg);
X
X default:
X printk(KERN_WARNING
- "%s -- lvm_blk_ioctl: unknown command %d\n",
+ "%s -- lvm_blk_ioctl: unknown command 0x%x\n",
X lvm_name, command);
X return -EINVAL;
X }
@@ -1030,18 +991,49 @@
X vg_t *vg_ptr = vg[VG_BLK(minor)];
X lv_t *lv_ptr = vg_ptr->lv[LV_BLK(minor)];
X
-#ifdef DEBUG
- printk(KERN_DEBUG
- "%s -- lvm_blk_close MINOR: %d VG#: %d LV#: %d\n",
- lvm_name, minor, VG_BLK(minor), LV_BLK(minor));
-#endif
+ P_DEV("blk_close MINOR: %d VG#: %d LV#: %d\n",
+ minor, VG_BLK(minor), LV_BLK(minor));
X
X if (lv_ptr->lv_open == 1) vg_ptr->lv_open--;
X lv_ptr->lv_open--;
X
+ MOD_DEC_USE_COUNT;
+
X return 0;
X } /* lvm_blk_close() */
X
+static int lvm_get_snapshot_use_rate(lv_t *lv, void *arg)
+{
+ lv_snapshot_use_rate_req_t lv_rate_req;
+
+ if (!(lv->lv_access & LV_SNAPSHOT))
+ return -EPERM;
+
+ if (copy_from_user(&lv_rate_req, arg, sizeof(lv_rate_req)))
+ return -EFAULT;
+
+ if (lv_rate_req.rate < 0 || lv_rate_req.rate > 100)
+ return -EINVAL;
+
+ switch (lv_rate_req.block) {
+ case 0:
+ lv->lv_snapshot_use_rate = lv_rate_req.rate;
+ if (lv->lv_remap_ptr * 100 / lv->lv_remap_end <
+ lv->lv_snapshot_use_rate)
+ interruptible_sleep_on(&lv->lv_snapshot_wait);
+ break;
+
+ case O_NONBLOCK:


+ break;
+
+ default:

+ return -EINVAL;
+ }
+ lv_rate_req.rate = lv->lv_remap_ptr * 100 / lv->lv_remap_end;
+
+ return copy_to_user(arg, &lv_rate_req,
+ sizeof(lv_rate_req)) ? -EFAULT : 0;
+}
X
X static int lvm_user_bmap(struct inode *inode, struct lv_bmap *user_result)
X {
@@ -1056,6 +1048,7 @@
X bh.b_blocknr = block;
X bh.b_dev = bh.b_rdev = inode->i_rdev;
X bh.b_size = lvm_get_blksize(bh.b_dev);
+ bh.b_rsector = block * (bh.b_size >> 9);
X if ((err=lvm_map(&bh, READ)) < 0) {
X printk("lvm map failed: %d\n", err);
X return -EINVAL;
@@ -1068,557 +1061,202 @@
X
X
X /*
- * provide VG info for proc filesystem use (global)
+ * block device support function for /usr/src/linux/drivers/block/ll_rw_blk.c
+ * (see init_module/lvm_init)
X */
-int lvm_vg_info(vg_t *vg_ptr, char *buf) {
- int sz = 0;
- char inactive_flag = ' ';
-
- if (!(vg_ptr->vg_status & VG_ACTIVE)) inactive_flag = 'I';
- sz = sprintf(buf,
- "\nVG: %c%s [%d PV, %d LV/%d open] "
- " PE Size: %d KB\n"
- " Usage [KB/PE]: %d /%d total "
- "%d /%d used %d /%d free",
- inactive_flag,
- vg_ptr->vg_name,
- vg_ptr->pv_cur,
- vg_ptr->lv_cur,
- vg_ptr->lv_open,
- vg_ptr->pe_size >> 1,
- vg_ptr->pe_size * vg_ptr->pe_total >> 1,
- vg_ptr->pe_total,
- vg_ptr->pe_allocated * vg_ptr->pe_size >> 1,
- vg_ptr->pe_allocated,
- (vg_ptr->pe_total - vg_ptr->pe_allocated) *
- vg_ptr->pe_size >> 1,
- vg_ptr->pe_total - vg_ptr->pe_allocated);
- return sz;
-}
+static void __remap_snapshot(kdev_t rdev, ulong rsector,
+ ulong pe_start, lv_t *lv, vg_t *vg) {
X
+ /* copy a chunk from the origin to a snapshot device */
+ down_write(&lv->lv_lock);
X
-/*
- * provide LV info for proc filesystem use (global)
- */
-int lvm_lv_info(vg_t *vg_ptr, lv_t *lv_ptr, char *buf) {
- int sz = 0;
- char inactive_flag = 'A', allocation_flag = ' ',
- stripes_flag = ' ', rw_flag = ' ';
-
- if (!(lv_ptr->lv_status & LV_ACTIVE))
- inactive_flag = 'I';
- rw_flag = 'R';
- if (lv_ptr->lv_access & LV_WRITE)
- rw_flag = 'W';
- allocation_flag = 'D';
- if (lv_ptr->lv_allocation & LV_CONTIGUOUS)
- allocation_flag = 'C';
- stripes_flag = 'L';
- if (lv_ptr->lv_stripes > 1)
- stripes_flag = 'S';
- sz += sprintf(buf+sz,
- "[%c%c%c%c",
- inactive_flag,
- rw_flag,
- allocation_flag,
- stripes_flag);
- if (lv_ptr->lv_stripes > 1)
- sz += sprintf(buf+sz, "%-2d",
- lv_ptr->lv_stripes);
- else
- sz += sprintf(buf+sz, " ");
- basename = strrchr(lv_ptr->lv_name, '/');
- if ( basename == 0) basename = lv_ptr->lv_name;
- else basename++;
- sz += sprintf(buf+sz, "] %-25s", basename);
- if (strlen(basename) > 25)
- sz += sprintf(buf+sz,
- "\n ");
- sz += sprintf(buf+sz, "%9d /%-6d ",
- lv_ptr->lv_size >> 1,
- lv_ptr->lv_size / vg_ptr->pe_size);
-
- if (lv_ptr->lv_open == 0)
- sz += sprintf(buf+sz, "close");
- else
- sz += sprintf(buf+sz, "%dx open",
- lv_ptr->lv_open);
+ /* we must redo lvm_snapshot_remap_block in order to avoid a
+ race condition in the gap where no lock was held */
+ if (!lvm_snapshot_remap_block(&rdev, &rsector, pe_start, lv) &&
+ !lvm_snapshot_COW(rdev, rsector, pe_start, rsector, vg, lv))
+ lvm_write_COW_table_block(vg, lv);
X
- return sz;
+ up_write(&lv->lv_lock);
X }
X
-
-/*
- * provide PV info for proc filesystem use (global)
- */
-int lvm_pv_info(pv_t *pv_ptr, char *buf) {
- int sz = 0;
- char inactive_flag = 'A', allocation_flag = ' ';
- char *pv_name = NULL;
-
- if (!(pv_ptr->pv_status & PV_ACTIVE))
- inactive_flag = 'I';
- allocation_flag = 'A';
- if (!(pv_ptr->pv_allocatable & PV_ALLOCATABLE))
- allocation_flag = 'N';
- pv_name = strrchr(pv_ptr->pv_name+1,'/');
- if ( pv_name == 0) pv_name = pv_ptr->pv_name;
- else pv_name++;
- sz = sprintf(buf,
- "[%c%c] %-21s %8d /%-6d "
- "%8d /%-6d %8d /%-6d",
- inactive_flag,
- allocation_flag,
- pv_name,
- pv_ptr->pe_total *
- pv_ptr->pe_size >> 1,
- pv_ptr->pe_total,
- pv_ptr->pe_allocated *
- pv_ptr->pe_size >> 1,
- pv_ptr->pe_allocated,
- (pv_ptr->pe_total -
- pv_ptr->pe_allocated) *
- pv_ptr->pe_size >> 1,
- pv_ptr->pe_total -
- pv_ptr->pe_allocated);
- return sz;
+static inline void _remap_snapshot(kdev_t rdev, ulong rsector,
+ ulong pe_start, lv_t *lv, vg_t *vg) {
+ int r;
+
+ /* check to see if this chunk is already in the snapshot */
+ down_read(&lv->lv_lock);
+ r = lvm_snapshot_remap_block(&rdev, &rsector, pe_start, lv);
+ up_read(&lv->lv_lock);
+
+ if (!r)
+ /* we haven't yet copied this block to the snapshot */
+ __remap_snapshot(rdev, rsector, pe_start, lv, vg);
X }
X
X
X /*
- * Support functions /proc-Filesystem
+ * extents destined for a pe that is on the move should be deferred
X */
+static inline int _should_defer(kdev_t pv, ulong sector, uint32_t pe_size) {
+ return ((pe_lock_req.lock == LOCK_PE) &&
+ (pv == pe_lock_req.data.pv_dev) &&
+ (sector >= pe_lock_req.data.pv_offset) &&
+ (sector < (pe_lock_req.data.pv_offset + pe_size)));
+}
X
-#define LVM_PROC_BUF ( i == 0 ? dummy_buf : &buf[sz])
-
-/*
- * provide global LVM information
- */
-static int lvm_proc_get_global_info(char *page, char **start, off_t pos, int count, int *eof, void *data)
+static inline int _defer_extent(struct buffer_head *bh, int rw,
+ kdev_t pv, ulong sector, uint32_t pe_size)
X {
- int c, i, l, p, v, vg_counter, pv_counter, lv_counter, lv_open_counter,
- lv_open_total, pe_t_bytes, hash_table_bytes, lv_block_exception_t_bytes, seconds;
- static off_t sz;
- off_t sz_last;
- static char *buf = NULL;
- static char dummy_buf[160]; /* sized for 2 lines */
- vg_t *vg_ptr;
- lv_t *lv_ptr;
- pv_t *pv_ptr;
-
-
-#ifdef DEBUG_LVM_PROC_GET_INFO
- printk(KERN_DEBUG
- "%s - lvm_proc_get_global_info CALLED pos: %lu count: %d whence: %d\n",
- lvm_name, pos, count, whence);
-#endif
-
- MOD_INC_USE_COUNT;
-
- if (pos == 0 || buf == NULL) {
- sz_last = vg_counter = pv_counter = lv_counter = lv_open_counter = \
- lv_open_total = pe_t_bytes = hash_table_bytes = \
- lv_block_exception_t_bytes = 0;
-
- /* search for activity */
- for (v = 0; v < ABS_MAX_VG; v++) {
- if ((vg_ptr = vg[v]) != NULL) {
- vg_counter++;
- pv_counter += vg_ptr->pv_cur;
- lv_counter += vg_ptr->lv_cur;
- if (vg_ptr->lv_cur > 0) {
- for (l = 0; l < vg[v]->lv_max; l++) {
- if ((lv_ptr = vg_ptr->lv[l]) != NULL) {
- pe_t_bytes += lv_ptr->lv_allocated_le;
- hash_table_bytes += lv_ptr->lv_snapshot_hash_table_size;
- if (lv_ptr->lv_block_exception != NULL)
- lv_block_exception_t_bytes += lv_ptr->lv_remap_end;
- if (lv_ptr->lv_open > 0) {
- lv_open_counter++;
- lv_open_total += lv_ptr->lv_open;
- }
- }
- }
- }
- }
- }
- pe_t_bytes *= sizeof(pe_t);
- lv_block_exception_t_bytes *= sizeof(lv_block_exception_t);
-
- if (buf != NULL) {
- P_KFREE("%s -- vfree %d\n", lvm_name, __LINE__);
- lock_kernel();
- vfree(buf);
- unlock_kernel();
- buf = NULL;
- }
- /* 2 times: first to get size to allocate buffer,
- 2nd to fill the malloced buffer */
- for (i = 0; i < 2; i++) {
- sz = 0;
- sz += sprintf(LVM_PROC_BUF,
- "LVM "
-#ifdef MODULE
- "module"
-#else
- "driver"
-#endif
- " %s\n\n"
- "Total: %d VG%s %d PV%s %d LV%s ",
- lvm_short_version,
- vg_counter, vg_counter == 1 ? "" : "s",
- pv_counter, pv_counter == 1 ? "" : "s",
- lv_counter, lv_counter == 1 ? "" : "s");
- sz += sprintf(LVM_PROC_BUF,
- "(%d LV%s open",
- lv_open_counter,
- lv_open_counter == 1 ? "" : "s");
- if (lv_open_total > 0)
- sz += sprintf(LVM_PROC_BUF,
- " %d times)\n",
- lv_open_total);
- else
- sz += sprintf(LVM_PROC_BUF, ")");
- sz += sprintf(LVM_PROC_BUF,
- "\nGlobal: %lu bytes malloced IOP version: %d ",
- vg_counter * sizeof(vg_t) +
- pv_counter * sizeof(pv_t) +
- lv_counter * sizeof(lv_t) +
- pe_t_bytes + hash_table_bytes + lv_block_exception_t_bytes + sz_last,
- lvm_iop_version);
-
- seconds = CURRENT_TIME - loadtime;
- if (seconds < 0)
- loadtime = CURRENT_TIME + seconds;
- if (seconds / 86400 > 0) {
- sz += sprintf(LVM_PROC_BUF, "%d day%s ",
- seconds / 86400,
- seconds / 86400 == 0 ||
- seconds / 86400 > 1 ? "s" : "");
- }
- sz += sprintf(LVM_PROC_BUF, "%d:%02d:%02d active\n",
- (seconds % 86400) / 3600,
- (seconds % 3600) / 60,
- seconds % 60);
-
- if (vg_counter > 0) {
- for (v = 0; v < ABS_MAX_VG; v++) {
- /* volume group */
- if ((vg_ptr = vg[v]) != NULL) {
- sz += lvm_vg_info(vg_ptr, LVM_PROC_BUF);
-
- /* physical volumes */
- sz += sprintf(LVM_PROC_BUF,
- "\n PV%s ",
- vg_ptr->pv_cur == 1 ? ": " : "s:");
- c = 0;
- for (p = 0; p < vg_ptr->pv_max; p++) {
- if ((pv_ptr = vg_ptr->pv[p]) != NULL) {
- sz += lvm_pv_info(pv_ptr, LVM_PROC_BUF);
-
- c++;
- if (c < vg_ptr->pv_cur)
- sz += sprintf(LVM_PROC_BUF,
- "\n ");
- }
- }
-
- /* logical volumes */
- sz += sprintf(LVM_PROC_BUF,
- "\n LV%s ",
- vg_ptr->lv_cur == 1 ? ": " : "s:");
- c = 0;
- for (l = 0; l < vg_ptr->lv_max; l++) {
- if ((lv_ptr = vg_ptr->lv[l]) != NULL) {
- sz += lvm_lv_info(vg_ptr, lv_ptr, LVM_PROC_BUF);
- c++;
- if (c < vg_ptr->lv_cur)
- sz += sprintf(LVM_PROC_BUF,
- "\n ");
- }
- }
- if (vg_ptr->lv_cur == 0) sz += sprintf(LVM_PROC_BUF, "none");
- sz += sprintf(LVM_PROC_BUF, "\n");
- }
- }
- }
- if (buf == NULL) {
- lock_kernel();
- buf = vmalloc(sz);
- unlock_kernel();
- if (buf == NULL) {
- sz = 0;
- MOD_DEC_USE_COUNT;
- return sprintf(page, "%s - vmalloc error at line %d\n",
- lvm_name, __LINE__);
- }
- }
- sz_last = sz;
+ if (pe_lock_req.lock == LOCK_PE) {
+ down_read(&_pe_lock);
+ if (_should_defer(pv, sector, pe_size)) {
+ up_read(&_pe_lock);
+ down_write(&_pe_lock);
+ if (_should_defer(pv, sector, pe_size))
+ _queue_io(bh, rw);
+ up_write(&_pe_lock);
+ return 1;
X }
+ up_read(&_pe_lock);
X }
- MOD_DEC_USE_COUNT;
- if (pos > sz - 1) {
- lock_kernel();
- vfree(buf);
- unlock_kernel();
- buf = NULL;
- return 0;
- }
- *start = &buf[pos];
- if (sz - pos < count)
- return sz - pos;
- else
- return count;
-} /* lvm_proc_get_global_info() */
-
-
-/*
- * provide VG information
- */
-int lvm_proc_read_vg_info(char *page, char **start, off_t off,
- int count, int *eof, void *data) {
- int sz = 0;
- vg_t *vg = data;
-
- sz += sprintf ( page+sz, "name: %s\n", vg->vg_name);
- sz += sprintf ( page+sz, "size: %u\n",
- vg->pe_total * vg->pe_size / 2);
- sz += sprintf ( page+sz, "access: %u\n", vg->vg_access);
- sz += sprintf ( page+sz, "status: %u\n", vg->vg_status);
- sz += sprintf ( page+sz, "number: %u\n", vg->vg_number);
- sz += sprintf ( page+sz, "LV max: %u\n", vg->lv_max);
- sz += sprintf ( page+sz, "LV current: %u\n", vg->lv_cur);
- sz += sprintf ( page+sz, "LV open: %u\n", vg->lv_open);
- sz += sprintf ( page+sz, "PV max: %u\n", vg->pv_max);
- sz += sprintf ( page+sz, "PV current: %u\n", vg->pv_cur);
- sz += sprintf ( page+sz, "PV active: %u\n", vg->pv_act);
- sz += sprintf ( page+sz, "PE size: %u\n", vg->pe_size / 2);
- sz += sprintf ( page+sz, "PE total: %u\n", vg->pe_total);
- sz += sprintf ( page+sz, "PE allocated: %u\n", vg->pe_allocated);
- sz += sprintf ( page+sz, "uuid: %s\n", lvm_show_uuid(vg->vg_uuid));
-
- return sz;
-}
-
-
-/*
- * provide LV information
- */
-int lvm_proc_read_lv_info(char *page, char **start, off_t off,
- int count, int *eof, void *data) {
- int sz = 0;
- lv_t *lv = data;
-
- sz += sprintf ( page+sz, "name: %s\n", lv->lv_name);
- sz += sprintf ( page+sz, "size: %u\n", lv->lv_size);
- sz += sprintf ( page+sz, "access: %u\n", lv->lv_access);
- sz += sprintf ( page+sz, "status: %u\n", lv->lv_status);
- sz += sprintf ( page+sz, "number: %u\n", lv->lv_number);
- sz += sprintf ( page+sz, "open: %u\n", lv->lv_open);
- sz += sprintf ( page+sz, "allocation: %u\n", lv->lv_allocation);
- sz += sprintf ( page+sz, "device: %02u:%02u\n",
- MAJOR(lv->lv_dev), MINOR(lv->lv_dev));
-
- return sz;
-}
-
-
-/*
- * provide PV information
- */
-int lvm_proc_read_pv_info(char *page, char **start, off_t off,
- int count, int *eof, void *data) {
- int sz = 0;
- pv_t *pv = data;
-
- sz += sprintf ( page+sz, "name: %s\n", pv->pv_name);
- sz += sprintf ( page+sz, "size: %u\n", pv->pv_size);
- sz += sprintf ( page+sz, "status: %u\n", pv->pv_status);
- sz += sprintf ( page+sz, "number: %u\n", pv->pv_number);
- sz += sprintf ( page+sz, "allocatable: %u\n", pv->pv_allocatable);
- sz += sprintf ( page+sz, "LV current: %u\n", pv->lv_cur);
- sz += sprintf ( page+sz, "PE size: %u\n", pv->pe_size / 2);
- sz += sprintf ( page+sz, "PE total: %u\n", pv->pe_total);
- sz += sprintf ( page+sz, "PE allocated: %u\n", pv->pe_allocated);
- sz += sprintf ( page+sz, "device: %02u:%02u\n",
- MAJOR(pv->pv_dev), MINOR(pv->pv_dev));
- sz += sprintf ( page+sz, "uuid: %s\n", lvm_show_uuid(pv->pv_uuid));
-
-
- return sz;


+ return 0;
X }
X

-
-/*
- * block device support function for /usr/src/linux/drivers/block/ll_rw_blk.c
- * (see init_module/lvm_init)
- */
X static int lvm_map(struct buffer_head *bh, int rw)
X {
X int minor = MINOR(bh->b_rdev);
- int ret = 0;
X ulong index;
X ulong pe_start;
X ulong size = bh->b_size >> 9;
- ulong rsector_tmp = bh->b_rsector;
- ulong rsector_sav;
- kdev_t rdev_tmp = bh->b_rdev;
- kdev_t rdev_sav;
+ ulong rsector_org = bh->b_rsector;
+ ulong rsector_map;
+ kdev_t rdev_map;
X vg_t *vg_this = vg[VG_BLK(minor)];
X lv_t *lv = vg_this->lv[LV_BLK(minor)];
X
X
+ down_read(&lv->lv_lock);
X if (!(lv->lv_status & LV_ACTIVE)) {
X printk(KERN_ALERT
X "%s - lvm_map: ll_rw_blk for inactive LV %s\n",
X lvm_name, lv->lv_name);
- return -1;
+ goto bad;
X }
X
X if ((rw == WRITE || rw == WRITEA) &&
X !(lv->lv_access & LV_WRITE)) {
X printk(KERN_CRIT
- "%s - lvm_map: ll_rw_blk write for readonly LV %s\n",
+ "%s - lvm_map: ll_rw_blk write for readonly LV %s\n",
X lvm_name, lv->lv_name);
- return -1;
+ goto bad;
X }
X
- P_MAP("%s - lvm_map minor:%d *rdev: %02d:%02d *rsector: %lu "
- "size:%lu\n",
+ P_MAP("%s - lvm_map minor: %d *rdev: %s *rsector: %lu size:%lu\n",
X lvm_name, minor,
- MAJOR(rdev_tmp),
- MINOR(rdev_tmp),
- rsector_tmp, size);
+ kdevname(bh->b_rdev),
+ rsector_org, size);
X
- if (rsector_tmp + size > lv->lv_size) {
+ if (rsector_org + size > lv->lv_size) {
X printk(KERN_ALERT
X "%s - lvm_map access beyond end of device; *rsector: "
X "%lu or size: %lu wrong for minor: %2d\n",
- lvm_name, rsector_tmp, size, minor);
- return -1;
+ lvm_name, rsector_org, size, minor);
+ goto bad;
X }
- rsector_sav = rsector_tmp;
- rdev_sav = rdev_tmp;
X
-lvm_second_remap:
- /* linear mapping */
- if (lv->lv_stripes < 2) {
+
+ if (lv->lv_stripes < 2) { /* linear mapping */
X /* get the index */
- index = rsector_tmp / vg_this->pe_size;
+ index = rsector_org / vg_this->pe_size;
X pe_start = lv->lv_current_pe[index].pe;
- rsector_tmp = lv->lv_current_pe[index].pe +
- (rsector_tmp % vg_this->pe_size);
- rdev_tmp = lv->lv_current_pe[index].dev;
-
- P_MAP("lv_current_pe[%ld].pe: %ld rdev: %02d:%02d "
- "rsector:%ld\n",
- index,
- lv->lv_current_pe[index].pe,
- MAJOR(rdev_tmp),
- MINOR(rdev_tmp),
- rsector_tmp);
+ rsector_map = lv->lv_current_pe[index].pe +
+ (rsector_org % vg_this->pe_size);
+ rdev_map = lv->lv_current_pe[index].dev;
+
+ P_MAP("lv_current_pe[%ld].pe: %d rdev: %s rsector:%ld\n",
+ index, lv->lv_current_pe[index].pe,
+ kdevname(rdev_map), rsector_map);
X
- /* striped mapping */
- } else {
+ } else { /* striped mapping */
X ulong stripe_index;
X ulong stripe_length;
X
X stripe_length = vg_this->pe_size * lv->lv_stripes;
- stripe_index = (rsector_tmp % stripe_length) / lv->lv_stripesize;
- index = rsector_tmp / stripe_length +
- (stripe_index % lv->lv_stripes) *
- (lv->lv_allocated_le / lv->lv_stripes);
+ stripe_index = (rsector_org % stripe_length) /
+ lv->lv_stripesize;
+ index = rsector_org / stripe_length +
+ (stripe_index % lv->lv_stripes) *
+ (lv->lv_allocated_le / lv->lv_stripes);
X pe_start = lv->lv_current_pe[index].pe;
- rsector_tmp = lv->lv_current_pe[index].pe +
- (rsector_tmp % stripe_length) -
- (stripe_index % lv->lv_stripes) * lv->lv_stripesize -
- stripe_index / lv->lv_stripes *
- (lv->lv_stripes - 1) * lv->lv_stripesize;
- rdev_tmp = lv->lv_current_pe[index].dev;
- }
-
- P_MAP("lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n"
- "stripe_length: %ld stripe_index: %ld\n",
- index,
- lv->lv_current_pe[index].pe,
- MAJOR(rdev_tmp),
- MINOR(rdev_tmp),
- rsector_tmp,
- stripe_length,
- stripe_index);
+ rsector_map = lv->lv_current_pe[index].pe +
+ (rsector_org % stripe_length) -
+ (stripe_index % lv->lv_stripes) * lv->lv_stripesize -
+ stripe_index / lv->lv_stripes *
+ (lv->lv_stripes - 1) * lv->lv_stripesize;
+ rdev_map = lv->lv_current_pe[index].dev;
+
+ P_MAP("lv_current_pe[%ld].pe: %d rdev: %s rsector:%ld\n"
+ "stripe_length: %ld stripe_index: %ld\n",
+ index, lv->lv_current_pe[index].pe, kdevname(rdev_map),
+ rsector_map, stripe_length, stripe_index);
+ }
+
+ /*
+ * Queue writes to physical extents on the move until move completes.
+ * Don't get _pe_lock until there is a reasonable expectation that
+ * we need to queue this request, because this is in the fast path.
+ */
+ if (rw == WRITE || rw == WRITEA) {
+ if(_defer_extent(bh, rw, rdev_map,
+ rsector_map, vg_this->pe_size)) {
X
- /* handle physical extents on the move */
- if (pe_lock_req.lock == LOCK_PE) {
- if (rdev_tmp == pe_lock_req.data.pv_dev &&
- rsector_tmp >= pe_lock_req.data.pv_offset &&
- rsector_tmp < (pe_lock_req.data.pv_offset +
- vg_this->pe_size)) {
- sleep_on(&lvm_map_wait);
- rsector_tmp = rsector_sav;
- rdev_tmp = rdev_sav;
- goto lvm_second_remap;
+ up_read(&lv->lv_lock);
+ return 0;
X }
- }
- /* statistic */
- if (rw == WRITE || rw == WRITEA)
- lv->lv_current_pe[index].writes++;
- else
- lv->lv_current_pe[index].reads++;
+
+ lv->lv_current_pe[index].writes++; /* statistic */
+ } else
+ lv->lv_current_pe[index].reads++; /* statistic */
X
X /* snapshot volume exception handling on physical device address base */
- if (lv->lv_access & (LV_SNAPSHOT|LV_SNAPSHOT_ORG)) {
- /* original logical volume */
- if (lv->lv_access & LV_SNAPSHOT_ORG) {
- /* Serializes the access to the lv_snapshot_next list */
- down(&lv->lv_snapshot_sem);
- if (rw == WRITE || rw == WRITEA)
- {
- lv_t *lv_ptr;
-
- /* start with first snapshot and loop thrugh all of them */
- for (lv_ptr = lv->lv_snapshot_next;
- lv_ptr != NULL;
- lv_ptr = lv_ptr->lv_snapshot_next) {
- /* Check for inactive snapshot */
- if (!(lv_ptr->lv_status & LV_ACTIVE)) continue;
- /* Serializes the COW with the accesses to the snapshot device */
- down(&lv_ptr->lv_snapshot_sem);
- /* do we still have exception storage for this snapshot free? */
- if (lv_ptr->lv_block_exception != NULL) {
- rdev_sav = rdev_tmp;
- rsector_sav = rsector_tmp;
- if (!lvm_snapshot_remap_block(&rdev_tmp,
- &rsector_tmp,
- pe_start,
- lv_ptr)) {
- /* create a new mapping */
- if (!(ret = lvm_snapshot_COW(rdev_tmp,
- rsector_tmp,
- pe_start,
- rsector_sav,
- lv_ptr)))
- ret = lvm_write_COW_table_block(vg_this,
- lv_ptr);
- }
- rdev_tmp = rdev_sav;
- rsector_tmp = rsector_sav;
- }
- up(&lv_ptr->lv_snapshot_sem);
- }
- }
- up(&lv->lv_snapshot_sem);
- } else {
- /* remap snapshot logical volume */
- down(&lv->lv_snapshot_sem);
- if (lv->lv_block_exception != NULL)
- lvm_snapshot_remap_block(&rdev_tmp, &rsector_tmp, pe_start, lv);
- up(&lv->lv_snapshot_sem);
- }
- }
- bh->b_rdev = rdev_tmp;
- bh->b_rsector = rsector_tmp;
+ if (!(lv->lv_access & (LV_SNAPSHOT|LV_SNAPSHOT_ORG)))
+ goto out;
X
- return ret;
+ if (lv->lv_access & LV_SNAPSHOT) { /* remap snapshot */
+ if (lv->lv_block_exception)
+ lvm_snapshot_remap_block(&rdev_map, &rsector_map,
+ pe_start, lv);
+ else
+ goto bad;
+
+ } else if (rw == WRITE || rw == WRITEA) { /* snapshot origin */
+ lv_t *snap;
+
+ /* start with first snapshot and loop through all of
+ them */
+ for (snap = lv->lv_snapshot_next; snap;
+ snap = snap->lv_snapshot_next) {
+ /* Check for inactive snapshot */
+ if (!(snap->lv_status & LV_ACTIVE))
+ continue;
+
+ /* Serializes the COW with the accesses to the
+ snapshot device */
+ _remap_snapshot(rdev_map, rsector_map,
+ pe_start, snap, vg_this);
+ }
+ }
+
+ out:
+ bh->b_rdev = rdev_map;
+ bh->b_rsector = rsector_map;
+ up_read(&lv->lv_lock);
+ return 1;
+
+ bad:
+ buffer_IO_error(bh);
+ up_read(&lv->lv_lock);
+ return -1;
X } /* lvm_map() */
X
X
@@ -1651,13 +1289,8 @@
X */
X static int lvm_make_request_fn(request_queue_t *q,
X int rw,
- struct buffer_head *bh)
-{
- if (lvm_map(bh, rw) >= 0)
- return 1;
-


- buffer_IO_error(bh);
- return 0;

+ struct buffer_head *bh) {
+ return (lvm_map(bh, rw) <= 0) ? 0 : 1;
X }
X
X
@@ -1674,8 +1307,7 @@
X lock_try_again:
X spin_lock(&lvm_lock);
X if (lock != 0 && lock != current->pid) {
- P_IOCTL("lvm_do_lock_lvm: %s is locked by pid %d ...\n",
- lvm_name, lock);
+ P_DEV("lvm_do_lock_lvm: locked by pid %d ...\n", lock);
X spin_unlock(&lvm_lock);
X interruptible_sleep_on(&lvm_wait);
X if (current->sigpending != 0)
@@ -1687,6 +1319,7 @@
X goto lock_try_again;
X }
X lock = current->pid;
+ P_DEV("lvm_do_lock_lvm: locking LVM for pid %d\n", lock);
X spin_unlock(&lvm_lock);
X return 0;
X } /* lvm_do_lock_lvm */
@@ -1697,33 +1330,60 @@
X */
X static int lvm_do_pe_lock_unlock(vg_t *vg_ptr, void *arg)
X {
+ pe_lock_req_t new_lock;
+ struct buffer_head *bh;
X uint p;
X
X if (vg_ptr == NULL) return -ENXIO;
- if (copy_from_user(&pe_lock_req, arg,
- sizeof(pe_lock_req_t)) != 0) return -EFAULT;
+ if (copy_from_user(&new_lock, arg, sizeof(new_lock)) != 0)
+ return -EFAULT;
X
- switch (pe_lock_req.lock) {
+ switch (new_lock.lock) {
X case LOCK_PE:
X for (p = 0; p < vg_ptr->pv_max; p++) {
X if (vg_ptr->pv[p] != NULL &&
- pe_lock_req.data.pv_dev ==
- vg_ptr->pv[p]->pv_dev)
+ new_lock.data.pv_dev == vg_ptr->pv[p]->pv_dev)
X break;
X }
X if (p == vg_ptr->pv_max) return -ENXIO;
X
- pe_lock_req.lock = UNLOCK_PE;
+ /*
+ * this sync releaves memory pressure to lessen the
+ * likelyhood of pvmove being paged out - resulting in
+ * deadlock.
+ *
+ * This method of doing a pvmove is broken
+ */
X fsync_dev(pe_lock_req.data.lv_dev);
+
+ down_write(&_pe_lock);
+ if (pe_lock_req.lock == LOCK_PE) {
+ up_write(&_pe_lock);


+ return -EBUSY;
+ }
+

+ /* Should we do to_kdev_t() on the pv_dev and lv_dev??? */
X pe_lock_req.lock = LOCK_PE;
+ pe_lock_req.data.lv_dev = new_lock.data.lv_dev;
+ pe_lock_req.data.pv_dev = new_lock.data.pv_dev;
+ pe_lock_req.data.pv_offset = new_lock.data.pv_offset;
+ up_write(&_pe_lock);
+
+ /* some requests may have got through since the fsync */
+ fsync_dev(pe_lock_req.data.pv_dev);
X break;
X
X case UNLOCK_PE:
+ down_write(&_pe_lock);
X pe_lock_req.lock = UNLOCK_PE;
- pe_lock_req.data.lv_dev = \
- pe_lock_req.data.pv_dev = \
+ pe_lock_req.data.lv_dev = 0;
+ pe_lock_req.data.pv_dev = 0;
X pe_lock_req.data.pv_offset = 0;
- wake_up(&lvm_map_wait);
+ bh = _dequeue_io();
+ up_write(&_pe_lock);
+
+ /* handle all deferred io for this PE */
+ _flush_io(bh);


X break;
X
X default:

@@ -1760,6 +1420,8 @@
X le_remap_req.new_dev;
X lv_ptr->lv_current_pe[le].pe =
X le_remap_req.new_pe;
+
+ __update_hardsectsize(lv_ptr);


X return 0;
X }
X }

@@ -1773,7 +1435,7 @@
X /*
X * character device support function VGDA create
X */
-int lvm_do_vg_create(int minor, void *arg)
+static int lvm_do_vg_create(void *arg, int minor)
X {
X int ret = 0;
X ulong l, ls = 0, p, size;
@@ -1781,8 +1443,6 @@
X vg_t *vg_ptr;
X lv_t **snap_lv_ptr;
X
- if (vg[VG_CHR(minor)] != NULL) return -EPERM;
-
X if ((vg_ptr = kmalloc(sizeof(vg_t),GFP_KERNEL)) == NULL) {
X printk(KERN_CRIT
X "%s -- VG_CREATE: kmalloc error VG at line %d\n",
@@ -1791,35 +1451,51 @@
X }
X /* get the volume group structure */
X if (copy_from_user(vg_ptr, arg, sizeof(vg_t)) != 0) {
+ P_IOCTL("lvm_do_vg_create ERROR: copy VG ptr %p (%d bytes)\n",
+ arg, sizeof(vg_t));
X kfree(vg_ptr);
X return -EFAULT;


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

echo 'End of part 047'
echo 'File patch-2.4.15 is continued in part 048'
echo "048" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:18 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part042

#!/bin/sh -x
# this is part 042 of a 115 - part archive


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

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

+{
+ u8 hp_slot;
+
+ hp_slot = func->device - ctrl->slot_device_offset;
+
+ if (func == NULL)
+ return(1);
+
+ // Wait for exclusive access to hardware
+ down(&ctrl->crit_sect);
+
+ if (status == 1) {
+ amber_LED_on (ctrl, hp_slot);
+ } else if (status == 0) {
+ amber_LED_off (ctrl, hp_slot);
+ } else {
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);
+ return(1);
+ }
+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);
+
+ return(0);
+}
+
+
+/**
+ * set_attention_status - Turns the Amber LED for a slot on or off
+ *
+ */
+static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
+{
+ struct pci_func *slot_func;
+ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+ struct controller *ctrl;
+ u8 bus;
+ u8 devfn;
+ u8 device;
+ u8 function;


+
+ if (slot == NULL)
+ return -ENODEV;
+

+ dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+ ctrl = slot->ctrl;
+ if (ctrl == NULL)
+ return -ENODEV;
+
+ if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
+ return -ENODEV;
+
+ device = devfn >> 3;
+ function = devfn & 0x7;
+ dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function);
+
+ slot_func = cpqhp_slot_find(bus, device, function);
+ if (!slot_func) {


+ return -ENODEV;
+ }
+

+ return cpqhp_set_attention_status(ctrl, slot_func, status);
+}
+
+
+static int process_SI (struct hotplug_slot *hotplug_slot)
+{
+ struct pci_func *slot_func;
+ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+ struct controller *ctrl;
+ u8 bus;
+ u8 devfn;
+ u8 device;
+ u8 function;


+
+ if (slot == NULL)
+ return -ENODEV;
+

+ dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+ ctrl = slot->ctrl;
+ if (ctrl == NULL)
+ return -ENODEV;
+
+ if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
+ return -ENODEV;
+
+ device = devfn >> 3;
+ function = devfn & 0x7;
+ dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function);
+
+ slot_func = cpqhp_slot_find(bus, device, function);
+ if (!slot_func) {


+ return -ENODEV;
+ }
+

+ slot_func->bus = bus;
+ slot_func->device = device;
+ slot_func->function = function;
+ slot_func->configured = 0;
+ dbg("board_added(%p, %p)\n", slot_func, ctrl);
+ return cpqhp_process_SI(ctrl, slot_func);
+}
+
+
+static int process_SS (struct hotplug_slot *hotplug_slot)
+{
+ struct pci_func *slot_func;
+ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+ struct controller *ctrl;
+ u8 bus;
+ u8 devfn;
+ u8 device;
+ u8 function;


+
+ if (slot == NULL)
+ return -ENODEV;
+

+ dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+ ctrl = slot->ctrl;
+ if (ctrl == NULL)
+ return -ENODEV;
+
+ if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
+ return -ENODEV;
+
+ device = devfn >> 3;
+ function = devfn & 0x7;
+ dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function);
+
+ slot_func = cpqhp_slot_find(bus, device, function);
+ if (!slot_func) {


+ return -ENODEV;
+ }
+

+ dbg("In power_down_board, slot_func = %p, ctrl = %p\n", slot_func, ctrl);
+ return cpqhp_process_SS(ctrl, slot_func);
+}
+
+
+static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value)
+{
+ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+ struct controller *ctrl;
+
+ dbg(__FUNCTION__"\n");


+
+ if (slot == NULL)
+ return -ENODEV;
+

+ ctrl = slot->ctrl;
+ if (ctrl == NULL)
+ return -ENODEV;
+
+ return cpqhp_hardware_test (ctrl, value);
+}
+
+
+static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+ struct controller *ctrl;


+
+ if (slot == NULL)
+ return -ENODEV;
+

+ dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+ ctrl = slot->ctrl;
+ if (ctrl == NULL)
+ return -ENODEV;
+
+ *value = get_slot_enabled(ctrl, slot);


+ return 0;
+}
+

+static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+ struct controller *ctrl;


+
+ if (slot == NULL)
+ return -ENODEV;
+

+ dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+ ctrl = slot->ctrl;
+ if (ctrl == NULL)
+ return -ENODEV;
+
+ *value = cpq_get_attention_status(ctrl, slot);


+ return 0;
+}
+

+static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+ struct controller *ctrl;


+
+ if (slot == NULL)
+ return -ENODEV;
+

+ dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+ ctrl = slot->ctrl;
+ if (ctrl == NULL)
+ return -ENODEV;
+
+ *value = cpq_get_latch_status (ctrl, slot);
+


+ return 0;
+}
+

+static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+ struct controller *ctrl;


+
+ if (slot == NULL)
+ return -ENODEV;
+

+ dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+ ctrl = slot->ctrl;
+ if (ctrl == NULL)
+ return -ENODEV;
+
+ *value = get_presence_status (ctrl, slot);
+


+ return 0;
+}
+

+static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ u8 num_of_slots = 0;
+ u8 hp_slot = 0;
+ u8 device;
+ u8 rev;
+ u16 temp_word;
+ u16 vendor_id;
+ u16 subsystem_vid;
+ u16 subsystem_deviceid;
+ u32 rc;
+ struct controller *ctrl;
+ struct pci_func *func;
+
+ // Need to read VID early b/c it's used to differentiate CPQ and INTC discovery
+ rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
+ if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
+ err(msg_HPC_non_compaq_or_intel);
+ return -ENODEV;
+ }
+ dbg("Vendor ID: %x\n", vendor_id);
+
+ rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+ dbg("revision: %d\n", rev);
+ if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) {
+ err(msg_HPC_rev_error);


+ return -ENODEV;
+ }
+

+ /* Check for the proper subsytem ID's
+ * Intel uses a different SSID programming model than Compaq.
+ * For Intel, each SSID bit identifies a PHP capability.
+ * Also Intel HPC's may have RID=0.
+ */
+ if ((rev > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
+ // TODO: This code can be made to support non-Compaq or Intel subsystem IDs
+ rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
+ if (rc) {
+ err(__FUNCTION__" : pci_read_config_word failed\n");
+ return rc;
+ }
+ dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
+ if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
+ err(msg_HPC_non_compaq_or_intel);


+ return -ENODEV;
+ }
+

+ ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
+ if (!ctrl) {
+ err(__FUNCTION__" : out of memory\n");
+ return -ENOMEM;
+ }
+ memset(ctrl, 0, sizeof(struct controller));
+
+ rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
+ if (rc) {
+ err(__FUNCTION__" : pci_read_config_word failed\n");
+ goto err_free_ctrl;
+ }
+
+ info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid);
+
+ /* Set Vendor ID, so it can be accessed later from other functions */
+ ctrl->vendor_id = vendor_id;
+
+ switch (subsystem_vid) {
+ case PCI_VENDOR_ID_COMPAQ:
+ switch (subsystem_deviceid) {
+ case PCI_SUB_HPC_ID:
+ /* Original 6500/7000 implementation */
+ ctrl->slot_switch_type = 1; // Switch is present
+ ctrl->speed_capability = CTRL_SPEED_33MHz;
+ ctrl->push_button = 0; // No pushbutton
+ ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported
+ ctrl->defeature_PHP = 1; // PHP is supported
+ ctrl->pcix_support = 0; // PCI-X not supported
+ ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported
+ break;
+ case PCI_SUB_HPC_ID2:
+ /* First Pushbutton implementation */
+ ctrl->push_flag = 1;
+ ctrl->slot_switch_type = 1; // Switch is present
+ ctrl->speed_capability = CTRL_SPEED_33MHz;
+ ctrl->push_button = 1; // Pushbutton is present
+ ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported
+ ctrl->defeature_PHP = 1; // PHP is supported
+ ctrl->pcix_support = 0; // PCI-X not supported
+ ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported
+ break;
+ case PCI_SUB_HPC_ID_INTC:
+ /* Third party (6500/7000) */
+ ctrl->slot_switch_type = 1; // Switch is present
+ ctrl->speed_capability = CTRL_SPEED_33MHz;
+ ctrl->push_button = 0; // No pushbutton
+ ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported
+ ctrl->defeature_PHP = 1; // PHP is supported
+ ctrl->pcix_support = 0; // PCI-X not supported
+ ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported
+ break;
+ case PCI_SUB_HPC_ID3:
+ /* First 66 Mhz implementation */
+ ctrl->push_flag = 1;
+ ctrl->slot_switch_type = 1; // Switch is present
+ ctrl->speed_capability = CTRL_SPEED_66MHz;
+ ctrl->push_button = 1; // Pushbutton is present
+ ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported
+ ctrl->defeature_PHP = 1; // PHP is supported
+ ctrl->pcix_support = 0; // PCI-X not supported
+ ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported
+ break;
+ default:
+ // TODO: Add SSIDs for CPQ systems that support PCI-X
+ err(msg_HPC_not_supported);
+ rc = -ENODEV;
+ goto err_free_ctrl;
+ }
+ break;
+
+ case PCI_VENDOR_ID_INTEL:
+ /* Check for speed capability (0=33, 1=66) */
+ if (subsystem_deviceid & 0x0001) {
+ ctrl->speed_capability = CTRL_SPEED_66MHz;
+ } else {
+ ctrl->speed_capability = CTRL_SPEED_33MHz;
+ }
+
+ /* Check for push button */
+ if (subsystem_deviceid & 0x0002) {
+ /* no push button */
+ ctrl->push_button = 0;
+ } else {
+ /* push button supported */
+ ctrl->push_button = 1;
+ }
+
+ /* Check for slot switch type (0=mechanical, 1=not mechanical) */
+ if (subsystem_deviceid & 0x0004) {
+ /* no switch */
+ ctrl->slot_switch_type = 0;
+ } else {
+ /* switch */
+ ctrl->slot_switch_type = 1;
+ }
+
+ /* PHP Status (0=De-feature PHP, 1=Normal operation) */
+ if (subsystem_deviceid & 0x0008) {
+ ctrl->defeature_PHP = 1; // PHP supported
+ } else {
+ ctrl->defeature_PHP = 0; // PHP not supported
+ }
+
+ /* Alternate Base Address Register Interface (0=not supported, 1=supported) */
+ if (subsystem_deviceid & 0x0010) {
+ ctrl->alternate_base_address = 1; // supported
+ } else {
+ ctrl->alternate_base_address = 0; // not supported
+ }
+
+ /* PCI Config Space Index (0=not supported, 1=supported) */
+ if (subsystem_deviceid & 0x0020) {
+ ctrl->pci_config_space = 1; // supported
+ } else {
+ ctrl->pci_config_space = 0; // not supported
+ }
+
+ /* PCI-X support */
+ if (subsystem_deviceid & 0x0080) {
+ /* PCI-X capable */
+ ctrl->pcix_support = 1;
+ /* Frequency of operation in PCI-X mode */
+ if (subsystem_deviceid & 0x0040) {
+ /* 133MHz PCI-X if bit 7 is 1 */
+ ctrl->pcix_speed_capability = 1;
+ } else {
+ /* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */
+ /* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */
+ ctrl->pcix_speed_capability = 0;
+ }
+ } else {
+ /* Conventional PCI */
+ ctrl->pcix_support = 0;
+ ctrl->pcix_speed_capability = 0;
+ }


+ break;
+
+ default:

+ err(msg_HPC_not_supported);
+ rc = -ENODEV;
+ goto err_free_ctrl;
+ }
+
+ } else {
+ err(msg_HPC_not_supported);


+ return -ENODEV;
+ }
+

+ // Tell the user that we found one.
+ info("Initializing the PCI hot plug controller residing on PCI bus %d\n", pdev->bus->number);
+
+ dbg ("Hotplug controller capabilities:\n");
+ dbg (" speed_capability %s\n", ctrl->speed_capability == CTRL_SPEED_33MHz ? "33MHz" : "66Mhz");
+ dbg (" slot_switch_type %s\n", ctrl->slot_switch_type == 0 ? "no switch" : "switch present");
+ dbg (" defeature_PHP %s\n", ctrl->defeature_PHP == 0 ? "PHP not supported" : "PHP supported");
+ dbg (" alternate_base_address %s\n", ctrl->alternate_base_address == 0 ? "not supported" : "supported");
+ dbg (" pci_config_space %s\n", ctrl->pci_config_space == 0 ? "not supported" : "supported");
+ dbg (" pcix_speed_capability %s\n", ctrl->pcix_speed_capability == 0 ? "not supported" : "supported");
+ dbg (" pcix_support %s\n", ctrl->pcix_support == 0 ? "not supported" : "supported");
+
+ ctrl->pci_dev = pdev;
+ ctrl->pci_ops = pdev->bus->ops;
+ ctrl->bus = pdev->bus->number;
+ ctrl->device = PCI_SLOT(pdev->devfn);
+ ctrl->function = PCI_FUNC(pdev->devfn);
+ ctrl->rev = rev;
+ dbg("bus device function rev: %d %d %d %d\n", ctrl->bus, ctrl->device, ctrl->function, ctrl->rev);
+
+ init_MUTEX(&ctrl->crit_sect);
+ init_waitqueue_head(&ctrl->queue);
+
+ /* initialize our threads if they haven't already been started up */
+ rc = one_time_init();
+ if (rc) {
+ goto err_free_ctrl;
+ }
+
+ dbg("pdev = %p\n", pdev);
+ dbg("pci resource start %lx\n", pci_resource_start(pdev, 0));
+ dbg("pci resource len %lx\n", pci_resource_len(pdev, 0));
+
+ if (!request_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0), MY_NAME)) {
+ err("cannot reserve MMIO region\n");
+ rc = -ENOMEM;
+ goto err_free_ctrl;
+ }
+
+ ctrl->hpc_reg = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+ if (!ctrl->hpc_reg) {
+ err("cannot remap MMIO region %lx @ %lx\n", pci_resource_len(pdev, 0), pci_resource_start(pdev, 0));
+ rc = -ENODEV;
+ goto err_free_mem_region;
+ }
+
+ // Check for 66Mhz operation
+ // TODO: Add PCI-X support
+ ctrl->speed = get_controller_speed(ctrl);
+
+
+ //**************************************************
+ //
+ // Save configuration headers for this and
+ // subordinate PCI buses
+ //
+ //**************************************************
+
+ // find the physical slot number of the first hot plug slot
+
+ // Get slot won't work for devices behind bridges, but
+ // in this case it will always be called for the "base"
+ // bus/dev/func of a slot.
+ // CS: this is leveraging the PCIIRQ routing code from the kernel (pci-pc.c: get_irq_routing_table)
+ rc = get_slot_mapping(ctrl->pci_ops, pdev->bus->number, (readb(ctrl->hpc_reg + SLOT_MASK) >> 4), &(ctrl->first_slot));
+ dbg("get_slot_mapping: first_slot = %d, returned = %d\n", ctrl->first_slot, rc);
+ if (rc) {
+ err(msg_initialization_err, rc);
+ goto err_iounmap;
+ }
+
+ // Store PCI Config Space for all devices on this bus
+ rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK));
+ if (rc) {
+ err(__FUNCTION__": unable to save PCI configuration data, error %d\n", rc);
+ goto err_iounmap;
+ }
+
+ /*
+ * Get IO, memory, and IRQ resources for new devices
+ */
+ rc = cpqhp_find_available_resources(ctrl, cpqhp_rom_start);
+ ctrl->add_support = !rc;
+ if (rc) {
+ dbg("cpqhp_find_available_resources = 0x%x\n", rc);
+ err("unable to locate PCI configuration resources for hot plug add.\n");
+ goto err_iounmap;
+ }
+
+ /*
+ * Finish setting up the hot plug ctrl device
+ */
+ ctrl->slot_device_offset = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
+ dbg("NumSlots %d \n", ctrl->slot_device_offset);
+
+ ctrl->next_event = 0;
+
+ /* Setup the slot information structures */
+ rc = ctrl_slot_setup(ctrl, smbios_start, smbios_table);
+ if (rc) {
+ err(msg_initialization_err, 6);
+ err(__FUNCTION__": unable to save PCI configuration data, error %d\n", rc);
+ goto err_iounmap;
+ }
+
+ /* Mask all general input interrupts */
+ writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_MASK);
+
+ /* set up the interrupt */
+ ctrl->interrupt = pdev->irq;
+ dbg("HPC interrupt = %d \n", ctrl->interrupt);
+ if (request_irq(ctrl->interrupt,
+ (void (*)(int, void *, struct pt_regs *)) &cpqhp_ctrl_intr,
+ SA_SHIRQ, MY_NAME, ctrl)) {
+ err("Can't get irq %d for the hotplug pci controller\n", ctrl->interrupt);
+ rc = -ENODEV;
+ goto err_iounmap;
+ }
+
+ /* Enable Shift Out interrupt and clear it, also enable SERR on power fault */
+ temp_word = readw(ctrl->hpc_reg + MISC);
+ temp_word |= 0x4006;
+ writew(temp_word, ctrl->hpc_reg + MISC);
+
+ // Changed 05/05/97 to clear all interrupts at start
+ writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+ ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+ writel(0x0L, ctrl->hpc_reg + INT_MASK);
+
+ if (!cpqhp_ctrl_list) {
+ cpqhp_ctrl_list = ctrl;
+ ctrl->next = NULL;
+ } else {
+ ctrl->next = cpqhp_ctrl_list;
+ cpqhp_ctrl_list = ctrl;
+ }
+
+ // turn off empty slots here unless command line option "ON" set
+ // Wait for exclusive access to hardware
+ down(&ctrl->crit_sect);
+
+ num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
+
+ // find first device number for the ctrl
+ device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
+
+ while (num_of_slots) {
+ dbg("num_of_slots: %d\n", num_of_slots);
+ func = cpqhp_slot_find(ctrl->bus, device, 0);
+ if (!func)
+ break;
+
+ hp_slot = func->device - ctrl->slot_device_offset;
+ dbg("hp_slot: %d\n", hp_slot);
+
+ // We have to save the presence info for these slots
+ temp_word = ctrl->ctrl_int_comp >> 16;
+ func->presence_save = (temp_word >> hp_slot) & 0x01;
+ func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;
+
+ if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {
+ func->switch_save = 0;
+ } else {
+ func->switch_save = 0x10;
+ }
+
+ if (!power_mode) {
+ if (!func->is_a_board) {
+ green_LED_off (ctrl, hp_slot);
+ slot_disable (ctrl, hp_slot);
+ }
+ }
+
+ device++;
+ num_of_slots--;
+ }
+
+ if (!power_mode) {
+ set_SOGO(ctrl);
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+ }
+
+ rc = init_SERR(ctrl);
+ if (rc) {
+ err("init_SERR failed\n");
+ up(&ctrl->crit_sect);
+ goto err_free_irq;
+ }
+
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);
+
+ rc = cpqhp_proc_create_ctrl (ctrl);
+ if (rc) {
+ err("cpqhp_proc_create_ctrl failed\n");
+ goto err_free_irq;
+ }


+
+ return 0;
+

+err_free_irq:
+ free_irq(ctrl->interrupt, ctrl);
+err_iounmap:
+ iounmap(ctrl->hpc_reg);
+err_free_mem_region:
+ release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+err_free_ctrl:
+ kfree(ctrl);
+ return rc;
+}
+
+
+static int one_time_init(void)
+{
+ int loop;


+ int retval = 0;

+ static int initialized = 0;
+
+ if (initialized)
+ return 0;
+
+ power_mode = 0;
+
+ retval = pci_print_IRQ_route();
+ if (retval)
+ goto error;
+
+ dbg("Initialize + Start the notification mechanism \n");
+
+ retval = cpqhp_event_start_thread();
+ if (retval)
+ goto error;
+
+ dbg("Initialize slot lists\n");
+ for (loop = 0; loop < 256; loop++) {
+ cpqhp_slot_list[loop] = NULL;
+ }
+
+ // FIXME: We also need to hook the NMI handler eventually.
+ // this also needs to be worked with Christoph
+ // register_NMI_handler();
+
+ // Map rom address
+ cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
+ if (!cpqhp_rom_start) {
+ err ("Could not ioremap memory region for ROM\n");
+ retval = -EIO;;
+ goto error;
+ }
+
+ /* Now, map the int15 entry point if we are on compaq specific hardware */
+ compaq_nvram_init(cpqhp_rom_start);
+
+ /* Map smbios table entry point structure */
+ smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start, cpqhp_rom_start + ROM_PHY_LEN);
+ if (!smbios_table) {
+ err ("Could not find the SMBIOS pointer in memory\n");
+ retval = -EIO;;
+ goto error;
+ }
+
+ smbios_start = ioremap(readl(smbios_table + ST_ADDRESS), readw(smbios_table + ST_LENGTH));
+ if (!smbios_start) {
+ err ("Could not ioremap memory region taken from SMBIOS values\n");
+ retval = -EIO;;
+ goto error;
+ }
+
+ retval = cpqhp_proc_init_ctrl();
+ if (retval)
+ goto error;
+
+ initialized = 1;


+
+ return retval;
+

+error:
+ if (cpqhp_rom_start)
+ iounmap(cpqhp_rom_start);
+ if (smbios_start)
+ iounmap(smbios_start);
+
+ return retval;
+}
+
+
+static void unload_cpqphpd(void)
+{
+ struct pci_func *next;
+ struct pci_func *TempSlot;
+ int loop;
+ u32 rc;
+ struct controller *ctrl;
+ struct controller *tctrl;
+ struct pci_resource *res;
+ struct pci_resource *tres;
+
+ rc = compaq_nvram_store(cpqhp_rom_start);
+
+ ctrl = cpqhp_ctrl_list;
+
+ while (ctrl) {
+ cpqhp_proc_remove_ctrl (ctrl);
+
+ if (ctrl->hpc_reg) {
+ u16 misc;
+ rc = read_slot_enable (ctrl);
+
+ writeb(0, ctrl->hpc_reg + SLOT_SERR);
+ writel(0xFFFFFFC0L | ~rc, ctrl->hpc_reg + INT_MASK);
+
+ misc = readw(ctrl->hpc_reg + MISC);
+ misc &= 0xFFFD;
+ writew(misc, ctrl->hpc_reg + MISC);
+ }
+
+ ctrl_slot_cleanup(ctrl);
+


+ res = ctrl->io_head;

+ while (res) {
+ tres = res;


+ res = res->next;

+ kfree(tres);
+ }
+


+ res = ctrl->mem_head;

+ while (res) {
+ tres = res;


+ res = res->next;

+ kfree(tres);
+ }
+


+ res = ctrl->p_mem_head;

+ while (res) {
+ tres = res;


+ res = res->next;

+ kfree(tres);
+ }
+


+ res = ctrl->bus_head;

+ while (res) {
+ tres = res;


+ res = res->next;

+ kfree(tres);
+ }
+
+ tctrl = ctrl;
+ ctrl = ctrl->next;
+ kfree(tctrl);
+ }
+
+ for (loop = 0; loop < 256; loop++) {
+ next = cpqhp_slot_list[loop];
+ while (next != NULL) {
+ res = next->io_head;
+ while (res) {
+ tres = res;


+ res = res->next;

+ kfree(tres);
+ }
+
+ res = next->mem_head;
+ while (res) {
+ tres = res;


+ res = res->next;

+ kfree(tres);
+ }
+
+ res = next->p_mem_head;
+ while (res) {
+ tres = res;


+ res = res->next;

+ kfree(tres);
+ }
+
+ res = next->bus_head;
+ while (res) {
+ tres = res;


+ res = res->next;

+ kfree(tres);
+ }
+
+ TempSlot = next;
+ next = next->next;
+ kfree(TempSlot);
+ }
+ }
+
+ remove_proc_entry("hpc", 0);
+
+ // Stop the notification mechanism
+ cpqhp_event_stop_thread();
+
+ //unmap the rom address
+ if (cpqhp_rom_start)
+ iounmap(cpqhp_rom_start);
+ if (smbios_start)
+ iounmap(smbios_start);
+}
+
+
+
+static struct pci_device_id hpcd_pci_tbl[] __devinitdata = {
+ {
+ /* handle any PCI Hotplug controller */
+ class: ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00),
+ class_mask: ~0,
+
+ /* no matter who makes it */
+ vendor: PCI_ANY_ID,
+ device: PCI_ANY_ID,
+ subvendor: PCI_ANY_ID,
+ subdevice: PCI_ANY_ID,
+
+ }, { /* end: all zeroes */ }
+};
+
+MODULE_DEVICE_TABLE(pci, hpcd_pci_tbl);
+
+
+
+static struct pci_driver cpqhpc_driver = {
+ name: "pci_hotplug",
+ id_table: hpcd_pci_tbl,
+ probe: cpqhpc_probe,
+ /* remove: cpqhpc_remove_one, */
+};
+
+
+
+static int __init cpqhpc_init(void)


+{
+ int result;
+

+ cpqhp_debug = debug;
+
+ result = pci_module_init(&cpqhpc_driver);
+ dbg("pci_module_init = %d\n", result);


+ if (result)
+ return result;

+ info (DRIVER_DESC " version: " DRIVER_VERSION "\n");

+ return 0;
+}
+

+
+static void __exit cpqhpc_cleanup(void)
+{
+ dbg("cleaning up proc entries\n");
+ cpqhp_proc_destroy_ctrl();
+
+ dbg("unload_cpqphpd()\n");
+ unload_cpqphpd();
+
+ dbg("pci_unregister_driver\n");
+ pci_unregister_driver(&cpqhpc_driver);
+}
+
+
+module_init(cpqhpc_init);
+module_exit(cpqhpc_cleanup);
+
+
diff -u --recursive --new-file v2.4.14/linux/drivers/hotplug/cpqphp_ctrl.c linux/drivers/hotplug/cpqphp_ctrl.c
--- v2.4.14/linux/drivers/hotplug/cpqphp_ctrl.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/hotplug/cpqphp_ctrl.c Fri Nov 9 14:01:22 2001
@@ -0,0 +1,3047 @@
+/*
+ * Compaq Hot Plug Controller Driver
+ *


+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (gr...@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.

+ *


+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.

+ *


+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *

+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *


+ * Send feedback to <gr...@kroah.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>

+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/smp_lock.h>


+#include <linux/pci.h>
+#include "cpqphp.h"
+

+static u32 configure_new_device(struct controller* ctrl, struct pci_func *func,u8 behind_bridge, struct resource_lists *resources);
+static int configure_new_function(struct controller* ctrl, struct pci_func *func,u8 behind_bridge, struct resource_lists *resources);
+static void interrupt_event_handler(struct controller *ctrl);
+
+static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */
+static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */
+static int event_finished;
+static unsigned long pushbutton_pending; /* = 0 */
+
+/* things needed for the long_delay function */
+static struct semaphore delay_sem;
+static wait_queue_head_t delay_wait;
+
+/* delay is in jiffies to wait for */
+static void long_delay (int delay)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ /* only allow 1 customer into the delay queue at once
+ * yes this makes some people wait even longer, but who really cares?
+ * this is for _huge_ delays to make the hardware happy as the
+ * signals bounce around
+ */
+ down (&delay_sem);
+
+ init_waitqueue_head (&delay_wait);
+
+ add_wait_queue(&delay_wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(delay);
+ remove_wait_queue(&delay_wait, &wait);
+ set_current_state(TASK_RUNNING);
+
+ up (&delay_sem);
+}
+
+
+//FIXME: The following line needs to be somewhere else...
+#define WRONG_BUS_FREQUENCY 0x07
+static u8 handle_switch_change(u8 change, struct controller * ctrl)
+{
+ int hp_slot;
+ u8 rc = 0;
+ u16 temp_word;
+ struct pci_func *func;
+ struct event_info *taskInfo;
+
+ if (!change)
+ return 0;
+
+ // Switch Change
+ dbg("cpqsbd: Switch interrupt received.\n");
+
+ for (hp_slot = 0; hp_slot < 6; hp_slot++) {
+ if (change & (0x1L << hp_slot)) {
+ //*********************************
+ // this one changed.
+ //*********************************
+ func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+ //this is the structure that tells the worker thread
+ //what to do
+ taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+ ctrl->next_event = (ctrl->next_event + 1) % 10;
+ taskInfo->hp_slot = hp_slot;
+
+ rc++;
+
+ temp_word = ctrl->ctrl_int_comp >> 16;
+ func->presence_save = (temp_word >> hp_slot) & 0x01;
+ func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;
+
+ if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {
+ //*********************************
+ // Switch opened
+ //*********************************
+
+ func->switch_save = 0;
+
+ taskInfo->event_type = INT_SWITCH_OPEN;
+ } else {
+ //*********************************
+ // Switch closed
+ //*********************************
+
+ func->switch_save = 0x10;
+
+ taskInfo->event_type = INT_SWITCH_CLOSE;
+ }
+ }
+ }
+
+ return rc;
+}
+
+
+/*
+ * find_slot
+ */
+static inline struct slot *find_slot (struct controller * ctrl, u8 device)
+{


+ struct slot *slot;
+

+ if (!ctrl)
+ return NULL;
+
+ slot = ctrl->slot;
+
+ while (slot && (slot->device != device)) {
+ slot = slot->next;
+ }
+


+ return slot;
+}
+

+
+static u8 handle_presence_change(u16 change, struct controller * ctrl)
+{
+ int hp_slot;
+ u8 rc = 0;
+ u8 temp_byte;
+ u16 temp_word;
+ struct pci_func *func;
+ struct event_info *taskInfo;
+ struct slot *p_slot;
+
+ if (!change)
+ return 0;
+
+ //*********************************
+ // Presence Change
+ //*********************************
+ dbg("cpqsbd: Presence/Notify input change.\n");
+ dbg(" Changed bits are 0x%4.4x\n", change );
+
+ for (hp_slot = 0; hp_slot < 6; hp_slot++) {
+ if (change & (0x0101 << hp_slot)) {
+ //*********************************
+ // this one changed.
+ //*********************************
+ func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+ taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+ ctrl->next_event = (ctrl->next_event + 1) % 10;
+ taskInfo->hp_slot = hp_slot;
+
+ rc++;
+
+ p_slot = find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4));
+
+ // If the switch closed, must be a button
+ // If not in button mode, nevermind
+ if (func->switch_save && (ctrl->push_button == 1)) {
+ temp_word = ctrl->ctrl_int_comp >> 16;
+ temp_byte = (temp_word >> hp_slot) & 0x01;
+ temp_byte |= (temp_word >> (hp_slot + 7)) & 0x02;
+
+ if (temp_byte != func->presence_save) {
+ //*********************************
+ // button Pressed (doesn't do anything)
+ //*********************************
+ dbg("hp_slot %d button pressed\n", hp_slot);
+ taskInfo->event_type = INT_BUTTON_PRESS;
+ } else {
+ //*********************************
+ // button Released - TAKE ACTION!!!!
+ //*********************************
+ dbg("hp_slot %d button released\n", hp_slot);
+ taskInfo->event_type = INT_BUTTON_RELEASE;
+
+ // Cancel if we are still blinking
+ if ((p_slot->state == BLINKINGON_STATE)
+ || (p_slot->state == BLINKINGOFF_STATE)) {
+ taskInfo->event_type = INT_BUTTON_CANCEL;
+ dbg("hp_slot %d button cancel\n", hp_slot);
+ } else if ((p_slot->state == POWERON_STATE)
+ || (p_slot->state == POWEROFF_STATE)) {
+ //info(msg_button_ignore, p_slot->number);
+ taskInfo->event_type = INT_BUTTON_IGNORE;
+ dbg("hp_slot %d button ignore\n", hp_slot);
+ }
+ }
+ } else {
+ // Switch is open, assume a presence change
+ // Save the presence state
+ temp_word = ctrl->ctrl_int_comp >> 16;
+ func->presence_save = (temp_word >> hp_slot) & 0x01;
+ func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;
+
+ if ((!(ctrl->ctrl_int_comp & (0x010000 << hp_slot))) ||
+ (!(ctrl->ctrl_int_comp & (0x01000000 << hp_slot)))) {
+ //*********************************
+ // Present
+ //*********************************
+ taskInfo->event_type = INT_PRESENCE_ON;
+ } else {
+ //*********************************
+ // Not Present
+ //*********************************
+ taskInfo->event_type = INT_PRESENCE_OFF;
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+
+static u8 handle_power_fault(u8 change, struct controller * ctrl)
+{
+ int hp_slot;
+ u8 rc = 0;
+ struct pci_func *func;
+ struct event_info *taskInfo;
+
+ if (!change)
+ return 0;
+
+ //*********************************
+ // power fault
+ //*********************************
+
+ info("power fault interrupt\n");
+
+ for (hp_slot = 0; hp_slot < 6; hp_slot++) {
+ if (change & (0x01 << hp_slot)) {
+ //*********************************
+ // this one changed.
+ //*********************************
+ func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+ taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+ ctrl->next_event = (ctrl->next_event + 1) % 10;
+ taskInfo->hp_slot = hp_slot;
+
+ rc++;
+
+ if (ctrl->ctrl_int_comp & (0x00000100 << hp_slot)) {
+ //*********************************
+ // power fault Cleared
+ //*********************************
+ func->status = 0x00;
+
+ taskInfo->event_type = INT_POWER_FAULT_CLEAR;
+ } else {
+ //*********************************
+ // power fault
+ //*********************************
+ taskInfo->event_type = INT_POWER_FAULT;
+
+ if (ctrl->rev < 4) {
+ amber_LED_on (ctrl, hp_slot);
+ green_LED_off (ctrl, hp_slot);
+ set_SOGO (ctrl);
+
+ // this is a fatal condition, we want to crash the
+ // machine to protect from data corruption
+ // simulated_NMI shouldn't ever return
+ //FIXME
+ //simulated_NMI(hp_slot, ctrl);
+
+ //The following code causes a software crash just in
+ //case simulated_NMI did return
+ //FIXME
+ //panic(msg_power_fault);
+ } else {
+ // set power fault status for this board
+ func->status = 0xFF;
+ info("power fault bit %x set\n", hp_slot);
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+
+/*
+ * sort_by_size
+ *
+ * Sorts nodes on the list by their length.
+ * Smallest first.
+ *
+ */
+static int sort_by_size(struct pci_resource **head)
+{
+ struct pci_resource *current_res;
+ struct pci_resource *next_res;
+ int out_of_order = 1;
+
+ if (!(*head))
+ return(1);
+
+ if (!((*head)->next))
+ return(0);
+
+ while (out_of_order) {
+ out_of_order = 0;
+
+ // Special case for swapping list head
+ if (((*head)->next) &&
+ ((*head)->length > (*head)->next->length)) {
+ out_of_order++;
+ current_res = *head;
+ *head = (*head)->next;
+ current_res->next = (*head)->next;
+ (*head)->next = current_res;
+ }
+
+ current_res = *head;
+
+ while (current_res->next && current_res->next->next) {
+ if (current_res->next->length > current_res->next->next->length) {
+ out_of_order++;
+ next_res = current_res->next;
+ current_res->next = current_res->next->next;
+ current_res = current_res->next;
+ next_res->next = current_res->next;
+ current_res->next = next_res;
+ } else
+ current_res = current_res->next;
+ }
+ } // End of out_of_order loop
+
+ return(0);
+}
+
+
+/*
+ * sort_by_max_size
+ *
+ * Sorts nodes on the list by their length.
+ * Largest first.
+ *
+ */
+static int sort_by_max_size(struct pci_resource **head)
+{
+ struct pci_resource *current_res;
+ struct pci_resource *next_res;
+ int out_of_order = 1;
+
+ if (!(*head))
+ return(1);
+
+ if (!((*head)->next))
+ return(0);
+
+ while (out_of_order) {
+ out_of_order = 0;
+
+ // Special case for swapping list head
+ if (((*head)->next) &&
+ ((*head)->length < (*head)->next->length)) {
+ out_of_order++;
+ current_res = *head;
+ *head = (*head)->next;
+ current_res->next = (*head)->next;
+ (*head)->next = current_res;
+ }
+
+ current_res = *head;
+
+ while (current_res->next && current_res->next->next) {
+ if (current_res->next->length < current_res->next->next->length) {
+ out_of_order++;
+ next_res = current_res->next;
+ current_res->next = current_res->next->next;
+ current_res = current_res->next;
+ next_res->next = current_res->next;
+ current_res->next = next_res;
+ } else
+ current_res = current_res->next;
+ }
+ } // End of out_of_order loop
+
+ return(0);
+}
+
+
+/*
+ * do_pre_bridge_resource_split
+ *
+ * Returns zero or one node of resources that aren't in use
+ *
+ */
+static struct pci_resource *do_pre_bridge_resource_split (struct pci_resource **head, struct pci_resource **orig_head, u32 alignment)
+{
+ struct pci_resource *prevnode = NULL;
+ struct pci_resource *node;
+ struct pci_resource *split_node;
+ u32 rc;
+ u32 temp_dword;
+ dbg("do_pre_bridge_resource_split\n");
+
+ if (!(*head) || !(*orig_head))
+ return(NULL);
+
+ rc = cpqhp_resource_sort_and_combine(head);
+
+ if (rc)
+ return(NULL);
+
+ if ((*head)->base != (*orig_head)->base)
+ return(NULL);
+
+ if ((*head)->length == (*orig_head)->length)
+ return(NULL);
+
+
+ // If we got here, there the bridge requires some of the resource, but
+ // we may be able to split some off of the front
+
+ node = *head;
+
+ if (node->length & (alignment -1)) {
+ // this one isn't an aligned length, so we'll make a new entry
+ // and split it up.
+ split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+ if (!split_node)
+ return(NULL);
+
+ temp_dword = (node->length | (alignment-1)) + 1 - alignment;
+
+ split_node->base = node->base;
+ split_node->length = temp_dword;
+
+ node->length -= temp_dword;
+ node->base += split_node->length;
+
+ // Put it in the list
+ *head = split_node;
+ split_node->next = node;
+ }
+
+ if (node->length < alignment) {
+ return(NULL);
+ }
+
+ // Now unlink it
+ if (*head == node) {
+ *head = node->next;
+ node->next = NULL;
+ } else {
+ prevnode = *head;
+ while (prevnode->next != node)
+ prevnode = prevnode->next;
+
+ prevnode->next = node->next;
+ node->next = NULL;
+ }
+
+ return(node);
+}
+
+
+/*
+ * do_bridge_resource_split
+ *
+ * Returns zero or one node of resources that aren't in use
+ *
+ */
+static struct pci_resource *do_bridge_resource_split (struct pci_resource **head, u32 alignment)
+{
+ struct pci_resource *prevnode = NULL;
+ struct pci_resource *node;
+ u32 rc;
+ u32 temp_dword;
+
+ if (!(*head))
+ return(NULL);
+
+ rc = cpqhp_resource_sort_and_combine(head);
+
+ if (rc)
+ return(NULL);
+
+ node = *head;
+
+ while (node->next) {
+ prevnode = node;
+ node = node->next;
+ kfree(prevnode);
+ }
+
+ if (node->length < alignment) {
+ kfree(node);
+ return(NULL);
+ }
+
+ if (node->base & (alignment - 1)) {
+ // Short circuit if adjusted size is too small
+ temp_dword = (node->base | (alignment-1)) + 1;
+ if ((node->length - (temp_dword - node->base)) < alignment) {
+ kfree(node);
+ return(NULL);
+ }
+
+ node->length -= (temp_dword - node->base);
+ node->base = temp_dword;
+ }
+
+ if (node->length & (alignment - 1)) {
+ // There's stuff in use after this node
+ kfree(node);
+ return(NULL);
+ }
+
+ return(node);
+}
+
+
+/*
+ * get_io_resource
+ *
+ * this function sorts the resource list by size and then
+ * returns the first node of "size" length that is not in the
+ * ISA aliasing window. If it finds a node larger than "size"
+ * it will split it up.
+ *
+ * size must be a power of two.
+ */
+static struct pci_resource *get_io_resource (struct pci_resource **head, u32 size)
+{
+ struct pci_resource *prevnode;
+ struct pci_resource *node;
+ struct pci_resource *split_node;
+ u32 temp_dword;
+
+ if (!(*head))
+ return(NULL);
+
+ if ( cpqhp_resource_sort_and_combine(head) )
+ return(NULL);
+
+ if ( sort_by_size(head) )
+ return(NULL);
+
+ for (node = *head; node; node = node->next) {
+ if (node->length < size)
+ continue;
+
+ if (node->base & (size - 1)) {
+ // this one isn't base aligned properly
+ // so we'll make a new entry and split it up
+ temp_dword = (node->base | (size-1)) + 1;
+
+ // Short circuit if adjusted size is too small
+ if ((node->length - (temp_dword - node->base)) < size)
+ continue;
+
+ split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+ if (!split_node)
+ return(NULL);
+
+ split_node->base = node->base;
+ split_node->length = temp_dword - node->base;
+ node->base = temp_dword;
+ node->length -= split_node->length;
+
+ // Put it in the list
+ split_node->next = node->next;
+ node->next = split_node;
+ } // End of non-aligned base
+
+ // Don't need to check if too small since we already did
+ if (node->length > size) {
+ // this one is longer than we need
+ // so we'll make a new entry and split it up
+ split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+ if (!split_node)
+ return(NULL);
+
+ split_node->base = node->base + size;
+ split_node->length = node->length - size;
+ node->length = size;
+
+ // Put it in the list
+ split_node->next = node->next;
+ node->next = split_node;
+ } // End of too big on top end
+
+ // For IO make sure it's not in the ISA aliasing space
+ if (node->base & 0x300L)
+ continue;
+
+ // If we got here, then it is the right size
+ // Now take it out of the list
+ if (*head == node) {
+ *head = node->next;
+ } else {
+ prevnode = *head;
+ while (prevnode->next != node)
+ prevnode = prevnode->next;
+
+ prevnode->next = node->next;
+ }
+ node->next = NULL;
+ // Stop looping
+ break;
+ }
+
+ return(node);
+}
+
+
+/*
+ * get_max_resource
+ *
+ * Gets the largest node that is at least "size" big from the
+ * list pointed to by head. It aligns the node on top and bottom
+ * to "size" alignment before returning it.
+ */
+static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size)
+{
+ struct pci_resource *max;
+ struct pci_resource *temp;
+ struct pci_resource *split_node;
+ u32 temp_dword;
+
+ if (!(*head))
+ return(NULL);
+
+ if (cpqhp_resource_sort_and_combine(head))
+ return(NULL);
+
+ if (sort_by_max_size(head))
+ return(NULL);
+
+ for (max = *head;max; max = max->next) {
+
+ // If not big enough we could probably just bail,
+ // instead we'll continue to the next.
+ if (max->length < size)
+ continue;
+
+ if (max->base & (size - 1)) {
+ // this one isn't base aligned properly
+ // so we'll make a new entry and split it up
+ temp_dword = (max->base | (size-1)) + 1;
+
+ // Short circuit if adjusted size is too small
+ if ((max->length - (temp_dword - max->base)) < size)
+ continue;
+
+ split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+ if (!split_node)
+ return(NULL);
+
+ split_node->base = max->base;
+ split_node->length = temp_dword - max->base;
+ max->base = temp_dword;
+ max->length -= split_node->length;
+
+ // Put it next in the list
+ split_node->next = max->next;
+ max->next = split_node;
+ }
+
+ if ((max->base + max->length) & (size - 1)) {
+ // this one isn't end aligned properly at the top
+ // so we'll make a new entry and split it up
+ split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+ if (!split_node)
+ return(NULL);
+ temp_dword = ((max->base + max->length) & ~(size - 1));
+ split_node->base = temp_dword;
+ split_node->length = max->length + max->base
+ - split_node->base;
+ max->length -= split_node->length;
+
+ // Put it in the list
+ split_node->next = max->next;
+ max->next = split_node;
+ }
+
+ // Make sure it didn't shrink too much when we aligned it
+ if (max->length < size)
+ continue;
+
+ // Now take it out of the list
+ temp = (struct pci_resource*) *head;
+ if (temp == max) {
+ *head = max->next;
+ } else {
+ while (temp && temp->next != max) {
+ temp = temp->next;
+ }
+
+ temp->next = max->next;
+ }
+
+ max->next = NULL;
+ return(max);
+ }
+
+ // If we get here, we couldn't find one
+ return(NULL);
+}
+
+
+/*
+ * get_resource
+ *
+ * this function sorts the resource list by size and then
+ * returns the first node of "size" length. If it finds a node
+ * larger than "size" it will split it up.
+ *
+ * size must be a power of two.
+ */
+static struct pci_resource *get_resource (struct pci_resource **head, u32 size)
+{
+ struct pci_resource *prevnode;
+ struct pci_resource *node;
+ struct pci_resource *split_node;
+ u32 temp_dword;
+
+ if (!(*head))
+ return(NULL);
+
+ if ( cpqhp_resource_sort_and_combine(head) )
+ return(NULL);
+
+ if ( sort_by_size(head) )
+ return(NULL);
+
+ for (node = *head; node; node = node->next) {
+ dbg(__FUNCTION__": req_size =%x node=%p, base=%x, length=%x\n",
+ size, node, node->base, node->length);
+ if (node->length < size)
+ continue;
+
+ if (node->base & (size - 1)) {
+ dbg(__FUNCTION__": not aligned\n");
+ // this one isn't base aligned properly
+ // so we'll make a new entry and split it up
+ temp_dword = (node->base | (size-1)) + 1;
+
+ // Short circuit if adjusted size is too small
+ if ((node->length - (temp_dword - node->base)) < size)
+ continue;
+
+ split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+ if (!split_node)
+ return(NULL);
+
+ split_node->base = node->base;
+ split_node->length = temp_dword - node->base;
+ node->base = temp_dword;
+ node->length -= split_node->length;
+
+ // Put it in the list
+ split_node->next = node->next;
+ node->next = split_node;
+ } // End of non-aligned base
+
+ // Don't need to check if too small since we already did
+ if (node->length > size) {
+ dbg(__FUNCTION__": too big\n");
+ // this one is longer than we need
+ // so we'll make a new entry and split it up
+ split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+ if (!split_node)
+ return(NULL);
+
+ split_node->base = node->base + size;
+ split_node->length = node->length - size;
+ node->length = size;
+
+ // Put it in the list
+ split_node->next = node->next;
+ node->next = split_node;
+ } // End of too big on top end
+
+ dbg(__FUNCTION__": got one!!!\n");
+ // If we got here, then it is the right size
+ // Now take it out of the list
+ if (*head == node) {
+ *head = node->next;
+ } else {
+ prevnode = *head;
+ while (prevnode->next != node)
+ prevnode = prevnode->next;
+
+ prevnode->next = node->next;
+ }
+ node->next = NULL;
+ // Stop looping
+ break;
+ }
+ return(node);
+}
+
+
+/*
+ * cpqhp_resource_sort_and_combine
+ *
+ * Sorts all of the nodes in the list in ascending order by
+ * their base addresses. Also does garbage collection by
+ * combining adjacent nodes.
+ *
+ * returns 0 if success
+ */
+int cpqhp_resource_sort_and_combine(struct pci_resource **head)
+{
+ struct pci_resource *node1;
+ struct pci_resource *node2;
+ int out_of_order = 1;
+
+ dbg(__FUNCTION__": head = %p, *head = %p\n", head, *head);
+
+ if (!(*head))
+ return(1);
+
+ dbg("*head->next = %p\n",(*head)->next);
+
+ if (!(*head)->next)
+ return(0); /* only one item on the list, already sorted! */
+
+ dbg("*head->base = 0x%x\n",(*head)->base);
+ dbg("*head->next->base = 0x%x\n",(*head)->next->base);
+ while (out_of_order) {
+ out_of_order = 0;
+
+ // Special case for swapping list head
+ if (((*head)->next) &&
+ ((*head)->base > (*head)->next->base)) {
+ node1 = *head;
+ (*head) = (*head)->next;
+ node1->next = (*head)->next;
+ (*head)->next = node1;
+ out_of_order++;
+ }
+
+ node1 = (*head);
+
+ while (node1->next && node1->next->next) {
+ if (node1->next->base > node1->next->next->base) {
+ out_of_order++;
+ node2 = node1->next;
+ node1->next = node1->next->next;
+ node1 = node1->next;
+ node2->next = node1->next;
+ node1->next = node2;
+ } else
+ node1 = node1->next;
+ }
+ } // End of out_of_order loop
+
+ node1 = *head;
+
+ while (node1 && node1->next) {
+ if ((node1->base + node1->length) == node1->next->base) {
+ // Combine
+ dbg("8..\n");
+ node1->length += node1->next->length;
+ node2 = node1->next;
+ node1->next = node1->next->next;
+ kfree(node2);
+ } else
+ node1 = node1->next;
+ }
+
+ return(0);
+}
+
+
+void cpqhp_ctrl_intr(int IRQ, struct controller * ctrl, struct pt_regs *regs)
+{
+ u8 schedule_flag = 0;
+ u16 misc;
+ u32 Diff;
+ u32 temp_dword;
+
+
+ misc = readw(ctrl->hpc_reg + MISC);
+ //*********************************
+ // Check to see if it was our interrupt
+ //*********************************
+ if (!(misc & 0x000C)) {
+ return;
+ }
+
+ if (misc & 0x0004) {
+ //*********************************
+ // Serial Output interrupt Pending
+ //*********************************
+
+ // Clear the interrupt
+ misc |= 0x0004;
+ writew(misc, ctrl->hpc_reg + MISC);
+
+ // Read to clear posted writes
+ misc = readw(ctrl->hpc_reg + MISC);
+
+ dbg (__FUNCTION__" - waking up\n");
+ wake_up_interruptible(&ctrl->queue);
+ }
+
+ if (misc & 0x0008) {
+ // General-interrupt-input interrupt Pending
+ Diff = readl(ctrl->hpc_reg + INT_INPUT_CLEAR) ^ ctrl->ctrl_int_comp;
+
+ ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+ // Clear the interrupt
+ writel(Diff, ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+ // Read it back to clear any posted writes
+ temp_dword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+ if (!Diff) {
+ // Clear all interrupts
+ writel(0xFFFFFFFF, ctrl->hpc_reg + INT_INPUT_CLEAR);
+ }
+
+ schedule_flag += handle_switch_change((u8)(Diff & 0xFFL), ctrl);
+ schedule_flag += handle_presence_change((u16)((Diff & 0xFFFF0000L) >> 16), ctrl);
+ schedule_flag += handle_power_fault((u8)((Diff & 0xFF00L) >> 8), ctrl);
+ }
+
+ if (schedule_flag) {
+ up(&event_semaphore);
+ dbg("Signal event_semaphore\n");
+ mark_bh(IMMEDIATE_BH);
+ }
+
+}
+
+
+/**
+ * cpqhp_slot_create - Creates a node and adds it to the proper bus.
+ * @busnumber - bus where new node is to be located
+ *
+ * Returns pointer to the new node or NULL if unsuccessful
+ */
+struct pci_func *cpqhp_slot_create(u8 busnumber)
+{
+ struct pci_func *new_slot;
+ struct pci_func *next;
+
+ new_slot = (struct pci_func *) kmalloc(sizeof(struct pci_func), GFP_KERNEL);
+
+ if (new_slot == NULL) {
+ // I'm not dead yet!
+ // You will be.
+ return(new_slot);
+ }
+
+ memset(new_slot, 0, sizeof(struct pci_func));
+
+ new_slot->next = NULL;
+ new_slot->configured = 1;
+
+ if (cpqhp_slot_list[busnumber] == NULL) {
+ cpqhp_slot_list[busnumber] = new_slot;
+ } else {
+ next = cpqhp_slot_list[busnumber];
+ while (next->next != NULL)
+ next = next->next;
+ next->next = new_slot;
+ }
+ return(new_slot);
+}
+
+
+/*
+ * slot_remove - Removes a node from the linked list of slots.
+ * @old_slot: slot to remove
+ *
+ * Returns 0 if successful, !0 otherwise.
+ */
+static int slot_remove(struct pci_func * old_slot)
+{
+ struct pci_func *next;
+
+ if (old_slot == NULL)
+ return(1);
+
+ next = cpqhp_slot_list[old_slot->bus];
+
+ if (next == NULL) {
+ return(1);
+ }
+
+ if (next == old_slot) {
+ cpqhp_slot_list[old_slot->bus] = old_slot->next;
+ cpqhp_destroy_board_resources(old_slot);
+ kfree(old_slot);
+ return(0);
+ }
+
+ while ((next->next != old_slot) && (next->next != NULL)) {
+ next = next->next;
+ }
+
+ if (next->next == old_slot) {
+ next->next = old_slot->next;
+ cpqhp_destroy_board_resources(old_slot);
+ kfree(old_slot);
+ return(0);
+ } else
+ return(2);
+}
+
+
+/**
+ * bridge_slot_remove - Removes a node from the linked list of slots.
+ * @bridge: bridge to remove
+ *
+ * Returns 0 if successful, !0 otherwise.
+ */
+static int bridge_slot_remove(struct pci_func *bridge)
+{
+ u8 subordinateBus, secondaryBus;
+ u8 tempBus;
+ struct pci_func *next;
+
+ if (bridge == NULL)
+ return(1);
+
+ secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;
+ subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;
+
+ for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
+ next = cpqhp_slot_list[tempBus];
+
+ while (!slot_remove(next)) {
+ next = cpqhp_slot_list[tempBus];
+ }
+ }
+
+ next = cpqhp_slot_list[bridge->bus];
+
+ if (next == NULL) {
+ return(1);
+ }
+
+ if (next == bridge) {
+ cpqhp_slot_list[bridge->bus] = bridge->next;
+ kfree(bridge);
+ return(0);
+ }
+
+ while ((next->next != bridge) && (next->next != NULL)) {
+ next = next->next;
+ }
+
+ if (next->next == bridge) {
+ next->next = bridge->next;
+ kfree(bridge);
+ return(0);
+ } else
+ return(2);
+}
+
+
+/**
+ * cpqhp_slot_find - Looks for a node by bus, and device, multiple functions accessed
+ * @bus: bus to find
+ * @device: device to find
+ * @index: is 0 for first function found, 1 for the second...
+ *
+ * Returns pointer to the node if successful, %NULL otherwise.
+ */
+struct pci_func *cpqhp_slot_find(u8 bus, u8 device, u8 index)
+{
+ int found = -1;
+ struct pci_func *func;
+
+ func = cpqhp_slot_list[bus];
+
+ if ((func == NULL) || ((func->device == device) && (index == 0)))
+ return(func);
+
+ if (func->device == device)
+ found++;
+
+ while (func->next != NULL) {
+ func = func->next;
+
+ if (func->device == device)
+ found++;
+
+ if (found == index)
+ return(func);
+ }
+
+ return(NULL);
+}
+
+
+// DJZ: I don't think is_bridge will work as is.
+//FIXME
+static int is_bridge(struct pci_func * func)
+{
+ // Check the header type
+ if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
+ return 1;
+ else


+ return 0;
+}
+

+
+/* the following routines constitute the bulk of the
+ hotplug controller logic
+ */
+
+
+/**
+ * board_replaced - Called after a board has been replaced in the system.
+ *
+ * This is only used if we don't have resources for hot add
+ * Turns power on for the board
+ * Checks to see if board is the same
+ * If board is same, reconfigures it
+ * If board isn't same, turns it back off.
+ *
+ */
+static u32 board_replaced(struct pci_func * func, struct controller * ctrl)
+{
+ u8 hp_slot;
+ u8 temp_byte;
+ u32 index;
+ u32 rc = 0;
+ u32 src = 8;
+
+ hp_slot = func->device - ctrl->slot_device_offset;
+
+ if (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot)) {
+ //*********************************
+ // The switch is open.
+ //*********************************
+ rc = INTERLOCK_OPEN;
+ } else if (is_slot_enabled (ctrl, hp_slot)) {
+ //*********************************
+ // The board is already on
+ //*********************************
+ rc = CARD_FUNCTIONING;
+ } else {
+ if (ctrl->speed == 1) {
+ // Wait for exclusive access to hardware
+ down(&ctrl->crit_sect);
+
+ // turn on board without attaching to the bus
+ enable_slot_power (ctrl, hp_slot);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ // Change bits in slot power register to force another shift out
+ // NOTE: this is to work around the timer bug
+ temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
+ writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
+ writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) {
+ rc = WRONG_BUS_FREQUENCY;
+ }
+ // turn off board without attaching to the bus
+ disable_slot_power (ctrl, hp_slot);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);
+
+ if (rc)
+ return(rc);
+ }
+
+ // Wait for exclusive access to hardware
+ down(&ctrl->crit_sect);
+
+ slot_enable (ctrl, hp_slot);
+ green_LED_blink (ctrl, hp_slot);
+
+ amber_LED_off (ctrl, hp_slot);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);
+
+ // Wait for ~1 second because of hot plug spec
+ long_delay(1*HZ);
+
+ // Check for a power fault
+ if (func->status == 0xFF) {
+ // power fault occurred, but it was benign
+ rc = POWER_FAILURE;
+ func->status = 0;
+ } else
+ rc = cpqhp_valid_replace(ctrl, func);
+
+ if (!rc) {
+ // It must be the same board
+
+ rc = cpqhp_configure_board(ctrl, func);
+
+ if (rc || src) {
+ // If configuration fails, turn it off
+ // Get slot won't work for devices behind bridges, but
+ // in this case it will always be called for the "base"
+ // bus/dev/func of an adapter.
+
+ // Wait for exclusive access to hardware
+ down(&ctrl->crit_sect);
+
+ amber_LED_on (ctrl, hp_slot);
+ green_LED_off (ctrl, hp_slot);
+ slot_disable (ctrl, hp_slot);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);
+
+ if (rc)
+ return(rc);
+ else
+ return(1);
+ }
+
+ func->status = 0;
+ func->switch_save = 0x10;
+
+ index = 1;
+ while (((func = cpqhp_slot_find(func->bus, func->device, index)) != NULL) && !rc) {
+ rc |= cpqhp_configure_board(ctrl, func);
+ index++;
+ }
+
+ if (rc) {
+ // If configuration fails, turn it off
+ // Get slot won't work for devices behind bridges, but
+ // in this case it will always be called for the "base"
+ // bus/dev/func of an adapter.
+
+ // Wait for exclusive access to hardware
+ down(&ctrl->crit_sect);
+
+ amber_LED_on (ctrl, hp_slot);
+ green_LED_off (ctrl, hp_slot);
+ slot_disable (ctrl, hp_slot);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);
+
+ return(rc);
+ }
+ // Done configuring so turn LED on full time
+
+ // Wait for exclusive access to hardware
+ down(&ctrl->crit_sect);
+
+ green_LED_on (ctrl, hp_slot);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);
+ rc = 0;
+ } else {
+ // Something is wrong
+
+ // Get slot won't work for devices behind bridges, but
+ // in this case it will always be called for the "base"
+ // bus/dev/func of an adapter.
+
+ // Wait for exclusive access to hardware
+ down(&ctrl->crit_sect);
+
+ amber_LED_on (ctrl, hp_slot);
+ green_LED_off (ctrl, hp_slot);
+ slot_disable (ctrl, hp_slot);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);
+ }
+
+ }
+ return(rc);
+
+}
+
+
+/**
+ * board_added - Called after a board has been added to the system.
+ *
+ * Turns power on for the board
+ * Configures board
+ *
+ */
+static u32 board_added(struct pci_func * func, struct controller * ctrl)
+{
+ u8 hp_slot;
+ u8 temp_byte;
+ int index;
+ u32 temp_register = 0xFFFFFFFF;
+ u32 rc = 0;
+ struct pci_func *new_slot = NULL;
+ struct slot *p_slot;
+ struct resource_lists res_lists;
+
+ hp_slot = func->device - ctrl->slot_device_offset;
+ dbg(__FUNCTION__": func->device, slot_offset, hp_slot = %d, %d ,%d\n",


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

echo 'End of part 042'
echo 'File patch-2.4.15 is continued in part 043'
echo "043" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:15 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part039

#!/bin/sh -x
# this is part 039 of a 115 - part archive


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

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

+/* 065 */ 0x9c849e63, /* cps = 144.50, nrm = 8, interval = 2444.00 */
+/* 066 */ 0x9cb29e4b, /* cps = 150.25, nrm = 8, interval = 2348.00 */
+/* 067 */ 0x9ce69e33, /* cps = 156.75, nrm = 8, interval = 2252.00 */
+/* 068 */ 0x9d1cde1c, /* cps = 163.50, nrm = 16, interval = 2160.00 */
+/* 069 */ 0x9d50de07, /* cps = 170.00, nrm = 16, interval = 2076.00 */
+/* 070 */ 0x9d8adbe4, /* cps = 177.25, nrm = 16, interval = 1992.00 */
+/* 071 */ 0x9dc4dbbc, /* cps = 184.50, nrm = 16, interval = 1912.00 */
+/* 072 */ 0x9e02db96, /* cps = 192.25, nrm = 16, interval = 1836.00 */
+/* 073 */ 0x9e42db71, /* cps = 200.25, nrm = 16, interval = 1762.00 */
+/* 074 */ 0x9e86db4d, /* cps = 208.75, nrm = 16, interval = 1690.00 */
+/* 075 */ 0x9ecedb2b, /* cps = 217.75, nrm = 16, interval = 1622.00 */
+/* 076 */ 0x9f16db0a, /* cps = 226.75, nrm = 16, interval = 1556.00 */
+/* 077 */ 0x9f62daeb, /* cps = 236.25, nrm = 16, interval = 1494.00 */
+/* 078 */ 0x9fb2dacd, /* cps = 246.25, nrm = 16, interval = 1434.00 */
+/* 079 */ 0xa002dab0, /* cps = 256.50, nrm = 16, interval = 1376.00 */
+/* 080 */ 0xa02eda94, /* cps = 267.50, nrm = 16, interval = 1320.00 */
+/* 081 */ 0xa05ada7a, /* cps = 278.50, nrm = 16, interval = 1268.00 */
+/* 082 */ 0xa088da60, /* cps = 290.00, nrm = 16, interval = 1216.00 */
+/* 083 */ 0xa0b8da48, /* cps = 302.00, nrm = 16, interval = 1168.00 */
+/* 084 */ 0xa0ecda30, /* cps = 315.00, nrm = 16, interval = 1120.00 */
+/* 085 */ 0xa1211a1a, /* cps = 328.00, nrm = 32, interval = 1076.00 */
+/* 086 */ 0xa1591a04, /* cps = 342.00, nrm = 32, interval = 1032.00 */
+/* 087 */ 0xa19117df, /* cps = 356.00, nrm = 32, interval = 991.00 */
+/* 088 */ 0xa1cd17b7, /* cps = 371.00, nrm = 32, interval = 951.00 */
+/* 089 */ 0xa20b1791, /* cps = 386.50, nrm = 32, interval = 913.00 */
+/* 090 */ 0xa24d176c, /* cps = 403.00, nrm = 32, interval = 876.00 */
+/* 091 */ 0xa28f1749, /* cps = 419.50, nrm = 32, interval = 841.00 */
+/* 092 */ 0xa2d71727, /* cps = 437.50, nrm = 32, interval = 807.00 */
+/* 093 */ 0xa31f1707, /* cps = 455.50, nrm = 32, interval = 775.00 */
+/* 094 */ 0xa36d16e7, /* cps = 475.00, nrm = 32, interval = 743.00 */
+/* 095 */ 0xa3bd16c9, /* cps = 495.00, nrm = 32, interval = 713.00 */
+/* 096 */ 0xa40716ad, /* cps = 515.00, nrm = 32, interval = 685.00 */
+/* 097 */ 0xa4331691, /* cps = 537.00, nrm = 32, interval = 657.00 */
+/* 098 */ 0xa45f1677, /* cps = 559.00, nrm = 32, interval = 631.00 */
+/* 099 */ 0xa48f165d, /* cps = 583.00, nrm = 32, interval = 605.00 */
+/* 100 */ 0xa4bf1645, /* cps = 607.00, nrm = 32, interval = 581.00 */
+/* 101 */ 0xa4f1162e, /* cps = 632.00, nrm = 32, interval = 558.00 */
+/* 102 */ 0xa5291617, /* cps = 660.00, nrm = 32, interval = 535.00 */
+/* 103 */ 0xa55f1602, /* cps = 687.00, nrm = 32, interval = 514.00 */
+/* 104 */ 0xa59913da, /* cps = 716.00, nrm = 32, interval = 493.00 */
+/* 105 */ 0xa5d513b2, /* cps = 746.00, nrm = 32, interval = 473.00 */
+/* 106 */ 0xa613138c, /* cps = 777.00, nrm = 32, interval = 454.00 */
+/* 107 */ 0xa6551368, /* cps = 810.00, nrm = 32, interval = 436.00 */
+/* 108 */ 0xa6971345, /* cps = 843.00, nrm = 32, interval = 418.50 */
+/* 109 */ 0xa6df1323, /* cps = 879.00, nrm = 32, interval = 401.50 */
+/* 110 */ 0xa7291303, /* cps = 916.00, nrm = 32, interval = 385.50 */
+/* 111 */ 0xa77512e4, /* cps = 954.00, nrm = 32, interval = 370.00 */
+/* 112 */ 0xa7c512c6, /* cps = 994.00, nrm = 32, interval = 355.00 */
+/* 113 */ 0xa80d12a9, /* cps = 1036.00, nrm = 32, interval = 340.50 */
+/* 114 */ 0xa839128e, /* cps = 1080.00, nrm = 32, interval = 327.00 */
+/* 115 */ 0xa8651274, /* cps = 1124.00, nrm = 32, interval = 314.00 */
+/* 116 */ 0xa895125a, /* cps = 1172.00, nrm = 32, interval = 301.00 */
+/* 117 */ 0xa8c71242, /* cps = 1222.00, nrm = 32, interval = 289.00 */
+/* 118 */ 0xa8f9122b, /* cps = 1272.00, nrm = 32, interval = 277.50 */
+/* 119 */ 0xa92f1214, /* cps = 1326.00, nrm = 32, interval = 266.00 */
+/* 120 */ 0xa9670ffe, /* cps = 1382.00, nrm = 32, interval = 255.50 */
+/* 121 */ 0xa9a10fd5, /* cps = 1440.00, nrm = 32, interval = 245.25 */
+/* 122 */ 0xa9db0fae, /* cps = 1498.00, nrm = 32, interval = 235.50 */
+/* 123 */ 0xaa1b0f88, /* cps = 1562.00, nrm = 32, interval = 226.00 */
+/* 124 */ 0xaa5d0f63, /* cps = 1628.00, nrm = 32, interval = 216.75 */
+/* 125 */ 0xaaa10f41, /* cps = 1696.00, nrm = 32, interval = 208.25 */
+/* 126 */ 0xaae90f1f, /* cps = 1768.00, nrm = 32, interval = 199.75 */
+/* 127 */ 0xab330eff, /* cps = 1842.00, nrm = 32, interval = 191.75 */
+/* 128 */ 0xab7f0ee0, /* cps = 1918.00, nrm = 32, interval = 184.00 */
+/* 129 */ 0xabd10ec2, /* cps = 2000.00, nrm = 32, interval = 176.50 */
+/* 130 */ 0xac110ea6, /* cps = 2080.00, nrm = 32, interval = 169.50 */
+/* 131 */ 0xac3d0e8b, /* cps = 2168.00, nrm = 32, interval = 162.75 */
+/* 132 */ 0xac6d0e70, /* cps = 2264.00, nrm = 32, interval = 156.00 */
+/* 133 */ 0xac9b0e57, /* cps = 2356.00, nrm = 32, interval = 149.75 */
+/* 134 */ 0xaccd0e3f, /* cps = 2456.00, nrm = 32, interval = 143.75 */
+/* 135 */ 0xacff0e28, /* cps = 2556.00, nrm = 32, interval = 138.00 */
+/* 136 */ 0xad350e12, /* cps = 2664.00, nrm = 32, interval = 132.50 */
+/* 137 */ 0xad6d0bf9, /* cps = 2776.00, nrm = 32, interval = 127.12 */
+/* 138 */ 0xada70bd0, /* cps = 2892.00, nrm = 32, interval = 122.00 */
+/* 139 */ 0xade30ba9, /* cps = 3012.00, nrm = 32, interval = 117.12 */
+/* 140 */ 0xae230b83, /* cps = 3140.00, nrm = 32, interval = 112.38 */
+/* 141 */ 0xae650b5f, /* cps = 3272.00, nrm = 32, interval = 107.88 */
+/* 142 */ 0xaeab0b3c, /* cps = 3412.00, nrm = 32, interval = 103.50 */
+/* 143 */ 0xaef10b1b, /* cps = 3552.00, nrm = 32, interval = 99.38 */
+/* 144 */ 0xaf3b0afb, /* cps = 3700.00, nrm = 32, interval = 95.38 */
+/* 145 */ 0xaf8b0adc, /* cps = 3860.00, nrm = 32, interval = 91.50 */
+/* 146 */ 0xafd90abf, /* cps = 4016.00, nrm = 32, interval = 87.88 */
+/* 147 */ 0xb0170aa3, /* cps = 4184.00, nrm = 32, interval = 84.38 */
+/* 148 */ 0xb0430a87, /* cps = 4360.00, nrm = 32, interval = 80.88 */
+/* 149 */ 0xb0710a6d, /* cps = 4544.00, nrm = 32, interval = 77.62 */
+/* 150 */ 0xb0a10a54, /* cps = 4736.00, nrm = 32, interval = 74.50 */
+/* 151 */ 0xb0d30a3c, /* cps = 4936.00, nrm = 32, interval = 71.50 */
+/* 152 */ 0xb1070a25, /* cps = 5144.00, nrm = 32, interval = 68.62 */
+/* 153 */ 0xb13d0a0f, /* cps = 5360.00, nrm = 32, interval = 65.88 */
+/* 154 */ 0xb17507f4, /* cps = 5584.00, nrm = 32, interval = 63.25 */
+/* 155 */ 0xb1af07cb, /* cps = 5816.00, nrm = 32, interval = 60.69 */
+/* 156 */ 0xb1eb07a4, /* cps = 6056.00, nrm = 32, interval = 58.25 */
+/* 157 */ 0xb22b077f, /* cps = 6312.00, nrm = 32, interval = 55.94 */
+/* 158 */ 0xb26d075b, /* cps = 6576.00, nrm = 32, interval = 53.69 */
+/* 159 */ 0xb2b30738, /* cps = 6856.00, nrm = 32, interval = 51.50 */
+/* 160 */ 0xb2fb0717, /* cps = 7144.00, nrm = 32, interval = 49.44 */
+/* 161 */ 0xb34506f7, /* cps = 7440.00, nrm = 32, interval = 47.44 */
+/* 162 */ 0xb39306d9, /* cps = 7752.00, nrm = 32, interval = 45.56 */
+/* 163 */ 0xb3e506bb, /* cps = 8080.00, nrm = 32, interval = 43.69 */
+/* 164 */ 0xb41d069f, /* cps = 8416.00, nrm = 32, interval = 41.94 */
+/* 165 */ 0xb4490684, /* cps = 8768.00, nrm = 32, interval = 40.25 */
+/* 166 */ 0xb477066a, /* cps = 9136.00, nrm = 32, interval = 38.62 */
+/* 167 */ 0xb4a70651, /* cps = 9520.00, nrm = 32, interval = 37.06 */
+/* 168 */ 0xb4d90639, /* cps = 9920.00, nrm = 32, interval = 35.56 */
+/* 169 */ 0xb50d0622, /* cps = 10336.00, nrm = 32, interval = 34.12 */
+/* 170 */ 0xb545060c, /* cps = 10784.00, nrm = 32, interval = 32.75 */
+/* 171 */ 0xb57b03ef, /* cps = 11216.00, nrm = 32, interval = 31.47 */
+/* 172 */ 0xb5b503c7, /* cps = 11680.00, nrm = 32, interval = 30.22 */
+/* 173 */ 0xb5f303a0, /* cps = 12176.00, nrm = 32, interval = 29.00 */
+/* 174 */ 0xb633037a, /* cps = 12688.00, nrm = 32, interval = 27.81 */
+/* 175 */ 0xb6750357, /* cps = 13216.00, nrm = 32, interval = 26.72 */
+/* 176 */ 0xb6bb0334, /* cps = 13776.00, nrm = 32, interval = 25.62 */
+/* 177 */ 0xb7030313, /* cps = 14352.00, nrm = 32, interval = 24.59 */
+/* 178 */ 0xb74f02f3, /* cps = 14960.00, nrm = 32, interval = 23.59 */
+/* 179 */ 0xb79d02d5, /* cps = 15584.00, nrm = 32, interval = 22.66 */
+/* 180 */ 0xb7ed02b8, /* cps = 16224.00, nrm = 32, interval = 21.75 */
+/* 181 */ 0xb821029c, /* cps = 16896.00, nrm = 32, interval = 20.88 */
+/* 182 */ 0xb84f0281, /* cps = 17632.00, nrm = 32, interval = 20.03 */
+/* 183 */ 0xb87d0267, /* cps = 18368.00, nrm = 32, interval = 19.22 */
+/* 184 */ 0xb8ad024e, /* cps = 19136.00, nrm = 32, interval = 18.44 */
+/* 185 */ 0xb8dd0237, /* cps = 19904.00, nrm = 32, interval = 17.72 */
+/* 186 */ 0xb9130220, /* cps = 20768.00, nrm = 32, interval = 17.00 */
+/* 187 */ 0xb949020a, /* cps = 21632.00, nrm = 32, interval = 16.31 */
+/* 188 */ 0xb98301f5, /* cps = 22560.00, nrm = 32, interval = 15.66 */
+/* 189 */ 0xb9bd01e1, /* cps = 23488.00, nrm = 32, interval = 15.03 */
+/* 190 */ 0xb9fd01cd, /* cps = 24512.00, nrm = 32, interval = 14.41 */
+/* 191 */ 0xba3b01bb, /* cps = 25504.00, nrm = 32, interval = 13.84 */
+/* 192 */ 0xba7f01a9, /* cps = 26592.00, nrm = 32, interval = 13.28 */
+/* 193 */ 0xbac30198, /* cps = 27680.00, nrm = 32, interval = 12.75 */
+/* 194 */ 0xbb0f0187, /* cps = 28896.00, nrm = 32, interval = 12.22 */
+/* 195 */ 0xbb570178, /* cps = 30048.00, nrm = 32, interval = 11.75 */
+/* 196 */ 0xbbab0168, /* cps = 31392.00, nrm = 32, interval = 11.25 */
+/* 197 */ 0xbbf9015a, /* cps = 32640.00, nrm = 32, interval = 10.81 */
+/* 198 */ 0xbc27014c, /* cps = 33984.00, nrm = 32, interval = 10.38 */
+/* 199 */ 0xbc53013f, /* cps = 35392.00, nrm = 32, interval = 9.97 */
+/* 200 */ 0xbc830132, /* cps = 36928.00, nrm = 32, interval = 9.56 */
+/* 201 */ 0xbcb50125, /* cps = 38528.00, nrm = 32, interval = 9.16 */
+/* 202 */ 0xbce5011a, /* cps = 40064.00, nrm = 32, interval = 8.81 */
+/* 203 */ 0xbd1d010e, /* cps = 41856.00, nrm = 32, interval = 8.44 */
+/* 204 */ 0xbd530103, /* cps = 43584.00, nrm = 32, interval = 8.09 */
+/* 205 */ 0xbd8b00f9, /* cps = 45376.00, nrm = 32, interval = 7.78 */
+/* 206 */ 0xbdc500ef, /* cps = 47232.00, nrm = 32, interval = 7.47 */
+/* 207 */ 0xbe0700e5, /* cps = 49344.00, nrm = 32, interval = 7.16 */
+/* 208 */ 0xbe4500dc, /* cps = 51328.00, nrm = 32, interval = 6.88 */
+/* 209 */ 0xbe8900d3, /* cps = 53504.00, nrm = 32, interval = 6.59 */
+/* 210 */ 0xbecb00cb, /* cps = 55616.00, nrm = 32, interval = 6.34 */
+/* 211 */ 0xbf1d00c2, /* cps = 58240.00, nrm = 32, interval = 6.06 */
+/* 212 */ 0xbf6100bb, /* cps = 60416.00, nrm = 32, interval = 5.84 */
+/* 213 */ 0xbfb500b3, /* cps = 63104.00, nrm = 32, interval = 5.59 */
+/* 214 */ 0xc00300ac, /* cps = 65664.00, nrm = 32, interval = 5.38 */
+/* 215 */ 0xc02f00a5, /* cps = 68480.00, nrm = 32, interval = 5.16 */
+/* 216 */ 0xc05d009e, /* cps = 71424.00, nrm = 32, interval = 4.94 */
+/* 217 */ 0xc0890098, /* cps = 74240.00, nrm = 32, interval = 4.75 */
+/* 218 */ 0xc0b90092, /* cps = 77312.00, nrm = 32, interval = 4.56 */
+/* 219 */ 0xc0ed008c, /* cps = 80640.00, nrm = 32, interval = 4.38 */
+/* 220 */ 0xc1250086, /* cps = 84224.00, nrm = 32, interval = 4.19 */
+/* 221 */ 0xc1590081, /* cps = 87552.00, nrm = 32, interval = 4.03 */
+/* 222 */ 0xc191007c, /* cps = 91136.00, nrm = 32, interval = 3.88 */
+/* 223 */ 0xc1cd0077, /* cps = 94976.00, nrm = 32, interval = 3.72 */
+/* 224 */ 0xc20d0072, /* cps = 99072.00, nrm = 32, interval = 3.56 */
+/* 225 */ 0xc255006d, /* cps = 103680.00, nrm = 32, interval = 3.41 */
+/* 226 */ 0xc2910069, /* cps = 107520.00, nrm = 32, interval = 3.28 */
+/* 227 */ 0xc2d50065, /* cps = 111872.00, nrm = 32, interval = 3.16 */
+/* 228 */ 0xc32f0060, /* cps = 117632.00, nrm = 32, interval = 3.00 */
+/* 229 */ 0xc36b005d, /* cps = 121472.00, nrm = 32, interval = 2.91 */
+/* 230 */ 0xc3c10059, /* cps = 126976.00, nrm = 32, interval = 2.78 */
+/* 231 */ 0xc40f0055, /* cps = 132864.00, nrm = 32, interval = 2.66 */
+/* 232 */ 0xc4350052, /* cps = 137728.00, nrm = 32, interval = 2.56 */
+/* 233 */ 0xc46d004e, /* cps = 144896.00, nrm = 32, interval = 2.44 */
+/* 234 */ 0xc499004b, /* cps = 150528.00, nrm = 32, interval = 2.34 */
+/* 235 */ 0xc4cb0048, /* cps = 156928.00, nrm = 32, interval = 2.25 */
+/* 236 */ 0xc4ff0045, /* cps = 163584.00, nrm = 32, interval = 2.16 */
+/* 237 */ 0xc5250043, /* cps = 168448.00, nrm = 32, interval = 2.09 */
+/* 238 */ 0xc5630040, /* cps = 176384.00, nrm = 32, interval = 2.00 */
+/* 239 */ 0xc5a7003d, /* cps = 185088.00, nrm = 32, interval = 1.91 */
+/* 240 */ 0xc5d9003b, /* cps = 191488.00, nrm = 32, interval = 1.84 */
+/* 241 */ 0xc6290038, /* cps = 201728.00, nrm = 32, interval = 1.75 */
+/* 242 */ 0xc6630036, /* cps = 209152.00, nrm = 32, interval = 1.69 */
+/* 243 */ 0xc6a30034, /* cps = 217344.00, nrm = 32, interval = 1.62 */
+/* 244 */ 0xc6e70032, /* cps = 226048.00, nrm = 32, interval = 1.56 */
+/* 245 */ 0xc72f0030, /* cps = 235264.00, nrm = 32, interval = 1.50 */
+/* 246 */ 0xc77f002e, /* cps = 245504.00, nrm = 32, interval = 1.44 */
+/* 247 */ 0xc7d7002c, /* cps = 256768.00, nrm = 32, interval = 1.38 */
+/* 248 */ 0xc81b002a, /* cps = 268800.00, nrm = 32, interval = 1.31 */
+/* 249 */ 0xc84f0028, /* cps = 282112.00, nrm = 32, interval = 1.25 */
+/* 250 */ 0xc86d0027, /* cps = 289792.00, nrm = 32, interval = 1.22 */
+/* 251 */ 0xc8a90025, /* cps = 305152.00, nrm = 32, interval = 1.16 */
+/* 252 */ 0xc8cb0024, /* cps = 313856.00, nrm = 32, interval = 1.12 */
+/* 253 */ 0xc9130022, /* cps = 332288.00, nrm = 32, interval = 1.06 */
+/* 254 */ 0xc9390021, /* cps = 342016.00, nrm = 32, interval = 1.03 */
+/* 255 */ 0xc9630020, /* cps = 352768.00, nrm = 32, interval = 1.00 */
+};
+
+static unsigned char rate_to_log[] =
+{
+/* 1.00 => 0 */ 0x00, /* => 10.02 */
+/* 1.06 => 0 */ 0x00, /* => 10.02 */
+/* 1.12 => 0 */ 0x00, /* => 10.02 */
+/* 1.19 => 0 */ 0x00, /* => 10.02 */
+/* 1.25 => 0 */ 0x00, /* => 10.02 */
+/* 1.31 => 0 */ 0x00, /* => 10.02 */
+/* 1.38 => 0 */ 0x00, /* => 10.02 */
+/* 1.44 => 0 */ 0x00, /* => 10.02 */
+/* 1.50 => 0 */ 0x00, /* => 10.02 */
+/* 1.56 => 0 */ 0x00, /* => 10.02 */
+/* 1.62 => 0 */ 0x00, /* => 10.02 */
+/* 1.69 => 0 */ 0x00, /* => 10.02 */
+/* 1.75 => 0 */ 0x00, /* => 10.02 */
+/* 1.81 => 0 */ 0x00, /* => 10.02 */
+/* 1.88 => 0 */ 0x00, /* => 10.02 */
+/* 1.94 => 0 */ 0x00, /* => 10.02 */
+/* 2.00 => 0 */ 0x00, /* => 10.02 */
+/* 2.12 => 0 */ 0x00, /* => 10.02 */
+/* 2.25 => 0 */ 0x00, /* => 10.02 */
+/* 2.38 => 0 */ 0x00, /* => 10.02 */
+/* 2.50 => 0 */ 0x00, /* => 10.02 */
+/* 2.62 => 0 */ 0x00, /* => 10.02 */
+/* 2.75 => 0 */ 0x00, /* => 10.02 */
+/* 2.88 => 0 */ 0x00, /* => 10.02 */
+/* 3.00 => 0 */ 0x00, /* => 10.02 */
+/* 3.12 => 0 */ 0x00, /* => 10.02 */
+/* 3.25 => 0 */ 0x00, /* => 10.02 */
+/* 3.38 => 0 */ 0x00, /* => 10.02 */
+/* 3.50 => 0 */ 0x00, /* => 10.02 */
+/* 3.62 => 0 */ 0x00, /* => 10.02 */
+/* 3.75 => 0 */ 0x00, /* => 10.02 */
+/* 3.88 => 0 */ 0x00, /* => 10.02 */
+/* 4.00 => 0 */ 0x00, /* => 10.02 */
+/* 4.25 => 0 */ 0x00, /* => 10.02 */
+/* 4.50 => 0 */ 0x00, /* => 10.02 */
+/* 4.75 => 0 */ 0x00, /* => 10.02 */
+/* 5.00 => 0 */ 0x00, /* => 10.02 */
+/* 5.25 => 0 */ 0x00, /* => 10.02 */
+/* 5.50 => 0 */ 0x00, /* => 10.02 */
+/* 5.75 => 0 */ 0x00, /* => 10.02 */
+/* 6.00 => 0 */ 0x00, /* => 10.02 */
+/* 6.25 => 0 */ 0x00, /* => 10.02 */
+/* 6.50 => 0 */ 0x00, /* => 10.02 */
+/* 6.75 => 0 */ 0x00, /* => 10.02 */
+/* 7.00 => 0 */ 0x00, /* => 10.02 */
+/* 7.25 => 0 */ 0x00, /* => 10.02 */
+/* 7.50 => 0 */ 0x00, /* => 10.02 */
+/* 7.75 => 0 */ 0x00, /* => 10.02 */
+/* 8.00 => 0 */ 0x00, /* => 10.02 */
+/* 8.50 => 0 */ 0x00, /* => 10.02 */
+/* 9.00 => 0 */ 0x00, /* => 10.02 */
+/* 9.50 => 0 */ 0x00, /* => 10.02 */
+/* 10.00 => 0 */ 0x00, /* => 10.02 */
+/* 10.50 => 1 */ 0x01, /* => 10.42 */
+/* 11.00 => 2 */ 0x02, /* => 10.86 */
+/* 11.50 => 3 */ 0x03, /* => 11.31 */
+/* 12.00 => 4 */ 0x04, /* => 11.78 */
+/* 12.50 => 5 */ 0x05, /* => 12.28 */
+/* 13.00 => 6 */ 0x06, /* => 12.80 */
+/* 13.50 => 7 */ 0x07, /* => 13.33 */
+/* 14.00 => 8 */ 0x08, /* => 13.89 */
+/* 14.50 => 9 */ 0x09, /* => 14.48 */
+/* 15.00 => 9 */ 0x09, /* => 14.48 */
+/* 15.50 => 10 */ 0x0a, /* => 15.08 */
+/* 16.00 => 11 */ 0x0b, /* => 15.72 */
+/* 17.00 => 12 */ 0x0c, /* => 16.38 */
+/* 18.00 => 14 */ 0x0e, /* => 17.75 */
+/* 19.00 => 15 */ 0x0f, /* => 18.50 */
+/* 20.00 => 16 */ 0x10, /* => 19.28 */
+/* 21.00 => 18 */ 0x12, /* => 20.94 */
+/* 22.00 => 19 */ 0x13, /* => 21.81 */
+/* 23.00 => 20 */ 0x14, /* => 22.75 */
+/* 24.00 => 21 */ 0x15, /* => 23.69 */
+/* 25.00 => 22 */ 0x16, /* => 24.69 */
+/* 26.00 => 23 */ 0x17, /* => 25.72 */
+/* 27.00 => 24 */ 0x18, /* => 26.81 */
+/* 28.00 => 25 */ 0x19, /* => 27.94 */
+/* 29.00 => 25 */ 0x19, /* => 27.94 */
+/* 30.00 => 26 */ 0x1a, /* => 29.09 */
+/* 31.00 => 27 */ 0x1b, /* => 30.31 */
+/* 32.00 => 28 */ 0x1c, /* => 31.56 */
+/* 34.00 => 29 */ 0x1d, /* => 32.94 */
+/* 36.00 => 31 */ 0x1f, /* => 35.69 */
+/* 38.00 => 32 */ 0x20, /* => 37.19 */
+/* 40.00 => 33 */ 0x21, /* => 38.75 */
+/* 42.00 => 34 */ 0x22, /* => 40.38 */
+/* 44.00 => 36 */ 0x24, /* => 43.88 */
+/* 46.00 => 37 */ 0x25, /* => 45.69 */
+/* 48.00 => 38 */ 0x26, /* => 47.62 */
+/* 50.00 => 39 */ 0x27, /* => 49.62 */
+/* 52.00 => 40 */ 0x28, /* => 51.69 */
+/* 54.00 => 41 */ 0x29, /* => 53.88 */
+/* 56.00 => 41 */ 0x29, /* => 53.88 */
+/* 58.00 => 42 */ 0x2a, /* => 56.12 */
+/* 60.00 => 43 */ 0x2b, /* => 58.44 */
+/* 62.00 => 44 */ 0x2c, /* => 60.94 */
+/* 64.00 => 45 */ 0x2d, /* => 63.50 */
+/* 68.00 => 46 */ 0x2e, /* => 66.12 */
+/* 72.00 => 48 */ 0x30, /* => 71.88 */
+/* 76.00 => 49 */ 0x31, /* => 74.75 */
+/* 80.00 => 50 */ 0x32, /* => 78.00 */
+/* 84.00 => 51 */ 0x33, /* => 81.25 */
+/* 88.00 => 52 */ 0x34, /* => 84.62 */
+/* 92.00 => 54 */ 0x36, /* => 91.88 */
+/* 96.00 => 55 */ 0x37, /* => 95.75 */
+/* 100.00 => 56 */ 0x38, /* => 99.75 */
+/* 104.00 => 56 */ 0x38, /* => 99.75 */
+/* 108.00 => 57 */ 0x39, /* => 104.00 */
+/* 112.00 => 58 */ 0x3a, /* => 108.25 */
+/* 116.00 => 59 */ 0x3b, /* => 112.88 */
+/* 120.00 => 60 */ 0x3c, /* => 117.50 */
+/* 124.00 => 61 */ 0x3d, /* => 122.38 */
+/* 128.00 => 62 */ 0x3e, /* => 127.50 */
+/* 136.00 => 63 */ 0x3f, /* => 132.75 */
+/* 144.00 => 64 */ 0x40, /* => 138.50 */
+/* 152.00 => 66 */ 0x42, /* => 150.25 */
+/* 160.00 => 67 */ 0x43, /* => 156.75 */
+/* 168.00 => 68 */ 0x44, /* => 163.50 */
+/* 176.00 => 69 */ 0x45, /* => 170.00 */
+/* 184.00 => 70 */ 0x46, /* => 177.25 */
+/* 192.00 => 71 */ 0x47, /* => 184.50 */
+/* 200.00 => 72 */ 0x48, /* => 192.25 */
+/* 208.00 => 73 */ 0x49, /* => 200.25 */
+/* 216.00 => 74 */ 0x4a, /* => 208.75 */
+/* 224.00 => 75 */ 0x4b, /* => 217.75 */
+/* 232.00 => 76 */ 0x4c, /* => 226.75 */
+/* 240.00 => 77 */ 0x4d, /* => 236.25 */
+/* 248.00 => 78 */ 0x4e, /* => 246.25 */
+/* 256.00 => 78 */ 0x4e, /* => 246.25 */
+/* 272.00 => 80 */ 0x50, /* => 267.50 */
+/* 288.00 => 81 */ 0x51, /* => 278.50 */
+/* 304.00 => 83 */ 0x53, /* => 302.00 */
+/* 320.00 => 84 */ 0x54, /* => 315.00 */
+/* 336.00 => 85 */ 0x55, /* => 328.00 */
+/* 352.00 => 86 */ 0x56, /* => 342.00 */
+/* 368.00 => 87 */ 0x57, /* => 356.00 */
+/* 384.00 => 88 */ 0x58, /* => 371.00 */
+/* 400.00 => 89 */ 0x59, /* => 386.50 */
+/* 416.00 => 90 */ 0x5a, /* => 403.00 */
+/* 432.00 => 91 */ 0x5b, /* => 419.50 */
+/* 448.00 => 92 */ 0x5c, /* => 437.50 */
+/* 464.00 => 93 */ 0x5d, /* => 455.50 */
+/* 480.00 => 94 */ 0x5e, /* => 475.00 */
+/* 496.00 => 95 */ 0x5f, /* => 495.00 */
+/* 512.00 => 95 */ 0x5f, /* => 495.00 */
+/* 544.00 => 97 */ 0x61, /* => 537.00 */
+/* 576.00 => 98 */ 0x62, /* => 559.00 */
+/* 608.00 => 100 */ 0x64, /* => 607.00 */
+/* 640.00 => 101 */ 0x65, /* => 632.00 */
+/* 672.00 => 102 */ 0x66, /* => 660.00 */
+/* 704.00 => 103 */ 0x67, /* => 687.00 */
+/* 736.00 => 104 */ 0x68, /* => 716.00 */
+/* 768.00 => 105 */ 0x69, /* => 746.00 */
+/* 800.00 => 106 */ 0x6a, /* => 777.00 */
+/* 832.00 => 107 */ 0x6b, /* => 810.00 */
+/* 864.00 => 108 */ 0x6c, /* => 843.00 */
+/* 896.00 => 109 */ 0x6d, /* => 879.00 */
+/* 928.00 => 110 */ 0x6e, /* => 916.00 */
+/* 960.00 => 111 */ 0x6f, /* => 954.00 */
+/* 992.00 => 111 */ 0x6f, /* => 954.00 */
+/* 1024.00 => 112 */ 0x70, /* => 994.00 */
+/* 1088.00 => 114 */ 0x72, /* => 1080.00 */
+/* 1152.00 => 115 */ 0x73, /* => 1124.00 */
+/* 1216.00 => 116 */ 0x74, /* => 1172.00 */
+/* 1280.00 => 118 */ 0x76, /* => 1272.00 */
+/* 1344.00 => 119 */ 0x77, /* => 1326.00 */
+/* 1408.00 => 120 */ 0x78, /* => 1382.00 */
+/* 1472.00 => 121 */ 0x79, /* => 1440.00 */
+/* 1536.00 => 122 */ 0x7a, /* => 1498.00 */
+/* 1600.00 => 123 */ 0x7b, /* => 1562.00 */
+/* 1664.00 => 124 */ 0x7c, /* => 1628.00 */
+/* 1728.00 => 125 */ 0x7d, /* => 1696.00 */
+/* 1792.00 => 126 */ 0x7e, /* => 1768.00 */
+/* 1856.00 => 127 */ 0x7f, /* => 1842.00 */
+/* 1920.00 => 128 */ 0x80, /* => 1918.00 */
+/* 1984.00 => 128 */ 0x80, /* => 1918.00 */
+/* 2048.00 => 129 */ 0x81, /* => 2000.00 */
+/* 2176.00 => 131 */ 0x83, /* => 2168.00 */
+/* 2304.00 => 132 */ 0x84, /* => 2264.00 */
+/* 2432.00 => 133 */ 0x85, /* => 2356.00 */
+/* 2560.00 => 135 */ 0x87, /* => 2556.00 */
+/* 2688.00 => 136 */ 0x88, /* => 2664.00 */
+/* 2816.00 => 137 */ 0x89, /* => 2776.00 */
+/* 2944.00 => 138 */ 0x8a, /* => 2892.00 */
+/* 3072.00 => 139 */ 0x8b, /* => 3012.00 */
+/* 3200.00 => 140 */ 0x8c, /* => 3140.00 */
+/* 3328.00 => 141 */ 0x8d, /* => 3272.00 */
+/* 3456.00 => 142 */ 0x8e, /* => 3412.00 */
+/* 3584.00 => 143 */ 0x8f, /* => 3552.00 */
+/* 3712.00 => 144 */ 0x90, /* => 3700.00 */
+/* 3840.00 => 144 */ 0x90, /* => 3700.00 */
+/* 3968.00 => 145 */ 0x91, /* => 3860.00 */
+/* 4096.00 => 146 */ 0x92, /* => 4016.00 */
+/* 4352.00 => 147 */ 0x93, /* => 4184.00 */
+/* 4608.00 => 149 */ 0x95, /* => 4544.00 */
+/* 4864.00 => 150 */ 0x96, /* => 4736.00 */
+/* 5120.00 => 151 */ 0x97, /* => 4936.00 */
+/* 5376.00 => 153 */ 0x99, /* => 5360.00 */
+/* 5632.00 => 154 */ 0x9a, /* => 5584.00 */
+/* 5888.00 => 155 */ 0x9b, /* => 5816.00 */
+/* 6144.00 => 156 */ 0x9c, /* => 6056.00 */
+/* 6400.00 => 157 */ 0x9d, /* => 6312.00 */
+/* 6656.00 => 158 */ 0x9e, /* => 6576.00 */
+/* 6912.00 => 159 */ 0x9f, /* => 6856.00 */
+/* 7168.00 => 160 */ 0xa0, /* => 7144.00 */
+/* 7424.00 => 160 */ 0xa0, /* => 7144.00 */
+/* 7680.00 => 161 */ 0xa1, /* => 7440.00 */
+/* 7936.00 => 162 */ 0xa2, /* => 7752.00 */
+/* 8192.00 => 163 */ 0xa3, /* => 8080.00 */
+/* 8704.00 => 164 */ 0xa4, /* => 8416.00 */
+/* 9216.00 => 166 */ 0xa6, /* => 9136.00 */
+/* 9728.00 => 167 */ 0xa7, /* => 9520.00 */
+/* 10240.00 => 168 */ 0xa8, /* => 9920.00 */
+/* 10752.00 => 169 */ 0xa9, /* => 10336.00 */
+/* 11264.00 => 171 */ 0xab, /* => 11216.00 */
+/* 11776.00 => 172 */ 0xac, /* => 11680.00 */
+/* 12288.00 => 173 */ 0xad, /* => 12176.00 */
+/* 12800.00 => 174 */ 0xae, /* => 12688.00 */
+/* 13312.00 => 175 */ 0xaf, /* => 13216.00 */
+/* 13824.00 => 176 */ 0xb0, /* => 13776.00 */
+/* 14336.00 => 176 */ 0xb0, /* => 13776.00 */
+/* 14848.00 => 177 */ 0xb1, /* => 14352.00 */
+/* 15360.00 => 178 */ 0xb2, /* => 14960.00 */
+/* 15872.00 => 179 */ 0xb3, /* => 15584.00 */
+/* 16384.00 => 180 */ 0xb4, /* => 16224.00 */
+/* 17408.00 => 181 */ 0xb5, /* => 16896.00 */
+/* 18432.00 => 183 */ 0xb7, /* => 18368.00 */
+/* 19456.00 => 184 */ 0xb8, /* => 19136.00 */
+/* 20480.00 => 185 */ 0xb9, /* => 19904.00 */
+/* 21504.00 => 186 */ 0xba, /* => 20768.00 */
+/* 22528.00 => 187 */ 0xbb, /* => 21632.00 */
+/* 23552.00 => 189 */ 0xbd, /* => 23488.00 */
+/* 24576.00 => 190 */ 0xbe, /* => 24512.00 */
+/* 25600.00 => 191 */ 0xbf, /* => 25504.00 */
+/* 26624.00 => 192 */ 0xc0, /* => 26592.00 */
+/* 27648.00 => 192 */ 0xc0, /* => 26592.00 */
+/* 28672.00 => 193 */ 0xc1, /* => 27680.00 */
+/* 29696.00 => 194 */ 0xc2, /* => 28896.00 */
+/* 30720.00 => 195 */ 0xc3, /* => 30048.00 */
+/* 31744.00 => 196 */ 0xc4, /* => 31392.00 */
+/* 32768.00 => 197 */ 0xc5, /* => 32640.00 */
+/* 34816.00 => 198 */ 0xc6, /* => 33984.00 */
+/* 36864.00 => 199 */ 0xc7, /* => 35392.00 */
+/* 38912.00 => 201 */ 0xc9, /* => 38528.00 */
+/* 40960.00 => 202 */ 0xca, /* => 40064.00 */
+/* 43008.00 => 203 */ 0xcb, /* => 41856.00 */
+/* 45056.00 => 204 */ 0xcc, /* => 43584.00 */
+/* 47104.00 => 205 */ 0xcd, /* => 45376.00 */
+/* 49152.00 => 206 */ 0xce, /* => 47232.00 */
+/* 51200.00 => 207 */ 0xcf, /* => 49344.00 */
+/* 53248.00 => 208 */ 0xd0, /* => 51328.00 */
+/* 55296.00 => 209 */ 0xd1, /* => 53504.00 */
+/* 57344.00 => 210 */ 0xd2, /* => 55616.00 */
+/* 59392.00 => 211 */ 0xd3, /* => 58240.00 */
+/* 61440.00 => 212 */ 0xd4, /* => 60416.00 */
+/* 63488.00 => 213 */ 0xd5, /* => 63104.00 */
+/* 65536.00 => 213 */ 0xd5, /* => 63104.00 */
+/* 69632.00 => 215 */ 0xd7, /* => 68480.00 */
+/* 73728.00 => 216 */ 0xd8, /* => 71424.00 */
+/* 77824.00 => 218 */ 0xda, /* => 77312.00 */
+/* 81920.00 => 219 */ 0xdb, /* => 80640.00 */
+/* 86016.00 => 220 */ 0xdc, /* => 84224.00 */
+/* 90112.00 => 221 */ 0xdd, /* => 87552.00 */
+/* 94208.00 => 222 */ 0xde, /* => 91136.00 */
+/* 98304.00 => 223 */ 0xdf, /* => 94976.00 */
+/* 102400.00 => 224 */ 0xe0, /* => 99072.00 */
+/* 106496.00 => 225 */ 0xe1, /* => 103680.00 */
+/* 110592.00 => 226 */ 0xe2, /* => 107520.00 */
+/* 114688.00 => 227 */ 0xe3, /* => 111872.00 */
+/* 118784.00 => 228 */ 0xe4, /* => 117632.00 */
+/* 122880.00 => 229 */ 0xe5, /* => 121472.00 */
+/* 126976.00 => 229 */ 0xe5, /* => 121472.00 */
+/* 131072.00 => 230 */ 0xe6, /* => 126976.00 */
+/* 139264.00 => 232 */ 0xe8, /* => 137728.00 */
+/* 147456.00 => 233 */ 0xe9, /* => 144896.00 */
+/* 155648.00 => 234 */ 0xea, /* => 150528.00 */
+/* 163840.00 => 236 */ 0xec, /* => 163584.00 */
+/* 172032.00 => 237 */ 0xed, /* => 168448.00 */
+/* 180224.00 => 238 */ 0xee, /* => 176384.00 */
+/* 188416.00 => 239 */ 0xef, /* => 185088.00 */
+/* 196608.00 => 240 */ 0xf0, /* => 191488.00 */
+/* 204800.00 => 241 */ 0xf1, /* => 201728.00 */
+/* 212992.00 => 242 */ 0xf2, /* => 209152.00 */
+/* 221184.00 => 243 */ 0xf3, /* => 217344.00 */
+/* 229376.00 => 244 */ 0xf4, /* => 226048.00 */
+/* 237568.00 => 245 */ 0xf5, /* => 235264.00 */
+/* 245760.00 => 246 */ 0xf6, /* => 245504.00 */
+/* 253952.00 => 246 */ 0xf6, /* => 245504.00 */
+/* 262144.00 => 247 */ 0xf7, /* => 256768.00 */
+/* 278528.00 => 248 */ 0xf8, /* => 268800.00 */
+/* 294912.00 => 250 */ 0xfa, /* => 289792.00 */
+/* 311296.00 => 251 */ 0xfb, /* => 305152.00 */
+/* 327680.00 => 252 */ 0xfc, /* => 313856.00 */
+/* 344064.00 => 254 */ 0xfe, /* => 342016.00 */
+/* 360448.00 => 255 */ 0xff, /* => 352768.00 */
+/* 376832.00 => 255 */ 0xff, /* => 352768.00 */
+/* 393216.00 => 255 */ 0xff, /* => 352768.00 */
+/* 409600.00 => 255 */ 0xff, /* => 352768.00 */
+/* 425984.00 => 255 */ 0xff, /* => 352768.00 */
+/* 442368.00 => 255 */ 0xff, /* => 352768.00 */
+/* 458752.00 => 255 */ 0xff, /* => 352768.00 */
+/* 475136.00 => 255 */ 0xff, /* => 352768.00 */
+/* 491520.00 => 255 */ 0xff, /* => 352768.00 */
+/* 507904.00 => 255 */ 0xff, /* => 352768.00 */
+/* 524288.00 => 255 */ 0xff, /* => 352768.00 */
+/* 557056.00 => 255 */ 0xff, /* => 352768.00 */
+/* 589824.00 => 255 */ 0xff, /* => 352768.00 */
+/* 622592.00 => 255 */ 0xff, /* => 352768.00 */
+/* 655360.00 => 255 */ 0xff, /* => 352768.00 */
+/* 688128.00 => 255 */ 0xff, /* => 352768.00 */
+/* 720896.00 => 255 */ 0xff, /* => 352768.00 */
+/* 753664.00 => 255 */ 0xff, /* => 352768.00 */
+/* 786432.00 => 255 */ 0xff, /* => 352768.00 */
+/* 819200.00 => 255 */ 0xff, /* => 352768.00 */
+/* 851968.00 => 255 */ 0xff, /* => 352768.00 */
+/* 884736.00 => 255 */ 0xff, /* => 352768.00 */
+/* 917504.00 => 255 */ 0xff, /* => 352768.00 */
+/* 950272.00 => 255 */ 0xff, /* => 352768.00 */
+/* 983040.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1015808.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1048576.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1114112.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1179648.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1245184.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1310720.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1376256.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1441792.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1507328.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1572864.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1638400.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1703936.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1769472.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1835008.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1900544.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1966080.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2031616.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2097152.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2228224.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2359296.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2490368.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2621440.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2752512.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2883584.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3014656.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3145728.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3276800.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3407872.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3538944.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3670016.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3801088.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3932160.00 => 255 */ 0xff, /* => 352768.00 */
+/* 4063232.00 => 255 */ 0xff, /* => 352768.00 */
+/* 4194304.00 => 255 */ 0xff, /* => 352768.00 */
+/* 4456448.00 => 255 */ 0xff, /* => 352768.00 */
+/* 4718592.00 => 255 */ 0xff, /* => 352768.00 */
+/* 4980736.00 => 255 */ 0xff, /* => 352768.00 */
+/* 5242880.00 => 255 */ 0xff, /* => 352768.00 */
+/* 5505024.00 => 255 */ 0xff, /* => 352768.00 */
+/* 5767168.00 => 255 */ 0xff, /* => 352768.00 */
+/* 6029312.00 => 255 */ 0xff, /* => 352768.00 */
+/* 6291456.00 => 255 */ 0xff, /* => 352768.00 */
+/* 6553600.00 => 255 */ 0xff, /* => 352768.00 */
+/* 6815744.00 => 255 */ 0xff, /* => 352768.00 */
+/* 7077888.00 => 255 */ 0xff, /* => 352768.00 */
+/* 7340032.00 => 255 */ 0xff, /* => 352768.00 */
+/* 7602176.00 => 255 */ 0xff, /* => 352768.00 */
+/* 7864320.00 => 255 */ 0xff, /* => 352768.00 */
+/* 8126464.00 => 255 */ 0xff, /* => 352768.00 */
+/* 8388608.00 => 255 */ 0xff, /* => 352768.00 */
+/* 8912896.00 => 255 */ 0xff, /* => 352768.00 */
+/* 9437184.00 => 255 */ 0xff, /* => 352768.00 */
+/* 9961472.00 => 255 */ 0xff, /* => 352768.00 */
+/* 10485760.00 => 255 */ 0xff, /* => 352768.00 */
+/* 11010048.00 => 255 */ 0xff, /* => 352768.00 */
+/* 11534336.00 => 255 */ 0xff, /* => 352768.00 */
+/* 12058624.00 => 255 */ 0xff, /* => 352768.00 */
+/* 12582912.00 => 255 */ 0xff, /* => 352768.00 */
+/* 13107200.00 => 255 */ 0xff, /* => 352768.00 */
+/* 13631488.00 => 255 */ 0xff, /* => 352768.00 */
+/* 14155776.00 => 255 */ 0xff, /* => 352768.00 */
+/* 14680064.00 => 255 */ 0xff, /* => 352768.00 */
+/* 15204352.00 => 255 */ 0xff, /* => 352768.00 */
+/* 15728640.00 => 255 */ 0xff, /* => 352768.00 */
+/* 16252928.00 => 255 */ 0xff, /* => 352768.00 */
+/* 16777216.00 => 255 */ 0xff, /* => 352768.00 */
+/* 17825792.00 => 255 */ 0xff, /* => 352768.00 */
+/* 18874368.00 => 255 */ 0xff, /* => 352768.00 */
+/* 19922944.00 => 255 */ 0xff, /* => 352768.00 */
+/* 20971520.00 => 255 */ 0xff, /* => 352768.00 */
+/* 22020096.00 => 255 */ 0xff, /* => 352768.00 */
+/* 23068672.00 => 255 */ 0xff, /* => 352768.00 */
+/* 24117248.00 => 255 */ 0xff, /* => 352768.00 */
+/* 25165824.00 => 255 */ 0xff, /* => 352768.00 */
+/* 26214400.00 => 255 */ 0xff, /* => 352768.00 */
+/* 27262976.00 => 255 */ 0xff, /* => 352768.00 */
+/* 28311552.00 => 255 */ 0xff, /* => 352768.00 */
+/* 29360128.00 => 255 */ 0xff, /* => 352768.00 */
+/* 30408704.00 => 255 */ 0xff, /* => 352768.00 */
+/* 31457280.00 => 255 */ 0xff, /* => 352768.00 */
+/* 32505856.00 => 255 */ 0xff, /* => 352768.00 */
+/* 33554432.00 => 255 */ 0xff, /* => 352768.00 */
+/* 35651584.00 => 255 */ 0xff, /* => 352768.00 */
+/* 37748736.00 => 255 */ 0xff, /* => 352768.00 */
+/* 39845888.00 => 255 */ 0xff, /* => 352768.00 */
+/* 41943040.00 => 255 */ 0xff, /* => 352768.00 */
+/* 44040192.00 => 255 */ 0xff, /* => 352768.00 */
+/* 46137344.00 => 255 */ 0xff, /* => 352768.00 */
+/* 48234496.00 => 255 */ 0xff, /* => 352768.00 */
+/* 50331648.00 => 255 */ 0xff, /* => 352768.00 */
+/* 52428800.00 => 255 */ 0xff, /* => 352768.00 */
+/* 54525952.00 => 255 */ 0xff, /* => 352768.00 */
+/* 56623104.00 => 255 */ 0xff, /* => 352768.00 */
+/* 58720256.00 => 255 */ 0xff, /* => 352768.00 */
+/* 60817408.00 => 255 */ 0xff, /* => 352768.00 */
+/* 62914560.00 => 255 */ 0xff, /* => 352768.00 */
+/* 65011712.00 => 255 */ 0xff, /* => 352768.00 */
+/* 67108864.00 => 255 */ 0xff, /* => 352768.00 */
+/* 71303168.00 => 255 */ 0xff, /* => 352768.00 */
+/* 75497472.00 => 255 */ 0xff, /* => 352768.00 */
+/* 79691776.00 => 255 */ 0xff, /* => 352768.00 */
+/* 83886080.00 => 255 */ 0xff, /* => 352768.00 */
+/* 88080384.00 => 255 */ 0xff, /* => 352768.00 */
+/* 92274688.00 => 255 */ 0xff, /* => 352768.00 */
+/* 96468992.00 => 255 */ 0xff, /* => 352768.00 */
+/* 100663296.00 => 255 */ 0xff, /* => 352768.00 */
+/* 104857600.00 => 255 */ 0xff, /* => 352768.00 */
+/* 109051904.00 => 255 */ 0xff, /* => 352768.00 */
+/* 113246208.00 => 255 */ 0xff, /* => 352768.00 */
+/* 117440512.00 => 255 */ 0xff, /* => 352768.00 */
+/* 121634816.00 => 255 */ 0xff, /* => 352768.00 */
+/* 125829120.00 => 255 */ 0xff, /* => 352768.00 */
+/* 130023424.00 => 255 */ 0xff, /* => 352768.00 */
+/* 134217728.00 => 255 */ 0xff, /* => 352768.00 */
+/* 142606336.00 => 255 */ 0xff, /* => 352768.00 */
+/* 150994944.00 => 255 */ 0xff, /* => 352768.00 */
+/* 159383552.00 => 255 */ 0xff, /* => 352768.00 */
+/* 167772160.00 => 255 */ 0xff, /* => 352768.00 */
+/* 176160768.00 => 255 */ 0xff, /* => 352768.00 */
+/* 184549376.00 => 255 */ 0xff, /* => 352768.00 */
+/* 192937984.00 => 255 */ 0xff, /* => 352768.00 */
+/* 201326592.00 => 255 */ 0xff, /* => 352768.00 */
+/* 209715200.00 => 255 */ 0xff, /* => 352768.00 */
+/* 218103808.00 => 255 */ 0xff, /* => 352768.00 */
+/* 226492416.00 => 255 */ 0xff, /* => 352768.00 */
+/* 234881024.00 => 255 */ 0xff, /* => 352768.00 */
+/* 243269632.00 => 255 */ 0xff, /* => 352768.00 */
+/* 251658240.00 => 255 */ 0xff, /* => 352768.00 */
+/* 260046848.00 => 255 */ 0xff, /* => 352768.00 */
+/* 268435456.00 => 255 */ 0xff, /* => 352768.00 */
+/* 285212672.00 => 255 */ 0xff, /* => 352768.00 */
+/* 301989888.00 => 255 */ 0xff, /* => 352768.00 */
+/* 318767104.00 => 255 */ 0xff, /* => 352768.00 */
+/* 335544320.00 => 255 */ 0xff, /* => 352768.00 */
+/* 352321536.00 => 255 */ 0xff, /* => 352768.00 */
+/* 369098752.00 => 255 */ 0xff, /* => 352768.00 */
+/* 385875968.00 => 255 */ 0xff, /* => 352768.00 */
+/* 402653184.00 => 255 */ 0xff, /* => 352768.00 */
+/* 419430400.00 => 255 */ 0xff, /* => 352768.00 */
+/* 436207616.00 => 255 */ 0xff, /* => 352768.00 */
+/* 452984832.00 => 255 */ 0xff, /* => 352768.00 */
+/* 469762048.00 => 255 */ 0xff, /* => 352768.00 */
+/* 486539264.00 => 255 */ 0xff, /* => 352768.00 */
+/* 503316480.00 => 255 */ 0xff, /* => 352768.00 */
+/* 520093696.00 => 255 */ 0xff, /* => 352768.00 */
+/* 536870912.00 => 255 */ 0xff, /* => 352768.00 */
+/* 570425344.00 => 255 */ 0xff, /* => 352768.00 */
+/* 603979776.00 => 255 */ 0xff, /* => 352768.00 */
+/* 637534208.00 => 255 */ 0xff, /* => 352768.00 */
+/* 671088640.00 => 255 */ 0xff, /* => 352768.00 */
+/* 704643072.00 => 255 */ 0xff, /* => 352768.00 */
+/* 738197504.00 => 255 */ 0xff, /* => 352768.00 */
+/* 771751936.00 => 255 */ 0xff, /* => 352768.00 */
+/* 805306368.00 => 255 */ 0xff, /* => 352768.00 */
+/* 838860800.00 => 255 */ 0xff, /* => 352768.00 */
+/* 872415232.00 => 255 */ 0xff, /* => 352768.00 */
+/* 905969664.00 => 255 */ 0xff, /* => 352768.00 */
+/* 939524096.00 => 255 */ 0xff, /* => 352768.00 */
+/* 973078528.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1006632960.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1040187392.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1073741824.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1140850688.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1207959552.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1275068416.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1342177280.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1409286144.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1476395008.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1543503872.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1610612736.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1677721600.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1744830464.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1811939328.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1879048192.00 => 255 */ 0xff, /* => 352768.00 */
+/* 1946157056.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2013265920.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2080374784.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2147483648.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2281701376.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2415919104.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2550136832.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2684354560.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2818572288.00 => 255 */ 0xff, /* => 352768.00 */
+/* 2952790016.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3087007744.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3221225472.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3355443200.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3489660928.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3623878656.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3758096384.00 => 255 */ 0xff, /* => 352768.00 */
+/* 3892314112.00 => 255 */ 0xff, /* => 352768.00 */
+/* 4026531840.00 => 255 */ 0xff, /* => 352768.00 */
+/* 4160749568.00 => 255 */ 0xff, /* => 352768.00 */
+};
diff -u --recursive --new-file v2.4.14/linux/drivers/atm/suni.c linux/drivers/atm/suni.c
--- v2.4.14/linux/drivers/atm/suni.c Sun Sep 23 11:40:57 2001
+++ linux/drivers/atm/suni.c Tue Nov 13 09:19:41 2001
@@ -232,6 +232,9 @@
X
X if (!(PRIV(dev) = kmalloc(sizeof(struct suni_priv),GFP_KERNEL)))
X return -ENOMEM;
+
+ MOD_INC_USE_COUNT;
+
X PRIV(dev)->dev = dev;
X spin_lock_irqsave(&sunis_lock,flags);
X first = !sunis;
@@ -276,6 +279,8 @@
X if (!sunis) del_timer_sync(&poll_timer);
X spin_unlock_irqrestore(&sunis_lock,flags);
X kfree(PRIV(dev));
+
+ MOD_DEC_USE_COUNT;


X return 0;
X }
X

@@ -316,7 +321,6 @@
X
X int init_module(void)
X {
- MOD_INC_USE_COUNT;


X return 0;
X }
X

diff -u --recursive --new-file v2.4.14/linux/drivers/block/acsi.c linux/drivers/block/acsi.c
--- v2.4.14/linux/drivers/block/acsi.c Mon Nov 5 15:55:29 2001
+++ linux/drivers/block/acsi.c Fri Nov 9 13:58:03 2001
@@ -1134,14 +1134,8 @@
X put_user( 0, &((Scsi_Idlun *) arg)->host_unique_id );
X return 0;
X
- case BLKGETSIZE: /* Return device size */
- return put_user(acsi_part[MINOR(inode->i_rdev)].nr_sects,
- (unsigned long *) arg);
-
- case BLKGETSIZE64: /* Return device size */
- return put_user((u64)acsi_part[MINOR(inode->i_rdev)].nr_sects << 9,
- (u64 *) arg);
-
+ case BLKGETSIZE:
+ case BLKGETSIZE64:
X case BLKROSET:
X case BLKROGET:
X case BLKFLSBUF:
diff -u --recursive --new-file v2.4.14/linux/drivers/block/blkpg.c linux/drivers/block/blkpg.c
--- v2.4.14/linux/drivers/block/blkpg.c Tue Oct 23 22:48:50 2001
+++ linux/drivers/block/blkpg.c Sun Nov 11 10:20:21 2001
@@ -195,8 +195,13 @@
X
X int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
X {
+ struct gendisk *g;
+ u64 ullval = 0;
X int intval;
X
+ if (!dev)
+ return -EINVAL;
+
X switch (cmd) {
X case BLKROSET:
X if (!capable(CAP_SYS_ADMIN))
@@ -212,7 +217,7 @@
X case BLKRASET:
X if(!capable(CAP_SYS_ADMIN))
X return -EACCES;
- if(!dev || arg > 0xff)
+ if(arg > 0xff)
X return -EINVAL;
X read_ahead[MAJOR(dev)] = arg;
X return 0;
@@ -224,8 +229,6 @@
X case BLKFLSBUF:
X if(!capable(CAP_SYS_ADMIN))
X return -EACCES;
- if (!dev)
- return -EINVAL;
X fsync_dev(dev);
X invalidate_buffers(dev);
X return 0;
@@ -235,18 +238,16 @@
X intval = get_hardsect_size(dev);
X return put_user(intval, (int *) arg);
X
-#if 0
X case BLKGETSIZE:
- /* Today get_gendisk() requires a linear scan;
- add this when dev has pointer type. */
- /* add BLKGETSIZE64 too */
+ case BLKGETSIZE64:
X g = get_gendisk(dev);
- if (!g)
- ulongval = 0;
+ if (g)
+ ullval = g->part[MINOR(dev)].nr_sects;
+
+ if (cmd == BLKGETSIZE)
+ return put_user((unsigned long)ullval, (unsigned long *)arg);
X else
- ulongval = g->part[MINOR(dev)].nr_sects;
- return put_user(ulongval, (unsigned long *) arg);
-#endif
+ return put_user(ullval, (u64 *)arg);
X #if 0
X case BLKRRPART: /* Re-read partition tables */
X if (!capable(CAP_SYS_ADMIN))
diff -u --recursive --new-file v2.4.14/linux/drivers/block/cciss.c linux/drivers/block/cciss.c
--- v2.4.14/linux/drivers/block/cciss.c Mon Nov 5 15:55:29 2001
+++ linux/drivers/block/cciss.c Fri Nov 9 14:28:46 2001
@@ -1307,6 +1307,8 @@
X if (( c = cmd_alloc(h, 1)) == NULL)
X goto startio;
X
+ blkdev_dequeue_request(creq);
+
X spin_unlock_irq(&io_request_lock);
X
X c->cmd_type = CMD_RWREQ;
@@ -1386,12 +1388,6 @@
X
X spin_lock_irq(&io_request_lock);
X
- blkdev_dequeue_request(creq);
-
- /*
- * ehh, we can't really end the request here since it's not
- * even started yet. for now it shouldn't hurt though
- */
X addQ(&(h->reqQ),c);
X h->Qdepth++;
X if(h->Qdepth > h->maxQsinceinit)
@@ -1928,7 +1924,7 @@
X
X /* Initialize the pdev driver private data.
X have it point to hba[i]. */
- pdev->driver_data = hba[i];
+ pci_set_drvdata(pdev, hba[i]);
X /* command and error info recs zeroed out before
X they are used */
X memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+31)/32)*sizeof(__u32));
@@ -1987,12 +1983,12 @@
X ctlr_info_t *tmp_ptr;
X int i;
X
- if (pdev->driver_data == NULL)
+ if (pci_get_drvdata(pdev) == NULL)
X {
X printk( KERN_ERR "cciss: Unable to remove device \n");
X return;
X }
- tmp_ptr = (ctlr_info_t *) pdev->driver_data;
+ tmp_ptr = pci_get_drvdata(pdev);
X i = tmp_ptr->ctlr;
X if (hba[i] == NULL)
X {
@@ -2003,7 +1999,7 @@
X /* Turn board interrupts off */
X hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
X free_irq(hba[i]->intr, hba[i]);
- pdev->driver_data = NULL;
+ pci_set_drvdata(pdev, NULL);
X iounmap((void*)hba[i]->vaddr);
X unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
X remove_proc_entry(hba[i]->devname, proc_cciss);
diff -u --recursive --new-file v2.4.14/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c
--- v2.4.14/linux/drivers/block/cpqarray.c Mon Nov 5 15:55:29 2001
+++ linux/drivers/block/cpqarray.c Fri Nov 9 14:28:46 2001
@@ -942,6 +942,8 @@
X if ((c = cmd_alloc(h,1)) == NULL)
X goto startio;
X
+ blkdev_dequeue_request(creq);
+
X spin_unlock_irq(&io_request_lock);
X
X bh = creq->bh;
@@ -987,13 +989,10 @@
X DBGPX( printk("Submitting %d sectors in %d segments\n", sect, seg); );
X c->req.hdr.sg_cnt = seg;
X c->req.hdr.blk_cnt = creq->nr_sectors;
-
- spin_lock_irq(&io_request_lock);
-
- blkdev_dequeue_request(creq);
-
X c->req.hdr.cmd = (creq->cmd == READ) ? IDA_READ : IDA_WRITE;
X c->type = CMD_RWREQ;
+
+ spin_lock_irq(&io_request_lock);
X
X /* Put the request on the tail of the request queue */
X addQ(&h->reqQ, c);
diff -u --recursive --new-file v2.4.14/linux/drivers/block/loop.c linux/drivers/block/loop.c
--- v2.4.14/linux/drivers/block/loop.c Mon Nov 5 15:55:29 2001
+++ linux/drivers/block/loop.c Mon Nov 19 14:48:02 2001
@@ -180,12 +180,15 @@
X unsigned size, offset;
X int len;
X
+ down(&mapping->host->i_sem);
X index = pos >> PAGE_CACHE_SHIFT;
X offset = pos & (PAGE_CACHE_SIZE - 1);
X len = bh->b_size;
X data = bh->b_data;
X while (len > 0) {
X int IV = index * (PAGE_CACHE_SIZE/bsize) + offset/bsize;
+ int transfer_result;
+
X size = PAGE_CACHE_SIZE - offset;
X if (size > len)
X size = len;
@@ -197,30 +200,35 @@
X goto unlock;
X kaddr = page_address(page);
X flush_dcache_page(page);
- if (lo_do_transfer(lo, WRITE, kaddr + offset, data, size, IV))
- goto write_fail;
+ transfer_result = lo_do_transfer(lo, WRITE, kaddr + offset, data, size, IV);
+ if (transfer_result) {
+ /*
+ * The transfer failed, but we still write the data to
+ * keep prepare/commit calls balanced.
+ */
+ printk(KERN_ERR "loop: transfer error block %ld\n", index);
+ memset(kaddr + offset, 0, size);
+ }
X if (aops->commit_write(file, page, offset, offset+size))
X goto unlock;
+ if (transfer_result)
+ goto unlock;
X data += size;
X len -= size;
X offset = 0;
X index++;
X pos += size;
X UnlockPage(page);
- deactivate_page(page);
X page_cache_release(page);
X }
+ up(&mapping->host->i_sem);
X return 0;
X
-write_fail:
- printk(KERN_ERR "loop: transfer error block %ld\n", index);
- ClearPageUptodate(page);
- kunmap(page);
X unlock:
X UnlockPage(page);
- deactivate_page(page);
X page_cache_release(page);
X fail:
+ up(&mapping->host->i_sem);
X return -1;
X }
X
diff -u --recursive --new-file v2.4.14/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c
--- v2.4.14/linux/drivers/block/paride/pd.c Mon Nov 5 15:55:29 2001
+++ linux/drivers/block/paride/pd.c Fri Nov 9 13:58:03 2001
@@ -475,18 +475,12 @@
X }
X put_user(pd_hd[dev].start_sect,(long *)&geo->start);
X return 0;
- case BLKGETSIZE:
- if (!arg) return -EINVAL;
- err = verify_area(VERIFY_WRITE,(unsigned long *) arg,sizeof(unsigned long));
- if (err) return (err);
- put_user(pd_hd[dev].nr_sects,(unsigned long *) arg);
- return (0);
- case BLKGETSIZE64:
- return put_user((u64)pd_hd[dev].nr_sects << 9, (u64 *)arg);
X case BLKRRPART:


X if (!capable(CAP_SYS_ADMIN))
X return -EACCES;

X return pd_revalidate(inode->i_rdev);
+ case BLKGETSIZE:
+ case BLKGETSIZE64:
X case BLKROSET:
X case BLKROGET:
X case BLKRASET:
diff -u --recursive --new-file v2.4.14/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c
--- v2.4.14/linux/drivers/block/ps2esdi.c Mon Nov 5 15:55:29 2001
+++ linux/drivers/block/ps2esdi.c Fri Nov 9 14:01:21 2001
@@ -47,6 +47,7 @@
X #include <linux/mca.h>
X #include <linux/init.h>
X #include <linux/ioport.h>
+#include <linux/module.h>
X
X #include <asm/system.h>
X #include <asm/io.h>
@@ -1106,24 +1107,13 @@
X }
X break;
X
- case BLKGETSIZE:
- if (arg) {
- if ((err = verify_area(VERIFY_WRITE, (unsigned long *) arg, sizeof(unsigned long))))
- return (err);
- put_user(ps2esdi[MINOR(inode->i_rdev)].nr_sects, (unsigned long *) arg);
-
- return (0);
- }
- break;
-
- case BLKGETSIZE64:
- return put_user((u64)ps2esdi[MINOR(inode->i_rdev)].nr_sects << 9, (u64 *) arg);
-
X case BLKRRPART:


X if (!capable(CAP_SYS_ADMIN))
X return -EACCES;

X return (ps2esdi_reread_partitions(inode->i_rdev));
X
+ case BLKGETSIZE:
+ case BLKGETSIZE64:
X case BLKROSET:
X case BLKROGET:
X case BLKRASET:
diff -u --recursive --new-file v2.4.14/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.4.14/linux/drivers/block/rd.c Mon Nov 5 15:55:29 2001
+++ linux/drivers/block/rd.c Fri Nov 9 14:15:00 2001
@@ -809,9 +809,6 @@
X
X static void __init rd_load_disk(int n)
X {
-#ifdef CONFIG_BLK_DEV_INITRD
- extern kdev_t real_root_dev;
-#endif
X
X if (rd_doload == 0)
X return;
diff -u --recursive --new-file v2.4.14/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v2.4.14/linux/drivers/block/xd.c Mon Nov 5 15:55:29 2001
+++ linux/drivers/block/xd.c Fri Nov 9 14:01:21 2001
@@ -332,11 +332,6 @@
X g.start = xd_struct[MINOR(inode->i_rdev)].start_sect;
X return copy_to_user(geometry, &g, sizeof g) ? -EFAULT : 0;
X }
- case BLKGETSIZE:
- if (!arg) return -EINVAL;
- return put_user(xd_struct[MINOR(inode->i_rdev)].nr_sects,(unsigned long *) arg);
- case BLKGETSIZE64:
- return put_user((u64)xd_struct[MINOR(inode->i_rdev)].nr_sects << 9, (u64 *)arg);
X case HDIO_SET_DMA:


X if (!capable(CAP_SYS_ADMIN)) return -EACCES;

X if (xdc_busy) return -EBUSY;
@@ -355,6 +350,8 @@
X return -EACCES;
X return xd_reread_partitions(inode->i_rdev);
X
+ case BLKGETSIZE:
+ case BLKGETSIZE64:
X case BLKFLSBUF:
X case BLKROSET:
X case BLKROGET:
diff -u --recursive --new-file v2.4.14/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.4.14/linux/drivers/cdrom/cdrom.c Mon Nov 5 15:55:29 2001
+++ linux/drivers/cdrom/cdrom.c Fri Nov 16 10:14:08 2001
@@ -2625,7 +2625,8 @@
X #ifdef CONFIG_SYSCTL
X cdrom_sysctl_register();
X #endif
- devfs_handle = devfs_mk_dir(NULL, "cdroms", NULL);
+ if (!devfs_handle)
+ devfs_handle = devfs_mk_dir(NULL, "cdroms", NULL);


X return 0;
X }
X

diff -u --recursive --new-file v2.4.14/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.4.14/linux/drivers/char/Config.in Mon Nov 5 15:55:29 2001
+++ linux/drivers/char/Config.in Mon Nov 12 09:34:16 2001
@@ -16,6 +16,9 @@
X tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL
X fi
X fi
+if [ "$CONFIG_ACPI" = "y" ]; then
+ bool ' Support for serial ports defined by ACPI tables' CONFIG_SERIAL_ACPI
+fi
X dep_mbool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED $CONFIG_SERIAL
X if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
X bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS
@@ -155,17 +158,18 @@
X tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
X tristate ' Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
X tristate ' Advantech SBC Watchdog Timer' CONFIG_ADVANTECH_WDT
- tristate ' IB700 SBC Watchdog Timer' CONFIG_IB700_WDT
- tristate ' SBC-60XX Watchdog Timer' CONFIG_60XX_WDT
- tristate ' W83877F (EMACS) Watchdog Timer' CONFIG_W83877F_WDT
- tristate ' Mixcom Watchdog' CONFIG_MIXCOMWD
- tristate ' Intel i810 TCO timer / Watchdog' CONFIG_I810_TCO
X if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
X tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG
X if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then
X tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG
X fi
X fi
+ tristate ' Eurotech CPU-1220/1410 Watchdog Timer' CONFIG_EUROTECH_WDT
+ tristate ' IB700 SBC Watchdog Timer' CONFIG_IB700_WDT
+ tristate ' Intel i810 TCO timer / Watchdog' CONFIG_I810_TCO
+ tristate ' Mixcom Watchdog' CONFIG_MIXCOMWD
+ tristate ' SBC-60XX Watchdog Timer' CONFIG_60XX_WDT
+ tristate ' W83877F (EMACS) Watchdog Timer' CONFIG_W83877F_WDT
X tristate ' ZF MachZ Watchdog' CONFIG_MACHZ_WDT
X fi
X endmenu
diff -u --recursive --new-file v2.4.14/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.4.14/linux/drivers/char/Makefile Mon Nov 5 15:55:29 2001
+++ linux/drivers/char/Makefile Sun Nov 11 10:09:32 2001
@@ -126,6 +126,7 @@
X
X obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o
X obj-$(CONFIG_SERIAL) += $(SERIAL)
+obj-$(CONFIG_SERIAL_ACPI) += acpi_serial.o
X obj-$(CONFIG_SERIAL_21285) += serial_21285.o
X obj-$(CONFIG_SERIAL_SA1100) += serial_sa1100.o
X obj-$(CONFIG_SERIAL_AMBA) += serial_amba.o
@@ -231,6 +232,7 @@
X obj-$(CONFIG_I810_TCO) += i810-tco.o
X obj-$(CONFIG_MACHZ_WDT) += machzwd.o
X obj-$(CONFIG_SH_WDT) += shwdt.o
+obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
X obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
X
X subdir-$(CONFIG_MWAVE) += mwave
diff -u --recursive --new-file v2.4.14/linux/drivers/char/acpi_serial.c linux/drivers/char/acpi_serial.c
--- v2.4.14/linux/drivers/char/acpi_serial.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/acpi_serial.c Wed Nov 14 11:45:41 2001
@@ -0,0 +1,203 @@
+/*
+ * linux/drivers/char/acpi_serial.c
+ *
+ * Copyright (C) 2000 Hewlett-Packard Co.
+ * Copyright (C) 2000 Khalid Aziz <khali...@hp.com>
+ *
+ * Detect and initialize the headless console serial port defined in
+ * SPCR table and debug serial port defined in DBGP table
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/pm.h>
+#include <linux/acpi.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/serial.h>
+#include <asm/io.h>
+#include <linux/acpi_serial.h>
+/*#include <asm/acpi-ext.h>*/
+
+#undef SERIAL_DEBUG_ACPI
+
+/*
+ * Query ACPI tables for a debug and a headless console serial
+ * port. If found, add them to rs_table[]. A pointer to either SPCR
+ * or DBGP table is passed as parameter. This function should be called
+ * before serial_console_init() is called to make sure the SPCR serial
+ * console will be available for use. IA-64 kernel calls this function
+ * from within acpi.c when it encounters SPCR or DBGP tables as it parses
+ * the ACPI 2.0 tables during bootup.
+ *
+ */
+void __init setup_serial_acpi(void *tablep)
+{
+ acpi_ser_t *acpi_ser_p;
+ struct serial_struct serial_req;
+ unsigned long iobase;
+ int global_sys_irq;
+
+#ifdef SERIAL_DEBUG_ACPI
+ printk("Entering setup_serial_acpi()\n");
+#endif
+
+ /* Now get the table */
+ if (tablep == NULL) {
+ return;
+ }
+
+ acpi_ser_p = (acpi_ser_t *)tablep;
+
+ /*
+ * Perform a sanity check on the table. Table should have a
+ * signature of "SPCR" or "DBGP" and it should be atleast 52 bytes
+ * long.
+ */
+ if ((strncmp(acpi_ser_p->signature, ACPI_SPCRT_SIGNATURE,
+ ACPI_SIG_LEN) != 0) &&
+ (strncmp(acpi_ser_p->signature, ACPI_DBGPT_SIGNATURE,
+ ACPI_SIG_LEN) != 0)) {
+ return;
+ }
+ if (acpi_ser_p->length < 52) {
+ return;
+ }
+
+ iobase = (((u64) acpi_ser_p->base_addr.addrh) << 32) | acpi_ser_p->base_addr.addrl;
+ global_sys_irq = (acpi_ser_p->global_int[3] << 24) |
+ (acpi_ser_p->global_int[2] << 16) |
+ (acpi_ser_p->global_int[1] << 8) |
+ acpi_ser_p->global_int[0];
+
+#ifdef SERIAL_DEBUG_ACPI
+ printk("setup_serial_acpi(): table pointer = 0x%p\n", acpi_ser_p);
+ printk(" sig = '%c%c%c%c'\n",


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

echo 'End of part 039'
echo 'File patch-2.4.15 is continued in part 040'
echo "040" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:26 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part050

#!/bin/sh -x
# this is part 050 of a 115 - part archive


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

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

+ */
+static int bond_get_info(char *buf, char **start, off_t offset, int length);
+
+/* #define BONDING_DEBUG 1 */
X
-typedef struct slave
+/* several macros */
+
+#define IS_UP(dev) ((((dev)->flags & (IFF_UP)) == (IFF_UP)) && \
+ (netif_running(dev) && netif_carrier_ok(dev)))
+
+static void bond_set_slave_inactive_flags(slave_t *slave)
X {
- struct slave *next;
- struct slave *prev;
- struct net_device *dev;
-} slave_t;
+ slave->state = BOND_STATE_BACKUP;
+ slave->dev->flags |= IFF_NOARP;
+}
X
-typedef struct bonding
+static void bond_set_slave_active_flags(slave_t *slave)
X {
- slave_t *next;
- slave_t *prev;
- struct net_device *master;
+ slave->state = BOND_STATE_ACTIVE;
+ slave->dev->flags &= ~IFF_NOARP;
+}
X
- slave_t *current_slave;
- struct net_device_stats stats;
-} bonding_t;
+/*
+ * This function detaches the slave <slave> from the list <bond>.
+ * WARNING: no check is made to verify if the slave effectively
+ * belongs to <bond>. It returns <slave> in case it's needed.
+ * Nothing is freed on return, structures are just unchained.
+ * If the bond->current_slave pointer was pointing to <slave>,
+ * it's replaced with slave->next, or <bond> if not applicable.
+ */
+static slave_t *bond_detach_slave(bonding_t *bond, slave_t *slave)
+{
+ if ((bond == NULL) || (slave == NULL) ||
+ ((void *)bond == (void *)slave)) {
+ printk(KERN_ERR
+ "bond_detach_slave(): trying to detach "
+ "slave %p from bond %p\n", bond, slave);
+ return slave;
+ }
X
+ if (bond->next == slave) { /* is the slave at the head ? */
+ if (bond->prev == slave) { /* is the slave alone ? */
+ write_lock(&bond->ptrlock);
+ bond->current_slave = NULL; /* no slave anymore */
+ write_unlock(&bond->ptrlock);
+ bond->prev = bond->next = (slave_t *)bond;
+ } else { /* not alone */
+ bond->next = slave->next;
+ slave->next->prev = (slave_t *)bond;
+ bond->prev->next = slave->next;
+
+ write_lock(&bond->ptrlock);
+ if (bond->current_slave == slave) {
+ bond->current_slave = slave->next;
+ }
+ write_unlock(&bond->ptrlock);
+ }
+ }
+ else {
+ slave->prev->next = slave->next;
+ if (bond->prev == slave) { /* is this slave the last one ? */
+ bond->prev = slave->prev;
+ } else {
+ slave->next->prev = slave->prev;
+ }
X
-static int bond_xmit(struct sk_buff *skb, struct net_device *dev);
-static struct net_device_stats *bond_get_stats(struct net_device *dev);
+ write_lock(&bond->ptrlock);
+ if (bond->current_slave == slave) {
+ bond->current_slave = slave->next;
+ }
+ write_unlock(&bond->ptrlock);
+ }
X
-static struct net_device *this_bond;
+ return slave;
+}
X
-static void release_one_slave(struct net_device *master, slave_t *slave)
+/*
+ * if <dev> supports MII link status reporting, check its link
+ * and report it as a bit field in a short int :
+ * - 0x04 means link is up,
+ * - 0x20 means end of autonegociation
+ * If the device doesn't support MII, then we only report 0x24,
+ * meaning that the link is up and running since we can't check it.
+ */
+static u16 bond_check_dev_link(struct net_device *dev)
X {
- bonding_t *bond = master->priv;
+ static int (* ioctl)(struct net_device *, struct ifreq *, int);
+ struct ifreq ifr;
+ u16 *data = (u16 *)&ifr.ifr_data;
+
+ /* data[0] automagically filled by the ioctl */
+ data[1] = 1; /* MII location 1 reports Link Status */
+
+ if (((ioctl = dev->do_ioctl) != NULL) && /* ioctl to access MII */
+ (ioctl(dev, &ifr, SIOCGMIIPHY) == 0)) {
+ /* now, data[3] contains info about link status :
+ - data[3] & 0x04 means link up
+ - data[3] & 0x20 means end of auto-negociation
+ */
+ return data[3];
+ } else {
+ return MII_LINK_READY; /* spoof link up ( we can't check it) */
+ }
+}
X
- spin_lock_bh(&master->xmit_lock);
- if (bond->current_slave == slave)
- bond->current_slave = slave->next;
- slave->next->prev = slave->prev;
- slave->prev->next = slave->next;
- spin_unlock_bh(&master->xmit_lock);
+static u16 bond_check_mii_link(bonding_t *bond)
+{
+ int has_active_interface = 0;
X
- netdev_set_master(slave->dev, NULL);
+ read_lock(&bond->ptrlock);
+ has_active_interface = (bond->current_slave != NULL);
+ read_unlock(&bond->ptrlock);
X
- dev_put(slave->dev);
- kfree(slave);
+ return (has_active_interface ? MII_LINK_READY : 0);
+}
+
+static int bond_open(struct net_device *dev)
+{
+ struct timer_list *timer = &((struct bonding *)(dev->priv))->mii_timer;
+ struct timer_list *arp_timer = &((struct bonding *)(dev->priv))->arp_timer;
+ MOD_INC_USE_COUNT;
+
+ if (miimon > 0) { /* link check interval, in milliseconds. */
+ init_timer(timer);
+ timer->expires = jiffies + (miimon * HZ / 1000);
+ timer->data = (unsigned long)dev;
+ timer->function = (void *)&bond_mii_monitor;
+ add_timer(timer);
+ }
+
+ if (arp_interval> 0) { /* arp interval, in milliseconds. */
+ init_timer(arp_timer);
+ arp_timer->expires = jiffies + (arp_interval * HZ / 1000);
+ arp_timer->data = (unsigned long)dev;
+ arp_timer->function = (void *)&bond_arp_monitor;
+ add_timer(arp_timer);
+ }


+ return 0;
X }
X

X static int bond_close(struct net_device *master)
X {
- bonding_t *bond = master->priv;
+ bonding_t *bond = (struct bonding *) master->priv;
X slave_t *slave;


+ unsigned long flags;
X

- while ((slave = bond->next) != (slave_t*)bond)
- release_one_slave(master, slave);
+ write_lock_irqsave(&bond->lock, flags);
X
+ if (miimon > 0) { /* link check interval, in milliseconds. */
+ del_timer(&bond->mii_timer);
+ }
+ if (arp_interval> 0) { /* arp interval, in milliseconds. */
+ del_timer(&bond->arp_timer);
+ }
+ /* We need to unlock this because bond_release will re-lock it */
+ write_unlock_irqrestore(&bond->lock, flags);
+
+ /* Release the bonded slaves */
+ while ((slave = bond->prev) != (slave_t *)bond) {
+ bond_release(master, slave->dev);
+ }


+
+ MOD_DEC_USE_COUNT;
X return 0;
X }
X

-static void bond_set_multicast_list(struct net_device *master)
+static void set_multicast_list(struct net_device *master)
X {
+/*
+ bonding_t *bond = master->priv;
+ slave_t *slave;
+
+ for (slave = bond->next; slave != (slave_t*)bond; slave = slave->next) {
+ slave->dev->mc_list = master->mc_list;
+ slave->dev->mc_count = master->mc_count;
+ slave->dev->flags = master->flags;
+ slave->dev->set_multicast_list(slave->dev);
+ }
+ */
X }
X
-static int bond_enslave(struct net_device *master, struct net_device *dev)
+/*
+ * This function counts the the number of attached
+ * slaves for use by bond_xmit_xor.
+ */
+static void update_slave_cnt(bonding_t *bond)
X {
- int err;
- bonding_t *bond = master->priv;
- slave_t *slave;
+ slave_t *slave = NULL;
+
+ bond->slave_cnt = 0;
+ for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev) {
+ bond->slave_cnt++;
+ }
+}
X
- if (dev->type != master->type)
+/* enslave device <slave> to bond device <master> */
+static int bond_enslave(struct net_device *master_dev,
+ struct net_device *slave_dev)
+{
+ bonding_t *bond = NULL;
+ slave_t *new_slave = NULL;
+ unsigned long flags = 0;
+ int ndx = 0;
+ int err = 0;
+
+ if (master_dev == NULL || slave_dev == NULL) {
X return -ENODEV;
+ }
+ bond = (struct bonding *) master_dev->priv;
+
+ if (slave_dev->do_ioctl == NULL) {
+ printk(KERN_DEBUG
+ "Warning : no link monitoring support for %s\n",
+ slave_dev->name);
+ }
+ write_lock_irqsave(&bond->lock, flags);
+
+ /* not running. */
+ if ((slave_dev->flags & IFF_UP) != IFF_UP) {
+#ifdef BONDING_DEBUG
+ printk(KERN_CRIT "Error, slave_dev is not running\n");
+#endif
+ write_unlock_irqrestore(&bond->lock, flags);


+ return -EINVAL;
+ }
X

- if ((slave = kmalloc(sizeof(slave_t), GFP_KERNEL)) == NULL)
+ /* already enslaved */
+ if (master_dev->flags & IFF_SLAVE || slave_dev->flags & IFF_SLAVE) {
+#ifdef BONDING_DEBUG
+ printk(KERN_CRIT "Error, Device was already enslaved\n");
+#endif
+ write_unlock_irqrestore(&bond->lock, flags);


+ return -EBUSY;
+ }
+

+ if ((new_slave = kmalloc(sizeof(slave_t), GFP_KERNEL)) == NULL) {
+ write_unlock_irqrestore(&bond->lock, flags);
X return -ENOMEM;
+ }
+ memset(new_slave, 0, sizeof(slave_t));
X
- memset(slave, 0, sizeof(slave_t));
+ err = netdev_set_master(slave_dev, master_dev);
X
- err = netdev_set_master(dev, master);
X if (err) {
- kfree(slave);
- return err;
+#ifdef BONDING_DEBUG
+ printk(KERN_CRIT "Error %d calling netdev_set_master\n", err);
+#endif
+ kfree(new_slave);
+ write_unlock_irqrestore(&bond->lock, flags);


+ return err;
X }
X

- slave->dev = dev;
+ new_slave->dev = slave_dev;
X
- spin_lock_bh(&master->xmit_lock);
+ /*
+ * queue to the end of the slaves list, make the first element its
+ * successor, the last one its predecessor, and make it the bond's
+ * predecessor.
+ */
+ new_slave->prev = bond->prev;
+ new_slave->prev->next = new_slave;
+ bond->prev = new_slave;
+ new_slave->next = bond->next;
+
+ new_slave->delay = 0;
+ new_slave->link_failure_count = 0;
+
+ /* check for initial state */
+ if ((miimon <= 0) || ((bond_check_dev_link(slave_dev) & MII_LINK_READY)
+ == MII_LINK_READY)) {
+#ifdef BONDING_DEBUG
+ printk(KERN_CRIT "Initial state of slave_dev is BOND_LINK_UP\n");
+#endif
+ new_slave->link = BOND_LINK_UP;
+ }
+ else {
+#ifdef BONDING_DEBUG
+ printk(KERN_CRIT "Initial state of slave_dev is BOND_LINK_DOWN\n");
+#endif
+ new_slave->link = BOND_LINK_DOWN;
+ }
X
- dev_hold(dev);
+ /* if we're in active-backup mode, we need one and only one active
+ * interface. The backup interfaces will have their NOARP flag set
+ * because we need them to be completely deaf and not to respond to
+ * any ARP request on the network to avoid fooling a switch. Thus,
+ * since we guarantee that current_slave always point to the last
+ * usable interface, we just have to verify this interface's flag.
+ */
+ if (mode == BOND_MODE_ACTIVEBACKUP) {
+ if (((bond->current_slave == NULL)
+ || (bond->current_slave->dev->flags & IFF_NOARP))
+ && (new_slave->link == BOND_LINK_UP)) {
+#ifdef BONDING_DEBUG
+ printk(KERN_CRIT "This is the first active slave\n");
+#endif
+ /* first slave or no active slave yet, and this link
+ is OK, so make this interface the active one */
+ bond->current_slave = new_slave;
+ bond_set_slave_active_flags(new_slave);
+ }
+ else {
+#ifdef BONDING_DEBUG
+ printk(KERN_CRIT "This is just a backup slave\n");
+#endif
+ bond_set_slave_inactive_flags(new_slave);
+ }
+ } else {
+#ifdef BONDING_DEBUG
+ printk(KERN_CRIT "This slave is always active in trunk mode\n");
+#endif
+ /* always active in trunk mode */
+ new_slave->state = BOND_STATE_ACTIVE;
+ if (bond->current_slave == NULL) {
+ bond->current_slave = new_slave;
+ }
+ }
+
+ update_slave_cnt(bond);
X
- slave->prev = bond->prev;
- slave->next = (slave_t*)bond;
- slave->prev->next = slave;
- slave->next->prev = slave;
+ write_unlock_irqrestore(&bond->lock, flags);
+
+ /*
+ * !!! This is to support old versions of ifenslave. We can remove
+ * this in 2.5 because our ifenslave takes care of this for us.
+ * We check to see if the master has a mac address yet. If not,
+ * we'll give it the mac address of our slave device.
+ */
+ for (ndx = 0; ndx < slave_dev->addr_len; ndx++) {
+#ifdef BONDING_DEBUG
+ printk(KERN_CRIT "Checking ndx=%d of master_dev->dev_addr\n",
+ ndx);
+#endif
+ if (master_dev->dev_addr[ndx] != 0) {
+#ifdef BONDING_DEBUG
+ printk(KERN_CRIT "Found non-zero byte at ndx=%d\n",
+ ndx);
+#endif
+ break;
+ }
+ }
+ if (ndx == slave_dev->addr_len) {
+ /*
+ * We got all the way through the address and it was
+ * all 0's.
+ */
+#ifdef BONDING_DEBUG
+ printk(KERN_CRIT "%s doesn't have a MAC address yet. ",
+ master_dev->name);
+ printk(KERN_CRIT "Going to give assign it from %s.\n",
+ slave_dev->name);
+#endif
+ bond_sethwaddr(master_dev, slave_dev);
+ }
X
- spin_unlock_bh(&master->xmit_lock);
+ printk (KERN_INFO "%s: enslaving %s as a%s interface with a%s link.\n",
+ master_dev->name, slave_dev->name,
+ new_slave->state == BOND_STATE_ACTIVE ? "n active" : " backup",
+ new_slave->link == BOND_LINK_UP ? "n up" : " down");
X

X return 0;
X }
X

-static int bond_release(struct net_device *master, struct net_device *dev)
+/*
+ * This function changes the active slave to slave <slave_dev>.
+ * It returns -EINVAL in the following cases.
+ * - <slave_dev> is not found in the list.
+ * - There is not active slave now.
+ * - <slave_dev> is already active.
+ * - The link state of <slave_dev> is not BOND_LINK_UP.
+ * - <slave_dev> is not running.
+ * In these cases, this fuction does nothing.
+ * In the other cases, currnt_slave pointer is changed and 0 is returned.
+ */
+static int bond_change_active(struct net_device *master_dev, struct net_device *slave_dev)
X {
- bonding_t *bond = master->priv;
+ bonding_t *bond;
X slave_t *slave;
+ slave_t *oldactive = NULL;
+ slave_t *newactive = NULL;
+ unsigned long flags;
+ int ret = 0;
X
- if (dev->master != master)
+ if (master_dev == NULL || slave_dev == NULL) {


+ return -ENODEV;
+ }
+

+ bond = (struct bonding *) master_dev->priv;
+ write_lock_irqsave(&bond->lock, flags);
+ slave = (slave_t *)bond;
+ oldactive = bond->current_slave;
+
+ while ((slave = slave->prev) != (slave_t *)bond) {
+ if(slave_dev == slave->dev) {
+ newactive = slave;


+ break;
+ }
+ }
+

+ if ((newactive != NULL)&&
+ (oldactive != NULL)&&
+ (newactive != oldactive)&&
+ (newactive->link == BOND_LINK_UP)&&
+ IS_UP(newactive->dev)) {
+ bond_set_slave_inactive_flags(oldactive);
+ bond_set_slave_active_flags(newactive);
+ bond->current_slave = newactive;
+ printk("%s : activate %s(old : %s)\n",
+ master_dev->name, newactive->dev->name,
+ oldactive->dev->name);
+ }
+ else {


+ ret = -EINVAL;
+ }

+ write_unlock_irqrestore(&bond->lock, flags);


+ return ret;
+}
+

+/* Choose a new valid interface from the pool, set it active
+ * and make it the current slave. If no valid interface is
+ * found, the oldest slave in BACK state is choosen and
+ * activated. If none is found, it's considered as no
+ * interfaces left so the current slave is set to NULL.
+ * The result is a pointer to the current slave.
+ *
+ * Since this function sends messages tails through printk, the caller
+ * must have started something like `printk(KERN_INFO "xxxx ");'.
+ *
+ * Warning: must put locks around the call to this function if needed.
+ */
+slave_t *change_active_interface(bonding_t *bond)
+{
+ slave_t *newslave, *oldslave;
+ slave_t *bestslave = NULL;
+ int mintime;
+
+ read_lock(&bond->ptrlock);
+ newslave = oldslave = bond->current_slave;
+ read_unlock(&bond->ptrlock);
+
+ if (newslave == NULL) { /* there were no active slaves left */
+ if (bond->next != (slave_t *)bond) { /* found one slave */
+ write_lock(&bond->ptrlock);
+ newslave = bond->current_slave = bond->next;
+ write_unlock(&bond->ptrlock);
+ } else {
+ printk (" but could not find any %s interface.\n",
+ (mode == BOND_MODE_ACTIVEBACKUP) ? "backup":"other");
+ write_lock(&bond->ptrlock);
+ bond->current_slave = (slave_t *)NULL;
+ write_unlock(&bond->ptrlock);
+ return NULL; /* still no slave, return NULL */
+ }
+ }
+
+ mintime = updelay;
+
+ do {
+ if (IS_UP(newslave->dev)) {
+ if (newslave->link == BOND_LINK_UP) {
+ /* this one is immediately usable */
+ if (mode == BOND_MODE_ACTIVEBACKUP) {
+ bond_set_slave_active_flags(newslave);
+ printk (" and making interface %s the active one.\n",
+ newslave->dev->name);
+ }
+ else {
+ printk (" and setting pointer to interface %s.\n",
+ newslave->dev->name);
+ }
+
+ write_lock(&bond->ptrlock);
+ bond->current_slave = newslave;
+ write_unlock(&bond->ptrlock);
+ return newslave;
+ }
+ else if (newslave->link == BOND_LINK_BACK) {
+ /* link up, but waiting for stabilization */
+ if (newslave->delay < mintime) {
+ mintime = newslave->delay;
+ bestslave = newslave;
+ }
+ }
+ }
+ } while ((newslave = newslave->next) != oldslave);
+
+ /* no usable backup found, we'll see if we at least got a link that was
+ coming back for a long time, and could possibly already be usable.
+ */
+
+ if (bestslave != NULL) {
+ /* early take-over. */
+ printk (" and making interface %s the active one %d ms earlier.\n",
+ bestslave->dev->name,
+ (updelay - bestslave->delay)*miimon);
+
+ bestslave->delay = 0;
+ bestslave->link = BOND_LINK_UP;
+ bond_set_slave_active_flags(bestslave);
+
+ write_lock(&bond->ptrlock);
+ bond->current_slave = bestslave;
+ write_unlock(&bond->ptrlock);
+ return bestslave;
+ }
+
+ printk (" but could not find any %s interface.\n",
+ (mode == BOND_MODE_ACTIVEBACKUP) ? "backup":"other");
+
+ /* absolutely nothing found. let's return NULL */
+ write_lock(&bond->ptrlock);
+ bond->current_slave = (slave_t *)NULL;
+ write_unlock(&bond->ptrlock);


+ return NULL;
+}
+

+/*
+ * Try to release the slave device <slave> from the bond device <master>
+ * It is legal to access current_slave without a lock because all the function
+ * is write-locked.
+ *
+ * The rules for slave state should be:
+ * for Active/Backup:
+ * Active stays on all backups go down
+ * for Bonded connections:
+ * The first up interface should be left on and all others downed.
+ */
+static int bond_release(struct net_device *master, struct net_device *slave)
+{
+ bonding_t *bond;
+ slave_t *our_slave, *old_current;


+ unsigned long flags;
+

+ if (master == NULL || slave == NULL) {


+ return -ENODEV;
+ }
+

+ bond = (struct bonding *) master->priv;
+
+ write_lock_irqsave(&bond->lock, flags);
+
+ /* master already enslaved, or slave not enslaved,
+ or no slave for this master */
+ if ((master->flags & IFF_SLAVE) || !(slave->flags & IFF_SLAVE)) {
+ printk (KERN_DEBUG "%s: cannot release %s.\n", master->name, slave->name);
+ write_unlock_irqrestore(&bond->lock, flags);
X return -EINVAL;
+ }
X
- for (slave = bond->next; slave != (slave_t*)bond; slave = slave->next) {
- if (slave->dev == dev) {
- release_one_slave(master, slave);
+ our_slave = (slave_t *)bond;
+ old_current = bond->current_slave;
+ while ((our_slave = our_slave->prev) != (slave_t *)bond) {
+ if (our_slave->dev == slave) {
+ bond_detach_slave(bond, our_slave);
+
+ printk (KERN_INFO "%s: releasing %s interface %s",
+ master->name,
+ (our_slave->state == BOND_STATE_ACTIVE) ? "active" : "backup",
+ slave->name);
+
+ if (our_slave == old_current) {
+ /* find a new interface and be verbose */
+ change_active_interface(bond);
+ } else {
+ printk(".\n");
+ }
+ kfree(our_slave);
+
+ /* release the slave from its bond */
+
+ netdev_set_master(slave, NULL);
+
+ /* only restore its RUNNING flag if monitoring set it down */
+ if (slave->flags & IFF_UP) {
+ slave->flags |= IFF_RUNNING;
+ }
+
+ if (slave->flags & IFF_NOARP ||
+ bond->current_slave != NULL) {
+ dev_close(slave);
+ }
+
+ if (bond->current_slave == NULL) {
+ printk(KERN_INFO
+ "%s: now running without any active interface !\n",
+ master->name);
+ }
+
+ update_slave_cnt(bond);
+
+ write_unlock_irqrestore(&bond->lock, flags);
+ return 0; /* deletion OK */
+ }
+ }
+
+ /* if we get here, it's because the device was not found */
+ write_unlock_irqrestore(&bond->lock, flags);
+
+ printk (KERN_INFO "%s: %s not enslaved\n", master->name, slave->name);


+ return -EINVAL;
+}
+

+/* this function is called regularly to monitor each slave's link. */
+static void bond_mii_monitor(struct net_device *master)
+{
+ bonding_t *bond = (struct bonding *) master->priv;
+ slave_t *slave, *bestslave, *oldcurrent;
+ unsigned long flags;
+ int slave_died = 0;
+
+ read_lock_irqsave(&bond->lock, flags);
+
+ if (rtnl_shlock_nowait()) {
+ goto monitor_out;
+ }
+
+ if (rtnl_exlock_nowait()) {
+ rtnl_shunlock();
+ goto monitor_out;
+ }
+ /* we will try to read the link status of each of our slaves, and
+ * set their IFF_RUNNING flag appropriately. For each slave not
+ * supporting MII status, we won't do anything so that a user-space
+ * program could monitor the link itself if needed.
+ */
+
+ bestslave = NULL;
+ slave = (slave_t *)bond;
+
+ read_lock(&bond->ptrlock);
+ oldcurrent = bond->current_slave;
+ read_unlock(&bond->ptrlock);
+
+ while ((slave = slave->prev) != (slave_t *)bond) {
+ /* use updelay+1 to match an UP slave even when updelay is 0 */
+ int mindelay = updelay + 1;
+ struct net_device *dev = slave->dev;
+ u16 link_state;
+
+ link_state = bond_check_dev_link(dev);
+
+ switch (slave->link) {
+ case BOND_LINK_UP: /* the link was up */
+ if ((link_state & MII_LINK_UP) == MII_LINK_UP) {
+ /* link stays up, tell that this one
+ is immediately available */
+ if (IS_UP(dev) && (mindelay > -2)) {
+ /* -2 is the best case :
+ this slave was already up */
+ mindelay = -2;
+ bestslave = slave;
+ }
+ break;
+ }
+ else { /* link going down */
+ slave->link = BOND_LINK_FAIL;
+ slave->delay = downdelay;
+ if (slave->link_failure_count < UINT_MAX) {
+ slave->link_failure_count++;
+ }
+ if (downdelay > 0) {
+ printk (KERN_INFO
+ "%s: link status down for %sinterface "
+ "%s, disabling it in %d ms.\n",
+ master->name,
+ IS_UP(dev)
+ ? ((mode == BOND_MODE_ACTIVEBACKUP)
+ ? ((slave == oldcurrent)
+ ? "active " : "backup ")
+ : "")
+ : "idle ",
+ dev->name,
+ downdelay * miimon);
+ }
+ }
+ /* no break ! fall through the BOND_LINK_FAIL test to
+ ensure proper action to be taken
+ */
+ case BOND_LINK_FAIL: /* the link has just gone down */
+ if ((link_state & MII_LINK_UP) == 0) {
+ /* link stays down */
+ if (slave->delay <= 0) {
+ /* link down for too long time */
+ slave->link = BOND_LINK_DOWN;
+ /* in active/backup mode, we must
+ completely disable this interface */
+ if (mode == BOND_MODE_ACTIVEBACKUP) {
+ bond_set_slave_inactive_flags(slave);
+ }
+ printk(KERN_INFO
+ "%s: link status definitely down "
+ "for interface %s, disabling it",
+ master->name,
+ dev->name);
+
+ read_lock(&bond->ptrlock);
+ if (slave == bond->current_slave) {
+ read_unlock(&bond->ptrlock);
+ /* find a new interface and be verbose */
+ change_active_interface(bond);
+ } else {
+ read_unlock(&bond->ptrlock);
+ printk(".\n");
+ }
+ slave_died = 1;
+ } else {
+ slave->delay--;
+ }
+ } else if ((link_state & MII_LINK_READY) == MII_LINK_READY) {
+ /* link up again */
+ slave->link = BOND_LINK_UP;
+ printk(KERN_INFO
+ "%s: link status up again after %d ms "
+ "for interface %s.\n",
+ master->name,
+ (downdelay - slave->delay) * miimon,
+ dev->name);
+
+ if (IS_UP(dev) && (mindelay > -1)) {
+ /* -1 is a good case : this slave went
+ down only for a short time */
+ mindelay = -1;
+ bestslave = slave;
+ }
+ }
X break;
+ case BOND_LINK_DOWN: /* the link was down */
+ if ((link_state & MII_LINK_READY) != MII_LINK_READY) {
+ /* the link stays down, nothing more to do */
+ break;
+ } else { /* link going up */
+ slave->link = BOND_LINK_BACK;
+ slave->delay = updelay;
+
+ if (updelay > 0) {
+ /* if updelay == 0, no need to
+ advertise about a 0 ms delay */
+ printk (KERN_INFO
+ "%s: link status up for interface"
+ " %s, enabling it in %d ms.\n",
+ master->name,
+ dev->name,
+ updelay * miimon);
+ }
+ }
+ /* no break ! fall through the BOND_LINK_BACK state in
+ case there's something to do.
+ */
+ case BOND_LINK_BACK: /* the link has just come back */
+ if ((link_state & MII_LINK_UP) == 0) {
+ /* link down again */
+ slave->link = BOND_LINK_DOWN;
+ printk(KERN_INFO
+ "%s: link status down again after %d ms "
+ "for interface %s.\n",
+ master->name,
+ (updelay - slave->delay) * miimon,
+ dev->name);
+ }
+ else if ((link_state & MII_LINK_READY) == MII_LINK_READY) {
+ /* link stays up */
+ if (slave->delay == 0) {
+ /* now the link has been up for long time enough */
+ slave->link = BOND_LINK_UP;
+
+ if (mode == BOND_MODE_ACTIVEBACKUP) {
+ /* prevent it from being the active one */
+ slave->state = BOND_STATE_BACKUP;
+ }
+ else {
+ /* make it immediately active */
+ slave->state = BOND_STATE_ACTIVE;
+ }
+
+ printk(KERN_INFO
+ "%s: link status definitely up "
+ "for interface %s.\n",
+ master->name,
+ dev->name);
+ }
+ else
+ slave->delay--;
+
+ /* we'll also look for the mostly eligible slave */
+ if (IS_UP(dev) && (slave->delay < mindelay)) {
+ mindelay = slave->delay;
+ bestslave = slave;
+ }
+ }
+ break;
+ } /* end of switch */
+ } /* end of while */
+
+ /* if there's no active interface and we discovered that one
+ of the slaves could be activated earlier, so we do it.
+ */
+ read_lock(&bond->ptrlock);
+ oldcurrent = bond->current_slave;
+ read_unlock(&bond->ptrlock);
+
+ if (oldcurrent == NULL) { /* no active interface at the moment */
+ if (bestslave != NULL) { /* last chance to find one ? */
+ if (bestslave->link == BOND_LINK_UP) {
+ printk (KERN_INFO
+ "%s: making interface %s the new active one.\n",
+ master->name, bestslave->dev->name);
+ } else {
+ printk (KERN_INFO
+ "%s: making interface %s the new "
+ "active one %d ms earlier.\n",
+ master->name, bestslave->dev->name,
+ (updelay - bestslave->delay) * miimon);
+
+ bestslave->delay= 0;
+ bestslave->link = BOND_LINK_UP;
+ }
+
+ if (mode == BOND_MODE_ACTIVEBACKUP) {
+ bond_set_slave_active_flags(bestslave);
+ } else {
+ bestslave->state = BOND_STATE_ACTIVE;
+ }
+ write_lock(&bond->ptrlock);
+ bond->current_slave = bestslave;
+ write_unlock(&bond->ptrlock);
+ } else if (slave_died) {
+ /* print this message only once a slave has just died */
+ printk(KERN_INFO
+ "%s: now running without any active interface !\n",
+ master->name);
X }
X }
X
- return 0;
+ rtnl_exunlock();
+ rtnl_shunlock();
+monitor_out:
+ read_unlock_irqrestore(&bond->lock, flags);
+ /* re-arm the timer */
+ mod_timer(&bond->mii_timer, jiffies + (miimon * HZ / 1000));
X }
X
-/* It is pretty silly, SIOCSIFHWADDR exists to make this. */
+/*
+ * this function is called regularly to monitor each slave's link
+ * insuring that traffic is being sent and received. If the adapter
+ * has been dormant, then an arp is transmitted to generate traffic
+ */
+static void bond_arp_monitor(struct net_device *master)
+{
+ bonding_t *bond;
+ unsigned long flags;
+ slave_t *slave;
+ int the_delta_in_ticks = arp_interval * HZ / 1000;
+ int next_timer = jiffies + (arp_interval * HZ / 1000);
+
+ bond = (struct bonding *) master->priv;
+ if (master->priv == NULL) {
+ mod_timer(&bond->arp_timer, next_timer);
+ return;
+ }
+
+ read_lock_irqsave(&bond->lock, flags);
+
+ if (!IS_UP(master)) {
+ mod_timer(&bond->arp_timer, next_timer);
+ goto monitor_out;
+ }
+
+
+ if (rtnl_shlock_nowait()) {
+ goto monitor_out;
+ }
+
+ if (rtnl_exlock_nowait()) {
+ rtnl_shunlock();
+ goto monitor_out;
+ }
+
+ /* see if any of the previous devices are up now (i.e. they have seen a
+ * response from an arp request sent by another adapter, since they
+ * have the same hardware address).
+ */
+
+ slave = (slave_t *)bond;
+ while ((slave = slave->prev) != (slave_t *)bond) {
+
+ read_lock(&bond->ptrlock);
+ if ( (!(slave->link == BOND_LINK_UP))
+ && (slave!= bond->current_slave) ) {
+
+ read_unlock(&bond->ptrlock);
+
+ if ( ((jiffies - slave->dev->trans_start) <=
+ the_delta_in_ticks) &&
+ ((jiffies - slave->dev->last_rx) <=
+ the_delta_in_ticks) ) {
+
+ slave->link = BOND_LINK_UP;
+ write_lock(&bond->ptrlock);
+ if (bond->current_slave == NULL) {
+ slave->state = BOND_STATE_ACTIVE;
+ bond->current_slave = slave;
+ }
+ if (slave!=bond->current_slave) {
+ slave->dev->flags |= IFF_NOARP;
+ }
+ write_unlock(&bond->ptrlock);
+ } else {
+ if ((jiffies - slave->dev->last_rx) <=
+ the_delta_in_ticks) {
+ arp_send(ARPOP_REQUEST, ETH_P_ARP,
+ arp_target, slave->dev,
+ my_ip, arp_target_hw_addr,
+ slave->dev->dev_addr,
+ arp_target_hw_addr);
+ }
+ }
+ } else
+ read_unlock(&bond->ptrlock);
+ }
+
+ read_lock(&bond->ptrlock);
+ slave = bond->current_slave;
+ read_unlock(&bond->ptrlock);
+
+ if (slave != 0) {
+
+ /* see if you need to take down the current_slave, since
+ * you haven't seen an arp in 2*arp_intervals
+ */
+
+ if ( ((jiffies - slave->dev->trans_start) >=
+ (2*the_delta_in_ticks)) ||
+ ((jiffies - slave->dev->last_rx) >=
+ (2*the_delta_in_ticks)) ) {
+
+ if (slave->link == BOND_LINK_UP) {
+ slave->link = BOND_LINK_DOWN;
+ slave->state = BOND_STATE_BACKUP;
+ /*
+ * we want to see arps, otherwise we couldn't
+ * bring the adapter back online...
+ */
+ printk(KERN_INFO "%s: link status definitely "
+ "down for interface %s, "
+ "disabling it",
+ slave->dev->master->name,
+ slave->dev->name);
+ /* find a new interface and be verbose */
+ change_active_interface(bond);
+ read_lock(&bond->ptrlock);
+ slave = bond->current_slave;
+ read_unlock(&bond->ptrlock);
+ }
+ }
+
+ /*
+ * ok, we know up/down, so just send a arp out if there has
+ * been no activity for a while
+ */
+
+ if (slave != NULL ) {
+ if ( ((jiffies - slave->dev->trans_start) >=
+ the_delta_in_ticks) ||
+ ((jiffies - slave->dev->last_rx) >=
+ the_delta_in_ticks) ) {
+ arp_send(ARPOP_REQUEST, ETH_P_ARP,
+ arp_target, slave->dev,
+ my_ip, arp_target_hw_addr,
+ slave->dev->dev_addr,
+ arp_target_hw_addr);

+ }
+ }
+
+ }
+

+ /* if we have no current slave.. try sending
+ * an arp on all of the interfaces
+ */
+
+ if (bond->current_slave == NULL) {
+ slave = (slave_t *)bond;
+ while ((slave = slave->prev) != (slave_t *)bond) {
+ arp_send(ARPOP_REQUEST, ETH_P_ARP, arp_target,
+ slave->dev, my_ip, arp_target_hw_addr,
+ slave->dev->dev_addr, arp_target_hw_addr);
+ }
+ }
+
+ rtnl_exunlock();
+ rtnl_shunlock();
+
+monitor_out:
+ read_unlock_irqrestore(&bond->lock, flags);
+
+ /* re-arm the timer */
+ mod_timer(&bond->arp_timer, next_timer);
+}
+
+#define isdigit(c) (c >= '0' && c <= '9')
+__inline static int atoi( char **s)
+{
+int i=0;
+while (isdigit(**s))
+ i = i*20 + *((*s)++) - '0';
+return i;
+}
+
+#define isascii(c) (((unsigned char)(c))<=0x7f)
+#define LF 0xA
+#define isspace(c) (c==' ' || c==' '|| c==LF)
+typedef uint32_t in_addr_t;
+
+int
+my_inet_aton(char *cp, unsigned long *the_addr) {
+ static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
+ in_addr_t val;
+ char c;
+ union iaddr {
+ uint8_t bytes[4];
+ uint32_t word;
+ } res;
+ uint8_t *pp = res.bytes;
+ int digit,base;
+
+ res.word = 0;
+
+ c = *cp;
+ for (;;) {
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, isdigit=decimal.
+ */
+ if (!isdigit(c)) goto ret_0;
+ val = 0; base = 10; digit = 0;
+ for (;;) {
+ if (isdigit(c)) {
+ val = (val * base) + (c - '0');
+ c = *++cp;
+ digit = 1;
+ } else {
+ break;
+ }
+ }
+ if (c == '.') {
+ /*
+ * Internet format:
+ * a.b.c.d
+ * a.b.c (with c treated as 16 bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp > res.bytes + 2 || val > 0xff) {
+ goto ret_0;
+ }
+ *pp++ = val;
+ c = *++cp;
+ } else
+ break;
+ }
+ /*
+ * Check for trailing characters.
+ */
+ if (c != '\0' && (!isascii(c) || !isspace(c))) {
+ goto ret_0;
+ }
+ /*
+ * Did we get a valid digit?
+ */
+ if (!digit) {
+ goto ret_0;
+ }
+
+ /* Check whether the last part is in its limits depending on
+ the number of parts in total. */
+ if (val > max[pp - res.bytes]) {
+ goto ret_0;
+ }
+
+ if (the_addr!= NULL) {
+ *the_addr = res.word | htonl (val);
+ }
+
+ return (1);
+
+ret_0:
+ return (0);
+}
X
X static int bond_sethwaddr(struct net_device *master, struct net_device *slave)
X {
+#ifdef BONDING_DEBUG
+ printk(KERN_CRIT "bond_sethwaddr: master=%x\n", (unsigned int)master);
+ printk(KERN_CRIT "bond_sethwaddr: slave=%x\n", (unsigned int)slave);
+ printk(KERN_CRIT "bond_sethwaddr: slave->addr_len=%d\n", slave->addr_len);
+#endif
X memcpy(master->dev_addr, slave->dev_addr, slave->addr_len);


X return 0;
X }
X

-static int bond_ioctl(struct net_device *master, struct ifreq *ifr, int cmd)
+static int bond_info_query(struct net_device *master, struct ifbond *info)
X {
- struct net_device *slave = __dev_get_by_name(ifr->ifr_slave);
+ bonding_t *bond = (struct bonding *) master->priv;
+ slave_t *slave;
+
+ info->bond_mode = mode;
+ info->num_slaves = 0;
+ info->miimon = miimon;
+
+ read_lock(&bond->ptrlock);
+ for (slave = bond->prev; slave!=(slave_t *)bond; slave = slave->prev) {
+ info->num_slaves++;
+ }
+ read_unlock(&bond->ptrlock);


+
+ return 0;
+}

X
- if (slave == NULL)
+static int bond_slave_info_query(struct net_device *master,
+ struct ifslave *info)
+{
+ bonding_t *bond = (struct bonding *) master->priv;
+ slave_t *slave;
+ int cur_ndx = 0;
+
+ if (info->slave_id < 0) {
X return -ENODEV;
+ }
X
- switch (cmd) {
- case BOND_ENSLAVE:
- return bond_enslave(master, slave);
- case BOND_RELEASE:
- return bond_release(master, slave);
- case BOND_SETHWADDR:
- return bond_sethwaddr(master, slave);
- default:
- return -EOPNOTSUPP;
+ read_lock(&bond->ptrlock);
+ for (slave = bond->prev;
+ slave != (slave_t *)bond && cur_ndx < info->slave_id;
+ slave = slave->prev) {
+ cur_ndx++;
X }
+ if (cur_ndx == info->slave_id) {
+ strcpy(info->slave_name, slave->dev->name);
+ info->link = slave->link;
+ info->state = slave->state;
+ info->link_failure_count = slave->link_failure_count;
+ } else {
+ read_unlock(&bond->ptrlock);
+ return -ENODEV;
+ }
+ read_unlock(&bond->ptrlock);
+


+ return 0;
X }
X

-static int bond_event(struct notifier_block *this, unsigned long event, void *ptr)
+static int bond_ioctl(struct net_device *master_dev, struct ifreq *ifr, int cmd)
X {
- struct net_device *slave = ptr;
+ struct net_device *slave_dev = NULL;
+ struct ifbond *u_binfo = NULL, k_binfo;
+ struct ifslave *u_sinfo = NULL, k_sinfo;
+ u16 *data = NULL;
+ int ret = 0;
+
+#ifdef BONDING_DEBUG
+ printk(KERN_INFO "bond_ioctl: master=%s, cmd=%d\n",
+ master_dev->name, cmd);
+#endif
+
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ data = (u16 *)&ifr->ifr_data;
+ if (data == NULL) {
+ return -EINVAL;
+ }
+ data[0] = 0;
+ /* Fall Through */
+ case SIOCGMIIREG:
+ /*
+ * We do this again just in case we were called by SIOCGMIIREG
+ * instead of SIOCGMIIPHY.
+ */
+ data = (u16 *)&ifr->ifr_data;
+ if (data == NULL) {
+ return -EINVAL;
+ }
+ if (data[1] == 1) {
+ data[3] = bond_check_mii_link(
+ (struct bonding *)master_dev->priv);
+ }
+ return 0;
+ case BOND_INFO_QUERY_OLD:
+ case SIOCBONDINFOQUERY:
+ u_binfo = (struct ifbond *)ifr->ifr_data;
+ if (copy_from_user(&k_binfo, u_binfo, sizeof(ifbond))) {
+ return -EFAULT;
+ }
+ ret = bond_info_query(master_dev, &k_binfo);
+ if (ret == 0) {
+ if (copy_to_user(u_binfo, &k_binfo, sizeof(ifbond))) {


+ return -EFAULT;
+ }
+ }

+ return ret;
+ case BOND_SLAVE_INFO_QUERY_OLD:
+ case SIOCBONDSLAVEINFOQUERY:
+ u_sinfo = (struct ifslave *)ifr->ifr_data;
+ if (copy_from_user(&k_sinfo, u_sinfo, sizeof(ifslave))) {
+ return -EFAULT;
+ }
+ ret = bond_slave_info_query(master_dev, &k_sinfo);
+ if (ret == 0) {
+ if (copy_to_user(u_sinfo, &k_sinfo, sizeof(ifslave))) {


+ return -EFAULT;
+ }
+ }

+ return ret;
+ }
X
- if (this_bond == NULL ||
- this_bond == slave ||
- this_bond != slave->master)
- return NOTIFY_DONE;
+ if (!capable(CAP_NET_ADMIN)) {


+ return -EPERM;
+ }
X

- switch (event) {
- case NETDEV_UNREGISTER:
- bond_release(this_bond, slave);
+ slave_dev = dev_get_by_name(ifr->ifr_slave);
+#ifdef BONDING_DEBUG
+ printk(KERN_INFO "slave_dev=%x: \n", (unsigned int)slave_dev);
+ printk(KERN_INFO "slave_dev->name=%s: \n", slave_dev->name);
+#endif
+ switch (cmd) {
+ case BOND_ENSLAVE_OLD:
+ case SIOCBONDENSLAVE:
+ ret = bond_enslave(master_dev, slave_dev);
+ break;
+ case BOND_RELEASE_OLD:
+ case SIOCBONDRELEASE:
+ ret = bond_release(master_dev, slave_dev);
X break;
+ case BOND_SETHWADDR_OLD:
+ case SIOCBONDSETHWADDR:
+ ret = bond_sethwaddr(master_dev, slave_dev);
+ break;
+ case BOND_CHANGE_ACTIVE_OLD:
+ case SIOCBONDCHANGEACTIVE:
+ if (mode == BOND_MODE_ACTIVEBACKUP) {
+ ret = bond_change_active(master_dev, slave_dev);
+ }
+ else {


+ ret = -EINVAL;
+ }

+ break;
+ default:
+ ret = -EOPNOTSUPP;
X }
X
- return NOTIFY_DONE;
+ if (slave_dev) {
+ /*
+ * Clear the module reference that was added by dev_get_by_name
+ */
+ dev_put(slave_dev);
+ }


+ return ret;
X }
X

-static struct notifier_block bond_netdev_notifier={
- notifier_call: bond_event
-};
+#ifdef CONFIG_NET_FASTROUTE
+static int bond_accept_fastpath(struct net_device *dev, struct dst_entry *dst)


+{
+ return -1;
+}

+#endif
X
-static int __init bond_init(struct net_device *dev)
+static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *dev)
X {
- bonding_t *bond;
+ slave_t *slave, *start_at;
+ struct bonding *bond = (struct bonding *) dev->priv;


+ unsigned long flags;
X

- bond = kmalloc(sizeof(struct bonding), GFP_KERNEL);
- if (bond == NULL)
- return -ENOMEM;
+ if (!IS_UP(dev)) { /* bond down */
+ dev_kfree_skb(skb);


+ return 0;
+ }
X

- memset(bond, 0, sizeof(struct bonding));
- bond->next = (slave_t*)bond;
- bond->prev = (slave_t*)bond;
- bond->master = dev;
- bond->current_slave = (slave_t*)bond;
- dev->priv = bond;
+ read_lock_irqsave(&bond->lock, flags);
X
- /* Initialize the device structure. */
- dev->hard_start_xmit = bond_xmit;
- dev->get_stats = bond_get_stats;
- dev->stop = bond_close;
- dev->set_multicast_list = bond_set_multicast_list;
- dev->do_ioctl = bond_ioctl;
+ read_lock(&bond->ptrlock);
+ slave = start_at = bond->current_slave;
+ read_unlock(&bond->ptrlock);
X
- /* Fill in the fields of the device structure with ethernet-generic
- values. */
- ether_setup(dev);
- dev->tx_queue_len = 0;
- dev->flags |= IFF_MASTER;
+ if (slave == NULL) { /* we're at the root, get the first slave */
+ /* no suitable interface, frame not sent */
+ dev_kfree_skb(skb);
+ read_unlock_irqrestore(&bond->lock, flags);
+ return 0;
+ }
X
- this_bond = dev;
+ do {
+ if (IS_UP(slave->dev)
+ && (slave->link == BOND_LINK_UP)
+ && (slave->state == BOND_STATE_ACTIVE)) {
+
+ skb->dev = slave->dev;
+ skb->priority = 1;
+ dev_queue_xmit(skb);
X
- register_netdevice_notifier(&bond_netdev_notifier);
+ write_lock(&bond->ptrlock);
+ bond->current_slave = slave->next;
+ write_unlock(&bond->ptrlock);
X
+ read_unlock_irqrestore(&bond->lock, flags);
+ return 0;
+ }
+ } while ((slave = slave->next) != start_at);
+
+ /* no suitable interface, frame not sent */
+ dev_kfree_skb(skb);
+ read_unlock_irqrestore(&bond->lock, flags);


X return 0;
X }
X

-static int bond_xmit(struct sk_buff *skb, struct net_device *dev)
+/*
+ * in XOR mode, we determine the output device by performing xor on
+ * the source and destination hw adresses. If this device is not
+ * enabled, find the next slave following this xor slave.
+ */
+static int bond_xmit_xor(struct sk_buff *skb, struct net_device *dev)
X {
- bonding_t *bond = dev->priv;
X slave_t *slave, *start_at;
- int pkt_len = skb->len;
+ struct bonding *bond = (struct bonding *) dev->priv;
+ unsigned long flags;
+ struct ethhdr *data = (struct ethhdr *)skb->data;
+ int slave_no;
+
+ if (!IS_UP(dev)) { /* bond down */
+ dev_kfree_skb(skb);


+ return 0;
+ }
X

- slave = start_at = bond->current_slave;
+ read_lock_irqsave(&bond->lock, flags);
+ read_lock(&bond->ptrlock);
+ slave = bond->prev;
+
+ /* we're at the root, get the first slave */
+ if ((slave == NULL) || (slave->dev == NULL)) {
+ /* no suitable interface, frame not sent */
+ read_unlock(&bond->ptrlock);
+ dev_kfree_skb(skb);
+ read_unlock_irqrestore(&bond->lock, flags);


+ return 0;
+ }
+

+ slave_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % bond->slave_cnt;
+
+ read_unlock(&bond->ptrlock);
+
+ while ( (slave_no > 0) && (slave != (slave_t *)bond) ) {
+ slave = slave->prev;
+ slave_no--;
+ }
+ start_at = slave;
X
X do {
- if (slave == (slave_t*)bond)
- continue;
+ if (IS_UP(slave->dev)
+ && (slave->link == BOND_LINK_UP)
+ && (slave->state == BOND_STATE_ACTIVE)) {
X
- if (netif_running(slave->dev) && netif_carrier_ok(slave->dev)) {
- bond->current_slave = slave->next;
X skb->dev = slave->dev;
+ skb->priority = 1;
+ dev_queue_xmit(skb);
X
- if (dev_queue_xmit(skb)) {
- bond->stats.tx_dropped++;
- } else {
- bond->stats.tx_packets++;
- bond->stats.tx_bytes += pkt_len;
- }
+ read_unlock_irqrestore(&bond->lock, flags);
X return 0;
X }
X } while ((slave = slave->next) != start_at);
X
- bond->stats.tx_dropped++;
- kfree_skb(skb);
+ /* no suitable interface, frame not sent */
+ dev_kfree_skb(skb);
+ read_unlock_irqrestore(&bond->lock, flags);


+ return 0;
+}
+

+/*
+ * in active-backup mode, we know that bond->current_slave is always valid if
+ * the bond has a usable interface.
+ */
+static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *dev)
+{
+ struct bonding *bond = (struct bonding *) dev->priv;
+ unsigned long flags;
+ int ret;
+
+ if (!IS_UP(dev)) { /* bond down */
+ dev_kfree_skb(skb);


+ return 0;
+ }
+

+ /* if we are sending arp packets, try to at least
+ identify our own ip address */
+ if ( (arp_interval > 0) && (my_ip==0) &&
+ (skb->protocol == __constant_htons(ETH_P_ARP) ) ) {
+ char *the_ip = (((char *)skb->data))
+ + sizeof(struct ethhdr)
+ + sizeof(struct arphdr) +
+ ETH_ALEN;
+ memcpy(&my_ip, the_ip, 4);
+ }
+
+ /* if we are sending arp packets and don't know
+ the target hw address, save it so we don't need
+ to use a broadcast address */
+ if ( (arp_interval > 0) && (arp_target_hw_addr==NULL) &&
+ (skb->protocol == __constant_htons(ETH_P_IP) ) ) {
+ struct ethhdr *eth_hdr =
+ (struct ethhdr *) (((char *)skb->data));
+ arp_target_hw_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
+ memcpy(arp_target_hw_addr, eth_hdr->h_dest, ETH_ALEN);
+ }
+
+ read_lock_irqsave(&bond->lock, flags);
+
+ read_lock(&bond->ptrlock);
+ if (bond->current_slave != NULL) { /* one usable interface */
+ skb->dev = bond->current_slave->dev;
+ read_unlock(&bond->ptrlock);
+ skb->priority = 1;
+ ret = dev_queue_xmit(skb);
+ read_unlock_irqrestore(&bond->lock, flags);
+ return 0;
+ }
+ else {
+ read_unlock(&bond->ptrlock);
+ }
+
+ /* no suitable interface, frame not sent */
+#ifdef BONDING_DEBUG
+ printk(KERN_INFO "There was no suitable interface, so we don't transmit\n");
+#endif
+ dev_kfree_skb(skb);
+ read_unlock_irqrestore(&bond->lock, flags);


X return 0;
X }
X

X static struct net_device_stats *bond_get_stats(struct net_device *dev)
X {
X bonding_t *bond = dev->priv;
+ struct net_device_stats *stats = bond->stats, *sstats;
+ slave_t *slave;


+ unsigned long flags;
+

+ memset(bond->stats, 0, sizeof(struct net_device_stats));
+
+ read_lock_irqsave(&bond->lock, flags);
+
+ for (slave = bond->prev; slave!=(slave_t *)bond; slave = slave->prev) {
+ sstats = slave->dev->get_stats(slave->dev);
+
+ stats->rx_packets += sstats->rx_packets;
+ stats->rx_bytes += sstats->rx_bytes;
+ stats->rx_errors += sstats->rx_errors;
+ stats->rx_dropped += sstats->rx_dropped;
+
+ stats->tx_packets += sstats->tx_packets;
+ stats->tx_bytes += sstats->tx_bytes;
+ stats->tx_errors += sstats->tx_errors;
+ stats->tx_dropped += sstats->tx_dropped;
+
+ stats->multicast += sstats->multicast;
+ stats->collisions += sstats->collisions;
+
+ stats->rx_length_errors += sstats->rx_length_errors;
+ stats->rx_over_errors += sstats->rx_over_errors;
+ stats->rx_crc_errors += sstats->rx_crc_errors;
+ stats->rx_frame_errors += sstats->rx_frame_errors;
+ stats->rx_fifo_errors += sstats->rx_fifo_errors;
+ stats->rx_missed_errors += sstats->rx_missed_errors;
+
+ stats->tx_aborted_errors += sstats->tx_aborted_errors;
+ stats->tx_carrier_errors += sstats->tx_carrier_errors;
+ stats->tx_fifo_errors += sstats->tx_fifo_errors;
+ stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;
+ stats->tx_window_errors += sstats->tx_window_errors;
+
+ }
+
+ read_unlock_irqrestore(&bond->lock, flags);
+ return stats;
+}
+
+static int bond_get_info(char *buf, char **start, off_t offset, int length)
+{
+ bonding_t *bond = these_bonds;


+ int len = 0;

+ off_t begin = 0;
+ u16 link;
+ slave_t *slave = NULL;
+
+ while (bond != NULL) {
+ /*
+ * This function locks the mutex, so we can't lock it until
+ * afterwards
+ */
+ link = bond_check_mii_link(bond);
+
+ read_lock(&bond->ptrlock);
+
+ len += sprintf(buf + len, "Bonding Mode: ");
+ len += sprintf(buf + len, "%s\n", mode ? "active-backup" : "load balancing");
+
+ if (mode == BOND_MODE_ACTIVEBACKUP) {
+ if (bond->current_slave != NULL) {


+ len += sprintf(buf + len,

+ "Currently Active Slave: %s\n",
+ bond->current_slave->dev->name);
+ }
+ }
+
+ len += sprintf(buf + len, "MII Status: ");


+ len += sprintf(buf + len,

+ link == MII_LINK_READY ? "up\n" : "down\n");
+ len += sprintf(buf + len, "MII Polling Interval (ms): %d\n",
+ miimon);
+ len += sprintf(buf + len, "Up Delay (ms): %d\n", updelay);
+ len += sprintf(buf + len, "Down Delay (ms): %d\n", downdelay);
+
+ for (slave = bond->prev; slave != (slave_t *)bond;
+ slave = slave->prev) {
+ len += sprintf(buf + len, "\nSlave Interface: %s\n", slave->dev->name);
+
+ len += sprintf(buf + len, "MII Status: ");
+


+ len += sprintf(buf + len,

+ slave->link == BOND_LINK_UP ?
+ "up\n" : "down\n");
+ len += sprintf(buf + len, "Link Failure Count: %d\n",
+ slave->link_failure_count);
+ }
+
+ /*
+ * Figure out the calcs for the /proc/net interface
+ */
+ *start = buf + (offset - begin);
+ len -= (offset - begin);
+ if (len > length) {
+ len = length;
+ }
+ if (len < 0) {


+ len = 0;
+ }

+
+ read_unlock(&bond->ptrlock);
+
+ bond = bond->next_bond;


+ }
+ return len;
+}
+

+static int bond_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ struct bonding *this_bond=(struct bonding *)these_bonds;
+ struct bonding *last_bond;
+ struct net_device *event_dev = (struct net_device *)ptr;
+
+ /* while there are bonds configured */
+ while (this_bond != NULL) {
+ if (this_bond == event_dev->priv ) {
+ switch (event) {
+ case NETDEV_UNREGISTER:
+ /*
+ * remove this bond from a linked list of
+ * bonds
+ */
+ if (this_bond == these_bonds) {
+ these_bonds = this_bond->next_bond;
+ } else {
+ for (last_bond = these_bonds;
+ last_bond != NULL;
+ last_bond = last_bond->next_bond) {
+ if (last_bond->next_bond ==
+ this_bond) {
+ last_bond->next_bond =
+ this_bond->next_bond;
+ }
+ }
+ }
+ return NOTIFY_DONE;
+
+ default:
+ return NOTIFY_DONE;
+ }
+ }
+ this_bond = this_bond->next_bond;
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block bond_netdev_notifier={
+ bond_event,
+ NULL,
+ 0
+};
+
+static int __init bond_init(struct net_device *dev)
+{
+ bonding_t *bond, *this_bond, *last_bond;
X
- return &bond->stats;
+#ifdef BONDING_DEBUG
+ printk (KERN_INFO "Begin bond_init for %s\n", dev->name);
+#endif
+ bond = kmalloc(sizeof(struct bonding), GFP_KERNEL);
+ if (bond == NULL) {
+ return -ENOMEM;
+ }
+ memset(bond, 0, sizeof(struct bonding));
+
+ /* initialize rwlocks */
+ rwlock_init(&bond->lock);
+ rwlock_init(&bond->ptrlock);
+
+ bond->stats = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
+ if (bond->stats == NULL) {
+ kfree(bond);
+ return -ENOMEM;
+ }
+ memset(bond->stats, 0, sizeof(struct net_device_stats));
+
+ bond->next = bond->prev = (slave_t *)bond;
+ bond->current_slave = NULL;
+ bond->device = dev;
+ dev->priv = bond;
+
+ /* Initialize the device structure. */
+ if (mode == BOND_MODE_ACTIVEBACKUP) {
+ dev->hard_start_xmit = bond_xmit_activebackup;
+ } else if (mode == BOND_MODE_ROUNDROBIN) {
+ dev->hard_start_xmit = bond_xmit_roundrobin;
+ } else if (mode == BOND_MODE_XOR) {
+ dev->hard_start_xmit = bond_xmit_xor;
+ } else {
+ printk(KERN_ERR "Unknown bonding mode %d\n", mode);
+ kfree(bond->stats);
+ kfree(bond);


+ return -EINVAL;
+ }
+

+ dev->get_stats = bond_get_stats;
+ dev->open = bond_open;
+ dev->stop = bond_close;
+ dev->set_multicast_list = set_multicast_list;
+ dev->do_ioctl = bond_ioctl;
+
+ /*
+ * Fill in the fields of the device structure with ethernet-generic
+ * values.
+ */
+
+ ether_setup(dev);
+
+ dev->tx_queue_len = 0;
+ dev->flags |= IFF_MASTER|IFF_MULTICAST;
+#ifdef CONFIG_NET_FASTROUTE
+ dev->accept_fastpath = bond_accept_fastpath;
+#endif
+
+ printk(KERN_INFO "%s registered with", dev->name);
+ if (miimon > 0) {
+ printk(" MII link monitoring set to %d ms", miimon);
+ updelay /= miimon;
+ downdelay /= miimon;
+ } else {
+ printk("out MII link monitoring");
+ }
+ printk(", in %s mode.\n",mode?"active-backup":"bonding");
+
+#ifdef CONFIG_PROC_FS
+ bond->bond_proc_dir = proc_mkdir(dev->name, proc_net);
+ if (bond->bond_proc_dir == NULL) {
+ printk(KERN_ERR "%s: Cannot init /proc/net/%s/\n",
+ dev->name, dev->name);
+ kfree(bond->stats);
+ kfree(bond);
+ return -ENOMEM;
+ }
+ bond->bond_proc_info_file =
+ create_proc_info_entry("info", 0, bond->bond_proc_dir,
+ bond_get_info);
+ if (bond->bond_proc_info_file == NULL) {
+ printk(KERN_ERR "%s: Cannot init /proc/net/%s/info\n",
+ dev->name, dev->name);
+ remove_proc_entry(dev->name, proc_net);
+ kfree(bond->stats);
+ kfree(bond);
+ return -ENOMEM;
+ }
+#endif /* CONFIG_PROC_FS */
+
+ if (first_pass == 1) {
+ these_bonds = bond;
+ register_netdevice_notifier(&bond_netdev_notifier);
+ first_pass = 0;
+ } else {
+ last_bond = these_bonds;
+ this_bond = these_bonds->next_bond;
+ while (this_bond != NULL) {
+ last_bond = this_bond;
+ this_bond = this_bond->next_bond;
+ }
+ last_bond->next_bond = bond;


+ }
+
+ return 0;

X }
X
-static struct net_device dev_bond;
+/*
+static int __init bond_probe(struct net_device *dev)
+{
+ bond_init(dev);
+ return 0;
+}
+ */
X
X static int __init bonding_init(void)
X {
- /* Find a name for this unit */
+ int no;
X int err;
-
- dev_bond.init = bond_init;
X
- err = dev_alloc_name(&dev_bond,"bond%d");
- if (err<0)
- return err;
-
- SET_MODULE_OWNER(&dev_bond);
- if (register_netdev(&dev_bond) != 0)
- return -EIO;
+ /* Find a name for this unit */
+ static struct net_device *dev_bond = NULL;
X
+ dev_bond = dev_bonds = kmalloc(max_bonds*sizeof(struct net_device),
+ GFP_KERNEL);
+ if (dev_bond == NULL) {
+ return -ENOMEM;
+ }
+ memset(dev_bonds, 0, max_bonds*sizeof(struct net_device));
+
+ if (arp_ip_target) {
+ if (my_inet_aton(arp_ip_target, &arp_target) == 0) {
+ arp_interval = 0;
+ }
+ }
+
+ for (no = 0; no < max_bonds; no++) {
+ dev_bond->init = bond_init;
+
+ err = dev_alloc_name(dev_bond,"bond%d");
+ if (err < 0) {
+ kfree(dev_bonds);
+ return err;
+ }
+ SET_MODULE_OWNER(dev_bond);
+ if (register_netdev(dev_bond) != 0) {
+ kfree(dev_bonds);
+ return -EIO;
+ }
+ dev_bond++;
+ }


X return 0;
X }
X

X static void __exit bonding_exit(void)
X {
- unregister_netdevice_notifier(&bond_netdev_notifier);
+ struct net_device *dev_bond = dev_bonds;
+ struct bonding *bond;
+ int no;
X
- unregister_netdev(&dev_bond);
+ unregister_netdevice_notifier(&bond_netdev_notifier);
+
+ for (no = 0; no < max_bonds; no++) {
X
- kfree(dev_bond.priv);
+#ifdef CONFIG_PROC_FS
+ bond = (struct bonding *) dev_bond->priv;
+ remove_proc_entry("info", bond->bond_proc_dir);
+ remove_proc_entry(dev_bond->name, proc_net);
+#endif
+ unregister_netdev(dev_bond);
+ kfree(bond->stats);
+ kfree(dev_bond->priv);
+
+ dev_bond->priv = NULL;
+ dev_bond++;
+ }
+ kfree(dev_bonds);
X }
X
X module_init(bonding_init);
diff -u --recursive --new-file v2.4.14/linux/drivers/net/bsd_comp.c linux/drivers/net/bsd_comp.c
--- v2.4.14/linux/drivers/net/bsd_comp.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/net/bsd_comp.c Fri Nov 9 14:01:22 2001
@@ -1173,4 +1173,4 @@
X
X module_init(bsdcomp_init);
X module_exit(bsdcomp_cleanup);
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/net/dl2k.c linux/drivers/net/dl2k.c
--- v2.4.14/linux/drivers/net/dl2k.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/net/dl2k.c Mon Nov 19 15:19:42 2001
@@ -12,34 +12,41 @@
X /*
X Rev Date Description
X ==========================================================================
- 0.01 2001/05/03 Create DL2000-based linux driver
- 0.02 2001/05/21 Add VLAN and hardware checksum support.
- 1.00 2001/06/26 Add jumbo frame support.
- 1.01 2001/08/21 Add two parameters, int_count and int_timeout.
+ 0.01 2001/05/03 Created DL2000-based linux driver
+ 0.02 2001/05/21 Added VLAN and hardware checksum support.
+ 1.00 2001/06/26 Added jumbo frame support.
+ 1.01 2001/08/21 Added two parameters, int_count and int_timeout.
+ 1.02 2001/10/08 Supported fiber media.
+ Added flow control parameters.
+ 1.03 2001/10/12 Changed the default media to 1000mbps_fd for the
+ fiber devices.
+ 1.04 2001/11/08 Fixed a bug which Tx stop when a very busy case.
X */
X
X #include "dl2k.h"
X
X static char version[] __devinitdata =
- KERN_INFO "D-Link DL2000-based linux driver v1.01 2001/08/30\n";
+ KERN_INFO "D-Link DL2000-based linux driver v1.04 2001/11/08\n";
X
X #define MAX_UNITS 8
X static int mtu[MAX_UNITS];
X static int vlan[MAX_UNITS];
X static int jumbo[MAX_UNITS];
X static char *media[MAX_UNITS];
+static int tx_flow[MAX_UNITS];
+static int rx_flow[MAX_UNITS];
X static int copy_thresh;
X static int int_count; /* Rx frame count each interrupt */
X static int int_timeout; /* Rx DMA wait time in 64ns increments */
X
X MODULE_AUTHOR ("Edward Peng");
X MODULE_DESCRIPTION ("D-Link DL2000-based Gigabit Ethernet Adapter");
-MODULE_LICENSE("GPL");
-
X MODULE_PARM (mtu, "1-" __MODULE_STRING (MAX_UNITS) "i");
X MODULE_PARM (media, "1-" __MODULE_STRING (MAX_UNITS) "s");
X MODULE_PARM (vlan, "1-" __MODULE_STRING (MAX_UNITS) "i");
X MODULE_PARM (jumbo, "1-" __MODULE_STRING (MAX_UNITS) "i");
+MODULE_PARM (tx_flow, "1-" __MODULE_STRING (MAX_UNITS) "i");
+MODULE_PARM (rx_flow, "1-" __MODULE_STRING (MAX_UNITS) "i");
X MODULE_PARM (copy_thresh, "i");
X MODULE_PARM (int_count, "i");
X MODULE_PARM (int_timeout, "i");
@@ -72,6 +79,8 @@
X static int mii_wait_link (struct net_device *dev, int wait);
X static int mii_set_media (struct net_device *dev);
X static int mii_get_media (struct net_device *dev);
+static int mii_set_media_pcs (struct net_device *dev);
+static int mii_get_media_pcs (struct net_device *dev);
X static int mii_read (struct net_device *dev, int phy_addr, int reg_num);
X static int mii_write (struct net_device *dev, int phy_addr, int reg_num,
X u16 data);
@@ -104,7 +113,6 @@
X goto err_out_disable;
X
X pci_set_master (pdev);
-
X dev = alloc_etherdev (sizeof (*np));
X if (!dev) {
X err = -ENOMEM;
@@ -134,7 +142,11 @@
X if (card_idx < MAX_UNITS) {
X if (media[card_idx] != NULL) {
X np->an_enable = 0;
- if (strcmp (media[card_idx], "100mbps_fd") == 0 ||
+ if (strcmp (media[card_idx], "auto") == 0 ||
+ strcmp (media[card_idx], "autosense") == 0 ||
+ strcmp (media[card_idx], "0") == 0 ) {
+ np->an_enable = 2;
+ } else if (strcmp (media[card_idx], "100mbps_fd") == 0 ||
X strcmp (media[card_idx], "4") == 0) {
X np->speed = 100;
X np->full_duplex = 1;
@@ -150,16 +162,14 @@
X strcmp (media[card_idx], "1") == 0) {
X np->speed = 10;
X np->full_duplex = 0;
- }
- /* Auto-Negotiation is mandatory for 1000BASE-T,
- IEEE 802.3ab Annex 28D page 14 */
- else if (strcmp (media[card_idx], "1000mbps_fd") == 0 ||
- strcmp (media[card_idx], "5") == 0 ||
- strcmp (media[card_idx], "1000mbps_hd") == 0 ||
+ } else if (strcmp (media[card_idx], "1000mbps_fd") == 0 ||
+ strcmp (media[card_idx], "5") == 0) {
+ np->speed=1000;
+ np->full_duplex=1;
+ } else if (strcmp (media[card_idx], "1000mbps_hd") == 0 ||
X strcmp (media[card_idx], "6") == 0) {
X np->speed = 1000;
- np->full_duplex = 1;
- np->an_enable = 1;
+ np->full_duplex = 0;
X } else {
X np->an_enable = 1;
X }
@@ -179,6 +189,9 @@
X np->int_timeout = int_timeout;
X np->coalesce = 1;
X }
+ np->tx_flow = (tx_flow[card_idx]) ? 1 : 0;
+ np->rx_flow = (rx_flow[card_idx]) ? 1 : 0;
+
X }
X dev->open = &rio_open;
X dev->hard_start_xmit = &start_xmit;
@@ -213,9 +226,27 @@
X err = find_miiphy (dev);
X if (err)
X goto err_out_unmap_rx;
-
+
+ /* Fiber device? */
+ np->phy_media = (readw(ioaddr + ASICCtrl) & PhyMedia) ? 1 : 0;
X /* Set media and reset PHY */
- mii_set_media (dev);
+ if (np->phy_media) {
+ /* default 1000mbps_fd for fiber deivices */
+ if (np->an_enable == 1) {
+ np->an_enable = 0;
+ np->speed = 1000;
+ np->full_duplex = 1;
+ } else if (np->an_enable == 2) {
+ np->an_enable = 1;
+ }
+ mii_set_media_pcs (dev);
+ } else {
+ /* Auto-Negotiation is mandatory for 1000BASE-T,
+ IEEE 802.3ab Annex 28D page 14 */
+ if (np->speed == 1000)
+ np->an_enable = 1;
+ mii_set_media (dev);
+ }
X
X /* Reset all logic functions */
X writew (GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset,
@@ -227,7 +258,7 @@
X
X card_idx++;


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

echo 'End of part 050'
echo 'File patch-2.4.15 is continued in part 051'
echo "051" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:31 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part055

#!/bin/sh -x
# this is part 055 of a 115 - part archive


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

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

+ printk(KERN_WARNING "%s: Unexpected data error\n",
+ dev->name);
+ goto drop;
+ case E_LST_LNK_ERR:
+ printk(KERN_WARNING "%s: Link lost error\n",
+ dev->name);
+ goto drop;
+ case E_FRM_ERR:
+ printk(KERN_WARNING "%s: Framming Error\n",
+ dev->name);
+ goto drop;
+ case E_FLG_SYN_ERR:
+ printk(KERN_WARNING "%s: Flag sync. lost during"
+ "packet\n", dev->name);
+ goto drop;
X case E_RX_INV_BUF:
X printk(KERN_ERR "%s: Invalid receive buffer "
X "address\n", dev->name);
@@ -942,6 +970,23 @@
X &regs->HostCtrl);
X wmb();
X break;
+ drop:
+ /* Label packet to be dropped.
+ * Actual dropping occurs in rx
+ * handling.
+ *
+ * The index of packet we get to drop is
+ * the index of the packet following
+ * the bad packet. -kbf
+ */
+ {
+ u16 index = rrpriv->evt_ring[eidx].index;
+ index = (index + (RX_RING_ENTRIES - 1)) %
+ RX_RING_ENTRIES;
+ rrpriv->rx_ring[index].mode |=
+ (PACKET_BAD | PACKET_END);


+ }
+ break;
X default:

X printk(KERN_WARNING "%s: Unhandled event 0x%02x\n",
X dev->name, rrpriv->evt_ring[eidx].code);
@@ -968,6 +1013,11 @@
X printk("len %x, mode %x\n", pkt_len,
X rrpriv->rx_ring[index].mode);
X #endif
+ if ( (rrpriv->rx_ring[index].mode & PACKET_BAD) == PACKET_BAD){
+ rrpriv->stats.rx_dropped++;
+ goto defer;
+ }
+
X if (pkt_len > 0){
X struct sk_buff *skb;
X
@@ -1046,6 +1096,15 @@
X printk("%s: interrupt, prodidx = %i, eidx = %i\n", dev->name,
X prodidx, rrpriv->info->evt_ctrl.pi);
X #endif
+ /*
+ * Order here is important. We must handle events
+ * before doing anything else in order to catch
+ * such things as LLRC errors, etc -kbf
+ */
+
+ eidx = rrpriv->info->evt_ctrl.pi;
+ if (prodidx != eidx)
+ eidx = rr_handle_event(dev, prodidx, eidx);
X
X rxindex = rrpriv->cur_rx;
X if (rxindex != rxlimit)
@@ -1054,15 +1113,19 @@
X txcon = rrpriv->dirty_tx;
X if (txcsmr != txcon) {
X do {
- rrpriv->stats.tx_packets++;
- rrpriv->stats.tx_bytes +=rrpriv->tx_skbuff[txcon]->len;
- dev_kfree_skb_irq(rrpriv->tx_skbuff[txcon]);
-
- rrpriv->tx_skbuff[txcon] = NULL;
- rrpriv->tx_ring[txcon].size = 0;
- set_rraddr(&rrpriv->tx_ring[txcon].addr, 0);
- rrpriv->tx_ring[txcon].mode = 0;
-
+ /* Due to occational firmware TX producer/consumer out
+ * of sync. error need to check entry in ring -kbf
+ */
+ if(rrpriv->tx_skbuff[txcon]){
+ rrpriv->stats.tx_packets++;
+ rrpriv->stats.tx_bytes +=rrpriv->tx_skbuff[txcon]->len;
+ dev_kfree_skb_irq(rrpriv->tx_skbuff[txcon]);
+
+ rrpriv->tx_skbuff[txcon] = NULL;
+ rrpriv->tx_ring[txcon].size = 0;
+ set_rraddr(&rrpriv->tx_ring[txcon].addr, 0);
+ rrpriv->tx_ring[txcon].mode = 0;
+ }
X txcon = (txcon + 1) % TX_RING_ENTRIES;
X } while (txcsmr != txcon);
X wmb();
@@ -1077,10 +1140,6 @@
X }
X }
X
- eidx = rrpriv->info->evt_ctrl.pi;
- if (prodidx != eidx)
- eidx = rr_handle_event(dev, prodidx, eidx);
-
X eidx |= ((txcsmr << 8) | (rxlimit << 16));
X writel(eidx, &regs->EvtCon);
X wmb();
@@ -1238,7 +1297,7 @@
X index, cons);
X
X if (rrpriv->tx_skbuff[index]){
- len = min(0x80, rrpriv->tx_skbuff[index]->len);
+ len = min_t(int, 0x80, rrpriv->tx_skbuff[index]->len);
X printk("skbuff for index %i is valid - dumping data (0x%x bytes - DMA len 0x%x)\n", index, len, rrpriv->tx_ring[index].size);
X for (i = 0; i < len; i++){
X if (!(i & 7))
@@ -1249,7 +1308,7 @@
X }
X
X if (rrpriv->tx_skbuff[cons]){
- len = min(0x80, rrpriv->tx_skbuff[cons]->len);
+ len = min_t(int, 0x80, rrpriv->tx_skbuff[cons]->len);
X printk("skbuff for cons %i is valid - dumping data (0x%x bytes - skbuff len 0x%x)\n", cons, len, rrpriv->tx_skbuff[cons]->len);
X printk("mode 0x%x, size 0x%x,\n phys %08x (virt %08lx), skbuff-addr %08lx, truesize 0x%x\n",
X rrpriv->tx_ring[cons].mode,
diff -u --recursive --new-file v2.4.14/linux/drivers/net/rrunner.h linux/drivers/net/rrunner.h
--- v2.4.14/linux/drivers/net/rrunner.h Mon Dec 11 13:01:04 2000
+++ linux/drivers/net/rrunner.h Fri Nov 9 13:45:35 2001
@@ -478,6 +478,7 @@
X * Mode bits
X */
X
+#define PACKET_BAD 0x01 /* Packet had link-layer error */
X #define INTERRUPT 0x02
X #define TX_IP_CKSUM 0x04
X #define PACKET_END 0x08
diff -u --recursive --new-file v2.4.14/linux/drivers/net/sk98lin/skvpd.c linux/drivers/net/sk98lin/skvpd.c
--- v2.4.14/linux/drivers/net/sk98lin/skvpd.c Wed Jul 25 17:10:21 2001
+++ linux/drivers/net/sk98lin/skvpd.c Tue Nov 13 09:19:41 2001
@@ -237,6 +237,7 @@
X 2: error, data verify error
X
X */
+#if 0 /* Unused at the moment */
X static int VpdWriteDWord(
X SK_AC *pAC, /* pAC pointer */
X SK_IOC IoC, /* IO Context */
@@ -268,6 +269,7 @@
X }
X return(0) ;
X }
+#endif
X
X /*
X * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
diff -u --recursive --new-file v2.4.14/linux/drivers/net/slhc.c linux/drivers/net/slhc.c
--- v2.4.14/linux/drivers/net/slhc.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/slhc.c Fri Nov 9 14:02:24 2001
@@ -797,4 +797,4 @@
X EXPORT_SYMBOL(slhc_toss);
X
X #endif /* CONFIG_INET */


-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");

diff -u --recursive --new-file v2.4.14/linux/drivers/net/strip.c linux/drivers/net/strip.c
--- v2.4.14/linux/drivers/net/strip.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/strip.c Fri Nov 9 14:02:24 2001
@@ -2871,7 +2871,7 @@
X
X MODULE_AUTHOR("Stuart Cheshire <ches...@cs.stanford.edu>");
X MODULE_DESCRIPTION("Starmode Radio IP (STRIP) Device Driver");
-MODULE_LICENSE("BSD without advertisement clause");
+MODULE_LICENSE("Dual BSD/GPL");
X
X MODULE_SUPPORTED_DEVICE("Starmode Radio IP (STRIP) modem");
X
diff -u --recursive --new-file v2.4.14/linux/drivers/net/tokenring/ibmtr.c linux/drivers/net/tokenring/ibmtr.c
--- v2.4.14/linux/drivers/net/tokenring/ibmtr.c Sun Sep 23 11:40:58 2001
+++ linux/drivers/net/tokenring/ibmtr.c Fri Nov 9 14:02:24 2001
@@ -1230,6 +1230,7 @@
X ti->open_action = RESTART;
X outb(0, dev->base_addr + ADAPTRESET);
X ibmtr_reset_timer(&(ti->tr_timer), dev);/*BMS try to reopen*/
+ spin_unlock(&(ti->lock));
X return;
X }
X if (readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN)
diff -u --recursive --new-file v2.4.14/linux/drivers/net/tokenring/lanstreamer.c linux/drivers/net/tokenring/lanstreamer.c
--- v2.4.14/linux/drivers/net/tokenring/lanstreamer.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/tokenring/lanstreamer.c Sat Nov 10 15:38:59 2001
@@ -299,7 +299,7 @@
X streamer_priv->streamer_ring_speed = ringspeed[card_no];
X streamer_priv->streamer_message_level = message_level[card_no];
X
- pdev->driver_data=dev;
+ pci_set_drvdata(pdev, dev);
X
X spin_lock_init(&streamer_priv->streamer_lock);
X
@@ -329,7 +329,7 @@
X }
X
X static void __devexit streamer_remove_one(struct pci_dev *pdev) {
- struct net_device *dev=pdev->driver_data;
+ struct net_device *dev=pci_get_drvdata(pdev);
X struct streamer_private *streamer_priv;
X
X #if STREAMER_DEBUG
@@ -373,7 +373,7 @@
X release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev,0));
X release_mem_region(pci_resource_start(pdev, 1), pci_resource_len(pdev,1));
X kfree(dev);
- pdev->driver_data=NULL;
+ pci_set_drvdata(pdev, NULL);
X }
X
X
@@ -1704,7 +1704,7 @@
X
X for(sdev=dev_streamer; sdev; sdev=sdev->next) {
X pci_device=sdev->pci_dev;
- dev=pci_device->driver_data;
+ dev=pci_get_drvdata(pci_device);
X
X size = sprintf_info(buffer + len, dev);
X len += size;
diff -u --recursive --new-file v2.4.14/linux/drivers/net/tokenring/olympic.c linux/drivers/net/tokenring/olympic.c
--- v2.4.14/linux/drivers/net/tokenring/olympic.c Sun Sep 23 11:40:58 2001
+++ linux/drivers/net/tokenring/olympic.c Fri Nov 9 13:46:29 2001
@@ -737,7 +737,7 @@
X } else {
X
X if (buffer_cnt == 1) {
- skb = dev_alloc_skb(olympic_priv->pkt_buf_sz) ;
+ skb = dev_alloc_skb(max_t(int, olympic_priv->pkt_buf_sz,length)) ;
X } else {
X skb = dev_alloc_skb(length) ;
X }
@@ -1684,7 +1684,7 @@
X
X static void __devexit olympic_remove_one(struct pci_dev *pdev)
X {
- struct net_device *dev = pdev->driver_data ;
+ struct net_device *dev = pci_get_drvdata(pdev) ;
X struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
X
X if (olympic_priv->olympic_network_monitor) {
@@ -1722,4 +1722,4 @@
X module_init(olympic_pci_init) ;
X module_exit(olympic_pci_cleanup) ;
X
-MODULE_LICENSE("GPL");
\ No newline at end of file
+MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/net/tulip/21142.c linux/drivers/net/tulip/21142.c
--- v2.4.14/linux/drivers/net/tulip/21142.c Wed Jul 25 17:10:22 2001
+++ linux/drivers/net/tulip/21142.c Fri Nov 9 13:45:35 2001
@@ -106,10 +106,6 @@
X dev->if_port = 0;
X tp->nway = tp->mediasense = 1;
X tp->nwayset = tp->lpar = 0;
- if (tp->chip_id == PNIC2) {
- tp->csr6 = 0x01000000 | (tp->sym_advertise & 0x0040 ? FullDuplex : 0);
- return;
- }
X if (tulip_debug > 1)
X printk(KERN_DEBUG "%s: Restarting 21143 autonegotiation, csr14=%8.8x.\n",
X dev->name, csr14);
@@ -127,23 +123,6 @@
X }
X
X
-void pnic2_lnk_change(struct net_device *dev, int csr5)
-{
- struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
- int csr12 = inl(ioaddr + CSR12);
-
- if (tulip_debug > 1)
- printk(KERN_INFO"%s: PNIC-2 link status changed, CSR5/12/14 %8.8x"
- " %8.8x, %8.8x.\n",
- dev->name, csr12, csr5, (int)inl(ioaddr + CSR14));
- dev->if_port = 5;
- tp->lpar = csr12 >> 16;
- tp->nwayset = 1;
- tp->csr6 = 0x01000000 | (tp->csr6 & 0xffff);
- outl(tp->csr6, ioaddr + CSR6);
-
-}
X
X void t21142_lnk_change(struct net_device *dev, int csr5)
X {
diff -u --recursive --new-file v2.4.14/linux/drivers/net/tulip/ChangeLog linux/drivers/net/tulip/ChangeLog
--- v2.4.14/linux/drivers/net/tulip/ChangeLog Wed Jul 25 17:10:22 2001
+++ linux/drivers/net/tulip/ChangeLog Mon Nov 19 15:19:42 2001
@@ -1,3 +1,28 @@
+2001-11-13 David S. Miller <da...@redhat.com>
+
+ * tulip_core.c (tulip_mwi_config): Kill unused label early_out.
+
+2001-11-06 Richard Mortimer <ri...@oldelvet.netscapeonline.co.uk>
+
+ * tulip_core.c: Correct set of values to mask out of csr0,
+ for DM9102A chips. Limit burst/alignment of DM9102A chips
+ on Sparcs.
+
+2001-11-06 Jun Sun <js...@mvista.com>
+
+ * tulip_core.c: Support finding MAC address on
+ two MIPS boards, DDB5476 and DDB5477.
+
+2001-11-06 Kevin B. Hendricks <khend...@ivey.uwo.ca>
+
+ * Makefile, tulip.h, tulip_core.c, pnic2.c, 21142.c:
+ Fixes for PNIC II support.
+
+2001-11-06 David S. Miller <da...@redhat.com>
+
+ * tulip_core.c: Support reading MAC address from
+ Sparc OBP property local-mac-address.
+
X 2001-07-17 Erik A. Hendriks <hend...@lanl.gov>
X
X * 21142.c: Merge fix from tulip.c 0.92w which prevents the
diff -u --recursive --new-file v2.4.14/linux/drivers/net/tulip/Makefile linux/drivers/net/tulip/Makefile
--- v2.4.14/linux/drivers/net/tulip/Makefile Tue Apr 3 10:19:43 2001
+++ linux/drivers/net/tulip/Makefile Fri Nov 9 13:45:35 2001


@@ -11,7 +11,7 @@
X

X obj-y := eeprom.o interrupt.o media.o \
X timer.o tulip_core.o \
- 21142.o pnic.o
+ 21142.o pnic.o pnic2.o
X obj-m := $(O_TARGET)
X
X include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.14/linux/drivers/net/tulip/interrupt.c linux/drivers/net/tulip/interrupt.c
--- v2.4.14/linux/drivers/net/tulip/interrupt.c Tue Oct 23 22:48:51 2001
+++ linux/drivers/net/tulip/interrupt.c Fri Nov 9 13:45:35 2001
@@ -28,8 +28,8 @@
X #define MIT_SIZE 15
X unsigned int mit_table[MIT_SIZE+1] =
X {
- /* CRS11 21143 hardware Mitigation Control Interrupt
- We use only RX mitigation we other techniques for
+ /* CRS11 21143 hardware Mitigation Control Interrupt
+ We use only RX mitigation we other techniques for
X TX intr. mitigation.
X
X 31 Cycle Size (timer control)
@@ -39,7 +39,7 @@
X 19:17 RX No pkts before Int.
X 16 Continues Mode (CM)
X */
-
+
X 0x0, /* IM disabled */
X 0x80150000, /* RX time = 1, RX pkts = 2, CM = 1 */
X 0x80150000,
@@ -110,7 +110,7 @@
X #ifdef CONFIG_NET_HW_FLOWCONTROL
X int drop = 0, mit_sel = 0;
X
-/* that one buffer is needed for mit activation; or might be a
+/* that one buffer is needed for mit activation; or might be a
X bug in the ring buffer code; check later -- JHS*/
X
X if (rx_work_limit >=RX_RING_SIZE) rx_work_limit--;
@@ -210,7 +210,7 @@
X }
X skb->protocol = eth_type_trans(skb, dev);
X #ifdef CONFIG_NET_HW_FLOWCONTROL
- mit_sel =
+ mit_sel =
X #endif
X netif_rx(skb);
X
@@ -258,34 +258,34 @@
X
X /* We use this simplistic scheme for IM. It's proven by
X real life installations. We can have IM enabled
- continuesly but this would cause unnecessary latency.
- Unfortunely we can't use all the NET_RX_* feedback here.
- This would turn on IM for devices that is not contributing
- to backlog congestion with unnecessary latency.
+ continuesly but this would cause unnecessary latency.
+ Unfortunely we can't use all the NET_RX_* feedback here.
+ This would turn on IM for devices that is not contributing
+ to backlog congestion with unnecessary latency.
X
X We monitor the the device RX-ring and have:
X
X HW Interrupt Mitigation either ON or OFF.
X
- ON: More then 1 pkt received (per intr.) OR we are dropping
+ ON: More then 1 pkt received (per intr.) OR we are dropping
X OFF: Only 1 pkt received
-
+
X Note. We only use min and max (0, 15) settings from mit_table */
X
X
X if( tp->flags & HAS_INTR_MITIGATION) {
- if((received > 1 || mit_sel == NET_RX_DROP)
- && tp->mit_sel != 15 ) {
- tp->mit_sel = 15;
+ if((received > 1 || mit_sel == NET_RX_DROP)
+ && tp->mit_sel != 15 ) {
+ tp->mit_sel = 15;
X tp->mit_change = 1; /* Force IM change */
X }
X if((received <= 1 && mit_sel != NET_RX_DROP) && tp->mit_sel != 0 ) {
- tp->mit_sel = 0;
+ tp->mit_sel = 0;
X tp->mit_change = 1; /* Force IM change */
X }
X }
X
- return RX_RING_SIZE+1; /* maxrx+1 */
+ return RX_RING_SIZE+1; /* maxrx+1 */
X #else
X return received;
X #endif
diff -u --recursive --new-file v2.4.14/linux/drivers/net/tulip/pnic.c linux/drivers/net/tulip/pnic.c
--- v2.4.14/linux/drivers/net/tulip/pnic.c Tue Jul 3 17:08:20 2001
+++ linux/drivers/net/tulip/pnic.c Fri Nov 9 13:45:35 2001
@@ -62,7 +62,7 @@
X dev->name, phy_reg, csr5);
X if (inl(ioaddr + CSR5) & TPLnkFail) {
X outl((inl(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7);
- /* If we use an external MII, then we mustn't use the
+ /* If we use an external MII, then we mustn't use the
X * internal negotiation.
X */
X if (tulip_media_cap[dev->if_port] & MediaIsMII)
@@ -92,7 +92,7 @@
X struct tulip_private *tp = (struct tulip_private *)dev->priv;
X long ioaddr = dev->base_addr;
X int next_tick = 60*HZ;
-
+
X if(!inl(ioaddr + CSR7)) {
X /* the timer was called due to a work overflow
X * in the interrupt handler. Skip the connection
diff -u --recursive --new-file v2.4.14/linux/drivers/net/tulip/pnic2.c linux/drivers/net/tulip/pnic2.c
--- v2.4.14/linux/drivers/net/tulip/pnic2.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/tulip/pnic2.c Fri Nov 9 13:45:35 2001
@@ -0,0 +1,407 @@
+/*
+ drivers/net/tulip/pnic2.c
+
+ Maintained by Jeff Garzik <jga...@mandrakesoft.com>
+ Copyright 2000,2001 The Linux Kernel Team
+ Written/copyright 1994-2001 by Donald Becker.
+ Modified to hep support PNIC_II by Kevin B. Hendricks
+
+ This software may be used and distributed according to the terms
+ of the GNU General Public License, incorporated herein by reference.
+
+ Please refer to Documentation/DocBook/tulip.{pdf,ps,html}
+ for more information on this driver, or visit the project
+ Web page at http://sourceforge.net/projects/tulip/
+
+*/
+
+
+/* Understanding the PNIC_II - everything is this file is based
+ * on the PNIC_II_PDF datasheet which is sorely lacking in detail
+ *
+ * As I understand things, here are the registers and bits that
+ * explain the masks and constants used in this file that are
+ * either different from the 21142/3 or important for basic operation.
+ *
+ *
+ * CSR 6 (mask = 0xfe3bd1fd of bits not to change)
+ * -----
+ * Bit 24 - SCR
+ * Bit 23 - PCS
+ * Bit 22 - TTM (Trasmit Threshold Mode)
+ * Bit 18 - Port Select
+ * Bit 13 - Start - 1, Stop - 0 Transmissions
+ * Bit 11:10 - Loop Back Operation Mode
+ * Bit 9 - Full Duplex mode (Advertise 10BaseT-FD is CSR14<7> is set)
+ * Bit 1 - Start - 1, Stop - 0 Receive
+ *
+ *
+ * CSR 14 (mask = 0xfff0ee39 of bits not to change)
+ * ------
+ * Bit 19 - PAUSE-Pause
+ * Bit 18 - Advertise T4
+ * Bit 17 - Advertise 100baseTx-FD
+ * Bit 16 - Advertise 100baseTx-HD
+ * Bit 12 - LTE - Link Test Enable
+ * Bit 7 - ANE - Auto Negotiate Enable
+ * Bit 6 - HDE - Advertise 10baseT-HD
+ * Bit 2 - Reset to Power down - kept as 1 for normal operation
+ * Bit 1 - Loop Back enable for 10baseT MCC
+ *
+ *
+ * CSR 12
+ * ------
+ * Bit 25 - Partner can do T4
+ * Bit 24 - Partner can do 100baseTx-FD
+ * Bit 23 - Partner can do 100baseTx-HD
+ * Bit 22 - Partner can do 10baseT-FD
+ * Bit 21 - Partner can do 10baseT-HD
+ * Bit 15 - LPN is 1 if all above bits are valid other wise 0
+ * Bit 14:12 - autonegotiation state (write 001 to start autonegotiate)
+ * Bit 3 - Autopolarity state
+ * Bit 2 - LS10B - link state of 10baseT 0 - good, 1 - failed
+ * Bit 1 - LS100B - link state of 100baseT 0 - good, 1- faild
+ *
+ *
+ * Data Port Selection Info
+ *-------------------------
+ *
+ * CSR14<7> CSR6<18> CSR6<22> CSR6<23> CSR6<24> MODE/PORT
+ * 1 0 0 (X) 0 (X) 1 NWAY
+ * 0 0 1 0 (X) 0 10baseT
+ * 0 1 0 1 1 (X) 100baseT
+ *


+ *
+ */
+
+

+
+#include "tulip.h"
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+
+void pnic2_timer(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ int next_tick = 60*HZ;
+
+ if (tulip_debug > 3)
+ printk(KERN_INFO"%s: PNIC2 negotiation status %8.8x.\n",
+ dev->name,inl(ioaddr + CSR12));
+
+ if (next_tick) {
+ mod_timer(&tp->timer, RUN_AT(next_tick));
+ }
+}
+
+
+void pnic2_start_nway(struct net_device *dev)
+{
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ int csr14;
+ int csr12;
+
+ /* set up what to advertise during the negotiation */
+
+ /* load in csr14 and mask off bits not to touch
+ * comment at top of file explains mask value
+ */
+ csr14 = (inl(ioaddr + CSR14) & 0xfff0ee39);
+
+ /* bit 17 - advetise 100baseTx-FD */
+ if (tp->sym_advertise & 0x0100) csr14 |= 0x00020000;
+
+ /* bit 16 - advertise 100baseTx-HD */
+ if (tp->sym_advertise & 0x0080) csr14 |= 0x00010000;
+
+ /* bit 6 - advertise 10baseT-HD */
+ if (tp->sym_advertise & 0x0020) csr14 |= 0x00000040;
+
+ /* Now set bit 12 Link Test Enable, Bit 7 Autonegotiation Enable
+ * and bit 0 Don't PowerDown 10baseT
+ */
+ csr14 |= 0x00001184;
+
+ if (tulip_debug > 1)
+ printk(KERN_DEBUG "%s: Restarting PNIC2 autonegotiation, "
+ "csr14=%8.8x.\n", dev->name, csr14);
+
+ /* tell pnic2_lnk_change we are doing an nway negotiation */
+ dev->if_port = 0;
+ tp->nway = tp->mediasense = 1;
+ tp->nwayset = tp->lpar = 0;
+
+ /* now we have to set up csr6 for NWAY state */
+
+ tp->csr6 = inl(ioaddr + CSR6);
+ if (tulip_debug > 1)
+ printk(KERN_DEBUG "%s: On Entry to Nway, "
+ "csr6=%8.8x.\n", dev->name, tp->csr6);
+
+ /* mask off any bits not to touch
+ * comment at top of file explains mask value
+ */
+ tp->csr6 = tp->csr6 & 0xfe3bd1fd;
+
+ /* don't forget that bit 9 is also used for advertising */
+ /* advertise 10baseT-FD for the negotiation (bit 9) */
+ if (tp->sym_advertise & 0x0040) tp->csr6 |= 0x00000200;
+
+ /* set bit 24 for nway negotiation mode ...
+ * see Data Port Selection comment at top of file
+ * and "Stop" - reset both Transmit (bit 13) and Receive (bit 1)
+ */
+ tp->csr6 |= 0x01000000;
+ outl(csr14, ioaddr + CSR14);
+ outl(tp->csr6, ioaddr + CSR6);
+ udelay(100);
+
+ /* all set up so now force the negotiation to begin */
+
+ /* read in current values and mask off all but the
+ * Autonegotiation bits 14:12. Writing a 001 to those bits
+ * should start the autonegotiation
+ */
+ csr12 = (inl(ioaddr + CSR12) & 0xffff8fff);
+ csr12 |= 0x1000;
+ outl(csr12, ioaddr + CSR12);
+}
+
+
+
+void pnic2_lnk_change(struct net_device *dev, int csr5)
+{
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ int csr14;
+
+ /* read the staus register to find out what is up */
+ int csr12 = inl(ioaddr + CSR12);
+
+ if (tulip_debug > 1)
+ printk(KERN_INFO"%s: PNIC2 link status interrupt %8.8x, "
+ " CSR5 %x, %8.8x.\n", dev->name, csr12,
+ csr5, inl(ioaddr + CSR14));
+
+ /* If NWay finished and we have a negotiated partner capability.
+ * check bits 14:12 for bit pattern 101 - all is good
+ */
+ if (tp->nway && !tp->nwayset) {
+
+ /* we did an auto negotiation */
+
+ if ((csr12 & 0x7000) == 0x5000) {
+
+ /* negotiation ended successfully */
+
+ /* get the link partners reply and mask out all but
+ * bits 24-21 which show the partners capabilites
+ * and match those to what we advertised
+ *
+ * then begin to interpret the results of the negotiation.
+ * Always go in this order : (we are ignoring T4 for now)
+ * 100baseTx-FD, 100baseTx-HD, 10baseT-FD, 10baseT-HD
+ */
+
+ int negotiated = ((csr12 >> 16) & 0x01E0) & tp->sym_advertise;
+ tp->lpar = (csr12 >> 16);
+ tp->nwayset = 1;
+
+ if (negotiated & 0x0100) dev->if_port = 5;
+ else if (negotiated & 0x0080) dev->if_port = 3;
+ else if (negotiated & 0x0040) dev->if_port = 4;
+ else if (negotiated & 0x0020) dev->if_port = 0;
+ else {
+ if (tulip_debug > 1)
+ printk(KERN_INFO "%s: funny autonegotiate result "
+ "csr12 %8.8x advertising %4.4x\n",
+ dev->name, csr12, tp->sym_advertise);
+ tp->nwayset = 0;
+ /* so check if 100baseTx link state is okay */
+ if ((csr12 & 2) == 0 && (tp->sym_advertise & 0x0180))
+ dev->if_port = 3;
+ }
+
+ /* now record the duplex that was negotiated */
+ tp->full_duplex = 0;
+ if ((dev->if_port == 4) || (dev->if_port == 5))
+ tp->full_duplex = 1;
+
+ if (tulip_debug > 1) {
+ if (tp->nwayset)
+ printk(KERN_INFO "%s: Switching to %s based on link "
+ "negotiation %4.4x & %4.4x = %4.4x.\n",
+ dev->name, medianame[dev->if_port],
+ tp->sym_advertise, tp->lpar, negotiated);
+ }
+
+ /* remember to turn off bit 7 - autonegotiate
+ * enable so we can properly end nway mode and
+ * set duplex (ie. use csr6<9> again)
+ */
+ csr14 = (inl(ioaddr + CSR14) & 0xffffff7f);
+ outl(csr14,ioaddr + CSR14);
+
+
+ /* now set the data port and operating mode
+ * (see the Data Port Selection comments at
+ * the top of the file
+ */
+
+ /* get current csr6 and mask off bits not to touch */
+ /* see comment at top of file */
+
+ tp->csr6 = (inl(ioaddr + CSR6) & 0xfe3bd1fd);
+
+ /* so if using if_port 3 or 5 then select the 100baseT
+ * port else select the 10baseT port.
+ * See the Data Port Selection table at the top
+ * of the file which was taken from the PNIC_II.PDF
+ * datasheet
+ */
+ if (dev->if_port & 1) tp->csr6 |= 0x01840000;
+ else tp->csr6 |= 0x00400000;
+
+ /* now set the full duplex bit appropriately */
+ if (tp->full_duplex) tp->csr6 |= 0x00000200;
+
+ outl(1, ioaddr + CSR13);
+
+ if (tulip_debug > 2)
+ printk(KERN_DEBUG "%s: Setting CSR6 %8.8x/%x CSR12 "
+ "%8.8x.\n", dev->name, tp->csr6,
+ inl(ioaddr + CSR6), inl(ioaddr + CSR12));
+
+ /* now the following actually writes out the
+ * new csr6 values
+ */
+ tulip_start_rxtx(tp);
+
+ return;
+
+ } else {
+ printk(KERN_INFO "%s: Autonegotiation failed, "
+ "using %s, link beat status %4.4x.\n",
+ dev->name, medianame[dev->if_port], csr12);
+
+ /* remember to turn off bit 7 - autonegotiate
+ * enable so we don't forget
+ */
+ csr14 = (inl(ioaddr + CSR14) & 0xffffff7f);
+ outl(csr14,ioaddr + CSR14);
+
+ /* what should we do when autonegotiate fails?
+ * should we try again or default to baseline
+ * case. I just don't know.
+ *
+ * for now default to some baseline case
+ */
+
+ dev->if_port = 0;
+ tp->nway = 0;
+ tp->nwayset = 1;
+
+ /* set to 10baseTx-HD - see Data Port Selection
+ * comment given at the top of the file
+ */
+ tp->csr6 = (inl(ioaddr + CSR6) & 0xfe3bd1fd);
+ tp->csr6 |= 0x00400000;
+
+ tulip_restart_rxtx(tp);
+


+ return;
+
+ }
+ }

+
+ if ((tp->nwayset && (csr5 & 0x08000000)
+ && (dev->if_port == 3 || dev->if_port == 5)
+ && (csr12 & 2) == 2) || (tp->nway && (csr5 & (TPLnkFail)))) {
+
+ /* Link blew? Maybe restart NWay. */
+
+ if (tulip_debug > 2)
+ printk(KERN_DEBUG "%s: Ugh! Link blew?\n", dev->name);
+
+ del_timer_sync(&tp->timer);
+ pnic2_start_nway(dev);
+ tp->timer.expires = RUN_AT(3*HZ);
+ add_timer(&tp->timer);
+


+ return;
+ }
+
+

+ if (dev->if_port == 3 || dev->if_port == 5) {
+
+ /* we are at 100mb and a potential link change occurred */
+
+ if (tulip_debug > 1)
+ printk(KERN_INFO"%s: PNIC2 %s link beat %s.\n",
+ dev->name, medianame[dev->if_port],
+ (csr12 & 2) ? "failed" : "good");
+
+ /* check 100 link beat */
+
+ tp->nway = 0;
+ tp->nwayset = 1;
+
+ /* if failed then try doing an nway to get in sync */
+ if ((csr12 & 2) && ! tp->medialock) {
+ del_timer_sync(&tp->timer);
+ pnic2_start_nway(dev);
+ tp->timer.expires = RUN_AT(3*HZ);
+ add_timer(&tp->timer);
+ }
+
+ return;
+ }
+
+ if (dev->if_port == 0 || dev->if_port == 4) {
+
+ /* we are at 10mb and a potential link change occurred */
+
+ if (tulip_debug > 1)
+ printk(KERN_INFO"%s: PNIC2 %s link beat %s.\n",
+ dev->name, medianame[dev->if_port],
+ (csr12 & 4) ? "failed" : "good");
+
+
+ tp->nway = 0;
+ tp->nwayset = 1;
+
+ /* if failed, try doing an nway to get in sync */
+ if ((csr12 & 4) && ! tp->medialock) {
+ del_timer_sync(&tp->timer);
+ pnic2_start_nway(dev);
+ tp->timer.expires = RUN_AT(3*HZ);
+ add_timer(&tp->timer);
+ }
+


+ return;
+ }
+
+

+ if (tulip_debug > 1)
+ printk(KERN_INFO"%s: PNIC2 Link Change Default?\n",dev->name);
+
+ /* if all else fails default to trying 10baseT-HD */
+ dev->if_port = 0;
+
+ /* make sure autonegotiate enable is off */
+ csr14 = (inl(ioaddr + CSR14) & 0xffffff7f);
+ outl(csr14,ioaddr + CSR14);
+
+ /* set to 10baseTx-HD - see Data Port Selection
+ * comment given at the top of the file
+ */
+ tp->csr6 = (inl(ioaddr + CSR6) & 0xfe3bd1fd);
+ tp->csr6 |= 0x00400000;
+
+ tulip_restart_rxtx(tp);
+}
+
diff -u --recursive --new-file v2.4.14/linux/drivers/net/tulip/tulip.h linux/drivers/net/tulip/tulip.h
--- v2.4.14/linux/drivers/net/tulip/tulip.h Tue Jul 3 17:08:20 2001
+++ linux/drivers/net/tulip/tulip.h Fri Nov 9 13:45:35 2001
@@ -118,7 +118,7 @@
X };
X
X /* register offset and bits for CFDD PCI config reg */
-enum pci_cfg_driver_reg {
+enum pci_cfg_driver_reg {
X CFDD = 0x40,
X CFDD_Sleep = (1 << 31),
X CFDD_Snooze = (1 << 30),
@@ -405,6 +405,12 @@
X void t21142_timer(unsigned long data);
X void t21142_start_nway(struct net_device *dev);
X void t21142_lnk_change(struct net_device *dev, int csr5);
+
+
+/* PNIC2.c */
+void pnic2_lnk_change(struct net_device *dev, int csr5);
+void pnic2_timer(unsigned long data);
+void pnic2_start_nway(struct net_device *dev);
X void pnic2_lnk_change(struct net_device *dev, int csr5);
X
X /* eeprom.c */
diff -u --recursive --new-file v2.4.14/linux/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c
--- v2.4.14/linux/drivers/net/tulip/tulip_core.c Tue Oct 23 22:48:51 2001
+++ linux/drivers/net/tulip/tulip_core.c Mon Nov 19 15:19:42 2001
@@ -15,8 +15,8 @@
X */
X
X #define DRV_NAME "tulip"
-#define DRV_VERSION "0.9.15-pre8"
-#define DRV_RELDATE "Oct 11, 2001"
+#define DRV_VERSION "0.9.15-pre9"
+#define DRV_RELDATE "Nov 6, 2001"
X
X #include <linux/config.h>
X #include <linux/module.h>
@@ -30,6 +30,10 @@
X #include <asm/unaligned.h>
X #include <asm/uaccess.h>
X
+#ifdef __sparc__
+#include <asm/pbm.h>
+#endif
+


X static char version[] __devinitdata =

X "Linux Tulip driver version " DRV_VERSION " (" DRV_RELDATE ")\n";
X
@@ -165,7 +169,7 @@
X
X /* PNIC2 */
X { "Lite-On PNIC-II", 256, 0x0801fbff,
- HAS_MII | HAS_NWAY | HAS_8023X | HAS_PCI_MWI, t21142_timer },
+ HAS_MII | HAS_NWAY | HAS_8023X | HAS_PCI_MWI, pnic2_timer },
X
X /* COMET */
X { "ADMtek Comet", 256, 0x0001abef,
@@ -261,7 +265,7 @@
X if (tmp != newtmp)
X pci_write_config_dword (tp->pdev, CFDD, newtmp);
X }
-
+
X }
X
X
@@ -297,14 +301,6 @@
X tp->cur_rx = tp->cur_tx = 0;
X tp->dirty_rx = tp->dirty_tx = 0;
X
- if (tp->chip_id == PNIC2) {
- u32 addr_high = (dev->dev_addr[1]<<8) + (dev->dev_addr[0]<<0);
- /* This address setting does not appear to impact chip operation?? */
- outl((dev->dev_addr[5]<<8) + dev->dev_addr[4] +
- (dev->dev_addr[3]<<24) + (dev->dev_addr[2]<<16),
- ioaddr + 0xB0);
- outl(addr_high + (addr_high<<16), ioaddr + 0xB8);
- }
X if (tp->flags & MC_HASH_ONLY) {
X u32 addr_low = cpu_to_le32(get_unaligned((u32 *)dev->dev_addr));
X u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(dev->dev_addr+4)));
@@ -420,7 +416,12 @@
X } else
X t21142_start_nway(dev);
X } else if (tp->chip_id == PNIC2) {
- t21142_start_nway(dev);
+ /* for initial startup advertise 10/100 Full and Half */
+ tp->sym_advertise = 0x01E0;
+ /* enable autonegotiate end interrupt */
+ outl(inl(ioaddr+CSR5)| 0x00008010, ioaddr + CSR5);
+ outl(inl(ioaddr+CSR7)| 0x00008010, ioaddr + CSR7);
+ pnic2_start_nway(dev);
X } else if (tp->chip_id == LC82C168 && ! tp->medialock) {
X if (tp->mii_cnt) {
X dev->if_port = 11;
@@ -901,7 +902,7 @@
X {
X struct tulip_private *np = dev->priv;
X u32 ethcmd;
-
+
X if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
X return -EFAULT;
X
@@ -917,7 +918,7 @@
X }
X
X }
-
+
X return -EOPNOTSUPP;
X }
X
@@ -971,7 +972,7 @@
X case 4:
X /* Advertised value, bogus 10baseTx-FD value from CSR6. */
X data->val_out =
- ((inl(ioaddr + CSR6) >> 3) & 0x0040) +
+ ((inl(ioaddr + CSR6) >> 3) & 0x0040) +
X ((csr14 >> 1) & 0x20) + 1;
X if (tp->chip_id != DC21041)
X data->val_out |= ((csr14 >> 9) & 0x03C0);
@@ -1007,8 +1008,13 @@
X if (data->phy_id == 32 && (tp->flags & HAS_NWAY)) {
X u16 value = data->val_in;
X if (regnum == 0) {
- if ((value & 0x1200) == 0x1200)
- t21142_start_nway (dev);
+ if ((value & 0x1200) == 0x1200) {
+ if (tp->chip_id == PNIC2) {
+ pnic2_start_nway (dev);
+ } else {
+ t21142_start_nway (dev);
+ }
+ }
X } else if (regnum == 4)
X tp->sym_advertise = value;
X } else {
@@ -1257,7 +1263,7 @@
X u8 cache;
X u16 pci_command, new_command;
X u32 csr0;
-
+
X if (tulip_debug > 3)
X printk(KERN_DEBUG "%s: tulip_mwi_config()\n", pdev->slot_name);
X
@@ -1283,7 +1289,7 @@
X
X /* if we have any cache line size at all, we can do MRM */
X csr0 |= MRM;
-
+
X /* ...and barring hardware bugs, MWI */
X if (!(tp->chip_id == DC21143 && tp->revision == 65))
X csr0 |= MWI;
@@ -1321,8 +1327,7 @@
X
X tp->csr0 = csr0;
X goto out;
-
-early_out:
+
X if (csr0 & MWI) {
X pci_command &= ~PCI_COMMAND_INVALIDATE;
X pci_write_config_word(pdev, PCI_COMMAND, pci_command);
@@ -1369,16 +1374,16 @@
X * Lan media wire a tulip chip to a wan interface. Needs a very
X * different driver (lmc driver)
X */
-
+
X if (pdev->subsystem_vendor == PCI_VENDOR_ID_LMC) {
X printk (KERN_ERR PFX "skipping LMC card.\n");
X return -ENODEV;
X }
-
+
X /*
X * Early DM9100's need software CRC and the DMFE driver
X */
-
+
X if (pdev->vendor == 0x1282 && pdev->device == 0x9100)
X {
X u32 dev_rev;
@@ -1390,17 +1395,17 @@


X return -ENODEV;
X }
X }

-
+
X /*
- * Looks for early PCI chipsets where people report hangs
+ * Looks for early PCI chipsets where people report hangs
X * without the workarounds being on.
X */
-
- /* Intel Saturn. Switch to 8 long words burst, 8 long word cache aligned
+
+ /* Intel Saturn. Switch to 8 long words burst, 8 long word cache aligned
X Aries might need this too. The Saturn errata are not pretty reading but
X thankfully its an old 486 chipset.
X */
-
+
X if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424, NULL)) {
X csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift);
X force_csr0 = 1;
@@ -1410,25 +1415,31 @@
X csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift);
X force_csr0 = 1;
X }
-
+
X /* bugfix: the ASIX must have a burst limit or horrible things happen. */
X if (chip_idx == AX88140) {
X if ((csr0 & 0x3f00) == 0)
X csr0 |= 0x2000;
X }
-
+
X /* PNIC doesn't have MWI/MRL/MRM... */
X if (chip_idx == LC82C168)
X csr0 &= ~0xfff10000; /* zero reserved bits 31:20, 16 */
X
- /* DM9102A has troubles with MRM, clear bit 24 too. */
+ /* DM9102A has troubles with MRM & clear reserved bits 24:22, 20, 16, 7:1 */
X if (pdev->vendor == 0x1282 && pdev->device == 0x9102)
- csr0 &= ~0x01200000;
+ csr0 &= ~0x01f100ff;
+
+#if defined(__sparc__)
+ /* DM9102A needs 32-dword alignment/burst length on sparc - chip bug? */
+ if (pdev->vendor == 0x1282 && pdev->device == 0x9102)
+ csr0 = (csr0 & ~0xff00) | 0xe000;
+#endif
X
X /*
X * And back to business
X */
-
+
X i = pci_enable_device(pdev);
X if (i) {
X printk (KERN_ERR PFX
@@ -1575,6 +1586,22 @@
X sa_offset = 2; /* Grrr, damn Matrox boards. */
X multiport_cnt = 4;
X }
+#ifdef CONFIG_DDB5476
+ if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 6)) {
+ /* DDB5476 MAC address in first EEPROM locations. */
+ sa_offset = 0;
+ /* No media table either */
+ tp->flags &= ~HAS_MEDIA_TABLE;
+ }
+#endif
+#ifdef CONFIG_DDB5477
+ if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 4)) {
+ /* DDB5477 MAC address in first EEPROM locations. */
+ sa_offset = 0;
+ /* No media table either */
+ tp->flags &= ~HAS_MEDIA_TABLE;
+ }
+#endif
X for (i = 0; i < 6; i ++) {
X dev->dev_addr[i] = ee_data[i + sa_offset];
X sum += ee_data[i + sa_offset];
@@ -1590,14 +1617,26 @@
X }
X /* On the Zynx 315 Etherarray and other multiport boards only the
X first Tulip has an EEPROM.
+ On Sparc systems the mac address is held in the OBP property
+ "local-mac-address".
X The addresses of the subsequent ports are derived from the first.
X Many PCI BIOSes also incorrectly report the IRQ line, so we correct
X that here as well. */
X if (sum == 0 || sum == 6*0xff) {
+#if defined(__sparc__)
+ struct pcidev_cookie *pcp = pdev->sysdata;
+#endif
X eeprom_missing = 1;
X for (i = 0; i < 5; i++)
X dev->dev_addr[i] = last_phys_addr[i];
X dev->dev_addr[i] = last_phys_addr[i] + 1;
+#if defined(__sparc__)
+ if ((pcp != NULL) && prom_getproplen(pcp->prom_node,
+ "local-mac-address") == 6) {
+ prom_getproperty(pcp->prom_node, "local-mac-address",
+ dev->dev_addr, 6);
+ }
+#endif
X #if defined(__i386__) /* Patch up x86 BIOS bug. */
X if (last_irq)
X irq = last_irq;
@@ -1690,10 +1729,10 @@
X printk("%c%2.2X", i ? ':' : ' ', dev->dev_addr[i]);
X printk(", IRQ %d.\n", irq);
X
- if ((tp->flags & HAS_NWAY) || tp->chip_id == DC21041)
- tp->link_change = t21142_lnk_change;
- else if (tp->chip_id == PNIC2)
+ if (tp->chip_id == PNIC2)
X tp->link_change = pnic2_lnk_change;
+ else if ((tp->flags & HAS_NWAY) || tp->chip_id == DC21041)
+ tp->link_change = t21142_lnk_change;
X else if (tp->flags & HAS_PNICNWAY)
X tp->link_change = pnic_lnk_change;
X
@@ -1719,7 +1758,6 @@
X outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
X break;
X case DC21142:
- case PNIC2:
X if (tp->mii_cnt || tulip_media_cap[dev->if_port] & MediaIsMII) {
X outl(csr6_mask_defstate, ioaddr + CSR6);
X outl(0x0000, ioaddr + CSR13);
@@ -1727,6 +1765,11 @@
X outl(csr6_mask_hdcap, ioaddr + CSR6);
X } else
X t21142_start_nway(dev);
+ break;
+ case PNIC2:
+ /* just do a reset for sanity sake */
+ outl(0x0000, ioaddr + CSR13);
+ outl(0x0000, ioaddr + CSR14);
X break;
X case LC82C168:
X if ( ! tp->mii_cnt) {
diff -u --recursive --new-file v2.4.14/linux/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c
--- v2.4.14/linux/drivers/net/via-rhine.c Tue Oct 23 22:48:51 2001
+++ linux/drivers/net/via-rhine.c Fri Nov 9 13:45:36 2001
@@ -73,6 +73,9 @@
X - David Woodhouse: Set dev->base_addr before the first time we call
X wait_for_reset(). It's a lot happier that way.
X Free np->tx_bufs only if we actually allocated it.
+
+ LK1.1.12:
+ - Martin Eriksson: Allow Memory-Mapped IO to be enabled.
X */
X
X

@@ -155,7 +158,7 @@
X

X /* These identify the driver base version and may not be removed. */


X static char version[] __devinitdata =

-KERN_INFO "via-rhine.c:v1.10-LK1.1.11 20/08/2001 Written by Donald Becker\n"
+KERN_INFO "via-rhine.c:v1.10-LK1.1.12 03/11/2001 Written by Donald Becker\n"
X KERN_INFO " http://www.scyld.com/network/via-rhine.html\n";
X
X static char shortname[] __devinitdata = "via-rhine";
@@ -163,9 +166,8 @@
X
X /* This driver was written to use PCI memory space, however most versions
X of the Rhine only work correctly with I/O space accesses. */
-#if defined(VIA_USE_MEMORY)
-#warning Many adapters using the VIA Rhine chip are not configured to work
-#warning with PCI memory space accesses.
+#ifdef CONFIG_VIA_RHINE_MMIO
+#define USE_MEM
X #else
X #define USE_IO
X #undef readb
@@ -318,12 +320,10 @@
X CanHaveMII=1, HasESIPhy=2, HasDavicomPhy=4,
X ReqTxAlign=0x10, HasWOL=0x20, };
X
-#if defined(VIA_USE_MEMORY)
+#ifdef USE_MEM
X #define RHINE_IOTYPE (PCI_USES_MEM | PCI_USES_MASTER | PCI_ADDR1)
-#define RHINEII_IOSIZE 4096
X #else
X #define RHINE_IOTYPE (PCI_USES_IO | PCI_USES_MASTER | PCI_ADDR0)
-#define RHINEII_IOSIZE 256
X #endif
X
X /* directly indexed by enum via_rhine_chips, above */
@@ -331,7 +331,7 @@
X {
X { "VIA VT86C100A Rhine", RHINE_IOTYPE, 128,
X CanHaveMII | ReqTxAlign },
- { "VIA VT6102 Rhine-II", RHINE_IOTYPE, RHINEII_IOSIZE,
+ { "VIA VT6102 Rhine-II", RHINE_IOTYPE, 256,
X CanHaveMII | HasWOL },
X { "VIA VT3043 Rhine", RHINE_IOTYPE, 128,
X CanHaveMII | ReqTxAlign }
@@ -355,10 +355,19 @@
X RxRingPtr=0x18, TxRingPtr=0x1C, GFIFOTest=0x54,
X MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIBusConfig=0x6E,
X MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72, MACRegEEcsr=0x74,
- Config=0x78, ConfigA=0x7A, RxMissed=0x7C, RxCRCErrs=0x7E,
+ ConfigA=0x78, ConfigB=0x79, ConfigC=0x7A, ConfigD=0x7B,
+ RxMissed=0x7C, RxCRCErrs=0x7E,
X StickyHW=0x83, WOLcrClr=0xA4, WOLcgClr=0xA7, PwrcsrClr=0xAC,
X };
X
+#ifdef USE_MEM
+/* Registers we check that mmio and reg are the same. */
+int mmio_verify_registers[] = {
+ RxConfig, TxConfig, IntrEnable, ConfigA, ConfigB, ConfigC, ConfigD,
+ 0
+};
+#endif
+
X /* Bits in the interrupt status/mask registers. */
X enum intr_status_bits {
X IntrRxDone=0x0001, IntrRxErr=0x0004, IntrRxEmpty=0x0020,
@@ -505,6 +514,31 @@
X name, 5*i);
X }
X
+#ifdef USE_MEM
+static void __devinit enable_mmio(long ioaddr, int chip_id)
+{
+ int n;
+ if (chip_id == VT3043 || chip_id == VT86C100A) {
+ /* More recent docs say that this bit is reserved ... */
+ n = inb(ioaddr + ConfigA) | 0x20;
+ outb(n, ioaddr + ConfigA);
+ } else if (chip_id == VT6102) {
+ n = inb(ioaddr + ConfigD) | 0x80;
+ outb(n, ioaddr + ConfigD);
+ }
+}
+#endif
+
+static void __devinit reload_eeprom(long ioaddr)
+{
+ int i;
+ outb(0x20, ioaddr + MACRegEEcsr);
+ /* Typically 2 cycles to reload. */
+ for (i = 0; i < 150; i++)
+ if (! (inb(ioaddr + MACRegEEcsr) & 0x20))
+ break;
+}
+
X static int __devinit via_rhine_init_one (struct pci_dev *pdev,
X const struct pci_device_id *ent)
X {
@@ -514,8 +548,12 @@
X int chip_id = (int) ent->driver_data;
X static int card_idx = -1;
X long ioaddr;
+ long memaddr;
X int io_size;
X int pci_flags;
+#ifdef USE_MEM
+ long ioaddr0;
+#endif
X
X /* when built into the kernel, we only print version if device is found */
X #ifndef MODULE
@@ -545,8 +583,9 @@
X goto err_out;
X }
X
- ioaddr = pci_resource_start (pdev, pci_flags & PCI_ADDR0 ? 0 : 1);
-
+ ioaddr = pci_resource_start (pdev, 0);
+ memaddr = pci_resource_start (pdev, 1);
+
X if (pci_flags & PCI_USES_MASTER)
X pci_set_master (pdev);
X
@@ -560,14 +599,29 @@
X if (pci_request_regions(pdev, shortname))
X goto err_out_free_netdev;
X
-#ifndef USE_IO
- ioaddr = (long) ioremap (ioaddr, io_size);
+#ifdef USE_MEM
+ ioaddr0 = ioaddr;
+ enable_mmio(ioaddr0, chip_id);
+
+ ioaddr = (long) ioremap (memaddr, io_size);
X if (!ioaddr) {
- printk (KERN_ERR "ioremap failed for device %s, region 0x%X @ 0x%X\n",
- pdev->slot_name, io_size,
- pci_resource_start (pdev, 1));
+ printk (KERN_ERR "ioremap failed for device %s, region 0x%X @ 0x%lX\n",
+ pdev->slot_name, io_size, memaddr);
X goto err_out_free_res;
X }
+
+ /* Check that selected MMIO registers match the PIO ones */
+ i = 0;
+ while (mmio_verify_registers[i]) {
+ int reg = mmio_verify_registers[i++];
+ unsigned char a = inb(ioaddr0+reg);
+ unsigned char b = readb(ioaddr+reg);
+ if (a != b) {
+ printk (KERN_ERR "MMIO do not match PIO [%02x] (%02x != %02x)\n",
+ reg, a, b);
+ goto err_out_unmap;
+ }
+ }
X #endif
X
X /* D-Link provided reset code (with comment additions) */
@@ -595,11 +649,16 @@
X wait_for_reset(dev, shortname);
X
X /* Reload the station address from the EEPROM. */
- writeb(0x20, ioaddr + MACRegEEcsr);
- /* Typically 2 cycles to reload. */
- for (i = 0; i < 150; i++)
- if (! (readb(ioaddr + MACRegEEcsr) & 0x20))
- break;
+#ifdef USE_IO
+ reload_eeprom(ioaddr);
+#else
+ reload_eeprom(ioaddr0);
+ /* Reloading from eeprom overwrites cfgA-D, so we must re-enable MMIO.
+ If reload_eeprom() was done first this could be avoided, but it is
+ not known if that still works with the "win98-reboot" problem. */
+ enable_mmio(ioaddr0, chip_id);
+#endif
+
X for (i = 0; i < 6; i++)
X dev->dev_addr[i] = readb(ioaddr + StationAddr + i);
X
@@ -660,7 +719,9 @@
X goto err_out_unmap;
X
X printk(KERN_INFO "%s: %s at 0x%lx, ",
- dev->name, via_rhine_chip_info[chip_id].name, ioaddr);
+ dev->name, via_rhine_chip_info[chip_id].name,
+ (pci_flags & PCI_USES_IO) ? ioaddr : memaddr);
+
X for (i = 0; i < 5; i++)
X printk("%2.2x:", dev->dev_addr[i]);
X printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], pdev->irq);
@@ -711,7 +772,7 @@
X return 0;
X
X err_out_unmap:
-#ifndef USE_IO
+#ifdef USE_MEM
X iounmap((void *)ioaddr);
X err_out_free_res:
X #endif
@@ -1587,18 +1648,17 @@
X static void __devexit via_rhine_remove_one (struct pci_dev *pdev)
X {
X struct net_device *dev = pci_get_drvdata(pdev);
- struct netdev_private *np = dev->priv;
X
X unregister_netdev(dev);
X
X pci_release_regions(pdev);
X
-#ifndef USE_IO
+#ifdef USE_MEM
X iounmap((char *)(dev->base_addr));
X #endif
X
X kfree(dev);
-
+ pci_disable_device(pdev);
X pci_set_drvdata(pdev, NULL);
X }
X
diff -u --recursive --new-file v2.4.14/linux/drivers/net/wan/dscc4.c linux/drivers/net/wan/dscc4.c
--- v2.4.14/linux/drivers/net/wan/dscc4.c Sun Sep 23 11:40:59 2001
+++ linux/drivers/net/wan/dscc4.c Fri Nov 9 13:41:42 2001
@@ -672,7 +672,6 @@
X ppriv->root = dev;
X ppriv->pdev = pdev;
X spin_lock_init(&ppriv->lock);
- pdev->driver_data = ppriv;
X pci_set_drvdata(pdev, ppriv);
X return 0;
X
diff -u --recursive --new-file v2.4.14/linux/drivers/net/wan/farsync.c linux/drivers/net/wan/farsync.c
--- v2.4.14/linux/drivers/net/wan/farsync.c Sun Sep 23 11:40:59 2001
+++ linux/drivers/net/wan/farsync.c Fri Nov 9 13:41:42 2001
@@ -1746,7 +1746,7 @@
X }
X
X /* Record driver data for later use */
- pdev->driver_data = card;
+ pci_set_drvdata(pdev, card);
X
X /* Remainder of card setup */
X fst_init_card ( card );
@@ -1785,7 +1785,7 @@
X struct fst_card_info *card;
X int i;
X
- card = pdev->driver_data;
+ card = pci_get_drvdata(pdev);
X
X for ( i = 0 ; i < card->nports ; i++ )
X {
diff -u --recursive --new-file v2.4.14/linux/drivers/net/wan/z85230.c linux/drivers/net/wan/z85230.c
--- v2.4.14/linux/drivers/net/wan/z85230.c Sun Sep 23 11:40:59 2001
+++ linux/drivers/net/wan/z85230.c Fri Nov 9 14:03:11 2001
@@ -4,8 +4,8 @@
X * as published by the Free Software Foundation; either version
X * 2 of the License, or (at your option) any later version.
X *
- * (c) Copyright 1998 Building Number Three Ltd
- * (c) Copyright 2000 Red Hat Software
+ * (c) Copyright 1998 Alan Cox <al...@lxorguk.ukuu.org.uk>
+ * (c) Copyright 2000, 2001 Red Hat Inc
X *
X * Development of this driver was funded by Equiinet Ltd
X * http://www.equiinet.com
@@ -18,6 +18,8 @@
X * DMA now uses get_free_page as kmalloc buffers may span a 64K
X * boundary.
X *
+ * Modified for SMP safety and SMP locking by Alan Cox <al...@redhat.com>
+ *
X * Performance
X *
X * Z85230:
@@ -53,8 +55,6 @@
X #include "z85230.h"
X
X
-static spinlock_t z8530_buffer_lock = SPIN_LOCK_UNLOCKED;
-
X /**
X * z8530_read_port - Architecture specific interface function
X * @p: port to read
@@ -116,21 +116,14 @@
X *
X * Most of the Z8530 registers are indexed off the control registers.
X * A read is done by writing to the control register and reading the
- * register back. We do the locking needed to protect this
- * operation.
+ * register back. The caller must hold the lock
X */
X
X static inline u8 read_zsreg(struct z8530_channel *c, u8 reg)
X {
- u8 r;
- unsigned long flags;
- save_flags(flags);
- cli();
X if(reg)
X z8530_write_port(c->ctrlio, reg);
- r=z8530_read_port(c->ctrlio);
- restore_flags(flags);
- return r;
+ return z8530_read_port(c->ctrlio);
X }
X
X /**
@@ -154,7 +147,7 @@
X * @reg: Register number
X * @val: Value to write
X *
- * Write a value to an indexed register. Perform the locking needed
+ * Write a value to an indexed register. The caller must hold the lock
X * to honour the irritating delay rules. We know about register 0
X * being fast to access.
X */
@@ -162,12 +155,14 @@
X static inline void write_zsreg(struct z8530_channel *c, u8 reg, u8 val)
X {
X unsigned long flags;
- save_flags(flags);
- cli();
+
+ spin_lock_irqsave(c->lock, flags);
+
X if(reg)
X z8530_write_port(c->ctrlio, reg);
X z8530_write_port(c->ctrlio, val);
- restore_flags(flags);
+
+ spin_unlock_irqrestore(c->lock, flags);
X }
X
X /**
@@ -299,7 +294,7 @@
X * @set: 1 to set, 0 to clear
X *
X * Sets or clears DTR/RTS on the requested line. All locking is handled
- * for the caller. For now we assume all boards use the actual RTS/DTR
+ * by the caller. For now we assume all boards use the actual RTS/DTR
X * on the chip. Apparently one or two don't. We'll scream about them
X * later.
X */
@@ -333,12 +328,14 @@
X * do it yourself but consider medical assistance first. This non DMA
X * synchronous mode is portable code. The DMA mode assumes PCI like
X * ISA DMA
+ *
+ * Called with the device lock held
X */
X
X static void z8530_rx(struct z8530_channel *c)
X {
X u8 ch,stat;
-
+
X while(1)
X {
X /* FIFO empty ? */
@@ -382,6 +379,10 @@
X }
X else
X {
+ /*
+ * Drop the lock for RX processing, or
+ * there are deadlocks
+ */
X z8530_rx_done(c);
X write_zsctrl(c, RES_Rx_CRC);
X }
@@ -407,8 +408,7 @@
X
X static void z8530_tx(struct z8530_channel *c)
X {
- while(c->txcount)
- {
+ while(c->txcount) {
X /* FIFO full ? */
X if(!(read_zsreg(c, R0)&4))
X break;
@@ -424,8 +424,8 @@
X write_zsctrl(c, RES_EOM_L);
X write_zsreg(c, R10, c->regs[10]&~ABUNDER);
X }
- return;
X }
+
X
X /*
X * End of frame TX - fire another one
@@ -434,7 +434,6 @@
X write_zsctrl(c, RES_Tx_P);
X
X z8530_tx_done(c);
-/* write_zsreg(c, R8, *c->tx_ptr++); */
X write_zsctrl(c, RES_H_IUS);
X }
X
@@ -451,8 +450,10 @@
X
X static void z8530_status(struct z8530_channel *chan)
X {
- u8 status=read_zsreg(chan, R0);
- u8 altered=chan->status^status;
+ u8 status, altered;
+
+ status=read_zsreg(chan, R0);
+ altered=chan->status^status;
X
X chan->status=status;
X

@@ -512,11 +513,12 @@
X {

X /* Special condition check only */
X u8 status;
-
+
X read_zsreg(chan, R7);
X read_zsreg(chan, R6);
X
X status=read_zsreg(chan, R1);
+
X if(status&END_FR)
X {
X z8530_rx_done(chan); /* Fire up the next one */
@@ -565,16 +567,20 @@
X
X static void z8530_dma_status(struct z8530_channel *chan)
X {
- unsigned long flags;
- u8 status=read_zsreg(chan, R0);
- u8 altered=chan->status^status;
+ u8 status, altered;
+
+ status=read_zsreg(chan, R0);
+ altered=chan->status^status;
X
X chan->status=status;
X
+
X if(chan->dma_tx)
X {
X if(status&TxEOM)
X {


+ unsigned long flags;
+

X flags=claim_dma_lock();
X disable_dma(chan->txdma);
X clear_dma_ff(chan->txdma);
@@ -706,6 +712,10 @@
X * the channel specific call backs for each channel that has events.
X * We have to use callback functions because the two channels can be
X * in different modes.
+ *
+ * Locking is done for the handlers. Note that locking is done
+ * at the chip level (the 5uS delay issue is per chip not per
+ * channel). c->lock for both channels points to dev->lock
X */
X
X void z8530_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -714,6 +724,7 @@
X u8 intr;
X static volatile int locker=0;
X int work=0;
+ struct z8530_irqhandler *irqs=dev->chanA.irqs;
X
X if(locker)
X {
@@ -721,11 +732,12 @@
X return;
X }
X locker=1;
-
+
+ spin_lock(&dev->lock);
+
X while(++work<5000)
X {
- struct z8530_irqhandler *irqs=dev->chanA.irqs;
-
+
X intr = read_zsreg(&dev->chanA, R3);
X if(!(intr & (CHARxIP|CHATxIP|CHAEXT|CHBRxIP|CHBTxIP|CHBEXT)))
X break;
@@ -758,6 +770,7 @@
X irqs->status(&dev->chanB);
X }
X }
+ spin_unlock(&dev->lock);
X if(work==5000)
X printk(KERN_ERR "%s: interrupt jammed - abort(0x%X)!\n", dev->name, intr);
X /* Ok all done */
@@ -786,12 +799,17 @@
X
X int z8530_sync_open(struct net_device *dev, struct z8530_channel *c)
X {


+ unsigned long flags;
+

+ spin_lock_irqsave(c->lock, flags);
+
X c->sync = 1;
X c->mtu = dev->mtu+64;
X c->count = 0;
X c->skb = NULL;
X c->skb2 = NULL;
X c->irqs = &z8530_sync;
+
X /* This loads the double buffer up */
X z8530_rx_done(c); /* Load the frame ring */
X z8530_rx_done(c); /* Load the backup frame */
@@ -800,6 +818,8 @@
X c->regs[R1]|=TxINT_ENAB;
X write_zsreg(c, R1, c->regs[R1]);
X write_zsreg(c, R3, c->regs[R3]|RxENABLE);
+
+ spin_unlock_irqrestore(c->lock, flags);


X return 0;
X }
X

@@ -818,7 +838,9 @@
X int z8530_sync_close(struct net_device *dev, struct z8530_channel *c)
X {
X u8 chk;


+ unsigned long flags;
X

+ spin_lock_irqsave(c->lock, flags);
X c->irqs = &z8530_nop;
X c->max = 0;
X c->sync = 0;
@@ -826,6 +848,8 @@
X chk=read_zsreg(c,R0);
X write_zsreg(c, R3, c->regs[R3]);
X z8530_rtsdtr(c,0);
+
+ spin_unlock_irqrestore(c->lock, flags);


X return 0;
X }
X

@@ -887,6 +911,8 @@
X /*
X * Enable DMA control mode
X */
+
+ spin_lock_irqsave(c->lock, flags);
X
X /*
X * TX DMA via DIR/REQ
@@ -945,6 +971,8 @@
X c->irqs = &z8530_dma_sync;
X z8530_rtsdtr(c,1);
X write_zsreg(c, R3, c->regs[R3]|RxENABLE);
+
+ spin_unlock_irqrestore(c->lock, flags);


X
X return 0;
X }

@@ -986,6 +1014,8 @@
X c->txdma_on = 0;
X c->tx_dma_used = 0;
X
+ spin_lock_irqsave(c->lock, flags);
+
X /*
X * Disable DMA control mode
X */
@@ -1011,6 +1041,9 @@
X chk=read_zsreg(c,R0);
X write_zsreg(c, R3, c->regs[R3]);
X z8530_rtsdtr(c,0);
+
+ spin_unlock_irqrestore(c->lock, flags);


+
X return 0;
X }
X

@@ -1038,20 +1071,6 @@
X c->skb2 = NULL;
X
X /*
- * Load the PIO receive ring
- */
-
- z8530_rx_done(c);
- z8530_rx_done(c);
-
- /*
- * Load the DMA interfaces up
- */
-
- c->rxdma_on = 0;
- c->txdma_on = 0;
-
- /*
X * Allocate the DMA flip buffers. Limit by page size.
X * Everyone runs 1500 mtu or less on wan links so this
X * should be fine.
@@ -1066,6 +1085,23 @@
X
X c->tx_dma_buf[1] = c->tx_dma_buf[0] + PAGE_SIZE/2;
X
+
+ spin_lock_irqsave(c->lock, flags);
+
+ /*
+ * Load the PIO receive ring
+ */
+
+ z8530_rx_done(c);
+ z8530_rx_done(c);
+
+ /*
+ * Load the DMA interfaces up
+ */
+
+ c->rxdma_on = 0;
+ c->txdma_on = 0;
+
X c->tx_dma_used=0;
X c->dma_num=0;
X c->dma_ready=1;
@@ -1106,10 +1142,9 @@
X c->tx_dma_used = 1;
X
X c->irqs = &z8530_txdma_sync;
- printk("Loading RX\n");
X z8530_rtsdtr(c,1);
- printk("Rx interrupts ON\n");
X write_zsreg(c, R3, c->regs[R3]|RxENABLE);
+ spin_unlock_irqrestore(c->lock, flags);


X
X return 0;
X }

@@ -1129,6 +1164,9 @@
X {
X unsigned long flags;
X u8 chk;
+
+
+ spin_lock_irqsave(c->lock, flags);
X
X c->irqs = &z8530_nop;
X c->max = 0;
@@ -1208,25 +1246,11 @@
X
X EXPORT_SYMBOL(z8530_describe);
X
-/**
- * z8530_init - Initialise a Z8530 device
- * @dev: Z8530 device to initialise.
- *
- * Configure up a Z8530/Z85C30 or Z85230 chip. We check the device
- * is present, identify the type and then program it to hopefully
- * keep quite and behave. This matters a lot, a Z8530 in the wrong
- * state will sometimes get into stupid modes generating 10Khz
- * interrupt streams and the like.
- *
- * We set the interrupt handler up to discard any events, in case
- * we get them during reset or setp.
- *
- * Return 0 for success, or a negative value indicating the problem
- * in errno form.
+/*
+ * Locked operation part of the z8530 init code
X */
-
X
-int z8530_init(struct z8530_dev *dev)
+static int do_z8530_init(struct z8530_dev *dev)
X {
X /* NOP the interrupt handlers first - we might get a
X floating IRQ transition when we reset the chip */
@@ -1234,6 +1258,12 @@
X dev->chanB.irqs=&z8530_nop;
X dev->chanA.dcdcheck=DCD;
X dev->chanB.dcdcheck=DCD;
+
+ /* Set up the chip level lock */
+ spin_lock_init(&dev->lock);
+ dev->chanA.lock = &dev->lock;
+ dev->chanB.lock = &dev->lock;
+
X /* Reset the chip */
X write_zsreg(&dev->chanA, R9, 0xC0);
X udelay(200);
@@ -1287,6 +1317,40 @@


X return 0;
X }
X

+/**
+ * z8530_init - Initialise a Z8530 device
+ * @dev: Z8530 device to initialise.
+ *
+ * Configure up a Z8530/Z85C30 or Z85230 chip. We check the device
+ * is present, identify the type and then program it to hopefully
+ * keep quite and behave. This matters a lot, a Z8530 in the wrong
+ * state will sometimes get into stupid modes generating 10Khz
+ * interrupt streams and the like.
+ *
+ * We set the interrupt handler up to discard any events, in case
+ * we get them during reset or setp.
+ *
+ * Return 0 for success, or a negative value indicating the problem
+ * in errno form.
+ */
+
+int z8530_init(struct z8530_dev *dev)
+{


+ unsigned long flags;
+ int ret;
+

+ /* Set up the chip level lock */


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

echo 'End of part 055'
echo 'File patch-2.4.15 is continued in part 056'
echo "056" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:19 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part043

#!/bin/sh -x
# this is part 043 of a 115 - part archive


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

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

+ func->device, ctrl->slot_device_offset, hp_slot);
+

+ p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+ // turn on board and blink green LED


+
+ // Wait for exclusive access to hardware

+ dbg(__FUNCTION__": before down\n");
+ down(&ctrl->crit_sect);
+ dbg(__FUNCTION__": after down\n");
+
+ dbg(__FUNCTION__": before slot_enable\n");


+ slot_enable (ctrl, hp_slot);
+

+ dbg(__FUNCTION__": before green_LED_blink\n");


+ green_LED_blink (ctrl, hp_slot);
+

+ dbg(__FUNCTION__": before amber_LED_blink\n");


+ amber_LED_off (ctrl, hp_slot);
+

+ dbg(__FUNCTION__": before set_SOGO\n");


+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset

+ dbg(__FUNCTION__": before wait_for_ctrl_irq\n");
+ wait_for_ctrl_irq (ctrl);
+ dbg(__FUNCTION__": after wait_for_ctrl_irq\n");


+
+ // Done with exclusive hardware access

+ dbg(__FUNCTION__": before up\n");
+ up(&ctrl->crit_sect);
+ dbg(__FUNCTION__": after up\n");


+
+ // Wait for ~1 second because of hot plug spec

+ dbg(__FUNCTION__": before long_delay\n");
+ long_delay(1*HZ);
+ dbg(__FUNCTION__": after long_delay\n");
+
+ dbg(__FUNCTION__": func status = %x\n", func->status);


+ // Check for a power fault
+ if (func->status == 0xFF) {
+ // power fault occurred, but it was benign

+ temp_register = 0xFFFFFFFF;
+ dbg(__FUNCTION__": temp register set to %x by power fault\n", temp_register);


+ rc = POWER_FAILURE;
+ func->status = 0;
+ } else {

+ // Get vendor/device ID u32
+ rc = pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_VENDOR_ID, &temp_register);
+ dbg(__FUNCTION__": pci_read_config_dword returns %d\n", rc);
+ dbg(__FUNCTION__": temp_register is %x\n", temp_register);
+
+ if (rc != 0) {
+ // Something's wrong here
+ temp_register = 0xFFFFFFFF;
+ dbg(__FUNCTION__": temp register set to %x by error\n", temp_register);
+ }
+ // Preset return code. It will be changed later if things go okay.
+ rc = NO_ADAPTER_PRESENT;
+ }
+
+ // All F's is an empty slot or an invalid board
+ if (temp_register != 0xFFFFFFFF) { // Check for a board in the slot
+ res_lists.io_head = ctrl->io_head;
+ res_lists.mem_head = ctrl->mem_head;
+ res_lists.p_mem_head = ctrl->p_mem_head;
+ res_lists.bus_head = ctrl->bus_head;
+ res_lists.irqs = NULL;
+
+ rc = configure_new_device(ctrl, func, 0, &res_lists);
+
+ dbg(__FUNCTION__": back from configure_new_device\n");
+ ctrl->io_head = res_lists.io_head;
+ ctrl->mem_head = res_lists.mem_head;
+ ctrl->p_mem_head = res_lists.p_mem_head;
+ ctrl->bus_head = res_lists.bus_head;
+
+ cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
+ cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
+ cpqhp_resource_sort_and_combine(&(ctrl->io_head));
+ cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
+
+ if (rc) {


+ // Wait for exclusive access to hardware
+ down(&ctrl->crit_sect);
+
+ amber_LED_on (ctrl, hp_slot);
+ green_LED_off (ctrl, hp_slot);
+ slot_disable (ctrl, hp_slot);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);

+ return(rc);
+ } else {
+ cpqhp_save_slot_config(ctrl, func);
+ }


+
+
+ func->status = 0;
+ func->switch_save = 0x10;

+ func->is_a_board = 0x01;
+
+ //next, we will instantiate the linux pci_dev structures (with appropriate driver notification, if already present)
+ dbg(__FUNCTION__": configure linux pci_dev structure\n");
+ index = 0;
+ do {
+ new_slot = cpqhp_slot_find(ctrl->bus, func->device, index++);
+ if (new_slot && !new_slot->pci_dev) {
+ cpqhp_configure_device(ctrl, new_slot);
+ }
+ } while (new_slot);


+
+ // Wait for exclusive access to hardware
+ down(&ctrl->crit_sect);
+
+ green_LED_on (ctrl, hp_slot);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);

+ } else {


+ // Wait for exclusive access to hardware
+ down(&ctrl->crit_sect);
+
+ amber_LED_on (ctrl, hp_slot);
+ green_LED_off (ctrl, hp_slot);
+ slot_disable (ctrl, hp_slot);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);
+
+ return(rc);
+ }

+ return 0;
+}
+
+

+/**
+ * remove_board - Turns off slot and LED's
+ *
+ */
+static u32 remove_board(struct pci_func * func, u32 replace_flag, struct controller * ctrl)
+{
+ int index;
+ u8 skip = 0;
+ u8 device;


+ u8 hp_slot;
+ u8 temp_byte;

+ u32 rc;
+ struct resource_lists res_lists;
+ struct pci_func *temp_func;


+
+ if (func == NULL)
+ return(1);
+

+ if (cpqhp_unconfigure_device(func))
+ return(1);
+
+ device = func->device;


+
+ hp_slot = func->device - ctrl->slot_device_offset;

+ dbg("In "__FUNCTION__", hp_slot = %d\n", hp_slot);
+
+ // When we get here, it is safe to change base Address Registers.
+ // We will attempt to save the base Address Register Lengths
+ if (replace_flag || !ctrl->add_support)
+ rc = cpqhp_save_base_addr_length(ctrl, func);
+ else if (!func->bus_head && !func->mem_head &&
+ !func->p_mem_head && !func->io_head) {
+ // Here we check to see if we've saved any of the board's
+ // resources already. If so, we'll skip the attempt to
+ // determine what's being used.
+ index = 0;
+ temp_func = cpqhp_slot_find(func->bus, func->device, index++);
+ while (temp_func) {
+ if (temp_func->bus_head || temp_func->mem_head
+ || temp_func->p_mem_head || temp_func->io_head) {
+ skip = 1;
+ break;
+ }
+ temp_func = cpqhp_slot_find(temp_func->bus, temp_func->device, index++);
+ }
+
+ if (!skip)
+ rc = cpqhp_save_used_resources(ctrl, func);
+ }
+ // Change status to shutdown
+ if (func->is_a_board)
+ func->status = 0x01;
+ func->configured = 0;
+


+ // Wait for exclusive access to hardware
+ down(&ctrl->crit_sect);
+

+ green_LED_off (ctrl, hp_slot);
+ slot_disable (ctrl, hp_slot);
+
+ set_SOGO(ctrl);
+

+ // turn off SERR for slot
+ temp_byte = readb(ctrl->hpc_reg + SLOT_SERR);
+ temp_byte &= ~(0x01 << hp_slot);
+ writeb(temp_byte, ctrl->hpc_reg + SLOT_SERR);


+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);
+

+ if (!replace_flag && ctrl->add_support) {
+ while (func) {
+ res_lists.io_head = ctrl->io_head;
+ res_lists.mem_head = ctrl->mem_head;
+ res_lists.p_mem_head = ctrl->p_mem_head;
+ res_lists.bus_head = ctrl->bus_head;
+
+ cpqhp_return_board_resources(func, &res_lists);
+
+ ctrl->io_head = res_lists.io_head;
+ ctrl->mem_head = res_lists.mem_head;
+ ctrl->p_mem_head = res_lists.p_mem_head;
+ ctrl->bus_head = res_lists.bus_head;
+
+ cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
+ cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
+ cpqhp_resource_sort_and_combine(&(ctrl->io_head));
+ cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
+
+ if (is_bridge(func)) {
+ bridge_slot_remove(func);
+ } else
+ slot_remove(func);
+


+ func = cpqhp_slot_find(ctrl->bus, device, 0);
+ }

+
+ // Setup slot structure with entry for empty slot
+ func = cpqhp_slot_create(ctrl->bus);


+
+ if (func == NULL) {

+ // Out of memory
+ return(1);
+ }
+
+ func->bus = ctrl->bus;
+ func->device = device;
+ func->function = 0;
+ func->configured = 0;


+ func->switch_save = 0x10;

+ func->is_a_board = 0;
+ func->p_task_event = NULL;
+ }
+


+ return 0;
+}
+
+

+static void pushbutton_helper_thread (unsigned long data)
+{
+ pushbutton_pending = data;
+ up(&event_semaphore);
+}
+
+
+// this is the main worker thread
+static int event_thread(void* data)
+{
+ struct controller *ctrl;
+ lock_kernel();
+ daemonize();
+
+ // New name
+ strcpy(current->comm, "phpd_event");
+
+ unlock_kernel();
+
+ while (1) {
+ dbg("!!!!event_thread sleeping\n");
+ down_interruptible (&event_semaphore);
+ dbg("event_thread woken finished = %d\n", event_finished);
+ if (event_finished) break;
+ /* Do stuff here */
+ if (pushbutton_pending)
+ cpqhp_pushbutton_thread(pushbutton_pending);
+ else
+ for (ctrl = cpqhp_ctrl_list; ctrl; ctrl=ctrl->next)
+ interrupt_event_handler(ctrl);
+ }
+ dbg("event_thread signals exit\n");
+ up(&event_exit);


+ return 0;
+}
+
+

+int cpqhp_event_start_thread (void)
+{
+ int pid;
+
+ /* initialize our semaphores */
+ init_MUTEX(&delay_sem);
+ init_MUTEX_LOCKED(&event_semaphore);
+ init_MUTEX_LOCKED(&event_exit);
+ event_finished=0;
+
+ pid = kernel_thread(event_thread, 0, 0);
+ if (pid < 0) {
+ err ("Can't start up our event thread\n");
+ return -1;
+ }
+ dbg("Our event thread pid = %d\n", pid);


+ return 0;
+}
+
+

+void cpqhp_event_stop_thread (void)
+{
+ event_finished = 1;
+ dbg("event_thread finish command given\n");
+ up(&event_semaphore);
+ dbg("wait for event_thread to exit\n");
+ down(&event_exit);
+}
+
+
+static int update_slot_info (struct controller *ctrl, struct slot *slot)
+{
+ struct hotplug_slot_info *info;
+ char buffer[SLOT_NAME_SIZE];
+ int result;
+
+ info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot);
+ info->power_status = get_slot_enabled(ctrl, slot);
+ info->attention_status = cpq_get_attention_status(ctrl, slot);
+ info->latch_status = cpq_get_latch_status(ctrl, slot);
+ info->adapter_status = get_presence_status(ctrl, slot);
+ result = pci_hp_change_slot_info(buffer, info);
+ kfree (info);


+ return result;
+}
+

+static void interrupt_event_handler(struct controller *ctrl)

+{
+ int loop = 0;
+ int change = 1;
+ struct pci_func *func;
+ u8 hp_slot;


+ struct slot *p_slot;
+

+ while (change) {
+ change = 0;
+
+ for (loop = 0; loop < 10; loop++) {
+ //dbg("loop %d\n", loop);
+ if (ctrl->event_queue[loop].event_type != 0) {
+ hp_slot = ctrl->event_queue[loop].hp_slot;
+


+ func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);
+

+ p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+ dbg("hp_slot %d, func %p, p_slot %p\n",
+ hp_slot, func, p_slot);
+
+ if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {
+ dbg("button pressed\n");
+ } else if (ctrl->event_queue[loop].event_type ==
+ INT_BUTTON_CANCEL) {
+ dbg("button cancel\n");
+ del_timer(&p_slot->task_event);


+
+ // Wait for exclusive access to hardware
+ down(&ctrl->crit_sect);
+

+ if (p_slot->state == BLINKINGOFF_STATE) {
+ // slot is on
+ // turn on green LED
+ dbg("turn on green LED\n");
+ green_LED_on (ctrl, hp_slot);
+ } else if (p_slot->state == BLINKINGON_STATE) {
+ // slot is off
+ // turn off green LED
+ dbg("turn off green LED\n");


+ green_LED_off (ctrl, hp_slot);
+ }

+
+ info(msg_button_cancel, p_slot->number);
+
+ p_slot->state = STATIC_STATE;


+
+ amber_LED_off (ctrl, hp_slot);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);
+ }

+ // ***********button Released (No action on press...)
+ else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) {
+ dbg("button release\n");
+
+ if (is_slot_enabled (ctrl, hp_slot)) {
+ // slot is on
+ dbg("slot is on\n");
+ p_slot->state = BLINKINGOFF_STATE;
+ info(msg_button_off, p_slot->number);
+ } else {
+ // slot is off
+ dbg("slot is off\n");
+ p_slot->state = BLINKINGON_STATE;
+ info(msg_button_on, p_slot->number);


+ }
+ // Wait for exclusive access to hardware
+ down(&ctrl->crit_sect);
+

+ dbg("blink green LED and turn off amber\n");
+ amber_LED_off (ctrl, hp_slot);


+ green_LED_blink (ctrl, hp_slot);
+

+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+
+ // Done with exclusive hardware access
+ up(&ctrl->crit_sect);

+ init_timer(&p_slot->task_event);
+ p_slot->hp_slot = hp_slot;
+ p_slot->ctrl = ctrl;
+// p_slot->physical_slot = physical_slot;
+ p_slot->task_event.expires = jiffies + 5 * HZ; // 5 second delay
+ p_slot->task_event.function = pushbutton_helper_thread;
+ p_slot->task_event.data = (u32) p_slot;
+
+ dbg("add_timer p_slot = %p\n", p_slot);
+ add_timer(&p_slot->task_event);
+ }
+ // ***********POWER FAULT
+ else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
+ dbg("power fault\n");
+ } else {
+ /* refresh notification */
+ if (p_slot)
+ update_slot_info(ctrl, p_slot);
+ }
+
+ ctrl->event_queue[loop].event_type = 0;
+
+ change = 1;
+ }
+ } // End of FOR loop
+ }
+


+ return;
+}
+
+

+/**
+ * cpqhp_pushbutton_thread
+ *
+ * Scheduled procedure to handle blocking stuff for the pushbuttons
+ * Handles all pending events and exits.
+ *
+ */
+void cpqhp_pushbutton_thread (unsigned long slot)
+{
+ u8 hp_slot;
+ u8 device;
+ struct pci_func *func;
+ struct slot *p_slot = (struct slot *) slot;
+ struct controller *ctrl = (struct controller *) p_slot->ctrl;
+
+ pushbutton_pending = 0;
+ hp_slot = p_slot->hp_slot;
+
+ device = p_slot->device;
+
+ if (is_slot_enabled (ctrl, hp_slot)) {
+ p_slot->state = POWEROFF_STATE;
+ // power Down board
+ func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0);
+ dbg("In power_down_board, func = %p, ctrl = %p\n", func, ctrl);
+ if (!func) {
+ dbg("Error! func NULL in "__FUNCTION__"\n");
+ return ;
+ }
+
+ if (func != NULL && ctrl != NULL) {
+ if (cpqhp_process_SS(ctrl, func) != 0) {
+ amber_LED_on (ctrl, hp_slot);


+ green_LED_on (ctrl, hp_slot);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+ }
+ }

+
+ p_slot->state = STATIC_STATE;
+ } else {
+ p_slot->state = POWERON_STATE;
+ // slot is off
+
+ func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0);
+ dbg("In add_board, func = %p, ctrl = %p\n", func, ctrl);
+ if (!func) {
+ dbg("Error! func NULL in "__FUNCTION__"\n");
+ return ;
+ }
+
+ if (func != NULL && ctrl != NULL) {
+ if (cpqhp_process_SI(ctrl, func) != 0) {


+ amber_LED_on (ctrl, hp_slot);
+ green_LED_off (ctrl, hp_slot);
+

+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);
+ }
+ }

+
+ p_slot->state = STATIC_STATE;
+ }
+


+ return;
+}
+
+

+int cpqhp_process_SI (struct controller *ctrl, struct pci_func *func)
+{
+ u8 device, hp_slot;
+ u16 temp_word;
+ u32 tempdword;
+ int rc;
+ struct slot* p_slot;
+ int physical_slot = 0;
+
+ if (!ctrl)
+ return(1);
+
+ tempdword = 0;
+
+ device = func->device;
+ hp_slot = device - ctrl->slot_device_offset;
+ p_slot = find_slot(ctrl, device);
+ if (p_slot) {
+ physical_slot = p_slot->number;
+ }
+
+ // Check to see if the interlock is closed
+ tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+ if (tempdword & (0x01 << hp_slot)) {
+ return(1);
+ }
+
+ if (func->is_a_board) {
+ rc = board_replaced(func, ctrl);
+ } else {
+ // add board
+ slot_remove(func);
+
+ func = cpqhp_slot_create(ctrl->bus);


+ if (func == NULL) {
+ return(1);
+ }
+

+ func->bus = ctrl->bus;
+ func->device = device;
+ func->function = 0;
+ func->configured = 0;
+ func->is_a_board = 1;


+
+ // We have to save the presence info for these slots
+ temp_word = ctrl->ctrl_int_comp >> 16;
+ func->presence_save = (temp_word >> hp_slot) & 0x01;
+ func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;
+
+ if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {
+ func->switch_save = 0;
+ } else {
+ func->switch_save = 0x10;
+ }
+

+ rc = board_added(func, ctrl);
+ if (rc) {
+ if (is_bridge(func)) {
+ bridge_slot_remove(func);
+ } else
+ slot_remove(func);
+
+ // Setup slot structure with entry for empty slot
+ func = cpqhp_slot_create(ctrl->bus);


+
+ if (func == NULL) {

+ // Out of memory
+ return(1);
+ }
+
+ func->bus = ctrl->bus;
+ func->device = device;
+ func->function = 0;
+ func->configured = 0;
+ func->is_a_board = 0;
+


+ // We have to save the presence info for these slots
+ temp_word = ctrl->ctrl_int_comp >> 16;
+ func->presence_save = (temp_word >> hp_slot) & 0x01;
+ func->presence_save |=

+ (temp_word >> (hp_slot + 7)) & 0x02;


+
+ if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {
+ func->switch_save = 0;
+ } else {
+ func->switch_save = 0x10;
+ }
+ }
+ }

+
+ if (rc) {
+ dbg(__FUNCTION__": rc = %d\n", rc);
+ }
+
+ if (p_slot)
+ update_slot_info(ctrl, p_slot);


+
+ return rc;
+}
+
+

+int cpqhp_process_SS (struct controller *ctrl, struct pci_func *func)
+{
+ u8 device, class_code, header_type, BCR;
+ u8 index = 0;
+ u8 replace_flag;


+ u32 rc = 0;

+ struct slot* p_slot;
+ int physical_slot=0;
+
+ device = func->device;
+ func = cpqhp_slot_find(ctrl->bus, device, index++);
+ p_slot = find_slot(ctrl, device);
+ if (p_slot) {
+ physical_slot = p_slot->number;
+ }
+
+ // Make sure there are no video controllers here
+ while (func && !rc) {
+ // Check the Class Code
+ rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, 0x0B, &class_code);
+ if (rc)
+ return rc;
+
+ if (class_code == PCI_BASE_CLASS_DISPLAY) {
+ /* Display/Video adapter (not supported) */
+ rc = REMOVE_NOT_SUPPORTED;
+ } else {
+ // See if it's a bridge
+ rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type);
+ if (rc)
+ return rc;
+
+ // If it's a bridge, check the VGA Enable bit
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+ rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_BRIDGE_CONTROL, &BCR);
+ if (rc)
+ return rc;
+
+ // If the VGA Enable bit is set, remove isn't supported
+ if (BCR & PCI_BRIDGE_CTL_VGA) {
+ rc = REMOVE_NOT_SUPPORTED;
+ }
+ }
+ }
+
+ func = cpqhp_slot_find(ctrl->bus, device, index++);
+ }
+


+ func = cpqhp_slot_find(ctrl->bus, device, 0);

+ if ((func != NULL) && !rc) {
+ //FIXME: Replace flag should be passed into process_SS
+ replace_flag = !(ctrl->add_support);
+ rc = remove_board(func, replace_flag, ctrl);
+ } else if (!rc) {
+ rc = 1;
+ }
+
+ if (p_slot)
+ update_slot_info(ctrl, p_slot);


+
+ return(rc);
+}
+
+
+
+/**

+ * hardware_test - runs hardware tests
+ *
+ * For hot plug ctrl folks to play with.
+ * test_num is the number entered in the GUI
+ *
+ */
+int cpqhp_hardware_test(struct controller *ctrl, int test_num)
+{
+ u32 save_LED;
+ u32 work_LED;
+ int loop;
+ int num_of_slots;
+
+ num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0f;
+
+ switch (test_num) {
+ case 1:
+ // Do stuff here!
+
+ // Do that funky LED thing
+ save_LED = readl(ctrl->hpc_reg + LED_CONTROL); // so we can restore them later
+ work_LED = 0x01010101;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+ for (loop = 0; loop < num_of_slots; loop++) {
+ set_SOGO(ctrl);
+
+ // Wait for SOGO interrupt
+ wait_for_ctrl_irq (ctrl);
+
+ // Get ready for next iteration
+ work_LED = work_LED << 1;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+ long_delay((2*HZ)/10);
+ }
+ for (loop = 0; loop < num_of_slots; loop++) {
+ work_LED = work_LED >> 1;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOGO interrupt
+ wait_for_ctrl_irq (ctrl);
+
+ // Get ready for next iteration
+ long_delay((2*HZ)/10);
+ }
+ for (loop = 0; loop < num_of_slots; loop++) {
+ work_LED = work_LED << 1;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOGO interrupt
+ wait_for_ctrl_irq (ctrl);
+
+ // Get ready for next iteration
+ long_delay((2*HZ)/10);
+ }
+ for (loop = 0; loop < num_of_slots; loop++) {
+ work_LED = work_LED >> 1;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOGO interrupt
+ wait_for_ctrl_irq (ctrl);
+
+ // Get ready for next iteration
+ long_delay((2*HZ)/10);
+ }
+
+ work_LED = 0x01010000;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+ for (loop = 0; loop < num_of_slots; loop++) {
+ set_SOGO(ctrl);
+
+ // Wait for SOGO interrupt
+ wait_for_ctrl_irq (ctrl);
+
+ // Get ready for next iteration
+ work_LED = work_LED << 1;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+ long_delay((2*HZ)/10);
+ }
+ for (loop = 0; loop < num_of_slots; loop++) {
+ work_LED = work_LED >> 1;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOGO interrupt
+ wait_for_ctrl_irq (ctrl);
+
+ // Get ready for next iteration
+ long_delay((2*HZ)/10);
+ }
+ work_LED = 0x00000101;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+ for (loop = 0; loop < num_of_slots; loop++) {
+ work_LED = work_LED << 1;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOGO interrupt
+ wait_for_ctrl_irq (ctrl);
+
+ // Get ready for next iteration
+ long_delay((2*HZ)/10);
+ }
+ for (loop = 0; loop < num_of_slots; loop++) {
+ work_LED = work_LED >> 1;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOGO interrupt
+ wait_for_ctrl_irq (ctrl);
+
+ // Get ready for next iteration
+ long_delay((2*HZ)/10);
+ }
+
+
+ work_LED = 0x01010000;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+ for (loop = 0; loop < num_of_slots; loop++) {
+ set_SOGO(ctrl);
+
+ // Wait for SOGO interrupt
+ wait_for_ctrl_irq (ctrl);
+
+ // Get ready for next iteration
+ long_delay((3*HZ)/10);
+ work_LED = work_LED >> 16;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+
+ set_SOGO(ctrl);
+
+ // Wait for SOGO interrupt
+ wait_for_ctrl_irq (ctrl);
+
+ // Get ready for next iteration
+ long_delay((3*HZ)/10);
+ work_LED = work_LED << 16;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+ work_LED = work_LED << 1;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+ }
+
+ writel (save_LED, ctrl->hpc_reg + LED_CONTROL); // put it back the way it was


+
+ set_SOGO(ctrl);
+
+ // Wait for SOBS to be unset
+ wait_for_ctrl_irq (ctrl);

+ break;
+ case 2:

+ // Do other stuff here!


+ break;
+ case 3:

+ // and more...
+ break;


+ }
+ return 0;
+}
+
+

+/**
+ * configure_new_device - Configures the PCI header information of one board.
+ *
+ * @ctrl: pointer to controller structure
+ * @func: pointer to function structure
+ * @behind_bridge: 1 if this is a recursive call, 0 if not
+ * @resources: pointer to set of resource lists


+ *
+ * Returns 0 if success

+ *
+ */
+static u32 configure_new_device (struct controller * ctrl, struct pci_func * func,
+ u8 behind_bridge, struct resource_lists * resources)
+{
+ u8 temp_byte, function, max_functions, stop_it;
+ int rc;
+ u32 ID;
+ struct pci_func *new_slot;
+ int index;
+
+ new_slot = func;


+
+ dbg(__FUNCTION__"\n");

+ // Check for Multi-function device
+ rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, 0x0E, &temp_byte);
+ if (rc) {
+ dbg(__FUNCTION__": rc = %d\n", rc);


+ return rc;
+ }
+

+ if (temp_byte & 0x80) // Multi-function device
+ max_functions = 8;
+ else
+ max_functions = 1;
+
+ function = 0;
+
+ do {
+ rc = configure_new_function(ctrl, new_slot, behind_bridge, resources);
+
+ if (rc) {
+ dbg("configure_new_function failed %d\n",rc);
+ index = 0;
+
+ while (new_slot) {
+ new_slot = cpqhp_slot_find(new_slot->bus, new_slot->device, index++);
+
+ if (new_slot)
+ cpqhp_return_board_resources(new_slot, resources);


+ }
+
+ return(rc);
+ }
+

+ function++;
+
+ stop_it = 0;
+
+ // The following loop skips to the next present function
+ // and creates a board structure
+
+ while ((function < max_functions) && (!stop_it)) {
+ pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, function, 0x00, &ID);
+
+ if (ID == 0xFFFFFFFF) { // There's nothing there.
+ function++;
+ } else { // There's something there
+ // Setup slot structure.
+ new_slot = cpqhp_slot_create(func->bus);


+
+ if (new_slot == NULL) {

+ // Out of memory
+ return(1);
+ }
+
+ new_slot->bus = func->bus;
+ new_slot->device = func->device;
+ new_slot->function = function;
+ new_slot->is_a_board = 1;
+ new_slot->status = 0;
+
+ stop_it++;
+ }
+ }
+
+ } while (function < max_functions);
+ dbg("returning from configure_new_device\n");


+
+ return 0;
+}
+
+

+/*
+ Configuration logic that involves the hotplug data structures and
+ their bookkeeping


+ */
+
+
+/**

+ * configure_new_function - Configures the PCI header information of one device
+ *
+ * @ctrl: pointer to controller structure
+ * @func: pointer to function structure
+ * @behind_bridge: 1 if this is a recursive call, 0 if not
+ * @resources: pointer to set of resource lists
+ *
+ * Calls itself recursively for bridged devices.


+ * Returns 0 if success

+ *
+ */
+static int configure_new_function (struct controller * ctrl, struct pci_func * func,
+ u8 behind_bridge, struct resource_lists * resources)
+{
+ int cloop;
+ u8 IRQ;
+ u8 temp_byte;
+ u8 device;
+ u8 class_code;
+ u16 command;
+ u16 temp_word;
+ u32 temp_dword;
+ u32 rc;
+ u32 temp_register;
+ u32 base;
+ u32 ID;
+ struct pci_resource *mem_node;
+ struct pci_resource *p_mem_node;
+ struct pci_resource *io_node;
+ struct pci_resource *bus_node;
+ struct pci_resource *hold_mem_node;
+ struct pci_resource *hold_p_mem_node;
+ struct pci_resource *hold_IO_node;
+ struct pci_resource *hold_bus_node;
+ struct irq_mapping irqs;
+ struct pci_func *new_slot;
+ struct resource_lists temp_resources;
+
+ // Check for Bridge
+ rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &temp_byte);
+ if (rc)
+ return rc;
+
+ if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge
+ // set Primary bus
+ dbg("set Primary bus = %d\n", func->bus);
+ rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PRIMARY_BUS, func->bus);
+ if (rc)
+ return rc;
+
+ // find range of busses to use
+ dbg("find ranges of buses to use\n");
+ bus_node = get_max_resource(&resources->bus_head, 1);
+
+ // If we don't have any busses to allocate, we can't continue
+ if (!bus_node)
+ return -ENOMEM;
+
+ // set Secondary bus
+ temp_byte = bus_node->base;
+ dbg("set Secondary bus = %d\n", bus_node->base);
+ rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_SECONDARY_BUS, temp_byte);
+ if (rc)
+ return rc;
+
+ // set subordinate bus
+ temp_byte = bus_node->base + bus_node->length - 1;
+ dbg("set subordinate bus = %d\n", bus_node->base + bus_node->length - 1);
+ rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_SUBORDINATE_BUS, temp_byte);
+ if (rc)
+ return rc;
+
+ // set subordinate Latency Timer and base Latency Timer
+ temp_byte = 0x40;
+ rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_SEC_LATENCY_TIMER, temp_byte);
+ if (rc)
+ return rc;
+ rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_LATENCY_TIMER, temp_byte);
+ if (rc)
+ return rc;
+
+ // set Cache Line size
+ temp_byte = 0x08;
+ rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_CACHE_LINE_SIZE, temp_byte);
+ if (rc)
+ return rc;
+
+ // Setup the IO, memory, and prefetchable windows
+
+ io_node = get_max_resource(&(resources->io_head), 0x1000);
+ mem_node = get_max_resource(&(resources->mem_head), 0x100000);
+ p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000);
+ dbg("Setup the IO, memory, and prefetchable windows\n");
+ dbg("io_node\n");
+ dbg("(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next);
+ dbg("mem_node\n");
+ dbg("(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next);
+ dbg("p_mem_node\n");
+ dbg("(base, len, next) (%x, %x, %p)\n", p_mem_node->base, p_mem_node->length, p_mem_node->next);
+
+ // set up the IRQ info
+ if (!resources->irqs) {
+ irqs.barber_pole = 0;
+ irqs.interrupt[0] = 0;
+ irqs.interrupt[1] = 0;
+ irqs.interrupt[2] = 0;
+ irqs.interrupt[3] = 0;
+ irqs.valid_INT = 0;
+ } else {
+ irqs.barber_pole = resources->irqs->barber_pole;
+ irqs.interrupt[0] = resources->irqs->interrupt[0];
+ irqs.interrupt[1] = resources->irqs->interrupt[1];
+ irqs.interrupt[2] = resources->irqs->interrupt[2];
+ irqs.interrupt[3] = resources->irqs->interrupt[3];
+ irqs.valid_INT = resources->irqs->valid_INT;
+ }
+
+ // set up resource lists that are now aligned on top and bottom
+ // for anything behind the bridge.
+ temp_resources.bus_head = bus_node;
+ temp_resources.io_head = io_node;
+ temp_resources.mem_head = mem_node;
+ temp_resources.p_mem_head = p_mem_node;
+ temp_resources.irqs = &irqs;
+
+ // Make copies of the nodes we are going to pass down so that
+ // if there is a problem,we can just use these to free resources
+ hold_bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ hold_IO_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ hold_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ hold_p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+ if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) {
+ if (hold_bus_node)
+ kfree(hold_bus_node);
+ if (hold_IO_node)
+ kfree(hold_IO_node);
+ if (hold_mem_node)
+ kfree(hold_mem_node);
+ if (hold_p_mem_node)
+ kfree(hold_p_mem_node);
+
+ return(1);
+ }
+
+ memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource));
+
+ bus_node->base += 1;
+ bus_node->length -= 1;
+ bus_node->next = NULL;
+
+ // If we have IO resources copy them and fill in the bridge's
+ // IO range registers
+ if (io_node) {
+ memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
+ io_node->next = NULL;
+
+ // set IO base and Limit registers
+ temp_byte = io_node->base >> 8;
+ rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_BASE, temp_byte);
+
+ temp_byte = (io_node->base + io_node->length - 1) >> 8;
+ rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_LIMIT, temp_byte);
+ } else {
+ kfree(hold_IO_node);
+ hold_IO_node = NULL;
+ }
+
+ // If we have memory resources copy them and fill in the bridge's
+ // memory range registers. Otherwise, fill in the range
+ // registers with values that disable them.
+ if (mem_node) {
+ memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));
+ mem_node->next = NULL;
+
+ // set Mem base and Limit registers
+ temp_word = mem_node->base >> 16;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_BASE, temp_word);
+
+ temp_word = (mem_node->base + mem_node->length - 1) >> 16;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, temp_word);
+ } else {
+ temp_word = 0xFFFF;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_BASE, temp_word);
+
+ temp_word = 0x0000;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, temp_word);
+
+ kfree(hold_mem_node);
+ hold_mem_node = NULL;
+ }
+
+ // If we have prefetchable memory resources copy them and
+ // fill in the bridge's memory range registers. Otherwise,
+ // fill in the range registers with values that disable them.
+ if (p_mem_node) {
+ memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
+ p_mem_node->next = NULL;
+
+ // set Pre Mem base and Limit registers
+ temp_word = p_mem_node->base >> 16;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_BASE, temp_word);
+
+ temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, temp_word);
+ } else {
+ temp_word = 0xFFFF;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_BASE, temp_word);
+
+ temp_word = 0x0000;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, temp_word);
+
+ kfree(hold_p_mem_node);
+ hold_p_mem_node = NULL;
+ }
+
+ // Adjust this to compensate for extra adjustment in first loop
+ irqs.barber_pole--;
+


+ rc = 0;
+

+ // Here we actually find the devices and configure them
+ for (device = 0; (device <= 0x1F) && !rc; device++) {
+ irqs.barber_pole = (irqs.barber_pole + 1) & 0x03;
+
+ ID = 0xFFFFFFFF;
+ pci_read_config_dword_nodev (ctrl->pci_ops, hold_bus_node->base, device, 0, 0x00, &ID);
+
+ if (ID != 0xFFFFFFFF) { // device Present
+ // Setup slot structure.
+ new_slot = cpqhp_slot_create(hold_bus_node->base);


+
+ if (new_slot == NULL) {

+ // Out of memory
+ rc = -ENOMEM;
+ continue;
+ }
+
+ new_slot->bus = hold_bus_node->base;
+ new_slot->device = device;
+ new_slot->function = 0;
+ new_slot->is_a_board = 1;
+ new_slot->status = 0;
+
+ rc = configure_new_device(ctrl, new_slot, 1, &temp_resources);
+ dbg("configure_new_device rc=0x%x\n",rc);
+ } // End of IF (device in slot?)
+ } // End of FOR loop
+
+ if (rc) {
+ cpqhp_destroy_resource_list(&temp_resources);
+
+ return_resource(&(resources->bus_head), hold_bus_node);
+ return_resource(&(resources->io_head), hold_IO_node);
+ return_resource(&(resources->mem_head), hold_mem_node);
+ return_resource(&(resources->p_mem_head), hold_p_mem_node);
+ return(rc);
+ }
+ // save the interrupt routing information
+ if (resources->irqs) {
+ resources->irqs->interrupt[0] = irqs.interrupt[0];
+ resources->irqs->interrupt[1] = irqs.interrupt[1];
+ resources->irqs->interrupt[2] = irqs.interrupt[2];
+ resources->irqs->interrupt[3] = irqs.interrupt[3];
+ resources->irqs->valid_INT = irqs.valid_INT;
+ } else if (!behind_bridge) {
+ // We need to hook up the interrupts here
+ for (cloop = 0; cloop < 4; cloop++) {
+ if (irqs.valid_INT & (0x01 << cloop)) {
+ rc = cpqhp_set_irq(func->bus, func->device,
+ 0x0A + cloop, irqs.interrupt[cloop]);
+ if (rc) {
+ cpqhp_destroy_resource_list (&temp_resources);
+
+ return_resource(&(resources-> bus_head), hold_bus_node);
+ return_resource(&(resources-> io_head), hold_IO_node);
+ return_resource(&(resources-> mem_head), hold_mem_node);
+ return_resource(&(resources-> p_mem_head), hold_p_mem_node);


+ return rc;
+ }
+ }

+ } // end of for loop
+ }
+ // Return unused bus resources
+ // First use the temporary node to store information for the board
+ if (hold_bus_node && bus_node && temp_resources.bus_head) {
+ hold_bus_node->length = bus_node->base - hold_bus_node->base;
+
+ hold_bus_node->next = func->bus_head;
+ func->bus_head = hold_bus_node;
+
+ temp_byte = temp_resources.bus_head->base - 1;
+
+ // set subordinate bus
+ rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_SUBORDINATE_BUS, temp_byte);
+
+ if (temp_resources.bus_head->length == 0) {
+ kfree(temp_resources.bus_head);
+ temp_resources.bus_head = NULL;
+ } else {
+ return_resource(&(resources->bus_head), temp_resources.bus_head);
+ }
+ }
+
+ // If we have IO space available and there is some left,
+ // return the unused portion
+ if (hold_IO_node && temp_resources.io_head) {
+ io_node = do_pre_bridge_resource_split(&(temp_resources.io_head),
+ &hold_IO_node, 0x1000);
+
+ // Check if we were able to split something off
+ if (io_node) {
+ hold_IO_node->base = io_node->base + io_node->length;
+
+ temp_byte = (hold_IO_node->base) >> 8;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_BASE, temp_byte);
+
+ return_resource(&(resources->io_head), io_node);
+ }
+
+ io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000);
+
+ // Check if we were able to split something off
+ if (io_node) {
+ // First use the temporary node to store information for the board
+ hold_IO_node->length = io_node->base - hold_IO_node->base;
+
+ // If we used any, add it to the board's list
+ if (hold_IO_node->length) {
+ hold_IO_node->next = func->io_head;
+ func->io_head = hold_IO_node;
+
+ temp_byte = (io_node->base - 1) >> 8;
+ rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_LIMIT, temp_byte);
+
+ return_resource(&(resources->io_head), io_node);
+ } else {
+ // it doesn't need any IO
+ temp_word = 0x0000;
+ pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_LIMIT, temp_word);
+
+ return_resource(&(resources->io_head), io_node);
+ kfree(hold_IO_node);
+ }
+ } else {
+ // it used most of the range
+ hold_IO_node->next = func->io_head;
+ func->io_head = hold_IO_node;
+ }
+ } else if (hold_IO_node) {
+ // it used the whole range
+ hold_IO_node->next = func->io_head;
+ func->io_head = hold_IO_node;
+ }
+ // If we have memory space available and there is some left,
+ // return the unused portion
+ if (hold_mem_node && temp_resources.mem_head) {
+ mem_node = do_pre_bridge_resource_split(&(temp_resources. mem_head),
+ &hold_mem_node, 0x100000);
+
+ // Check if we were able to split something off
+ if (mem_node) {
+ hold_mem_node->base = mem_node->base + mem_node->length;
+
+ temp_word = (hold_mem_node->base) >> 16;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_BASE, temp_word);
+
+ return_resource(&(resources->mem_head), mem_node);
+ }
+
+ mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000);
+
+ // Check if we were able to split something off
+ if (mem_node) {
+ // First use the temporary node to store information for the board
+ hold_mem_node->length = mem_node->base - hold_mem_node->base;
+
+ if (hold_mem_node->length) {
+ hold_mem_node->next = func->mem_head;
+ func->mem_head = hold_mem_node;
+
+ // configure end address
+ temp_word = (mem_node->base - 1) >> 16;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, temp_word);
+
+ // Return unused resources to the pool
+ return_resource(&(resources->mem_head), mem_node);
+ } else {
+ // it doesn't need any Mem
+ temp_word = 0x0000;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, temp_word);
+
+ return_resource(&(resources->mem_head), mem_node);
+ kfree(hold_mem_node);
+ }
+ } else {
+ // it used most of the range
+ hold_mem_node->next = func->mem_head;
+ func->mem_head = hold_mem_node;
+ }
+ } else if (hold_mem_node) {
+ // it used the whole range
+ hold_mem_node->next = func->mem_head;
+ func->mem_head = hold_mem_node;
+ }
+ // If we have prefetchable memory space available and there is some
+ // left at the end, return the unused portion
+ if (hold_p_mem_node && temp_resources.p_mem_head) {
+ p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head),
+ &hold_p_mem_node, 0x100000);
+
+ // Check if we were able to split something off
+ if (p_mem_node) {
+ hold_p_mem_node->base = p_mem_node->base + p_mem_node->length;
+
+ temp_word = (hold_p_mem_node->base) >> 16;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_BASE, temp_word);
+
+ return_resource(&(resources->p_mem_head), p_mem_node);
+ }
+
+ p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000);
+
+ // Check if we were able to split something off
+ if (p_mem_node) {
+ // First use the temporary node to store information for the board
+ hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base;
+
+ // If we used any, add it to the board's list
+ if (hold_p_mem_node->length) {
+ hold_p_mem_node->next = func->p_mem_head;
+ func->p_mem_head = hold_p_mem_node;
+
+ temp_word = (p_mem_node->base - 1) >> 16;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, temp_word);
+
+ return_resource(&(resources->p_mem_head), p_mem_node);
+ } else {
+ // it doesn't need any PMem
+ temp_word = 0x0000;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, temp_word);
+
+ return_resource(&(resources->p_mem_head), p_mem_node);
+ kfree(hold_p_mem_node);
+ }
+ } else {
+ // it used the most of the range
+ hold_p_mem_node->next = func->p_mem_head;
+ func->p_mem_head = hold_p_mem_node;
+ }
+ } else if (hold_p_mem_node) {
+ // it used the whole range
+ hold_p_mem_node->next = func->p_mem_head;
+ func->p_mem_head = hold_p_mem_node;
+ }
+ // We should be configuring an IRQ and the bridge's base address
+ // registers if it needs them. Although we have never seen such
+ // a device
+
+ // enable card
+ command = 0x0157; // = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_COMMAND, command);
+
+ // set Bridge Control Register
+ command = 0x07; // = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_NO_ISA
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_BRIDGE_CONTROL, command);
+ } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
+ // Standard device
+ rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, 0x0B, &class_code);
+
+ if (class_code == PCI_BASE_CLASS_DISPLAY) {
+ // Display (video) adapter (not supported)
+ return(DEVICE_TYPE_NOT_SUPPORTED);
+ }
+ // Figure out IO and memory needs
+ for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
+ temp_register = 0xFFFFFFFF;
+
+ dbg("CND: bus=%d, device=%d, func=%d, offset=%d\n", func->bus, func->device, func->function, cloop);
+ rc = pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register);
+
+ rc = pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &temp_register);
+ dbg("CND: base = 0x%x\n", temp_register);
+
+ if (temp_register) { // If this register is implemented
+ if ((temp_register & 0x03L) == 0x01) {
+ // Map IO
+
+ // set base = amount of IO space
+ base = temp_register & 0xFFFFFFFC;
+ base = ~base + 1;
+
+ dbg("CND: length = 0x%x\n", base);
+ io_node = get_io_resource(&(resources->io_head), base);
+ dbg("Got io_node start = %8.8x, length = %8.8x next (%p)\n",
+ io_node->base, io_node->length, io_node->next);
+ dbg("func (%p) io_head (%p)\n", func, func->io_head);
+
+ // allocate the resource to the board
+ if (io_node) {
+ base = io_node->base;
+
+ io_node->next = func->io_head;
+ func->io_head = io_node;
+ } else
+ return -ENOMEM;
+ } else if ((temp_register & 0x0BL) == 0x08) {
+ // Map prefetchable memory
+ base = temp_register & 0xFFFFFFF0;
+ base = ~base + 1;
+
+ dbg("CND: length = 0x%x\n", base);
+ p_mem_node = get_resource(&(resources->p_mem_head), base);
+
+ // allocate the resource to the board
+ if (p_mem_node) {
+ base = p_mem_node->base;
+
+ p_mem_node->next = func->p_mem_head;
+ func->p_mem_head = p_mem_node;
+ } else
+ return -ENOMEM;
+ } else if ((temp_register & 0x0BL) == 0x00) {
+ // Map memory
+ base = temp_register & 0xFFFFFFF0;
+ base = ~base + 1;
+
+ dbg("CND: length = 0x%x\n", base);
+ mem_node = get_resource(&(resources->mem_head), base);
+
+ // allocate the resource to the board
+ if (mem_node) {
+ base = mem_node->base;
+
+ mem_node->next = func->mem_head;
+ func->mem_head = mem_node;
+ } else
+ return -ENOMEM;
+ } else if ((temp_register & 0x0BL) == 0x04) {
+ // Map memory
+ base = temp_register & 0xFFFFFFF0;
+ base = ~base + 1;
+
+ dbg("CND: length = 0x%x\n", base);
+ mem_node = get_resource(&(resources->mem_head), base);
+
+ // allocate the resource to the board
+ if (mem_node) {
+ base = mem_node->base;
+
+ mem_node->next = func->mem_head;
+ func->mem_head = mem_node;
+ } else
+ return -ENOMEM;
+ } else if ((temp_register & 0x0BL) == 0x06) {
+ // Those bits are reserved, we can't handle this
+ return(1);
+ } else {
+ // Requesting space below 1M
+ return(NOT_ENOUGH_RESOURCES);
+ }
+
+ rc = pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, base);
+
+ // Check for 64-bit base
+ if ((temp_register & 0x07L) == 0x04) {
+ cloop += 4;
+
+ // Upper 32 bits of address always zero on today's systems
+ // FIXME this is probably not true on Alpha and ia64???
+ base = 0;
+ rc = pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, base);
+ }
+ }
+ } // End of base register loop
+
+ // Figure out which interrupt pin this function uses
+ rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_INTERRUPT_PIN, &temp_byte);
+
+ // If this function needs an interrupt and we are behind a bridge
+ // and the pin is tied to something that's alread mapped,
+ // set this one the same
+ if (temp_byte && resources->irqs &&
+ (resources->irqs->valid_INT &
+ (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) {
+ // We have to share with something already set up
+ IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03];
+ } else {
+ // Program IRQ based on card type
+ rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, 0x0B, &class_code);
+
+ if (class_code == PCI_BASE_CLASS_STORAGE) {
+ IRQ = cpqhp_disk_irq;
+ } else {
+ IRQ = cpqhp_nic_irq;
+ }
+ }
+
+ // IRQ Line
+ rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_INTERRUPT_LINE, IRQ);
+
+ if (!behind_bridge) {
+ rc = cpqhp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ);
+ if (rc)
+ return(1);
+ } else {
+ //TBD - this code may also belong in the other clause of this If statement
+ resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03] = IRQ;
+ resources->irqs->valid_INT |= 0x01 << (temp_byte + resources->irqs->barber_pole - 1) & 0x03;
+ }
+
+ // Latency Timer
+ temp_byte = 0x40;
+ rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_LATENCY_TIMER, temp_byte);
+
+ // Cache Line size
+ temp_byte = 0x08;
+ rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_CACHE_LINE_SIZE, temp_byte);
+
+ // disable ROM base Address
+ temp_dword = 0x00L;
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_ROM_ADDRESS, temp_dword);
+
+ // enable card
+ temp_word = 0x0157; // = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR
+ rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_COMMAND, temp_word);
+ } // End of Not-A-Bridge else
+ else {
+ // It's some strange type of PCI adapter (Cardbus?)
+ return(DEVICE_TYPE_NOT_SUPPORTED);
+ }
+
+ func->configured = 1;
+
+ return 0;
+}
+
diff -u --recursive --new-file v2.4.14/linux/drivers/hotplug/cpqphp_nvram.c linux/drivers/hotplug/cpqphp_nvram.c
--- v2.4.14/linux/drivers/hotplug/cpqphp_nvram.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/hotplug/cpqphp_nvram.c Fri Nov 9 14:01:22 2001
@@ -0,0 +1,652 @@

+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include "cpqphp.h"
+#include "cpqphp_nvram.h"
+
+
+#define ROM_INT15_PHY_ADDR 0x0FF859
+#define READ_EV 0xD8A4
+#define WRITE_EV 0xD8A5
+
+struct register_foo {
+ union {
+ unsigned long lword; /* eax */
+ unsigned short word; /* ax */
+
+ struct {
+ unsigned char low; /* al */
+ unsigned char high; /* ah */
+ } byte;
+ } data;
+
+ unsigned char opcode; /* see below */
+ unsigned long length; /* if the reg. is a pointer, how much data */
+} __attribute__ ((packed));
+
+struct all_reg {
+ struct register_foo eax_reg;
+ struct register_foo ebx_reg;
+ struct register_foo ecx_reg;
+ struct register_foo edx_reg;
+ struct register_foo edi_reg;
+ struct register_foo esi_reg;
+ struct register_foo eflags_reg;
+} __attribute__ ((packed));
+
+
+struct ev_hrt_header {
+ u8 Version;
+ u8 num_of_ctrl;
+ u8 next;
+};
+
+struct ev_hrt_ctrl {
+ u8 bus;


+ u8 device;
+ u8 function;

+ u8 mem_avail;
+ u8 p_mem_avail;
+ u8 io_avail;
+ u8 bus_avail;
+ u8 next;
+};
+
+
+static u8 evbuffer_init;
+static u8 evbuffer_length;
+static u8 evbuffer[1024];
+
+static void *compaq_int15_entry_point;
+
+static spinlock_t int15_lock; /* lock for ordering int15_bios_call() */
+
+
+/* This is a series of function that deals with
+ setting & getting the hotplug resource table in some environment variable.
+*/
+
+/*
+ * We really shouldn't be doing this unless there is a _very_ good reason to!!!
+ * greg k-h
+ */
+
+
+static u32 add_byte( u32 **p_buffer, u8 value, u32 *used, u32 *avail)
+{
+ u8 **tByte;
+
+ if ((*used + 1) > *avail)
+ return(1);
+
+ *((u8*)*p_buffer) = value;
+ tByte = (u8**)p_buffer;
+ (*tByte)++;
+ *used+=1;


+ return(0);
+}
+
+

+static u32 add_dword( u32 **p_buffer, u32 value, u32 *used, u32 *avail)
+{
+ if ((*used + 4) > *avail)
+ return(1);
+
+ **p_buffer = value;
+ (*p_buffer)++;
+ *used+=4;


+ return(0);
+}
+
+
+/*

+ * check_for_compaq_ROM
+ *
+ * this routine verifies that the ROM OEM string is 'COMPAQ'
+ *
+ * returns 0 for non-Compaq ROM, 1 for Compaq ROM
+ */
+static int check_for_compaq_ROM (void *rom_start)
+{
+ u8 temp1, temp2, temp3, temp4, temp5, temp6;


+ int result = 0;
+

+ temp1 = readb(rom_start + 0xffea + 0);
+ temp2 = readb(rom_start + 0xffea + 1);
+ temp3 = readb(rom_start + 0xffea + 2);
+ temp4 = readb(rom_start + 0xffea + 3);
+ temp5 = readb(rom_start + 0xffea + 4);
+ temp6 = readb(rom_start + 0xffea + 5);
+ if ((temp1 == 'C') &&
+ (temp2 == 'O') &&
+ (temp3 == 'M') &&
+ (temp4 == 'P') &&
+ (temp5 == 'A') &&
+ (temp6 == 'Q')) {
+ result = 1;
+ }
+ dbg (__FUNCTION__" - returned %d\n", result);


+ return result;
+}
+
+

+static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)


+{
+ unsigned long flags;

+ int op = operation;
+ int ret_val;
+
+ if (!compaq_int15_entry_point)
+ return -ENODEV;
+
+ spin_lock_irqsave(&int15_lock, flags);
+ __asm__ (
+ "xorl %%ebx,%%ebx
+ xorl %%edx,%%edx
+ pushf
+ push %%cs
+ cli
+ call *%6"
+ : "=c" (*buf_size), "=a" (ret_val)
+ : "a" (op), "c" (*buf_size), "S" (ev_name),
+ "D" (buffer), "m" (compaq_int15_entry_point)
+ : "%ebx", "%edx");
+ spin_unlock_irqrestore(&int15_lock, flags);
+
+ return((ret_val & 0xFF00) >> 8);
+}
+
+
+/*
+ * load_HRT
+ *
+ * Read the hot plug Resource Table from NVRAM
+ */
+static int load_HRT (void *rom_start)
+{
+ u32 available;
+ u32 temp_dword;
+ u8 temp_byte = 0xFF;
+ u32 rc;
+
+ if (!check_for_compaq_ROM(rom_start)) {


+ return -ENODEV;
+ }
+

+ available = 1024;
+
+ // Now load the EV
+ temp_dword = available;
+
+ rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword);
+
+ evbuffer_length = temp_dword;
+
+ // We're maintaining the resource lists so write FF to invalidate old info
+ temp_dword = 1;
+
+ rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword);


+
+ return rc;
+}
+
+
+/*

+ * store_HRT
+ *
+ * Save the hot plug Resource Table in NVRAM
+ */
+static u32 store_HRT (void *rom_start)
+{
+ u32 *buffer;
+ u32 *pFill;
+ u32 usedbytes;
+ u32 available;
+ u32 temp_dword;
+ u32 rc;
+ u8 loop;
+ u8 numCtrl = 0;
+ struct controller *ctrl;
+ struct pci_resource *resNode;
+ struct ev_hrt_header *p_EV_header;
+ struct ev_hrt_ctrl *p_ev_ctrl;
+
+ available = 1024;
+
+ if (!check_for_compaq_ROM(rom_start)) {
+ return(1);
+ }
+
+ buffer = (u32*) evbuffer;
+
+ if (!buffer)
+ return(1);
+
+ pFill = buffer;
+ usedbytes = 0;
+
+ p_EV_header = (struct ev_hrt_header *) pFill;


+
+ ctrl = cpqhp_ctrl_list;
+

+ // The revision of this structure
+ rc = add_byte( &pFill, 1 + ctrl->push_flag, &usedbytes, &available);


+ if (rc)
+ return(rc);
+

+ // The number of controllers
+ rc = add_byte( &pFill, 1, &usedbytes, &available);


+ if (rc)
+ return(rc);
+

+ while (ctrl) {
+ p_ev_ctrl = (struct ev_hrt_ctrl *) pFill;
+
+ numCtrl++;
+
+ // The bus number
+ rc = add_byte( &pFill, ctrl->bus, &usedbytes, &available);


+ if (rc)
+ return(rc);
+

+ // The device Number
+ rc = add_byte( &pFill, ctrl->device, &usedbytes, &available);


+ if (rc)
+ return(rc);
+

+ // The function Number
+ rc = add_byte( &pFill, ctrl->function, &usedbytes, &available);


+ if (rc)
+ return(rc);
+

+ // Skip the number of available entries
+ rc = add_dword( &pFill, 0, &usedbytes, &available);


+ if (rc)
+ return(rc);
+

+ // Figure out memory Available
+
+ resNode = ctrl->mem_head;
+
+ loop = 0;
+
+ while (resNode) {
+ loop ++;
+
+ // base
+ rc = add_dword( &pFill, resNode->base, &usedbytes, &available);


+ if (rc)
+ return(rc);
+

+ // length
+ rc = add_dword( &pFill, resNode->length, &usedbytes, &available);


+ if (rc)
+ return(rc);
+

+ resNode = resNode->next;
+ }
+
+ // Fill in the number of entries
+ p_ev_ctrl->mem_avail = loop;
+
+ // Figure out prefetchable memory Available
+
+ resNode = ctrl->p_mem_head;
+
+ loop = 0;
+
+ while (resNode) {
+ loop ++;
+
+ // base
+ rc = add_dword( &pFill, resNode->base, &usedbytes, &available);


+ if (rc)
+ return(rc);
+

+ // length
+ rc = add_dword( &pFill, resNode->length, &usedbytes, &available);


+ if (rc)
+ return(rc);
+

+ resNode = resNode->next;
+ }
+
+ // Fill in the number of entries
+ p_ev_ctrl->p_mem_avail = loop;
+
+ // Figure out IO Available
+
+ resNode = ctrl->io_head;
+
+ loop = 0;
+
+ while (resNode) {
+ loop ++;
+
+ // base
+ rc = add_dword( &pFill, resNode->base, &usedbytes, &available);


+ if (rc)
+ return(rc);
+

+ // length
+ rc = add_dword( &pFill, resNode->length, &usedbytes, &available);


+ if (rc)
+ return(rc);
+

+ resNode = resNode->next;
+ }
+
+ // Fill in the number of entries
+ p_ev_ctrl->io_avail = loop;
+
+ // Figure out bus Available
+
+ resNode = ctrl->bus_head;
+
+ loop = 0;
+
+ while (resNode) {
+ loop ++;
+
+ // base
+ rc = add_dword( &pFill, resNode->base, &usedbytes, &available);


+ if (rc)
+ return(rc);
+

+ // length
+ rc = add_dword( &pFill, resNode->length, &usedbytes, &available);


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

echo 'End of part 043'
echo 'File patch-2.4.15 is continued in part 044'
echo "044" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:22 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part046

#!/bin/sh -x
# this is part 046 of a 115 - part archive


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

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

X return(ret);
X }
X
- timeout = jiffies + 50;
- while (timeout > jiffies) {
+ timeout = jiffies + HZ / 2;
+ while (time_before(jiffies, timeout)) {
X if (chan->e.B2Id) break;
X SLEEP(10);
X }


@@ -3181,8 +3181,8 @@
X

X eicon_schedule_tx(card);
X
- timeout = jiffies + 50;
- while (timeout > jiffies) {
+ timeout = jiffies + HZ / 2;
+ while (time_before(jiffies, timeout)) {
X if (chan->fsm_state) break;
X SLEEP(10);
X }
diff -u --recursive --new-file v2.4.14/linux/drivers/isdn/eicon/eicon_isa.c linux/drivers/isdn/eicon/eicon_isa.c
--- v2.4.14/linux/drivers/isdn/eicon/eicon_isa.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/isdn/eicon/eicon_isa.c Fri Nov 9 13:41:41 2001
@@ -1,4 +1,4 @@
-/* $Id: eicon_isa.c,v 1.16.6.1 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_isa.c,v 1.16.6.2 2001/11/06 20:58:29 kai Exp $
X *
X * ISDN low-level module for Eicon active ISDN-Cards.
X * Hardware-specific code for old ISA cards.
@@ -20,7 +20,7 @@
X #define release_shmem release_region
X #define request_shmem request_region
X
-char *eicon_isa_revision = "$Revision: 1.16.6.1 $";
+char *eicon_isa_revision = "$Revision: 1.16.6.2 $";
X
X #undef EICON_MCA_DEBUG
X
@@ -231,7 +231,7 @@
X boot = &card->shmem->boot;
X
X /* Delay 0.2 sec. */
- SLEEP(20);
+ SLEEP(HZ / 5);
X
X /* Start CPU */
X writeb(cbuf.boot_opt, &boot->ctrl);
@@ -244,10 +244,10 @@
X #endif /* CONFIG_MCA */
X
X /* Delay 0.2 sec. */
- SLEEP(20);
+ SLEEP(HZ / 5);
X
X timeout = jiffies + (HZ * 22);
- while (timeout > jiffies) {
+ while (time_before(jiffies, timeout)) {
X if (readb(&boot->ctrl) == 0)
X break;
X SLEEP(10);
@@ -362,8 +362,8 @@
X while (tmp--) {
X memcpy_toio(&boot->b, p, 256);
X writeb(1, &boot->ctrl);
- timeout = jiffies + 10;
- while (timeout > jiffies) {
+ timeout = jiffies + HZ / 10;
+ while (time_before(jiffies, timeout)) {
X if (readb(&boot->ctrl) == 0)
X break;
X SLEEP(2);
@@ -386,7 +386,7 @@
X /* Start firmware, wait for signature */
X writeb(2, &boot->ctrl);
X timeout = jiffies + (5*HZ);
- while (timeout > jiffies) {
+ while (time_before(jiffies, timeout)) {
X if (readw(&boot->signature) == 0x4447)
X break;
X SLEEP(2);
@@ -410,8 +410,8 @@
X tmp = readb(&card->shmem->com.ReadyInt);
X tmp ++;
X writeb(tmp, &card->shmem->com.ReadyInt);
- timeout = jiffies + 20;
- while (timeout > jiffies) {
+ timeout = jiffies + HZ / 5;
+ while (time_before(jiffies, timeout)) {
X if (card->irqprobe > 1)
X break;
X SLEEP(2);
diff -u --recursive --new-file v2.4.14/linux/drivers/isdn/hysdn/boardergo.c linux/drivers/isdn/hysdn/boardergo.c
--- v2.4.14/linux/drivers/isdn/hysdn/boardergo.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/isdn/hysdn/boardergo.c Fri Nov 9 13:41:42 2001
@@ -1,4 +1,4 @@
-/* $Id: boardergo.c,v 1.5.6.6 2001/09/23 22:24:54 kai Exp $
+/* $Id: boardergo.c,v 1.5.6.7 2001/11/06 21:58:19 kai Exp $
X *
X * Linux driver for HYSDN cards, specific routines for ergo type boards.
X *
diff -u --recursive --new-file v2.4.14/linux/drivers/isdn/hysdn/hysdn_sched.c linux/drivers/isdn/hysdn/hysdn_sched.c
--- v2.4.14/linux/drivers/isdn/hysdn/hysdn_sched.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/isdn/hysdn/hysdn_sched.c Fri Nov 9 13:41:42 2001
@@ -1,4 +1,4 @@
-/* $Id: hysdn_sched.c,v 1.5.6.3 2001/09/23 22:24:54 kai Exp $
+/* $Id: hysdn_sched.c,v 1.5.6.4 2001/11/06 21:58:19 kai Exp $
X *
X * Linux driver for HYSDN cards
X * scheduler routines for handling exchange card <-> pc.
diff -u --recursive --new-file v2.4.14/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- v2.4.14/linux/drivers/isdn/isdn_common.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/isdn/isdn_common.c Fri Nov 9 13:41:41 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.114.6.15 2001/09/23 22:24:31 kai Exp $
+/* $Id: isdn_common.c,v 1.114.6.16 2001/11/06 20:58:28 kai Exp $
X *
X * Linux ISDN subsystem, common used functions (linklevel).
X *
@@ -44,7 +44,7 @@
X
X isdn_dev *dev;
X
-static char *isdn_revision = "$Revision: 1.114.6.15 $";
+static char *isdn_revision = "$Revision: 1.114.6.16 $";
X
X extern char *isdn_net_revision;
X extern char *isdn_tty_revision;
@@ -1644,7 +1644,7 @@
X if (minor == ISDN_MINOR_STATUS) {
X infostruct *p;
X
- if ((p = (infostruct *) kmalloc(sizeof(infostruct), GFP_KERNEL))) {
+ if ((p = kmalloc(sizeof(infostruct), GFP_KERNEL))) {
X p->next = (char *) dev->infochain;
X p->private = (char *) &(filep->private_data);
X dev->infochain = p;
@@ -1996,7 +1996,7 @@
X
X if ((adding) && (d->rcverr))
X kfree(d->rcverr);
- if (!(d->rcverr = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {
+ if (!(d->rcverr = kmalloc(sizeof(int) * m, GFP_KERNEL))) {
X printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
X return -1;
X }


@@ -2004,7 +2004,7 @@
X

X if ((adding) && (d->rcvcount))
X kfree(d->rcvcount);
- if (!(d->rcvcount = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {
+ if (!(d->rcvcount = kmalloc(sizeof(int) * m, GFP_KERNEL))) {
X printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
X if (!adding) kfree(d->rcverr);
X return -1;
@@ -2016,8 +2016,7 @@
X skb_queue_purge(&d->rpqueue[j]);
X kfree(d->rpqueue);
X }
- if (!(d->rpqueue =
- (struct sk_buff_head *) kmalloc(sizeof(struct sk_buff_head) * m, GFP_KERNEL))) {
+ if (!(d->rpqueue = kmalloc(sizeof(struct sk_buff_head) * m, GFP_KERNEL))) {
X printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
X if (!adding) {
X kfree(d->rcvcount);
@@ -2031,8 +2030,7 @@
X
X if ((adding) && (d->rcv_waitq))
X kfree(d->rcv_waitq);
- d->rcv_waitq = (wait_queue_head_t *)
- kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL);
+ d->rcv_waitq = kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL);
X if (!d->rcv_waitq) {
X printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
X if (!adding) {
@@ -2157,7 +2155,7 @@
X printk(KERN_WARNING "register_isdn: No write routine given.\n");
X return 0;
X }
- if (!(d = (driver *) kmalloc(sizeof(driver), GFP_KERNEL))) {
+ if (!(d = kmalloc(sizeof(driver), GFP_KERNEL))) {
X printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");
X return 0;
X }
diff -u --recursive --new-file v2.4.14/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- v2.4.14/linux/drivers/isdn/isdn_net.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/isdn/isdn_net.c Fri Nov 9 13:41:41 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.140.6.10 2001/09/28 08:05:29 kai Exp $
+/* $Id: isdn_net.c,v 1.140.6.11 2001/11/06 20:58:28 kai Exp $
X *
X * Linux ISDN subsystem, network interfaces and related functions (linklevel).
X *
@@ -175,7 +175,7 @@
X static void isdn_net_ciscohdlck_connected(isdn_net_local *lp);
X static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp);
X
-char *isdn_net_revision = "$Revision: 1.140.6.10 $";
+char *isdn_net_revision = "$Revision: 1.140.6.11 $";
X
X /*
X * Code for raw-networking over ISDN
@@ -333,7 +333,7 @@
X anymore = 0;
X while (p) {
X isdn_net_local *l = p->local;
- if ((jiffies - last_jiffies) == 0)
+ if (jiffies == last_jiffies)
X l->cps = l->transcount;
X else
X l->cps = (l->transcount * HZ) / (jiffies - last_jiffies);


@@ -352,9 +352,9 @@
X {

X if (l->hupflags & ISDN_MANCHARGE &&
X l->hupflags & ISDN_CHARGEHUP) {
- while (jiffies - l->chargetime > l->chargeint)
+ while (time_after(jiffies, l->chargetime + l->chargeint))
X l->chargetime += l->chargeint;
- if (jiffies - l->chargetime >= l->chargeint - 2 * HZ)
+ if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ))
X if (l->outgoing || l->hupflags & ISDN_INHUP)
X isdn_net_hangup(&p->dev);
X } else if (l->outgoing) {
@@ -363,7 +363,7 @@
X printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n",
X l->name, l->hupflags);
X isdn_net_hangup(&p->dev);
- } else if (jiffies - l->chargetime > l->chargeint) {
+ } else if (time_after(jiffies, l->chargetime + l->chargeint)) {
X printk(KERN_DEBUG
X "isdn_net: %s: chtime = %lu, chint = %d\n",
X l->name, l->chargetime, l->chargeint);
@@ -599,7 +599,7 @@
X anymore = 1;
X
X if(lp->dialtimeout > 0)
- if(lp->dialstarted == 0 || jiffies > (lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
+ if(lp->dialstarted == 0 || time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
X lp->dialstarted = jiffies;
X lp->dialwait_timer = 0;
X }
@@ -659,7 +659,7 @@
X printk(KERN_INFO "%s: Open leased line ...\n", lp->name);
X } else {
X if(lp->dialtimeout > 0)
- if(jiffies > (lp->dialstarted + lp->dialtimeout)) {
+ if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
X restore_flags(flags);
X lp->dialwait_timer = jiffies + lp->dialwait;
X lp->dialstarted = 0;
@@ -1106,7 +1106,7 @@
X lp->sqfull_stamp = jiffies;
X } else {
X /* subsequent overload: if slavedelay exceeded, start dialing */
- if ((jiffies - lp->sqfull_stamp) > lp->slavedelay) {
+ if (time_after(jiffies, lp->sqfull_stamp + lp->slavedelay)) {
X slp = lp->slave->priv;
X if (!(slp->flags & ISDN_NET_CONNECTED)) {
X isdn_net_force_dial_lp((isdn_net_local *) lp->slave->priv);
@@ -1115,7 +1115,7 @@
X }
X }
X } else {
- if (lp->sqfull && ((jiffies - lp->sqfull_stamp) > (lp->slavedelay + (10 * HZ)))) {
+ if (lp->sqfull && time_after(jiffies, lp->sqfull_stamp + lp->slavedelay + (10 * HZ))) {
X lp->sqfull = 0;
X }
X /* this is a hack to allow auto-hangup for slaves on moderate loads */
@@ -1225,11 +1225,11 @@
X cli();
X
X if(lp->dialwait_timer <= 0)
- if(lp->dialstarted > 0 && lp->dialtimeout > 0 && jiffies < lp->dialstarted + lp->dialtimeout + lp->dialwait)
+ if(lp->dialstarted > 0 && lp->dialtimeout > 0 && time_before(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait))
X lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait;
X
X if(lp->dialwait_timer > 0) {
- if(jiffies < lp->dialwait_timer) {
+ if(time_before(jiffies, lp->dialwait_timer)) {
X isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
X dev_kfree_skb(skb);
X restore_flags(flags);
diff -u --recursive --new-file v2.4.14/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- v2.4.14/linux/drivers/isdn/isdn_ppp.c Mon Nov 5 15:55:30 2001
+++ linux/drivers/isdn/isdn_ppp.c Fri Nov 9 13:41:41 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.85.6.7 2001/09/23 22:24:31 kai Exp $
+/* $Id: isdn_ppp.c,v 1.85.6.9 2001/11/06 20:58:28 kai Exp $
X *
X * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
X *
@@ -69,7 +69,7 @@
X static int isdn_ppp_bundle(struct ippp_struct *, int unit);
X #endif /* CONFIG_ISDN_MPP */
X
-char *isdn_ppp_revision = "$Revision: 1.85.6.7 $";
+char *isdn_ppp_revision = "$Revision: 1.85.6.9 $";
X
X static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
X
@@ -977,7 +977,7 @@
X printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
X isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
X }
- if (is->compflags & SC_DECOMP_ON) {
+ if (mis->compflags & SC_DECOMP_ON) {
X skb = isdn_ppp_decompress(skb, is, mis, &proto);
X if (!skb) // decompression error
X return;
@@ -993,6 +993,10 @@
X printk(KERN_DEBUG "isdn_ppp: IP\n");
X skb->protocol = htons(ETH_P_IP);
X break;
+ case PPP_COMP:
+ case PPP_COMPFRAG:
+ printk(KERN_INFO "isdn_ppp: unexpected compressed frame dropped\n");
+ goto drop_packet;
X #ifdef CONFIG_ISDN_PPP_VJ
X case PPP_VJC_UNCOMP:
X if (is->debug & 0x20)
@@ -1216,8 +1220,15 @@
X /*
X * normal (single link) or bundle compression
X */
- if(ipts->compflags & SC_COMP_ON)
- skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
+ if(ipts->compflags & SC_COMP_ON) {
+ /* We send compressed only if both down- und upstream
+ compression is negotiated, that means, CCP is up */
+ if(ipts->compflags & SC_DECOMP_ON) {
+ skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
+ } else {
+ printk(KERN_DEBUG "isdn_ppp: CCP not yet up - sending as-is\n");
+ }
+ }
X
X if (ipt->debug & 0x24)
X printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);
@@ -2082,8 +2093,6 @@
X }
X if(rs->ta && rs->state == CCPResetSentReq) {
X /* We are correct here */
- printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
- rs->id);
X if(!rs->expra) {
X /* Hmm, there is no Ack really expected. We can clean
X up the state now, it will be reallocated if the
@@ -2092,6 +2101,8 @@
X isdn_ppp_ccp_reset_free_state(rs->is, rs->id);
X return;
X }
+ printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
+ rs->id);
X /* Push it again */
X isdn_ppp_ccp_xmit_reset(rs->is, PPP_CCP, CCP_RESETREQ, rs->id,
X rs->data, rs->dlen);
@@ -2318,7 +2329,6 @@
X if (len <= 0) {
X switch(len) {
X case DECOMP_ERROR:
- ri->pppcfg |= SC_DC_ERROR;
X printk(KERN_INFO "ippp: decomp wants reset %s params\n",
X rsparm.valid ? "with" : "without");
X
@@ -2482,7 +2492,6 @@
X len, NULL);
X /* TODO: This is not easy to decide here */
X mis->compflags &= ~SC_DECOMP_DISCARD;
- mis->pppcfg &= ~SC_DC_ERROR;
X }
X else {
X isdn_ppp_ccp_reset_ack_rcvd(is, skb->data[1]);
@@ -2495,7 +2504,6 @@
X len, NULL);
X /* TODO: neither here */
X is->compflags &= ~SC_LINK_DECOMP_DISCARD;
- is->pppcfg &= ~SC_DC_ERROR;
X }
X break;
X
@@ -2570,6 +2578,15 @@
X * that's too big of a change now. --kai
X */
X
+/* Actually, we might turn this into an advantage: deal with the RFC in
+ * the old tradition of beeing generous on what we accept, but beeing
+ * strict on what we send. Thus we should just
+ * - accept compressed frames as soon as decompression is negotiated
+ * - send compressed frames only when decomp *and* comp are negotiated
+ * - drop rx compressed frames if we cannot decomp (instead of pushing them
+ * up to ipppd)
+ * and I tried to modify this file according to that. --abp
+ */
X
X static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb)
X {
diff -u --recursive --new-file v2.4.14/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
--- v2.4.14/linux/drivers/isdn/isdn_tty.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/isdn/isdn_tty.c Fri Nov 9 13:41:41 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.c,v 1.94.6.8 2001/09/23 22:24:32 kai Exp $
+/* $Id: isdn_tty.c,v 1.94.6.9 2001/11/06 20:58:29 kai Exp $
X *
X * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
X *
@@ -53,7 +53,7 @@
X static int si2bit[8] =
X {4, 1, 4, 4, 4, 4, 4, 4};
X
-char *isdn_tty_revision = "$Revision: 1.94.6.8 $";
+char *isdn_tty_revision = "$Revision: 1.94.6.9 $";
X
X
X /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
@@ -2596,11 +2596,11 @@
X if (*(p++) == plus) {
X if ((*pluscount)++) {
X /* Time since last '+' > 0.5 sec. ? */
- if ((jiffies - *lastplus) > PLUSWAIT1)
+ if (time_after(jiffies, *lastplus + PLUSWAIT1))
X *pluscount = 1;
X } else {
X /* Time since last non-'+' < 1.5 sec. ? */
- if ((jiffies - *lastplus) < PLUSWAIT2)
+ if (time_before(jiffies, *lastplus + PLUSWAIT2))
X *pluscount = 0;
X }
X if ((*pluscount == 3) && (count == 1))
@@ -3974,7 +3974,7 @@
X if (info->online) {
X ton = 1;
X if ((info->emu.pluscount == 3) &&
- ((jiffies - info->emu.lastplus) > PLUSWAIT2)) {
+ time_after(jiffies , info->emu.lastplus + PLUSWAIT2)) {
X info->emu.pluscount = 0;
X info->online = 0;
X isdn_tty_modem_result(RESULT_OK, info);
diff -u --recursive --new-file v2.4.14/linux/drivers/isdn/isdnloop/isdnloop.c linux/drivers/isdn/isdnloop/isdnloop.c
--- v2.4.14/linux/drivers/isdn/isdnloop/isdnloop.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/isdn/isdnloop/isdnloop.c Mon Nov 12 10:02:54 2001
@@ -1,4 +1,4 @@
-/* $Id: isdnloop.c,v 1.11.6.6 2001/09/23 22:24:56 kai Exp $
+/* $Id: isdnloop.c,v 1.11.6.7 2001/11/11 19:54:31 kai Exp $
X *
X * ISDN low-level module implementing a dummy loop driver.
X *
@@ -14,7 +14,7 @@
X #include <linux/init.h>
X #include "isdnloop.h"
X
-static char *revision = "$Revision: 1.11.6.6 $";
+static char *revision = "$Revision: 1.11.6.7 $";
X static char *isdnloop_id;
X
X MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card");
@@ -1542,7 +1542,11 @@
X } else
X strcpy(rev, " ??? ");
X printk(KERN_NOTICE "isdnloop-ISDN-driver Rev%s\n", rev);
- return (isdnloop_addcard(isdnloop_id));
+
+ if (isdnloop_id)
+ return (isdnloop_addcard(isdnloop_id));
+
+ return 0;
X }
X
X static void __exit
diff -u --recursive --new-file v2.4.14/linux/drivers/isdn/tpam/tpam.h linux/drivers/isdn/tpam/tpam.h
--- v2.4.14/linux/drivers/isdn/tpam/tpam.h Tue Oct 9 17:06:51 2001
+++ linux/drivers/isdn/tpam/tpam.h Fri Nov 9 13:41:41 2001
@@ -1,4 +1,4 @@
-/* $Id: tpam.h,v 1.1.2.2 2001/09/23 22:25:03 kai Exp $
+/* $Id: tpam.h,v 1.1.2.3 2001/11/06 20:58:30 kai Exp $
X *
X * Turbo PAM ISDN driver for Linux. (Kernel Driver)
X *
@@ -213,8 +213,8 @@
X extern void tpam_recv_U3ReadyToReceiveInd(tpam_card *, struct sk_buff *);
X
X /* Function prototypes from tpam_hdlc.c */
-extern u32 hdlc_encode(u8 *, u8 *, u32 *, u32);
-extern u32 hdlc_decode(u8 *, u8 *, u32);
+extern u32 tpam_hdlc_encode(u8 *, u8 *, u32 *, u32);
+extern u32 tpam_hdlc_decode(u8 *, u8 *, u32);
X
X /* Function prototypes from tpam_crcpc.c */
X extern void init_CRC(void);
diff -u --recursive --new-file v2.4.14/linux/drivers/isdn/tpam/tpam_commands.c linux/drivers/isdn/tpam/tpam_commands.c
--- v2.4.14/linux/drivers/isdn/tpam/tpam_commands.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/isdn/tpam/tpam_commands.c Fri Nov 9 13:41:41 2001
@@ -1,4 +1,4 @@
-/* $Id: tpam_commands.c,v 1.1.2.3 2001/09/23 22:25:03 kai Exp $
+/* $Id: tpam_commands.c,v 1.1.2.4 2001/11/06 20:58:30 kai Exp $
X *
X * Turbo PAM ISDN driver for Linux. (Kernel Driver - ISDN commands)
X *


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

X /* wait for the board signature */
X timeout = jiffies + SIGNATURE_TIMEOUT;
- while (timeout > jiffies) {
+ while (time_before(jiffies, timeout)) {
X spin_lock_irq(&card->lock);
X signature = copy_from_pam_dword(card,
X (void *)TPAM_MAGICNUMBER_REGISTER);
@@ -241,7 +241,7 @@
X
X /* wait for NCO creation confirmation */
X timeout = jiffies + NCOCREATE_TIMEOUT;
- while (timeout > jiffies) {
+ while (time_before(jiffies, timeout)) {
X if (card->channels_tested == TPAM_NBCHANNEL)
X break;
X set_current_state(TASK_UNINTERRUPTIBLE);
@@ -572,7 +572,7 @@
X return -ENOMEM;
X }
X hdlc_no_accm_encode(skb->data, skb->len, tempdata, &templen);
- finallen = hdlc_encode(tempdata, finaldata,
+ finallen = tpam_hdlc_encode(tempdata, finaldata,
X &card->channels[channel].hdlcshift,
X templen);
X free_page((u32)tempdata);
@@ -897,7 +897,7 @@
X "get_free_page failed\n");
X return;
X }
- templen = hdlc_decode(data, tempdata, len);
+ templen = tpam_hdlc_decode(data, tempdata, len);
X templen = hdlc_no_accm_decode(tempdata, templen);
X if (!(result = alloc_skb(templen, GFP_ATOMIC))) {
X printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
@@ -1019,6 +1019,6 @@
X init_timer(timer);
X timer->function = tpam_statcallb_run;
X timer->data = (unsigned long)ds;
- timer->expires = jiffies + 0.1 * HZ; /* 0.1 second */
+ timer->expires = jiffies + HZ / 10; /* 0.1 second */
X add_timer(timer);
X }
diff -u --recursive --new-file v2.4.14/linux/drivers/isdn/tpam/tpam_hdlc.c linux/drivers/isdn/tpam/tpam_hdlc.c
--- v2.4.14/linux/drivers/isdn/tpam/tpam_hdlc.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/isdn/tpam/tpam_hdlc.c Fri Nov 9 13:41:41 2001
@@ -1,4 +1,4 @@
-/* $Id: tpam_hdlc.c,v 1.1.2.2 2001/09/23 22:25:03 kai Exp $
+/* $Id: tpam_hdlc.c,v 1.1.2.3 2001/11/06 20:58:30 kai Exp $
X *
X * Turbo PAM ISDN driver for Linux. (Kernel Driver - HDLC encoding)
X *
@@ -35,11 +35,11 @@
X destuff5 : array necessary for the bit destuffing algorithm
X destuffs[] : array conaining the previous 6 arrays
X
- hdlc_encode : bit stuffing of a byte array, with the addition of a start and
- end flag, using the bit shift given in parameter (which is
- updated at the end of encoding).
- hdlc_decode : bit de-stuffing of a byte array with detection of possible
- ABORTs.
+ tpam_hdlc_encode : bit stuffing of a byte array, with the addition
+ of a start and end flag, using the bit shift given in
+ parameter (which is updated at the end of encoding).
+ tpam_hdlc_decode : bit de-stuffing of a byte array with detection of
+ possible ABORTs.
X
X Revision History:
X
@@ -553,7 +553,7 @@
X
X /*- AuverTech Telecom -------------------------------------------------------+
X | |
- | @Function : hdlc_encode |
+ | @Function : tpam_hdlc_encode |
X | @Author : Cyrille Boudon |
X | |
X +---------------------------------------------------------------------------+
@@ -576,8 +576,8 @@
X | beginning (for the first frame), the shift must be initialized to 0. |
X | |
X +---------------------------------------------------------------------------*/
-DWORD hdlc_encode(BYTE *pbyBuffIn, BYTE *pbyBuffOut,
- DWORD *pdwInitialShift, DWORD dwLength)
+DWORD tpam_hdlc_encode(BYTE *pbyBuffIn, BYTE *pbyBuffOut,
+ DWORD *pdwInitialShift, DWORD dwLength)
X {
X DWORD dwShifter; // temporary variable
X DWORD dwShiftNb; // shift due to the insertion of '0'
@@ -754,7 +754,7 @@
X
X /*- AuverTech Telecom -------------------------------------------------------+
X | |
- | @Function : hdlc_decode |
+ | @Function : tpam_hdlc_decode |
X | @Author : Cyrille Boudon |
X | |
X +---------------------------------------------------------------------------+
@@ -773,7 +773,7 @@
X | If an abort is encountered, the returned count is '0'. |
X | |
X +---------------------------------------------------------------------------*/
-DWORD hdlc_decode(BYTE * pbyBuffIn, BYTE * pbyBuffOut, DWORD dwLength)
+DWORD tpam_hdlc_decode(BYTE * pbyBuffIn, BYTE * pbyBuffOut, DWORD dwLength)
X {
X BYTE byCharIn; // byte being decoded
X BYTE byCarry; // current carry
diff -u --recursive --new-file v2.4.14/linux/drivers/md/Makefile linux/drivers/md/Makefile
--- v2.4.14/linux/drivers/md/Makefile Sun Sep 23 11:40:58 2001
+++ linux/drivers/md/Makefile Sun Nov 11 10:09:32 2001
@@ -6,7 +6,7 @@
X
X export-objs := md.o xor.o
X list-multi := lvm-mod.o
-lvm-mod-objs := lvm.o lvm-snap.o
+lvm-mod-objs := lvm.o lvm-snap.o lvm-fs.o
X
X # Note: link order is important. All raid personalities
X # and xor.o must come before md.o, as they each initialise
diff -u --recursive --new-file v2.4.14/linux/drivers/md/lvm-fs.c linux/drivers/md/lvm-fs.c
--- v2.4.14/linux/drivers/md/lvm-fs.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/md/lvm-fs.c Sun Nov 11 10:09:32 2001
@@ -0,0 +1,623 @@
+/*
+ * kernel/lvm-fs.c
+ *
+ * Copyright (C) 2001 Sistina Software
+ *
+ * January,February 2001
+ *
+ * LVM driver is free software; you can redistribute it and/or modify


+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * LVM driver 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 GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.


+ *
+ */
+

+/*
+ * Changelog
+ *
+ * 11/01/2001 - First version (Joe Thornber)
+ * 21/03/2001 - added display of stripes and stripe size (HM)
+ * 04/10/2001 - corrected devfs_register() call in lvm_init_fs()
+ * 11/04/2001 - don't devfs_register("lvm") as user-space always does it
+ * 10/05/2001 - show more of PV name in /proc/lvm/global


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

+#include <linux/version.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/smp_lock.h>
+
+#include <linux/devfs_fs_kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/lvm.h>
+
+#include "lvm-internal.h"
+
+
+static int _proc_read_vg(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+static int _proc_read_lv(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+static int _proc_read_pv(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+static int _proc_read_global(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+
+static int _vg_info(vg_t *vg_ptr, char *buf);
+static int _lv_info(vg_t *vg_ptr, lv_t *lv_ptr, char *buf);
+static int _pv_info(pv_t *pv_ptr, char *buf);
+
+static void _show_uuid(const char *src, char *b, char *e);
+
+#if 0
+static devfs_handle_t lvm_devfs_handle;
+#endif
+static devfs_handle_t vg_devfs_handle[MAX_VG];
+static devfs_handle_t ch_devfs_handle[MAX_VG];
+static devfs_handle_t lv_devfs_handle[MAX_LV];
+
+static struct proc_dir_entry *lvm_proc_dir = NULL;
+static struct proc_dir_entry *lvm_proc_vg_subdir = NULL;
+
+/* inline functions */
+
+/* public interface */
+void __init lvm_init_fs() {
+ struct proc_dir_entry *pde;
+
+/* User-space has already registered this */
+#if 0
+ lvm_devfs_handle = devfs_register(
+ 0 , "lvm", 0, LVM_CHAR_MAJOR, 0,
+ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
+ &lvm_chr_fops, NULL);
+#endif
+
+ lvm_proc_dir = create_proc_entry(LVM_DIR, S_IFDIR, &proc_root);
+ if (lvm_proc_dir) {
+ lvm_proc_vg_subdir = create_proc_entry(LVM_VG_SUBDIR, S_IFDIR,
+ lvm_proc_dir);
+ pde = create_proc_entry(LVM_GLOBAL, S_IFREG, lvm_proc_dir);
+ if ( pde != NULL) pde->read_proc = _proc_read_global;
+ }
+}
+
+void lvm_fin_fs() {
+#if 0
+ devfs_unregister (lvm_devfs_handle);
+#endif
+
+ remove_proc_entry(LVM_GLOBAL, lvm_proc_dir);
+ remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir);
+ remove_proc_entry(LVM_DIR, &proc_root);
+}
+
+void lvm_fs_create_vg(vg_t *vg_ptr) {
+ struct proc_dir_entry *pde;
+
+ vg_devfs_handle[vg_ptr->vg_number] =
+ devfs_mk_dir(0, vg_ptr->vg_name, NULL);
+
+ ch_devfs_handle[vg_ptr->vg_number] = devfs_register(
+ vg_devfs_handle[vg_ptr->vg_number] , "group",
+ DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR, vg_ptr->vg_number,
+ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
+ &lvm_chr_fops, NULL);
+
+ vg_ptr->vg_dir_pde = create_proc_entry(vg_ptr->vg_name, S_IFDIR,
+ lvm_proc_vg_subdir);
+
+ if((pde = create_proc_entry("group", S_IFREG, vg_ptr->vg_dir_pde))) {
+ pde->read_proc = _proc_read_vg;
+ pde->data = vg_ptr;
+ }
+
+ vg_ptr->lv_subdir_pde =
+ create_proc_entry(LVM_LV_SUBDIR, S_IFDIR, vg_ptr->vg_dir_pde);
+
+ vg_ptr->pv_subdir_pde =
+ create_proc_entry(LVM_PV_SUBDIR, S_IFDIR, vg_ptr->vg_dir_pde);
+}
+
+void lvm_fs_remove_vg(vg_t *vg_ptr) {
+ int i;
+
+ devfs_unregister(ch_devfs_handle[vg_ptr->vg_number]);
+ devfs_unregister(vg_devfs_handle[vg_ptr->vg_number]);
+
+ /* remove lv's */
+ for(i = 0; i < vg_ptr->lv_max; i++)
+ if(vg_ptr->lv[i]) lvm_fs_remove_lv(vg_ptr, vg_ptr->lv[i]);
+
+ /* remove pv's */
+ for(i = 0; i < vg_ptr->pv_max; i++)
+ if(vg_ptr->pv[i]) lvm_fs_remove_pv(vg_ptr, vg_ptr->pv[i]);
+
+ if(vg_ptr->vg_dir_pde) {
+ remove_proc_entry(LVM_LV_SUBDIR, vg_ptr->vg_dir_pde);
+ vg_ptr->lv_subdir_pde = NULL;
+
+ remove_proc_entry(LVM_PV_SUBDIR, vg_ptr->vg_dir_pde);
+ vg_ptr->pv_subdir_pde = NULL;
+
+ remove_proc_entry("group", vg_ptr->vg_dir_pde);
+ vg_ptr->vg_dir_pde = NULL;
+
+ remove_proc_entry(vg_ptr->vg_name, lvm_proc_vg_subdir);
+ }
+}
+
+
+static inline const char *_basename(const char *str) {
+ const char *name = strrchr(str, '/');
+ name = name ? name + 1 : str;
+ return name;
+}
+
+devfs_handle_t lvm_fs_create_lv(vg_t *vg_ptr, lv_t *lv) {
+ struct proc_dir_entry *pde;
+ const char *name = _basename(lv->lv_name);
+
+ lv_devfs_handle[MINOR(lv->lv_dev)] = devfs_register(
+ vg_devfs_handle[vg_ptr->vg_number], name,
+ DEVFS_FL_DEFAULT, LVM_BLK_MAJOR, MINOR(lv->lv_dev),
+ S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
+ &lvm_blk_dops, NULL);
+
+ if(vg_ptr->lv_subdir_pde &&
+ (pde = create_proc_entry(name, S_IFREG, vg_ptr->lv_subdir_pde))) {
+ pde->read_proc = _proc_read_lv;
+ pde->data = lv;
+ }
+ return lv_devfs_handle[MINOR(lv->lv_dev)];
+}
+
+void lvm_fs_remove_lv(vg_t *vg_ptr, lv_t *lv) {
+ devfs_unregister(lv_devfs_handle[MINOR(lv->lv_dev)]);
+
+ if(vg_ptr->lv_subdir_pde) {
+ const char *name = _basename(lv->lv_name);
+ remove_proc_entry(name, vg_ptr->lv_subdir_pde);
+ }
+}
+
+
+static inline void _make_pv_name(const char *src, char *b, char *e) {
+ int offset = strlen(LVM_DIR_PREFIX);
+ if(strncmp(src, LVM_DIR_PREFIX, offset))
+ offset = 0;
+
+ e--;
+ src += offset;
+ while(*src && (b != e)) {
+ *b++ = (*src == '/') ? '_' : *src;
+ src++;
+ }
+ *b = '\0';
+}
+
+void lvm_fs_create_pv(vg_t *vg_ptr, pv_t *pv) {
+ struct proc_dir_entry *pde;
+ char name[NAME_LEN];
+
+ if(!vg_ptr->pv_subdir_pde)
+ return;
+
+ _make_pv_name(pv->pv_name, name, name + sizeof(name));
+ if((pde = create_proc_entry(name, S_IFREG, vg_ptr->pv_subdir_pde))) {
+ pde->read_proc = _proc_read_pv;
+ pde->data = pv;
+ }
+}
+
+void lvm_fs_remove_pv(vg_t *vg_ptr, pv_t *pv) {
+ char name[NAME_LEN];
+
+ if(!vg_ptr->pv_subdir_pde)
+ return;
+
+ _make_pv_name(pv->pv_name, name, name + sizeof(name));
+ remove_proc_entry(name, vg_ptr->pv_subdir_pde);
+}
+
+
+static int _proc_read_vg(char *page, char **start, off_t off,
+ int count, int *eof, void *data) {
+ int sz = 0;
+ vg_t *vg_ptr = data;
+ char uuid[NAME_LEN];
+
+ sz += sprintf(page + sz, "name: %s\n", vg_ptr->vg_name);
+ sz += sprintf(page + sz, "size: %u\n",
+ vg_ptr->pe_total * vg_ptr->pe_size / 2);
+ sz += sprintf(page + sz, "access: %u\n", vg_ptr->vg_access);
+ sz += sprintf(page + sz, "status: %u\n", vg_ptr->vg_status);
+ sz += sprintf(page + sz, "number: %u\n", vg_ptr->vg_number);
+ sz += sprintf(page + sz, "LV max: %u\n", vg_ptr->lv_max);
+ sz += sprintf(page + sz, "LV current: %u\n", vg_ptr->lv_cur);
+ sz += sprintf(page + sz, "LV open: %u\n", vg_ptr->lv_open);
+ sz += sprintf(page + sz, "PV max: %u\n", vg_ptr->pv_max);
+ sz += sprintf(page + sz, "PV current: %u\n", vg_ptr->pv_cur);
+ sz += sprintf(page + sz, "PV active: %u\n", vg_ptr->pv_act);
+ sz += sprintf(page + sz, "PE size: %u\n", vg_ptr->pe_size / 2);
+ sz += sprintf(page + sz, "PE total: %u\n", vg_ptr->pe_total);
+ sz += sprintf(page + sz, "PE allocated: %u\n", vg_ptr->pe_allocated);
+
+ _show_uuid(vg_ptr->vg_uuid, uuid, uuid + sizeof(uuid));
+ sz += sprintf(page + sz, "uuid: %s\n", uuid);
+
+ return sz;
+}
+
+static int _proc_read_lv(char *page, char **start, off_t off,
+ int count, int *eof, void *data) {
+ int sz = 0;
+ lv_t *lv = data;
+
+ sz += sprintf(page + sz, "name: %s\n", lv->lv_name);
+ sz += sprintf(page + sz, "size: %u\n", lv->lv_size);
+ sz += sprintf(page + sz, "access: %u\n", lv->lv_access);
+ sz += sprintf(page + sz, "status: %u\n", lv->lv_status);
+ sz += sprintf(page + sz, "number: %u\n", lv->lv_number);
+ sz += sprintf(page + sz, "open: %u\n", lv->lv_open);
+ sz += sprintf(page + sz, "allocation: %u\n", lv->lv_allocation);
+ if(lv->lv_stripes > 1) {
+ sz += sprintf(page + sz, "stripes: %u\n",
+ lv->lv_stripes);
+ sz += sprintf(page + sz, "stripesize: %u\n",
+ lv->lv_stripesize);
+ }
+ sz += sprintf(page + sz, "device: %02u:%02u\n",
+ MAJOR(lv->lv_dev), MINOR(lv->lv_dev));
+
+ return sz;
+}
+
+static int _proc_read_pv(char *page, char **start, off_t off,
+ int count, int *eof, void *data) {
+ int sz = 0;
+ pv_t *pv = data;
+ char uuid[NAME_LEN];
+
+ sz += sprintf(page + sz, "name: %s\n", pv->pv_name);
+ sz += sprintf(page + sz, "size: %u\n", pv->pv_size);
+ sz += sprintf(page + sz, "status: %u\n", pv->pv_status);
+ sz += sprintf(page + sz, "number: %u\n", pv->pv_number);
+ sz += sprintf(page + sz, "allocatable: %u\n", pv->pv_allocatable);
+ sz += sprintf(page + sz, "LV current: %u\n", pv->lv_cur);
+ sz += sprintf(page + sz, "PE size: %u\n", pv->pe_size / 2);
+ sz += sprintf(page + sz, "PE total: %u\n", pv->pe_total);
+ sz += sprintf(page + sz, "PE allocated: %u\n", pv->pe_allocated);
+ sz += sprintf(page + sz, "device: %02u:%02u\n",
+ MAJOR(pv->pv_dev), MINOR(pv->pv_dev));
+
+ _show_uuid(pv->pv_uuid, uuid, uuid + sizeof(uuid));
+ sz += sprintf(page + sz, "uuid: %s\n", uuid);
+
+ return sz;
+}
+
+static int _proc_read_global(char *page, char **start, off_t pos, int count,
+ int *eof, void *data) {
+
+#define LVM_PROC_BUF ( i == 0 ? dummy_buf : &buf[sz])
+
+ int c, i, l, p, v, vg_counter, pv_counter, lv_counter, lv_open_counter,
+ lv_open_total, pe_t_bytes, hash_table_bytes, lv_block_exception_t_bytes, seconds;
+ static off_t sz;
+ off_t sz_last;
+ static char *buf = NULL;
+ static char dummy_buf[160]; /* sized for 2 lines */
+ vg_t *vg_ptr;
+ lv_t *lv_ptr;
+ pv_t *pv_ptr;
+
+
+#ifdef DEBUG_LVM_PROC_GET_INFO
+ printk(KERN_DEBUG
+ "%s - lvm_proc_get_global_info CALLED pos: %lu count: %d\n",
+ lvm_name, pos, count);
+#endif
+
+ if(pos != 0 && buf != NULL)
+ goto out;
+
+ sz_last = vg_counter = pv_counter = lv_counter = lv_open_counter = \
+ lv_open_total = pe_t_bytes = hash_table_bytes = \
+ lv_block_exception_t_bytes = 0;
+
+ /* get some statistics */
+ for (v = 0; v < ABS_MAX_VG; v++) {
+ if ((vg_ptr = vg[v]) != NULL) {
+ vg_counter++;
+ pv_counter += vg_ptr->pv_cur;
+ lv_counter += vg_ptr->lv_cur;
+ if (vg_ptr->lv_cur > 0) {
+ for (l = 0; l < vg[v]->lv_max; l++) {
+ if ((lv_ptr = vg_ptr->lv[l]) != NULL) {
+ pe_t_bytes += lv_ptr->lv_allocated_le;
+ hash_table_bytes += lv_ptr->lv_snapshot_hash_table_size;
+ if (lv_ptr->lv_block_exception != NULL)
+ lv_block_exception_t_bytes += lv_ptr->lv_remap_end;
+ if (lv_ptr->lv_open > 0) {
+ lv_open_counter++;
+ lv_open_total += lv_ptr->lv_open;


+ }
+ }
+ }
+ }
+ }

+ }
+
+ pe_t_bytes *= sizeof(pe_t);
+ lv_block_exception_t_bytes *= sizeof(lv_block_exception_t);
+
+ if (buf != NULL) {
+ P_KFREE("%s -- vfree %d\n", lvm_name, __LINE__);
+ lock_kernel();
+ vfree(buf);
+ unlock_kernel();
+ buf = NULL;
+ }
+ /* 2 times: first to get size to allocate buffer,
+ 2nd to fill the malloced buffer */
+ for (i = 0; i < 2; i++) {
+ sz = 0;
+ sz += sprintf(LVM_PROC_BUF,
+ "LVM "
+#ifdef MODULE
+ "module"
+#else
+ "driver"
+#endif
+ " %s\n\n"
+ "Total: %d VG%s %d PV%s %d LV%s ",
+ lvm_version,
+ vg_counter, vg_counter == 1 ? "" : "s",
+ pv_counter, pv_counter == 1 ? "" : "s",
+ lv_counter, lv_counter == 1 ? "" : "s");
+ sz += sprintf(LVM_PROC_BUF,
+ "(%d LV%s open",
+ lv_open_counter,
+ lv_open_counter == 1 ? "" : "s");
+ if (lv_open_total > 0)
+ sz += sprintf(LVM_PROC_BUF,
+ " %d times)\n",
+ lv_open_total);
+ else
+ sz += sprintf(LVM_PROC_BUF, ")");
+ sz += sprintf(LVM_PROC_BUF,
+ "\nGlobal: %lu bytes malloced IOP version: %d ",
+ vg_counter * sizeof(vg_t) +
+ pv_counter * sizeof(pv_t) +
+ lv_counter * sizeof(lv_t) +
+ pe_t_bytes + hash_table_bytes + lv_block_exception_t_bytes + sz_last,
+ lvm_iop_version);
+
+ seconds = CURRENT_TIME - loadtime;
+ if (seconds < 0)
+ loadtime = CURRENT_TIME + seconds;
+ if (seconds / 86400 > 0) {
+ sz += sprintf(LVM_PROC_BUF, "%d day%s ",
+ seconds / 86400,
+ seconds / 86400 == 0 ||
+ seconds / 86400 > 1 ? "s" : "");
+ }
+ sz += sprintf(LVM_PROC_BUF, "%d:%02d:%02d active\n",
+ (seconds % 86400) / 3600,
+ (seconds % 3600) / 60,
+ seconds % 60);
+
+ if (vg_counter > 0) {
+ for (v = 0; v < ABS_MAX_VG; v++) {
+ /* volume group */
+ if ((vg_ptr = vg[v]) != NULL) {
+ sz += _vg_info(vg_ptr, LVM_PROC_BUF);
+
+ /* physical volumes */
+ sz += sprintf(LVM_PROC_BUF,
+ "\n PV%s ",
+ vg_ptr->pv_cur == 1 ? ": " : "s:");
+ c = 0;
+ for (p = 0; p < vg_ptr->pv_max; p++) {
+ if ((pv_ptr = vg_ptr->pv[p]) != NULL) {
+ sz += _pv_info(pv_ptr, LVM_PROC_BUF);
+
+ c++;
+ if (c < vg_ptr->pv_cur)
+ sz += sprintf(LVM_PROC_BUF,
+ "\n ");
+ }
+ }
+
+ /* logical volumes */
+ sz += sprintf(LVM_PROC_BUF,
+ "\n LV%s ",
+ vg_ptr->lv_cur == 1 ? ": " : "s:");
+ c = 0;
+ for (l = 0; l < vg_ptr->lv_max; l++) {
+ if ((lv_ptr = vg_ptr->lv[l]) != NULL) {
+ sz += _lv_info(vg_ptr, lv_ptr, LVM_PROC_BUF);
+ c++;
+ if (c < vg_ptr->lv_cur)
+ sz += sprintf(LVM_PROC_BUF,
+ "\n ");
+ }
+ }
+ if (vg_ptr->lv_cur == 0) sz += sprintf(LVM_PROC_BUF, "none");
+ sz += sprintf(LVM_PROC_BUF, "\n");
+ }
+ }
+ }
+ if (buf == NULL) {
+ lock_kernel();
+ buf = vmalloc(sz);
+ unlock_kernel();
+ if (buf == NULL) {
+ sz = 0;
+ return sprintf(page, "%s - vmalloc error at line %d\n",
+ lvm_name, __LINE__);
+ }
+ }
+ sz_last = sz;
+ }
+
+ out:
+ if (pos > sz - 1) {
+ lock_kernel();
+ vfree(buf);
+ unlock_kernel();
+ buf = NULL;
+ return 0;
+ }
+ *start = &buf[pos];
+ if (sz - pos < count)
+ return sz - pos;
+ else
+ return count;
+
+#undef LVM_PROC_BUF
+}
+
+/*
+ * provide VG info for proc filesystem use (global)
+ */
+static int _vg_info(vg_t *vg_ptr, char *buf) {
+ int sz = 0;
+ char inactive_flag = ' ';
+
+ if (!(vg_ptr->vg_status & VG_ACTIVE)) inactive_flag = 'I';
+ sz = sprintf(buf,
+ "\nVG: %c%s [%d PV, %d LV/%d open] "
+ " PE Size: %d KB\n"
+ " Usage [KB/PE]: %d /%d total "
+ "%d /%d used %d /%d free",
+ inactive_flag,
+ vg_ptr->vg_name,
+ vg_ptr->pv_cur,
+ vg_ptr->lv_cur,
+ vg_ptr->lv_open,
+ vg_ptr->pe_size >> 1,
+ vg_ptr->pe_size * vg_ptr->pe_total >> 1,
+ vg_ptr->pe_total,
+ vg_ptr->pe_allocated * vg_ptr->pe_size >> 1,
+ vg_ptr->pe_allocated,
+ (vg_ptr->pe_total - vg_ptr->pe_allocated) *
+ vg_ptr->pe_size >> 1,
+ vg_ptr->pe_total - vg_ptr->pe_allocated);
+ return sz;
+}
+
+
+/*
+ * provide LV info for proc filesystem use (global)
+ */
+static int _lv_info(vg_t *vg_ptr, lv_t *lv_ptr, char *buf) {
+ int sz = 0;
+ char inactive_flag = 'A', allocation_flag = ' ',
+ stripes_flag = ' ', rw_flag = ' ', *basename;
+
+ if (!(lv_ptr->lv_status & LV_ACTIVE))
+ inactive_flag = 'I';
+ rw_flag = 'R';
+ if (lv_ptr->lv_access & LV_WRITE)
+ rw_flag = 'W';
+ allocation_flag = 'D';
+ if (lv_ptr->lv_allocation & LV_CONTIGUOUS)
+ allocation_flag = 'C';
+ stripes_flag = 'L';
+ if (lv_ptr->lv_stripes > 1)
+ stripes_flag = 'S';
+ sz += sprintf(buf+sz,
+ "[%c%c%c%c",
+ inactive_flag,
+ rw_flag,
+ allocation_flag,
+ stripes_flag);
+ if (lv_ptr->lv_stripes > 1)
+ sz += sprintf(buf+sz, "%-2d",
+ lv_ptr->lv_stripes);
+ else
+ sz += sprintf(buf+sz, " ");
+
+ /* FIXME: use _basename */
+ basename = strrchr(lv_ptr->lv_name, '/');
+ if ( basename == 0) basename = lv_ptr->lv_name;
+ else basename++;
+ sz += sprintf(buf+sz, "] %-25s", basename);
+ if (strlen(basename) > 25)
+ sz += sprintf(buf+sz,
+ "\n ");
+ sz += sprintf(buf+sz, "%9d /%-6d ",
+ lv_ptr->lv_size >> 1,
+ lv_ptr->lv_size / vg_ptr->pe_size);
+
+ if (lv_ptr->lv_open == 0)
+ sz += sprintf(buf+sz, "close");
+ else
+ sz += sprintf(buf+sz, "%dx open",
+ lv_ptr->lv_open);
+
+ return sz;
+}
+
+
+/*
+ * provide PV info for proc filesystem use (global)
+ */
+static int _pv_info(pv_t *pv, char *buf) {
+ int sz = 0;
+ char inactive_flag = 'A', allocation_flag = ' ';
+ char *pv_name = NULL;
+
+ if (!(pv->pv_status & PV_ACTIVE))
+ inactive_flag = 'I';
+ allocation_flag = 'A';
+ if (!(pv->pv_allocatable & PV_ALLOCATABLE))
+ allocation_flag = 'N';
+ pv_name = strchr(pv->pv_name+1,'/');
+ if ( pv_name == 0) pv_name = pv->pv_name;
+ else pv_name++;
+ sz = sprintf(buf,
+ "[%c%c] %-21s %8d /%-6d "
+ "%8d /%-6d %8d /%-6d",
+ inactive_flag,
+ allocation_flag,
+ pv_name,
+ pv->pe_total * pv->pe_size >> 1,
+ pv->pe_total,
+ pv->pe_allocated * pv->pe_size >> 1,
+ pv->pe_allocated,
+ (pv->pe_total - pv->pe_allocated) *
+ pv->pe_size >> 1,
+ pv->pe_total - pv->pe_allocated);
+ return sz;
+}
+
+static void _show_uuid(const char *src, char *b, char *e) {
+ int i;
+
+ e--;
+ for(i = 0; *src && (b != e); i++) {
+ if(i && !(i & 0x3))
+ *b++ = '-';
+ *b++ = *src++;
+ }
+ *b = '\0';
+}
+MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/md/lvm-internal.h linux/drivers/md/lvm-internal.h
--- v2.4.14/linux/drivers/md/lvm-internal.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/md/lvm-internal.h Sun Nov 11 10:09:32 2001
@@ -0,0 +1,101 @@
+/*
+ * kernel/lvm-internal.h
+ *
+ * Copyright (C) 2001 Sistina Software
+ *
+ *
+ * LVM driver is free software; you can redistribute it and/or modify


+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * LVM driver 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 GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.


+ *
+ */
+

+/*
+ * Changelog
+ *
+ * 05/01/2001:Joe Thornber - Factored this file out of lvm.c


+ *
+ */
+

+#ifndef LVM_INTERNAL_H
+#define LVM_INTERNAL_H
+
+#include <linux/lvm.h>
+
+#define _LVM_INTERNAL_H_VERSION "LVM "LVM_RELEASE_NAME" ("LVM_RELEASE_DATE")"
+
+/* global variables, defined in lvm.c */
+extern char *lvm_version;
+extern ushort lvm_iop_version;
+extern int loadtime;
+extern const char *const lvm_name;
+
+
+extern vg_t *vg[];
+extern struct file_operations lvm_chr_fops;
+
+extern struct block_device_operations lvm_blk_dops;
+
+
+/* debug macros */
+#ifdef DEBUG_IOCTL
+#define P_IOCTL(fmt, args...) printk(KERN_DEBUG "lvm ioctl: " fmt, ## args)
+#else
+#define P_IOCTL(fmt, args...)
+#endif
+
+#ifdef DEBUG_MAP
+#define P_MAP(fmt, args...) printk(KERN_DEBUG "lvm map: " fmt, ## args)
+#else
+#define P_MAP(fmt, args...)
+#endif
+
+#ifdef DEBUG_KFREE
+#define P_KFREE(fmt, args...) printk(KERN_DEBUG "lvm kfree: " fmt, ## args)
+#else
+#define P_KFREE(fmt, args...)
+#endif
+
+#ifdef DEBUG_DEVICE
+#define P_DEV(fmt, args...) printk(KERN_DEBUG "lvm device: " fmt, ## args)
+#else
+#define P_DEV(fmt, args...)
+#endif
+
+
+/* lvm-snap.c */
+int lvm_get_blksize(kdev_t);
+int lvm_snapshot_alloc(lv_t *);
+int lvm_snapshot_fill_COW_page(vg_t *, lv_t *);
+int lvm_snapshot_COW(kdev_t, ulong, ulong, ulong, vg_t *vg, lv_t *);
+int lvm_snapshot_remap_block(kdev_t *, ulong *, ulong, lv_t *);
+void lvm_snapshot_release(lv_t *);
+int lvm_write_COW_table_block(vg_t *, lv_t *);
+void lvm_hash_link(lv_block_exception_t *, kdev_t, ulong, lv_t *);
+int lvm_snapshot_alloc_hash_table(lv_t *);
+void lvm_drop_snapshot(vg_t *vg, lv_t *, const char *);
+
+
+/* lvm_fs.c */
+void lvm_init_fs(void);
+void lvm_fin_fs(void);
+
+void lvm_fs_create_vg(vg_t *vg_ptr);
+void lvm_fs_remove_vg(vg_t *vg_ptr);
+devfs_handle_t lvm_fs_create_lv(vg_t *vg_ptr, lv_t *lv);
+void lvm_fs_remove_lv(vg_t *vg_ptr, lv_t *lv);
+void lvm_fs_create_pv(vg_t *vg_ptr, pv_t *pv);
+void lvm_fs_remove_pv(vg_t *vg_ptr, pv_t *pv);
+
+#endif
diff -u --recursive --new-file v2.4.14/linux/drivers/md/lvm-snap.c linux/drivers/md/lvm-snap.c
--- v2.4.14/linux/drivers/md/lvm-snap.c Sun Sep 23 11:40:58 2001
+++ linux/drivers/md/lvm-snap.c Mon Nov 12 09:34:20 2001
@@ -26,10 +26,19 @@
X *
X * 05/07/2000 - implemented persistent snapshot support
X * 23/11/2000 - used cpu_to_le64 rather than my own macro
+ * 25/01/2001 - Put LockPage back in
+ * 01/02/2001 - A dropped snapshot is now set as inactive
+ * 12/03/2001 - lvm_pv_get_number changes:
+ * o made it static
+ * o renamed it to _pv_get_number
+ * o pv number is returned in new uint * arg
+ * o -1 returned on error
+ * lvm_snapshot_fill_COW_table has a return value too.
X *
X */
X
X #include <linux/kernel.h>
+#include <linux/module.h>
X #include <linux/vmalloc.h>
X #include <linux/blkdev.h>
X #include <linux/smp_lock.h>
@@ -38,28 +47,43 @@
X #include <linux/lvm.h>
X

X
-#include "lvm-snap.h"
+#include "lvm-internal.h"

+
+static char *lvm_snap_version __attribute__ ((unused)) =
+ "LVM "LVM_RELEASE_NAME" snapshot code ("LVM_RELEASE_DATE")\n";
X
-static char *lvm_snap_version __attribute__ ((unused)) = "LVM 0.9.1_beta2 snapshot code (18/01/2001)\n";
X
X extern const char *const lvm_name;
X extern int lvm_blocksizes[];
X
X void lvm_snapshot_release(lv_t *);
+static int _write_COW_table_block(vg_t *vg, lv_t *lv, int idx,
+ const char **reason);
+static void _disable_snapshot(vg_t *vg, lv_t *lv);
X
-uint lvm_pv_get_number(vg_t * vg, kdev_t rdev)
-{
+
+static int _pv_get_number(vg_t * vg, kdev_t rdev, uint *pvn) {
X uint p;
+ for(p = 0; p < vg->pv_max; p++) {
+ if(vg->pv[p] == NULL)
+ continue;
+
+ if(vg->pv[p]->pv_dev == rdev)
+ break;
X
- for ( p = 0; p < vg->pv_max; p++)
- {
- if ( vg->pv[p] == NULL) continue;
- if ( vg->pv[p]->pv_dev == rdev) break;
X }
X
- return vg->pv[p]->pv_number;
-}
+ if(p >= vg->pv_max) {
+ /* bad news, the snapshot COW table is probably corrupt */
+ printk(KERN_ERR
+ "%s -- _pv_get_number failed for rdev = %u\n",
+ lvm_name, rdev);


+ return -1;
+ }
X

+ *pvn = vg->pv[p]->pv_number;


+ return 0;
+}
X

X #define hashfn(dev,block,mask,chunk_size) \
X ((HASHDEV(dev)^((block)/(chunk_size))) & (mask))
@@ -133,7 +157,7 @@


X return ret;
X }
X

-void lvm_drop_snapshot(lv_t * lv_snap, const char * reason)
+void lvm_drop_snapshot(vg_t *vg, lv_t *lv_snap, const char *reason)
X {
X kdev_t last_dev;
X int i;
@@ -142,6 +166,9 @@
X or error on this snapshot --> release it */
X invalidate_buffers(lv_snap->lv_dev);
X
+ /* wipe the snapshot since it's inconsistent now */
+ _disable_snapshot(vg, lv_snap);
+
X for (i = last_dev = 0; i < lv_snap->lv_remap_ptr; i++) {
X if ( lv_snap->lv_block_exception[i].rdev_new != last_dev) {
X last_dev = lv_snap->lv_block_exception[i].rdev_new;
@@ -150,26 +177,33 @@
X }
X
X lvm_snapshot_release(lv_snap);
+ lv_snap->lv_status &= ~LV_ACTIVE;
X
X printk(KERN_INFO
- "%s -- giving up to snapshot %s on %s due %s\n",
+ "%s -- giving up to snapshot %s on %s: %s\n",
X lvm_name, lv_snap->lv_snapshot_org->lv_name, lv_snap->lv_name,
X reason);
X }
X
-static inline void lvm_snapshot_prepare_blocks(unsigned long * blocks,
- unsigned long start,
- int nr_sectors,
- int blocksize)
+static inline int lvm_snapshot_prepare_blocks(unsigned long *blocks,
+ unsigned long start,
+ int nr_sectors,
+ int blocksize)
X {
X int i, sectors_per_block, nr_blocks;
X
- sectors_per_block = blocksize >> 9;
+ sectors_per_block = blocksize / SECTOR_SIZE;
+
+ if(start & (sectors_per_block - 1))
+ return 0;
+
X nr_blocks = nr_sectors / sectors_per_block;
X start /= sectors_per_block;
X
X for (i = 0; i < nr_blocks; i++)
X blocks[i] = start++;
+


+ return 1;
X }
X

X inline int lvm_get_blksize(kdev_t dev)
@@ -209,128 +243,59 @@
X #endif
X
X
-void lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap)
+int lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap)
X {
- int id = 0, is = lv_snap->lv_remap_ptr;
- ulong blksize_snap;
- lv_COW_table_disk_t * lv_COW_table =
- ( lv_COW_table_disk_t *) page_address(lv_snap->lv_COW_table_page);
+ uint pvn;
+ int id = 0, is = lv_snap->lv_remap_ptr;
+ ulong blksize_snap;
+ lv_COW_table_disk_t * lv_COW_table = (lv_COW_table_disk_t *)
+ page_address(lv_snap->lv_COW_table_iobuf->maplist[0]);
+
+ if (is == 0)
+ return 0;
X
- if (is == 0) return;
X is--;
- blksize_snap = lvm_get_blksize(lv_snap->lv_block_exception[is].rdev_new);
+ blksize_snap =
+ lvm_get_blksize(lv_snap->lv_block_exception[is].rdev_new);
X is -= is % (blksize_snap / sizeof(lv_COW_table_disk_t));
X
X memset(lv_COW_table, 0, blksize_snap);
X for ( ; is < lv_snap->lv_remap_ptr; is++, id++) {
X /* store new COW_table entry */
- lv_COW_table[id].pv_org_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_org));
- lv_COW_table[id].pv_org_rsector = cpu_to_le64(lv_snap->lv_block_exception[is].rsector_org);
- lv_COW_table[id].pv_snap_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_new));
- lv_COW_table[id].pv_snap_rsector = cpu_to_le64(lv_snap->lv_block_exception[is].rsector_new);
+ lv_block_exception_t *be = lv_snap->lv_block_exception + is;


+ if(_pv_get_number(vg, be->rdev_org, &pvn))

+ goto bad;
+
+ lv_COW_table[id].pv_org_number = cpu_to_le64(pvn);
+ lv_COW_table[id].pv_org_rsector = cpu_to_le64(be->rsector_org);
+ if(_pv_get_number(vg, be->rdev_new, &pvn))
+ goto bad;
+
+ lv_COW_table[id].pv_snap_number = cpu_to_le64(pvn);
+ lv_COW_table[id].pv_snap_rsector =
+ cpu_to_le64(be->rsector_new);
X }


+
+ return 0;
+

+ bad:
+ printk(KERN_ERR "%s -- lvm_snapshot_fill_COW_page failed", lvm_name);
+ return -1;
X }
X
X
X /*
X * writes a COW exception table sector to disk (HM)


- *
X */
X

-int lvm_write_COW_table_block(vg_t * vg, lv_t * lv_snap)
+int lvm_write_COW_table_block(vg_t * vg, lv_t *lv_snap)
X {
- int blksize_snap;
- int end_of_table;
- int idx = lv_snap->lv_remap_ptr, idx_COW_table;
- int nr_pages_tmp;
- int length_tmp;
- ulong snap_pe_start, COW_table_sector_offset,
- COW_entries_per_pe, COW_chunks_per_pe, COW_entries_per_block;
- const char * reason;
- kdev_t snap_phys_dev;
- struct kiobuf * iobuf = lv_snap->lv_iobuf;
- struct page * page_tmp;
- lv_COW_table_disk_t * lv_COW_table =
- ( lv_COW_table_disk_t *) page_address(lv_snap->lv_COW_table_page);
-
- idx--;
-
- COW_chunks_per_pe = LVM_GET_COW_TABLE_CHUNKS_PER_PE(vg, lv_snap);
- COW_entries_per_pe = LVM_GET_COW_TABLE_ENTRIES_PER_PE(vg, lv_snap);
-
- /* get physical addresse of destination chunk */
- snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new;
- snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size;
-
- blksize_snap = lvm_get_blksize(snap_phys_dev);
-
- COW_entries_per_block = blksize_snap / sizeof(lv_COW_table_disk_t);
- idx_COW_table = idx % COW_entries_per_pe % COW_entries_per_block;
-
- if ( idx_COW_table == 0) memset(lv_COW_table, 0, blksize_snap);
-
- /* sector offset into the on disk COW table */
- COW_table_sector_offset = (idx % COW_entries_per_pe) / (SECTOR_SIZE / sizeof(lv_COW_table_disk_t));
-
- /* COW table block to write next */
- iobuf->blocks[0] = (snap_pe_start + COW_table_sector_offset) >> (blksize_snap >> 10);
-
- /* store new COW_table entry */
- lv_COW_table[idx_COW_table].pv_org_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[idx].rdev_org));
- lv_COW_table[idx_COW_table].pv_org_rsector = cpu_to_le64(lv_snap->lv_block_exception[idx].rsector_org);
- lv_COW_table[idx_COW_table].pv_snap_number = cpu_to_le64(lvm_pv_get_number(vg, snap_phys_dev));
- lv_COW_table[idx_COW_table].pv_snap_rsector = cpu_to_le64(lv_snap->lv_block_exception[idx].rsector_new);
-
- length_tmp = iobuf->length;
- iobuf->length = blksize_snap;
- page_tmp = iobuf->maplist[0];
- iobuf->maplist[0] = lv_snap->lv_COW_table_page;
- nr_pages_tmp = iobuf->nr_pages;
- iobuf->nr_pages = 1;
-
- if (brw_kiovec(WRITE, 1, &iobuf, snap_phys_dev,
- iobuf->blocks, blksize_snap) != blksize_snap)
- goto fail_raw_write;
-
-
- /* initialization of next COW exception table block with zeroes */
- end_of_table = idx % COW_entries_per_pe == COW_entries_per_pe - 1;
- if (idx_COW_table % COW_entries_per_block == COW_entries_per_block - 1 || end_of_table)
- {
- /* don't go beyond the end */
- if (idx + 1 >= lv_snap->lv_remap_end) goto good_out;
-
- memset(lv_COW_table, 0, blksize_snap);
-
- if (end_of_table)
- {
- idx++;
- snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new;
- snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size;
- blksize_snap = lvm_get_blksize(snap_phys_dev);
- iobuf->blocks[0] = snap_pe_start >> (blksize_snap >> 10);
- } else iobuf->blocks[0]++;
-
- if (brw_kiovec(WRITE, 1, &iobuf, snap_phys_dev,
- iobuf->blocks, blksize_snap) != blksize_snap)
- goto fail_raw_write;
- }
-
-
- good_out:
- iobuf->length = length_tmp;
- iobuf->maplist[0] = page_tmp;
- iobuf->nr_pages = nr_pages_tmp;
- return 0;
-
- /* slow path */
- out:
- lvm_drop_snapshot(lv_snap, reason);
- return 1;
-
- fail_raw_write:
- reason = "write error";
- goto out;
+ int r;
+ const char *err;
+ if((r = _write_COW_table_block(vg, lv_snap,
+ lv_snap->lv_remap_ptr - 1, &err)))
+ lvm_drop_snapshot(vg, lv_snap, err);
+ return r;
X }
X
X /*
@@ -345,7 +310,7 @@
X unsigned long org_phys_sector,
X unsigned long org_pe_start,
X unsigned long org_virt_sector,
- lv_t * lv_snap)
+ vg_t *vg, lv_t* lv_snap)
X {
X const char * reason;
X unsigned long org_start, snap_start, snap_phys_dev, virt_start, pe_off;
@@ -370,13 +335,11 @@
X #ifdef DEBUG_SNAPSHOT
X printk(KERN_INFO
X "%s -- COW: "
- "org %02d:%02d faulting %lu start %lu, "
- "snap %02d:%02d start %lu, "
+ "org %s faulting %lu start %lu, snap %s start %lu, "
X "size %d, pe_start %lu pe_off %lu, virt_sec %lu\n",
X lvm_name,
- MAJOR(org_phys_dev), MINOR(org_phys_dev), org_phys_sector,
- org_start,
- MAJOR(snap_phys_dev), MINOR(snap_phys_dev), snap_start,
+ kdevname(org_phys_dev), org_phys_sector, org_start,
+ kdevname(snap_phys_dev), snap_start,
X chunk_size,
X org_pe_start, pe_off,
X org_virt_sector);
@@ -400,14 +363,18 @@
X
X iobuf->length = nr_sectors << 9;
X
- lvm_snapshot_prepare_blocks(iobuf->blocks, org_start,
- nr_sectors, blksize_org);
+ if(!lvm_snapshot_prepare_blocks(iobuf->blocks, org_start,
+ nr_sectors, blksize_org))
+ goto fail_prepare;
+
X if (brw_kiovec(READ, 1, &iobuf, org_phys_dev,
X iobuf->blocks, blksize_org) != (nr_sectors<<9))
X goto fail_raw_read;
X
- lvm_snapshot_prepare_blocks(iobuf->blocks, snap_start,
- nr_sectors, blksize_snap);
+ if(!lvm_snapshot_prepare_blocks(iobuf->blocks, snap_start,
+ nr_sectors, blksize_snap))
+ goto fail_prepare;
+
X if (brw_kiovec(WRITE, 1, &iobuf, snap_phys_dev,
X iobuf->blocks, blksize_snap) != (nr_sectors<<9))
X goto fail_raw_write;
@@ -435,7 +402,7 @@
X
X /* slow path */
X out:
- lvm_drop_snapshot(lv_snap, reason);
+ lvm_drop_snapshot(vg, lv_snap, reason);
X return 1;
X
X fail_out_of_space:
@@ -450,20 +417,24 @@
X fail_blksize:
X reason = "blocksize error";
X goto out;
+
+ fail_prepare:
+ reason = "couldn't prepare kiovec blocks "
+ "(start probably isn't block aligned)";
+ goto out;
X }
X
X int lvm_snapshot_alloc_iobuf_pages(struct kiobuf * iobuf, int sectors)
X {
X int bytes, nr_pages, err, i;
X
- bytes = sectors << 9;
+ bytes = sectors * SECTOR_SIZE;
X nr_pages = (bytes + ~PAGE_MASK) >> PAGE_SHIFT;
X err = expand_kiobuf(iobuf, nr_pages);


- if (err)
- goto out;

+ if (err) goto out;


X
X err = -ENOMEM;

- iobuf->locked = 0;
+ iobuf->locked = 1;
X iobuf->nr_pages = 0;
X for (i = 0; i < nr_pages; i++)
X {
@@ -474,6 +445,7 @@
X goto out;
X
X iobuf->maplist[i] = page;
+ LockPage(page);
X iobuf->nr_pages++;
X }
X iobuf->offset = 0;
@@ -521,47 +493,57 @@
X while (buckets--)
X INIT_LIST_HEAD(hash+buckets);
X err = 0;


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

echo 'End of part 046'
echo 'File patch-2.4.15 is continued in part 047'
echo "047" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:25 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part049

#!/bin/sh -x
# this is part 049 of a 115 - part archive


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

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

- * This will allow at least 16 concurrent reads or writes
- * even if kmalloc starts failing
+ * For now, try NR_RESERVED_BUFS mpbh and
+ * NR_RESERVED_BUFS*raid_disks bufferheads
+ * This will allow at least NR_RESERVED_BUFS concurrent
+ * reads or writes even if kmalloc starts failing
X */
- if (multipath_grow_mpbh(conf, 16) < 16 ||
- multipath_grow_bh(conf, 16*conf->raid_disks)< 16*conf->raid_disks) {
+ if (multipath_grow_mpbh(conf, NR_RESERVED_BUFS) < NR_RESERVED_BUFS) {
X printk(MEM_ERROR, mdidx(mddev));
X goto out_free_conf;
X }
X
- if (!start_recovery && (sb->state & (1 << MD_SB_CLEAN))) {
+ if ((sb->state & (1 << MD_SB_CLEAN))) {
X /*
X * we do sanity checks even if the device says
X * it's clean ...
@@ -1202,7 +1016,6 @@
X
X out_free_conf:
X multipath_shrink_mpbh(conf);
- multipath_shrink_bh(conf, conf->freebh_cnt);
X kfree(conf);
X mddev->private = NULL;
X out:
@@ -1228,7 +1041,6 @@
X
X md_unregister_thread(conf->thread);
X multipath_shrink_mpbh(conf);
- multipath_shrink_bh(conf, conf->freebh_cnt);
X kfree(conf);
X mddev->private = NULL;
X MOD_DEC_USE_COUNT;
diff -u --recursive --new-file v2.4.14/linux/drivers/media/radio/Config.in linux/drivers/media/radio/Config.in
--- v2.4.14/linux/drivers/media/radio/Config.in Mon Aug 27 12:41:42 2001
+++ linux/drivers/media/radio/Config.in Fri Nov 9 14:01:22 2001
@@ -21,7 +21,7 @@
X if [ "$CONFIG_RADIO_GEMTEK" = "y" ]; then
X hex ' GemTek i/o port (0x20c, 0x30c, 0x24c or 0x34c)' CONFIG_RADIO_GEMTEK_PORT 34c
X fi
-dep_tristate ' GemTek PCI Radio Card support' CONFIG_RADIO_GEMTEK_PCI $CONFIG_VIDEO_DEV
+dep_tristate ' GemTek PCI Radio Card support' CONFIG_RADIO_GEMTEK_PCI $CONFIG_VIDEO_DEV $CONFIG_PCI
X dep_tristate ' Guillemot MAXI Radio FM 2000 radio' CONFIG_RADIO_MAXIRADIO $CONFIG_VIDEO_DEV
X dep_tristate ' Maestro on board radio' CONFIG_RADIO_MAESTRO $CONFIG_VIDEO_DEV
X dep_tristate ' miroSOUND PCM20 radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV $CONFIG_SOUND_ACI_MIXER
diff -u --recursive --new-file v2.4.14/linux/drivers/media/video/Config.in linux/drivers/media/video/Config.in
--- v2.4.14/linux/drivers/media/video/Config.in Wed Jul 25 17:10:20 2001
+++ linux/drivers/media/video/Config.in Fri Nov 9 14:01:22 2001
@@ -46,6 +46,9 @@
X dep_tristate ' Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)' CONFIG_VIDEO_STRADIS $CONFIG_VIDEO_DEV $CONFIG_PCI
X fi
X dep_tristate ' Zoran ZR36057/36060 Video For Linux' CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C
+dep_tristate ' Iomega Buz support' CONFIG_VIDEO_ZORAN_BUZ $CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C
+dep_tristate ' Miro DC10(+) support' CONFIG_VIDEO_ZORAN_DC10 $CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C
+dep_tristate ' Linux Media Labs LML33 support' CONFIG_VIDEO_ZORAN_LML33 $CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C
X dep_tristate ' Zoran ZR36120/36125 Video For Linux' CONFIG_VIDEO_ZR36120 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C
X if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
X dep_tristate ' Sony Vaio Picturebook Motion Eye Video For Linux' CONFIG_VIDEO_MEYE $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_SONYPI
diff -u --recursive --new-file v2.4.14/linux/drivers/media/video/Makefile linux/drivers/media/video/Makefile
--- v2.4.14/linux/drivers/media/video/Makefile Wed Jul 25 17:10:20 2001
+++ linux/drivers/media/video/Makefile Fri Nov 9 14:01:22 2001
@@ -44,7 +44,10 @@
X obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
X obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
X obj-$(CONFIG_VIDEO_W9966) += w9966.o
-obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o i2c-old.o saa7110.o saa7111.o saa7185.o adv7175.o bt819.o bt856.o
+obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o i2c-old.o
+obj-$(CONFIG_VIDEO_ZORAN_BUZ) += saa7111.o saa7185.o
+obj-$(CONFIG_VIDEO_ZORAN_DC10) += saa7110.o adv7175.o
+obj-$(CONFIG_VIDEO_ZORAN_LML33) += bt819.o bt856.o
X obj-$(CONFIG_VIDEO_LML33) += bt856.o bt819.o
X obj-$(CONFIG_VIDEO_PMS) += pms.o
X obj-$(CONFIG_VIDEO_PLANB) += planb.o
diff -u --recursive --new-file v2.4.14/linux/drivers/media/video/saa7110.c linux/drivers/media/video/saa7110.c
--- v2.4.14/linux/drivers/media/video/saa7110.c Tue Oct 23 22:48:51 2001
+++ linux/drivers/media/video/saa7110.c Fri Nov 9 14:01:22 2001
@@ -83,6 +83,7 @@
X while (len-- > 0) {
X if (i2c_sendbyte(decoder->bus,*data,0)) {
X i2c_stop(decoder->bus);
+ UNLOCK_I2C_BUS(decoder->bus);
X return -EAGAIN;
X }
X decoder->reg[subaddr++] = *data++;
diff -u --recursive --new-file v2.4.14/linux/drivers/media/video/zr36067.c linux/drivers/media/video/zr36067.c
--- v2.4.14/linux/drivers/media/video/zr36067.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/media/video/zr36067.c Fri Nov 9 14:01:22 2001
@@ -245,6 +245,13 @@
X MODULE_PARM(lml33dpath, "i");
X MODULE_PARM(video_nr, "i");
X
+static struct pci_device_id zr36067_pci_tbl[] = {
+ { PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057,

+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0 }

+};
+MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl);
+
X /* Anybody who uses more than four? */
X #define BUZ_MAX 4
X
diff -u --recursive --new-file v2.4.14/linux/drivers/media/video/zr36120.c linux/drivers/media/video/zr36120.c
--- v2.4.14/linux/drivers/media/video/zr36120.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/media/video/zr36120.c Fri Nov 9 14:01:22 2001
@@ -60,6 +60,13 @@
X static int video_nr = -1;
X static int vbi_nr = -1;
X
+static struct pci_device_id zr36120_pci_tbl[] = {
+ { PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120,


+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0 }

+};
+MODULE_DEVICE_TABLE(pci, zr36120_pci_tbl);
+
X MODULE_AUTHOR("Pauline Middelink <midd...@polyware.nl>");
X MODULE_DESCRIPTION("Zoran ZR36120 based framegrabber");
X MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/mtd/chips/jedec.c linux/drivers/mtd/chips/jedec.c
--- v2.4.14/linux/drivers/mtd/chips/jedec.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/mtd/chips/jedec.c Fri Nov 9 14:29:40 2001
@@ -11,7 +11,7 @@
X * not going to guess how to send commands to them, plus I expect they will
X * all speak CFI..
X *
- * $Id: jedec.c,v 1.11 2001/10/02 15:05:12 dwmw2 Exp $
+ * $Id: jedec.c,v 1.12 2001/11/06 14:37:35 dwmw2 Exp $
X */
X
X #include <linux/mtd/jedec.h>
@@ -42,6 +42,7 @@
X {0xC2AD,"Macronix MX29F016",2*1024*1024,64*1024,MTD_CAP_NORFLASH},
X {}};
X
+static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id);
X static void jedec_sync(struct mtd_info *mtd) {};
X static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len,
X size_t *retlen, u_char *buf);
@@ -249,7 +250,7 @@
X /* Take an array of JEDEC numbers that represent interleved flash chips
X and process them. Check to make sure they are good JEDEC numbers, look
X them up and then add them to the chip list */
-int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count,
+static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count,
X unsigned long base,struct jedec_private *priv)
X {
X unsigned I,J;


@@ -336,7 +337,7 @@
X }

X
X /* Lookup the chip information from the JEDEC ID table. */
-const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id)
+static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id)
X {
X __u16 Id = (mfr << 8) | id;
X unsigned long I = 0;
@@ -873,19 +874,19 @@
X }
X }
X
-int __init jedec_probe_init(void)
+int __init jedec_init(void)
X {
X register_mtd_chip_driver(&jedec_chipdrv);


X return 0;
X }
X

-static void __exit jedec_probe_exit(void)
+static void __exit jedec_exit(void)
X {
X unregister_mtd_chip_driver(&jedec_chipdrv);
X }
X
-module_init(jedec_probe_init);
-module_exit(jedec_probe_exit);
+module_init(jedec_init);
+module_exit(jedec_exit);
X
X MODULE_LICENSE("GPL");
X MODULE_AUTHOR("Jason Gunthorpe <j...@deltatee.com> et al.");
diff -u --recursive --new-file v2.4.14/linux/drivers/mtd/redboot.c linux/drivers/mtd/redboot.c
--- v2.4.14/linux/drivers/mtd/redboot.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/mtd/redboot.c Fri Nov 9 14:01:22 2001


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

- * $Id: redboot.c,v 1.5 2001/10/02 15:05:11 dwmw2 Exp $
+ * $Id: redboot.c,v 1.6 2001/10/25 09:16:06 dwmw2 Exp $
X *
X * Parse RedBoot-style Flash Image System (FIS) tables and
X * produce a Linux partition array to match.
@@ -62,7 +62,15 @@


X goto out;
X }
X

- if (memcmp(buf, "RedBoot", 8)) {
+ /* RedBoot image could appear in any of the first three slots */
+ for (i = 0; i < 3; i++) {
+ if (!memcmp(buf[i].name, "RedBoot", 8))
+ break;
+ }
+ if (i == 3) {
+ /* Didn't find it */
+ printk(KERN_NOTICE "No RedBoot partition table detected in %s\n",
+ master->name);
X ret = 0;
X goto out;
X }
diff -u --recursive --new-file v2.4.14/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.4.14/linux/drivers/net/3c59x.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/net/3c59x.c Fri Nov 9 13:41:42 2001
@@ -868,7 +868,7 @@
X
X static int vortex_suspend (struct pci_dev *pdev, u32 state)


X {
- struct net_device *dev = pdev->driver_data;
+ struct net_device *dev = pci_get_drvdata(pdev);
X

X if (dev && dev->priv) {
X if (netif_running(dev)) {
@@ -881,7 +881,7 @@
X
X static int vortex_resume (struct pci_dev *pdev)


X {
- struct net_device *dev = pdev->driver_data;
+ struct net_device *dev = pci_get_drvdata(pdev);
X

X if (dev && dev->priv) {
X if (netif_running(dev)) {
diff -u --recursive --new-file v2.4.14/linux/drivers/net/8139cp.c linux/drivers/net/8139cp.c
--- v2.4.14/linux/drivers/net/8139cp.c Mon Nov 5 15:55:30 2001
+++ linux/drivers/net/8139cp.c Mon Nov 19 15:19:42 2001
@@ -625,6 +625,10 @@
X len = skb->len;
X mapping = pci_map_single(cp->pdev, skb->data, len, PCI_DMA_TODEVICE);
X eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
+ txd->opts2 = 0;
+ txd->addr_lo = cpu_to_le32(mapping);
+ wmb();
+
X #ifdef CP_TX_CHECKSUM
X txd->opts1 = cpu_to_le32(eor | len | DescOwn | FirstFrag |
X LastFrag | IPCS | UDPCS | TCPCS);
@@ -632,13 +636,11 @@
X txd->opts1 = cpu_to_le32(eor | len | DescOwn | FirstFrag |
X LastFrag);
X #endif
- txd->opts2 = 0;
- txd->addr_lo = cpu_to_le32(mapping);
+ wmb();
X
X cp->tx_skb[entry].skb = skb;
X cp->tx_skb[entry].mapping = mapping;
X cp->tx_skb[entry].frag = 0;
- wmb();
X entry = NEXT_TX(entry);
X } else {
X struct cp_desc *txd;
@@ -676,24 +678,29 @@
X ctrl |= LastFrag;
X
X txd = &cp->tx_ring[entry];
- txd->opts1 = cpu_to_le32(ctrl);
X txd->opts2 = 0;
X txd->addr_lo = cpu_to_le32(mapping);
+ wmb();
+
+ txd->opts1 = cpu_to_le32(ctrl);
+ wmb();
X
X cp->tx_skb[entry].skb = skb;
X cp->tx_skb[entry].mapping = mapping;
X cp->tx_skb[entry].frag = frag + 2;
- wmb();
X entry = NEXT_TX(entry);
X }
+
X txd = &cp->tx_ring[first_entry];
+ txd->opts2 = 0;
+ txd->addr_lo = cpu_to_le32(first_mapping);
+ wmb();
+
X #ifdef CP_TX_CHECKSUM
X txd->opts1 = cpu_to_le32(first_len | FirstFrag | DescOwn | IPCS | UDPCS | TCPCS);
X #else
X txd->opts1 = cpu_to_le32(first_len | FirstFrag | DescOwn);
X #endif
- txd->opts2 = 0;
- txd->addr_lo = cpu_to_le32(first_mapping);
X wmb();
X }
X cp->tx_head = entry;
diff -u --recursive --new-file v2.4.14/linux/drivers/net/8139too.c linux/drivers/net/8139too.c
--- v2.4.14/linux/drivers/net/8139too.c Tue Oct 23 22:48:51 2001
+++ linux/drivers/net/8139too.c Fri Nov 9 13:45:35 2001
@@ -80,6 +80,8 @@
X
X Kalle Olavi Niemitalo - Wake-on-LAN ioctls
X
+ Robert Kuebel - Save kernel thread from dying on any signal.
+
X Submitting bug reports:
X
X "rtl8139-diag -mmmaaavvveefN" output


@@ -87,64 +89,16 @@
X

X See 8139too.txt for more details.
X
------------------------------------------------------------------------------
-
- Theory of Operation
-
-I. Board Compatibility
-
-This device driver is designed for the RealTek RTL8139 series, the RealTek
-Fast Ethernet controllers for PCI and CardBus. This chip is used on many
-low-end boards, sometimes with its markings changed.
-
-
-II. Board-specific settings
-
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board. The system BIOS will assign the
-PCI INTA signal to a (preferably otherwise unused) system IRQ line.
-
-III. Driver operation
-
-IIIa. Rx Ring buffers
-
-The receive unit uses a single linear ring buffer rather than the more
-common (and more efficient) descriptor-based architecture. Incoming frames
-are sequentially stored into the Rx region, and the host copies them into
-skbuffs.
-
-Comment: While it is theoretically possible to process many frames in place,
-any delay in Rx processing would cause us to drop frames. More importantly,
-the Linux protocol stack is not designed to operate in this manner.
-
-IIIb. Tx operation
-
-The RTL8139 uses a fixed set of four Tx descriptors in register space.
-In a stunningly bad design choice, Tx frames must be 32 bit aligned. Linux
-aligns the IP header on word boundaries, and 14 byte ethernet header means
-that almost all frames will need to be copied to an alignment buffer.
-
-IVb. References
-
-http://www.realtek.com.tw/cn/cn.html
-http://www.scyld.com/expert/NWay.html
-
-IVc. Errata
-
-1) The RTL-8139 has a serious problem with motherboards which do
-posted MMIO writes to PCI space. This driver works around the
-problem by having an MMIO register write be immediately followed by
-an MMIO register read.
-
X */
X
X #define DRV_NAME "8139too"
-#define DRV_VERSION "0.9.20"
+#define DRV_VERSION "0.9.22"
X

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

X #include <linux/kernel.h>
+#include <linux/compiler.h>
X #include <linux/pci.h>
X #include <linux/init.h>
X #include <linux/ioport.h>
@@ -207,11 +161,10 @@
X
X /* Size of the in-memory receive ring. */
X #define RX_BUF_LEN_IDX 2 /* 0==8K, 1==16K, 2==32K, 3==64K */
-#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)
-#define RX_BUF_PAD 16
+#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)
+#define RX_BUF_PAD 16
X #define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */
-#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)
-#define RX_EARLY_THRESH 14
+#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)
X
X /* Number of Tx descriptor registers. */
X #define NUM_TX_DESC 4
@@ -231,7 +184,7 @@
X #define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */
X #define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */
X #define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
-
+#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */
X
X /* Operational parameters that usually are not changed. */
X /* Time in jiffies before concluding the transmitter is hung. */
@@ -315,8 +268,6 @@
X TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */
X TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */
X RxBuf = 0x30,
- RxEarlyCnt = 0x34,
- RxEarlyStatus = 0x36,
X ChipCmd = 0x37,
X RxBufPtr = 0x38,
X RxBufAddr = 0x3A,
@@ -415,7 +366,8 @@
X TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
X TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */
X TxClearAbt = (1 << 0), /* Clear abort (WO) */
- TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
+ TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */
+ TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */
X
X TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
X };
@@ -463,10 +415,6 @@
X };
X
X enum RxConfigBits {
- /* Early Rx threshold, none or X/16 */
- RxCfgEarlyRxNone = 0,
- RxCfgEarlyRxShift = 24,
-
X /* rx fifo threshold */
X RxCfgFIFOShift = 13,
X RxCfgFIFONone = (7 << RxCfgFIFOShift),
@@ -513,12 +461,6 @@
X {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83}
X };
X
-struct ring_info {
- struct sk_buff *skb;
- dma_addr_t mapping;
-};
-
-
X typedef enum {
X CH_8139 = 0,
X CH_8139_K,
@@ -595,8 +537,6 @@
X unsigned int tx_flag;
X unsigned long cur_tx;
X unsigned long dirty_tx;
- /* The saved address of a sent-in-place packet/buffer, for skfree(). */
- struct ring_info tx_info[NUM_TX_DESC];
X unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */
X unsigned char *tx_bufs; /* Tx bounce buffer region. */
X dma_addr_t rx_ring_dma;
@@ -616,6 +556,7 @@
X struct completion thr_exited;
X u32 rx_config;
X struct rtl_extra_stats xstats;
+ int time_to_die;
X };
X
X MODULE_AUTHOR ("Jeff Garzik <jga...@mandrakesoft.com>");
@@ -714,10 +655,12 @@
X TxErr | TxOK | RxErr | RxOK;
X
X static const unsigned int rtl8139_rx_config =
- (RX_EARLY_THRESH << RxCfgEarlyRxShift) | RxCfgRcv32K | RxNoWrap |
- (RX_FIFO_THRESH << RxCfgFIFOShift) |
- (RX_DMA_BURST << RxCfgDMAShift);
+ RxCfgRcv32K | RxNoWrap |
+ (RX_FIFO_THRESH << RxCfgFIFOShift) |
+ (RX_DMA_BURST << RxCfgDMAShift);
X
+static const unsigned int rtl8139_tx_config =
+ (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift);
X
X static void __rtl8139_cleanup_dev (struct net_device *dev)
X {
@@ -782,8 +725,6 @@
X unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
X u32 tmp;
X
- DPRINTK ("ENTER\n");
-
X assert (pdev != NULL);
X
X *dev_out = NULL;
@@ -792,7 +733,6 @@
X dev = alloc_etherdev (sizeof (*tp));
X if (dev == NULL) {
X printk (KERN_ERR PFX "%s: Unable to alloc new net device\n", pdev->slot_name);
- DPRINTK ("EXIT, returning -ENOMEM\n");
X return -ENOMEM;
X }
X SET_MODULE_OWNER(dev);
@@ -926,13 +866,11 @@
X
X rtl8139_chip_reset (ioaddr);
X
- DPRINTK ("EXIT, returning 0\n");
X *dev_out = dev;
X return 0;
X
X err_out:
X __rtl8139_cleanup_dev (dev);
- DPRINTK ("EXIT, returning %d\n", rc);
X return rc;
X }
X
@@ -947,8 +885,6 @@
X static int board_idx = -1;
X u8 pci_rev;
X
- DPRINTK ("ENTER\n");
-
X assert (pdev != NULL);
X assert (ent != NULL);
X
@@ -975,10 +911,8 @@
X }
X
X i = rtl8139_init_board (pdev, &dev);
- if (i < 0) {
- DPRINTK ("EXIT, returning %d\n", i);
+ if (i < 0)
X return i;
- }
X
X tp = dev->priv;
X ioaddr = tp->mmio_addr;
@@ -1091,12 +1025,10 @@
X if (rtl_chip_info[tp->chipset].flags & HasHltClk)
X RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */
X
- DPRINTK ("EXIT - returning 0\n");
X return 0;
X
X err_out:
X __rtl8139_cleanup_dev (dev);
- DPRINTK ("EXIT - returning %d\n", i);
X return i;
X }
X
@@ -1106,8 +1038,6 @@


X struct net_device *dev = pci_get_drvdata (pdev);

X struct rtl8139_private *np;
X
- DPRINTK ("ENTER\n");
-
X assert (dev != NULL);
X np = dev->priv;
X assert (np != NULL);
@@ -1115,8 +1045,6 @@
X unregister_netdev (dev);
X
X __rtl8139_cleanup_dev (dev);
-
- DPRINTK ("EXIT\n");
X }
X
X
@@ -1149,8 +1077,6 @@
X void *ee_addr = ioaddr + Cfg9346;
X int read_cmd = location | (EE_READ_CMD << addr_len);
X
- DPRINTK ("ENTER\n");
-
X writeb (EE_ENB & ~EE_CS, ee_addr);
X writeb (EE_ENB, ee_addr);
X eeprom_delay ();
@@ -1180,7 +1106,6 @@
X writeb (~EE_CS, ee_addr);
X eeprom_delay ();
X
- DPRINTK ("EXIT - returning %d\n", retval);


X return retval;
X }
X

@@ -1218,16 +1143,12 @@
X {
X int i;
X
- DPRINTK ("ENTER\n");
-
X for (i = 32; i >= 0; i--) {
X writeb (MDIO_WRITE1, mdio_addr);
X mdio_delay (mdio_addr);
X writeb (MDIO_WRITE1 | MDIO_CLK, mdio_addr);
X mdio_delay (mdio_addr);
X }
-
- DPRINTK ("EXIT\n");
X }
X #endif
X
@@ -1241,10 +1162,7 @@


X int i;
X #endif
X

- DPRINTK ("ENTER\n");
-
X if (phy_id > 31) { /* Really a 8139. Use internal registers. */
- DPRINTK ("EXIT after directly using 8139 internal regs\n");
X return location < 8 && mii_2_8139_map[location] ?
X readw (tp->mmio_addr + mii_2_8139_map[location]) : 0;
X }
@@ -1271,7 +1189,6 @@
X }
X #endif
X
- DPRINTK ("EXIT, returning %d\n", (retval >> 1) & 0xffff);
X return (retval >> 1) & 0xffff;
X }
X
@@ -1286,8 +1203,6 @@


X int i;
X #endif
X

- DPRINTK ("ENTER\n");
-
X if (phy_id > 31) { /* Really a 8139. Use internal registers. */
X void *ioaddr = tp->mmio_addr;
X if (location == 0) {
@@ -1330,13 +1245,9 @@
X void *ioaddr = tp->mmio_addr;
X #endif
X
- DPRINTK ("ENTER\n");
-
X retval = request_irq (dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev);
- if (retval) {
- DPRINTK ("EXIT, returning %d\n", retval);
+ if (retval)
X return retval;
- }
X
X tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
X &tp->tx_bufs_dma);
@@ -1352,7 +1263,6 @@
X pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
X tp->rx_ring, tp->rx_ring_dma);
X
- DPRINTK ("EXIT, returning -ENOMEM\n");


X return -ENOMEM;
X
X }

@@ -1375,7 +1285,6 @@
X printk (KERN_WARNING "%s: unable to start kernel thread\n",
X dev->name);
X
- DPRINTK ("EXIT, returning 0\n");
X return 0;
X }
X
@@ -1384,8 +1293,6 @@
X {
X struct rtl8139_private *tp = dev->priv;
X
- DPRINTK("ENTER\n");
-
X if (tp->phys[0] >= 0) {
X u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5);
X if (mii_reg5 == 0xffff)
@@ -1410,8 +1317,6 @@
X u32 i;
X u8 tmp;
X
- DPRINTK ("ENTER\n");
-
X /* Bring old chips out of low-power mode. */
X if (rtl_chip_info[tp->chipset].flags & HasHltClk)
X RTL_W8 (HltClk, 'R');
@@ -1431,7 +1336,7 @@
X RTL_W32 (RxConfig, tp->rx_config);
X
X /* Check this value: the documentation for IFG contradicts ifself. */
- RTL_W32 (TxConfig, (TX_DMA_BURST << TxDMAShift));
+ RTL_W32 (TxConfig, rtl8139_tx_config);
X
X tp->cur_rx = 0;
X
@@ -1472,8 +1377,6 @@
X RTL_W16 (IntrMask, rtl8139_intr_mask);
X
X netif_start_queue (dev);
-
- DPRINTK ("EXIT\n");
X }
X
X
@@ -1483,19 +1386,12 @@
X struct rtl8139_private *tp = dev->priv;
X int i;
X
- DPRINTK ("ENTER\n");
-
X tp->cur_rx = 0;
X tp->cur_tx = 0;
X tp->dirty_tx = 0;
X
- for (i = 0; i < NUM_TX_DESC; i++) {
- tp->tx_info[i].skb = NULL;
- tp->tx_info[i].mapping = 0;
+ for (i = 0; i < NUM_TX_DESC; i++)
X tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE];
- }
-
- DPRINTK ("EXIT\n");
X }
X
X
@@ -1512,8 +1408,6 @@
X int linkcase;
X void *ioaddr = tp->mmio_addr;
X
- DPRINTK ("ENTER\n");
-
X /* This is a complicated state machine to configure the "twister" for
X impedance/echos based on the cable length.
X All of this is magic and undocumented.
@@ -1591,8 +1485,6 @@
X /* do nothing */
X break;
X }
-
- DPRINTK ("EXIT\n");
X }
X #endif /* CONFIG_8139TOO_TUNE_TWISTER */
X
@@ -1636,11 +1528,8 @@
X
X DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n",
X dev->name, RTL_R16 (NWayLPAR));
- DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x"
- " RxStatus %4.4lx.\n", dev->name,
- RTL_R16 (IntrMask),
- RTL_R16 (IntrStatus),
- RTL_R32 (RxEarlyStatus));
+ DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n",
+ dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus));
X DPRINTK ("%s: Chip config %2.2x %2.2x.\n",
X dev->name, RTL_R8 (Config0),
X RTL_R8 (Config1));
@@ -1669,7 +1558,13 @@
X timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout);
X } while (!signal_pending (current) && (timeout > 0));
X
- if (signal_pending (current))
+ if (signal_pending (current)) {
+ spin_lock_irq(&current->sigmask_lock);
+ flush_signals(current);


+ spin_unlock_irq(&current->sigmask_lock);
+ }
+

+ if (tp->time_to_die)
X break;
X
X rtnl_lock ();
@@ -1683,25 +1578,10 @@
X
X static void rtl8139_tx_clear (struct rtl8139_private *tp)
X {
- int i;
-
X tp->cur_tx = 0;
X tp->dirty_tx = 0;
X
- /* Dump the unsent Tx packets. */
- for (i = 0; i < NUM_TX_DESC; i++) {
- struct ring_info *rp = &tp->tx_info[i];
- if (rp->mapping != 0) {
- pci_unmap_single (tp->pci_dev, rp->mapping,
- rp->skb->len, PCI_DMA_TODEVICE);
- rp->mapping = 0;
- }
- if (rp->skb) {
- dev_kfree_skb (rp->skb);
- rp->skb = NULL;
- tp->stats.tx_dropped++;
- }
- }
+ /* XXX account for unsent Tx packets in tp->stats.tx_dropped */
X }
X
X
@@ -1755,42 +1635,29 @@
X struct rtl8139_private *tp = dev->priv;
X void *ioaddr = tp->mmio_addr;
X unsigned int entry;
- u32 dma_addr;
-
- mb();
X
X /* Calculate the next Tx descriptor entry. */
X entry = tp->cur_tx % NUM_TX_DESC;
X
- assert (tp->tx_info[entry].skb == NULL);
- assert (tp->tx_info[entry].mapping == 0);
-
- tp->tx_info[entry].skb = skb;
- if ( !((unsigned long)skb->data & 3) && skb_shinfo(skb)->nr_frags == 0 &&
- skb->ip_summed != CHECKSUM_HW) {
- tp->xstats.tx_buf_mapped++;
- tp->tx_info[entry].mapping =
- pci_map_single (tp->pci_dev, skb->data, skb->len,
- PCI_DMA_TODEVICE);
- dma_addr = tp->tx_info[entry].mapping;
- } else if (skb->len < TX_BUF_SIZE) {
+ if (likely(skb->len < TX_BUF_SIZE)) {
X skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
- dma_addr = tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs);
+ dev_kfree_skb(skb);
X } else {
X dev_kfree_skb(skb);
- tp->tx_info[entry].skb = NULL;
+ tp->stats.tx_dropped++;
X return 0;
X }
+
X /* Note: the chip doesn't have auto-pad! */
X spin_lock_irq(&tp->lock);
- RTL_W32_F (TxAddr0 + (entry * 4), dma_addr);
X RTL_W32_F (TxStatus0 + (entry * sizeof (u32)),
X tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
X
X dev->trans_start = jiffies;
X
X tp->cur_tx++;
- mb();
+ wmb();
+
X if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
X netif_stop_queue (dev);
X spin_unlock_irq(&tp->lock);
@@ -1831,7 +1698,9 @@
X tp->stats.tx_errors++;
X if (txstatus & TxAborted) {
X tp->stats.tx_aborted_errors++;
- RTL_W32_F (TxConfig, TxClearAbt | (TX_DMA_BURST << TxDMAShift));
+ RTL_W32 (TxConfig, TxClearAbt);
+ RTL_W16 (IntrStatus, TxErr);
+ wmb();
X }
X if (txstatus & TxCarrierLost)
X tp->stats.tx_carrier_errors++;
@@ -1853,17 +1722,6 @@
X tp->stats.tx_packets++;
X }
X
- /* Free the original skb. */
- if (tp->tx_info[entry].mapping != 0) {
- pci_unmap_single(tp->pci_dev,
- tp->tx_info[entry].mapping,
- tp->tx_info[entry].skb->len,
- PCI_DMA_TODEVICE);
- tp->tx_info[entry].mapping = 0;
- }
- dev_kfree_skb_irq (tp->tx_info[entry].skb);
- tp->tx_info[entry].skb = NULL;
-
X dirty_tx++;
X tx_left--;
X }
@@ -2000,7 +1858,11 @@
X }
X #endif
X
- if (rx_size == 0xfff0) { /* Early Rx in progress */
+ /* Packet copy from FIFO still in progress.
+ * Theoretically, this should never happen
+ * since EarlyRx is disabled.
+ */
+ if (rx_size == 0xfff0) {
X tp->xstats.early_rx++;
X break;
X }
@@ -2059,10 +1921,6 @@
X RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
X
X tp->cur_rx = cur_rx;
-
- if ((RTL_R8 (ChipCmd) & RxBufEmpty) &&
- (RTL_R16 (IntrStatus) & RxAckBits))
- RTL_W16_F (IntrStatus, RxAckBits);
X }
X
X
@@ -2104,13 +1962,14 @@
X (RxUnderrun | RxOverflow | RxErr | RxFIFOOver))
X tp->stats.rx_errors++;
X
- if (status & (PCSTimeout))
+ if (status & PCSTimeout)
X tp->stats.rx_length_errors++;
X if (status & (RxUnderrun | RxFIFOOver))
X tp->stats.rx_fifo_errors++;
X if (status & PCIErr) {
X u16 pci_cmd_status;
X pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status);
+ pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status);
X
X printk (KERN_ERR "%s: PCI Bus error %4.4x.\n",
X dev->name, pci_cmd_status);
@@ -2139,6 +1998,11 @@
X if (status == 0xFFFF)
X break;
X
+ if ((status &
+ (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
+ RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0)
+ break;
+
X /* Acknowledge all of the current interrupt sources ASAP, but
X an first get an additional status bit from CSCR. */
X if (status & RxUnderrun)
@@ -2147,28 +2011,26 @@
X /* The chip takes special action when we clear RxAckBits,
X * so we clear them later in rtl8139_rx_interrupt
X */
- ackstat = status & ~RxAckBits;
+ ackstat = status & ~(RxAckBits | TxErr);
X RTL_W16 (IntrStatus, ackstat);
X
X DPRINTK ("%s: interrupt status=%#4.4x ackstat=%#4.4x new intstat=%#4.4x.\n",
X dev->name, ackstat, status, RTL_R16 (IntrStatus));
X
- if ((status &
- (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
- RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0)
- break;
-
X if (netif_running (dev) && (status & RxAckBits))
X rtl8139_rx_interrupt (dev, tp, ioaddr);
X
X /* Check uncommon events with one test. */
X if (status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
- RxFIFOOver | TxErr | RxErr))
+ RxFIFOOver | RxErr))
X rtl8139_weird_interrupt (dev, tp, ioaddr,
X status, link_changed);
X
- if (netif_running (dev) && (status & (TxOK | TxErr)))
+ if (netif_running (dev) && (status & (TxOK | TxErr))) {
X rtl8139_tx_interrupt (dev, tp, ioaddr);
+ if (status & TxErr)
+ RTL_W16 (IntrStatus, TxErr);
+ }
X
X boguscnt--;
X } while (boguscnt > 0);
@@ -2195,11 +2057,11 @@


X int ret = 0;

X unsigned long flags;
X

- DPRINTK ("ENTER\n");
-
X netif_stop_queue (dev);
X
X if (tp->thr_pid >= 0) {
+ tp->time_to_die = 1;
+ wmb();
X ret = kill_proc (tp->thr_pid, SIGTERM, 1);
X if (ret) {
X printk (KERN_ERR "%s: unable to signal thread\n", dev->name);
@@ -2243,7 +2105,6 @@
X if (rtl_chip_info[tp->chipset].flags & HasHltClk)
X RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */
X
- DPRINTK ("EXIT\n");
X return 0;
X }
X
@@ -2439,8 +2300,6 @@
X int rc = 0;
X int phy = tp->phys[0] & 0x3f;
X
- DPRINTK ("ENTER\n");
-
X if (cmd != SIOCETHTOOL) {
X /* With SIOCETHTOOL, this would corrupt the pointer. */
X data->phy_id &= 0x1f;
@@ -2488,7 +2347,6 @@
X break;
X }
X
- DPRINTK ("EXIT, returning %d\n", rc);
X return rc;
X }
X
@@ -2499,8 +2357,6 @@
X void *ioaddr = tp->mmio_addr;


X unsigned long flags;
X

- DPRINTK ("ENTER\n");
-
X if (netif_running(dev)) {
X spin_lock_irqsave (&tp->lock, flags);
X tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
@@ -2508,7 +2364,6 @@
X spin_unlock_irqrestore (&tp->lock, flags);
X }
X
- DPRINTK ("EXIT\n");
X return &tp->stats;
X }
X
@@ -2520,8 +2375,6 @@
X {
X int crc = -1;
X
- DPRINTK ("ENTER\n");
-
X while (--length >= 0) {
X unsigned char current_octet = *data++;
X int bit;
@@ -2530,7 +2383,6 @@
X ethernet_polynomial : 0);
X }
X
- DPRINTK ("EXIT, returning %u\n", crc);
X return crc;
X }
X
@@ -2543,8 +2395,6 @@
X int i, rx_mode;
X u32 tmp;
X
- DPRINTK ("ENTER\n");
-
X DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n",
X dev->name, dev->flags, RTL_R32 (RxConfig));
X
@@ -2583,9 +2433,6 @@
X }
X RTL_W32_F (MAR0 + 0, mc_filter[0]);
X RTL_W32_F (MAR0 + 4, mc_filter[1]);
-
-
- DPRINTK ("EXIT\n");
X }
X
X static void rtl8139_set_rx_mode (struct net_device *dev)
diff -u --recursive --new-file v2.4.14/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.4.14/linux/drivers/net/Config.in Tue Oct 23 22:48:51 2001
+++ linux/drivers/net/Config.in Mon Nov 19 15:19:42 2001
@@ -34,12 +34,12 @@
X fi
X fi
X if [ "$CONFIG_PPC" = "y" ]; then
- tristate ' MACE (Power Mac ethernet) support' CONFIG_MACE
+ dep_tristate ' MACE (Power Mac ethernet) support' CONFIG_MACE $CONFIG_ALL_PPC
X if [ "$CONFIG_MACE" != "n" ]; then
X bool ' Use AAUI port instead of TP by default' CONFIG_MACE_AAUI_PORT
X fi
- tristate ' BMAC (G3 ethernet) support' CONFIG_BMAC
- tristate ' GMAC (G4/iBook ethernet) support' CONFIG_GMAC
+ dep_tristate ' BMAC (G3 ethernet) support' CONFIG_BMAC $CONFIG_ALL_PPC
+ dep_tristate ' GMAC (G4/iBook ethernet) support' CONFIG_GMAC $CONFIG_ALL_PPC
X tristate ' National DP83902AV (Oak ethernet) support' CONFIG_OAKNET
X fi
X if [ "$CONFIG_ZORRO" = "y" ]; then
@@ -188,6 +188,7 @@
X tristate ' TI ThunderLAN support' CONFIG_TLAN
X fi
X dep_tristate ' VIA Rhine support' CONFIG_VIA_RHINE $CONFIG_PCI
+ dep_mbool ' Use MMIO instead of PIO (EXPERIMENTAL)' CONFIG_VIA_RHINE_MMIO $CONFIG_VIA_RHINE $CONFIG_EXPERIMENTAL
X dep_tristate ' Winbond W89c840 Ethernet support' CONFIG_WINBOND_840 $CONFIG_PCI
X if [ "$CONFIG_OBSOLETE" = "y" ]; then
X dep_bool ' Zenith Z-Note support (EXPERIMENTAL)' CONFIG_ZNET $CONFIG_ISA
@@ -273,6 +274,9 @@
X dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP
X if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
X dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
+ fi
+ if [ ! "$CONFIG_ATM" = "n" ]; then
+ dep_tristate ' PPP over ATM (EXPERIMENTAL)' CONFIG_PPPOATM $CONFIG_PPP
X fi
X fi
X
diff -u --recursive --new-file v2.4.14/linux/drivers/net/acenic.c linux/drivers/net/acenic.c
--- v2.4.14/linux/drivers/net/acenic.c Mon Nov 5 15:55:30 2001
+++ linux/drivers/net/acenic.c Mon Nov 19 15:19:42 2001
@@ -208,8 +208,32 @@
X (((u64)(mask) & 0xffffffff00000000) == 0 ? 0 : -EIO)
X #define pci_dma_supported(dev, mask) \
X (((u64)(mask) & 0xffffffff00000000) == 0 ? 1 : 0)
+
+#elif (LINUX_VERSION_CODE < 0x02040d)
+
+/*
+ * 2.4.13 introduced pci_map_page()/pci_unmap_page() - for 2.4.12 and prior,
+ * fall back on pci_map_single()/pci_unnmap_single().
+ *
+ * We are guaranteed that the page is mapped at this point since
+ * pci_map_page() is only used upon valid struct skb's.
+ */
+static inline dma_addr_t
+pci_map_page(struct pci_dev *cookie, struct page *page, unsigned long off,
+ size_t size, int dir)
+{
+ void *page_virt;
+
+ page_virt = page_address(page);
+ if (!page_virt)
+ BUG();
+ return pci_map_single(cookie, (page_virt + off), size, dir);
+}
+#define pci_unmap_page(cookie, dma_addr, size, dir) \
+ pci_unmap_single(cookie, dma_addr, size, dir)
X #endif
X
+
X #if (LINUX_VERSION_CODE < 0x02032b)
X /*
X * SoftNet
@@ -525,7 +549,7 @@
X static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
X
X static char version[] __initdata =
- "acenic.c: v0.83 09/30/2001 Jes Sorensen, linux-...@SunSITE.dk\n"
+ "acenic.c: v0.85 11/08/2001 Jes Sorensen, linux-...@SunSITE.dk\n"
X " http://home.cern.ch/~jes/gige/acenic.html\n";
X
X static struct net_device *root_dev;
@@ -538,7 +562,6 @@
X #ifdef NEW_NETINIT
X struct net_device *dev;
X #endif
-
X struct ace_private *ap;
X struct pci_dev *pdev = NULL;
X int boards_found = 0;
@@ -738,6 +761,7 @@
X kfree(dev);
X continue;
X }
+
X if (ap->pci_using_dac)
X dev->features |= NETIF_F_HIGHDMA;
X
@@ -767,12 +791,14 @@
X MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i");
X MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i");
X MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM_DESC(link, "Acenic/3C985/NetGear link state");
-MODULE_PARM_DESC(trace, "Acenic/3C985/NetGear firmware trace level");
+MODULE_PARM(tx_ratio, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM_DESC(link, "AceNIC/3C985/NetGear link state");
+MODULE_PARM_DESC(trace, "AceNIC/3C985/NetGear firmware trace level");
X MODULE_PARM_DESC(tx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first tx descriptor arrives");
X MODULE_PARM_DESC(max_tx_desc, "AceNIC/3C985/GA620 max number of transmit descriptors to wait");
X MODULE_PARM_DESC(rx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first rx descriptor arrives");
X MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descriptors to wait");
+MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)");
X #endif
X
X
@@ -911,8 +937,7 @@
X RX_JUMBO_RING_ENTRIES +
X RX_MINI_RING_ENTRIES +
X RX_RETURN_RING_ENTRIES));
- pci_free_consistent(ap->pdev, size,
- ap->rx_std_ring,
+ pci_free_consistent(ap->pdev, size, ap->rx_std_ring,
X ap->rx_ring_base_dma);
X ap->rx_std_ring = NULL;
X ap->rx_jumbo_ring = NULL;
@@ -921,8 +946,7 @@
X }
X if (ap->evt_ring != NULL) {
X size = (sizeof(struct event) * EVT_RING_ENTRIES);
- pci_free_consistent(ap->pdev, size,
- ap->evt_ring,
+ pci_free_consistent(ap->pdev, size, ap->evt_ring,
X ap->evt_ring_dma);
X ap->evt_ring = NULL;
X }
@@ -933,7 +957,8 @@
X }
X if (ap->rx_ret_prd != NULL) {
X pci_free_consistent(ap->pdev, sizeof(u32),
- (void *)ap->rx_ret_prd, ap->rx_ret_prd_dma);
+ (void *)ap->rx_ret_prd,
+ ap->rx_ret_prd_dma);
X ap->rx_ret_prd = NULL;
X }
X if (ap->tx_csm != NULL) {
@@ -1051,8 +1076,8 @@
X struct ace_private *ap;
X struct ace_regs *regs;
X struct ace_info *info = NULL;
- u64 tmp_ptr;
X unsigned long myjif;
+ u64 tmp_ptr;
X u32 tig_ver, mac1, mac2, tmp, pci_state;
X int board_idx, ecode = 0;
X short i;
@@ -1306,9 +1331,9 @@
X /*
X * Configure DMA attributes.
X */
- if (!pci_set_dma_mask(ap->pdev, (u64) 0xffffffffffffffff)) {
+ if (!pci_set_dma_mask(ap->pdev, 0xffffffffffffffffULL)) {
X ap->pci_using_dac = 1;
- } else if (!pci_set_dma_mask(ap->pdev, (u64) 0xffffffff)) {
+ } else if (!pci_set_dma_mask(ap->pdev, 0xffffffffULL)) {
X ap->pci_using_dac = 0;
X } else {
X ecode = -ENODEV;
@@ -1362,7 +1387,7 @@
X ace_load_firmware(dev);
X ap->fw_running = 0;
X
- tmp_ptr = (u64) ap->info_dma;
+ tmp_ptr = ap->info_dma;
X writel(tmp_ptr >> 32, &regs->InfoPtrHi);
X writel(tmp_ptr & 0xffffffff, &regs->InfoPtrLo);
X
@@ -1428,7 +1453,8 @@
X (RX_STD_RING_ENTRIES +
X RX_JUMBO_RING_ENTRIES))));
X info->rx_mini_ctrl.max_len = ACE_MINI_SIZE;
- info->rx_mini_ctrl.flags = RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR;
+ info->rx_mini_ctrl.flags =
+ RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR;
X
X for (i = 0; i < RX_MINI_RING_ENTRIES; i++)
X ap->rx_mini_ring[i].flags =
@@ -1712,11 +1738,13 @@
X dev->name, (unsigned int)readl(&regs->HostCtrl));
X /* This can happen due to ieee flow control. */
X } else {
- printk(KERN_DEBUG "%s: BUG... transmitter died. Kicking it.\n", dev->name);
+ printk(KERN_DEBUG "%s: BUG... transmitter died. Kicking it.\n",
+ dev->name);
X netif_wake_queue(dev);
X }
X }
X
+
X static void ace_tasklet(unsigned long dev)
X {
X struct ace_private *ap = ((struct net_device *)dev)->priv;
@@ -1747,7 +1775,7 @@
X if (ap->jumbo && (cur_size < RX_LOW_JUMBO_THRES) &&
X !test_and_set_bit(0, &ap->jumbo_refill_busy)) {
X #if DEBUG
- printk("refilling jumbo buffers (current %i)\n", >cur_size);
+ printk("refilling jumbo buffers (current %i)\n", cur_size);
X #endif
X ace_load_jumbo_rx_ring(ap, RX_JUMBO_SIZE - cur_size);
X }
@@ -1799,10 +1827,8 @@
X * Make sure IP header starts on a fresh cache line.
X */
X skb_reserve(skb, 2 + 16);
- mapping = pci_map_page(ap->pdev,
- virt_to_page(skb->data),
- ((unsigned long) skb->data &
- ~PAGE_MASK),
+ mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
+ ((unsigned long)skb->data & ~PAGE_MASK),
X ACE_STD_BUFSIZE - (2 + 16),
X PCI_DMA_FROMDEVICE);
X ap->skb->rx_std_skbuff[idx].skb = skb;
@@ -1866,10 +1892,8 @@
X * Make sure the IP header ends up on a fresh cache line
X */
X skb_reserve(skb, 2 + 16);
- mapping = pci_map_page(ap->pdev,
- virt_to_page(skb->data),
- ((unsigned long) skb->data &
- ~PAGE_MASK),
+ mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
+ ((unsigned long)skb->data & ~PAGE_MASK),
X ACE_MINI_BUFSIZE - (2 + 16),
X PCI_DMA_FROMDEVICE);
X ap->skb->rx_mini_skbuff[idx].skb = skb;
@@ -1928,10 +1952,8 @@
X * Make sure the IP header ends up on a fresh cache line
X */
X skb_reserve(skb, 2 + 16);
- mapping = pci_map_page(ap->pdev,
- virt_to_page(skb->data),
- ((unsigned long) skb->data &
- ~PAGE_MASK),
+ mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
+ ((unsigned long)skb->data & ~PAGE_MASK),
X ACE_JUMBO_BUFSIZE - (2 + 16),
X PCI_DMA_FROMDEVICE);
X ap->skb->rx_jumbo_skbuff[idx].skb = skb;
@@ -2499,7 +2521,7 @@
X mapping = info->mapping;
X
X if (mapping) {
- memset(ap->tx_ring+i, 0, sizeof(struct tx_desc));
+ memset(ap->tx_ring + i, 0, sizeof(struct tx_desc));
X pci_unmap_page(ap->pdev, mapping, info->maplen,
X PCI_DMA_TODEVICE);
X info->mapping = 0;
@@ -2523,24 +2545,23 @@


X return 0;
X }
X

+
X static inline dma_addr_t
X ace_map_tx_skb(struct ace_private *ap, struct sk_buff *skb,
X struct sk_buff *tail, u32 idx)
X {
- unsigned long addr;
+ dma_addr_t mapping;
X struct tx_ring_info *info;
X
- addr = pci_map_page(ap->pdev,
- virt_to_page(skb->data),
- ((unsigned long) skb->data &
- ~PAGE_MASK),
- skb->len, PCI_DMA_TODEVICE);
+ mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
+ ((unsigned long) skb->data & ~PAGE_MASK),
+ skb->len, PCI_DMA_TODEVICE);
X
X info = ap->skb->tx_skbuff + idx;
X info->skb = tail;
- info->mapping = addr;
+ info->mapping = mapping;
X info->maplen = skb->len;
- return addr;
+ return mapping;
X }
X
X
@@ -2581,9 +2602,9 @@
X if (!skb_shinfo(skb)->nr_frags)
X #endif
X {
- unsigned long addr;
+ dma_addr_t mapping;
X
- addr = ace_map_tx_skb(ap, skb, skb, idx);
+ mapping = ace_map_tx_skb(ap, skb, skb, idx);
X flagsize = (skb->len << 16) | (BD_FLG_END);
X if (skb->ip_summed == CHECKSUM_HW)
X flagsize |= BD_FLG_TCP_UDP_SUM;
@@ -2594,42 +2615,40 @@
X if (tx_ring_full(ap->tx_ret_csm, idx))
X flagsize |= BD_FLG_COAL_NOW;
X
- ace_load_tx_bd(desc, addr, flagsize);
+ ace_load_tx_bd(desc, mapping, flagsize);
X }
X #if MAX_SKB_FRAGS
X else {
- unsigned long addr;
+ dma_addr_t mapping;


X int i, len = 0;

X
- addr = ace_map_tx_skb(ap, skb, NULL, idx);
+ mapping = ace_map_tx_skb(ap, skb, NULL, idx);
X flagsize = ((skb->len - skb->data_len) << 16);
X if (skb->ip_summed == CHECKSUM_HW)
X flagsize |= BD_FLG_TCP_UDP_SUM;
X
- ace_load_tx_bd(ap->tx_ring + idx, addr, flagsize);
+ ace_load_tx_bd(ap->tx_ring + idx, mapping, flagsize);
X
X idx = (idx + 1) % TX_RING_ENTRIES;
X
X for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
X skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
X struct tx_ring_info *info;
- dma_addr_t phys;
X
X len += frag->size;
X info = ap->skb->tx_skbuff + idx;
X desc = ap->tx_ring + idx;
X
- phys = pci_map_page(ap->pdev, frag->page,
- frag->page_offset,
- frag->size,
- PCI_DMA_TODEVICE);
+ mapping = pci_map_page(ap->pdev, frag->page,
+ frag->page_offset, frag->size,
+ PCI_DMA_TODEVICE);
X
X flagsize = (frag->size << 16);
X if (skb->ip_summed == CHECKSUM_HW)
X flagsize |= BD_FLG_TCP_UDP_SUM;
X idx = (idx + 1) % TX_RING_ENTRIES;
X
- if (i == skb_shinfo(skb)->nr_frags-1) {
+ if (i == skb_shinfo(skb)->nr_frags - 1) {
X flagsize |= BD_FLG_END;
X if (tx_ring_full(ap->tx_ret_csm, idx))
X flagsize |= BD_FLG_COAL_NOW;
@@ -2642,9 +2661,9 @@
X } else {
X info->skb = NULL;
X }
- info->mapping = phys;
+ info->mapping = mapping;
X info->maplen = frag->size;
- ace_load_tx_bd(desc, phys, flagsize);
+ ace_load_tx_bd(desc, mapping, flagsize);
X }
X }
X #endif
diff -u --recursive --new-file v2.4.14/linux/drivers/net/acenic.h linux/drivers/net/acenic.h
--- v2.4.14/linux/drivers/net/acenic.h Tue Oct 23 22:48:51 2001
+++ linux/drivers/net/acenic.h Mon Nov 19 15:19:42 2001
@@ -582,11 +582,13 @@
X aceaddr stats2_ptr;
X };
X
+
X struct ring_info {
X struct sk_buff *skb;
X dma_addr_t mapping;
X };
X
+
X /*
X * Funny... As soon as we add maplen on alpha, it starts to work
X * much slower. Hmm... is it because struct does not fit to one cacheline?
@@ -597,6 +599,7 @@
X dma_addr_t mapping;
X int maplen;
X };
+
X
X /*
X * struct ace_skb holding the rings of skb's. This is an awful lot of
diff -u --recursive --new-file v2.4.14/linux/drivers/net/appletalk/Config.in linux/drivers/net/appletalk/Config.in
--- v2.4.14/linux/drivers/net/appletalk/Config.in Sat Mar 11 11:27:14 2000
+++ linux/drivers/net/appletalk/Config.in Fri Nov 9 14:01:22 2001
@@ -6,14 +6,14 @@
X mainmenu_option next_comment
X comment 'Appletalk devices'
X bool 'Appletalk interfaces support' CONFIG_APPLETALK
- if [ "$CONFIG_APPLETALK" != "n" ]; then
- dep_tristate ' Apple/Farallon LocalTalk PC support' CONFIG_LTPC $CONFIG_APPLETALK
- dep_tristate ' COPS LocalTalk PC support' CONFIG_COPS $CONFIG_APPLETALK
+ if [ "$CONFIG_ATALK" != "n" ]; then
+ dep_tristate ' Apple/Farallon LocalTalk PC support' CONFIG_LTPC $CONFIG_DEV_APPLETALK
+ dep_tristate ' COPS LocalTalk PC support' CONFIG_COPS $CONFIG_DEV_APPLETALK
X if [ "$CONFIG_COPS" != "n" ]; then
X bool ' Dayna firmware support' CONFIG_COPS_DAYNA
X bool ' Tangent firmware support' CONFIG_COPS_TANGENT
X fi
- dep_tristate ' Appletalk-IP driver support' CONFIG_IPDDP $CONFIG_APPLETALK
+ dep_tristate ' Appletalk-IP driver support' CONFIG_IPDDP $CONFIG_DEV_APPLETALK
X if [ "$CONFIG_IPDDP" != "n" ]; then
X bool ' IP to Appletalk-IP Encapsulation support' CONFIG_IPDDP_ENCAP
X bool ' Appletalk-IP to IP Decapsulation support' CONFIG_IPDDP_DECAP
diff -u --recursive --new-file v2.4.14/linux/drivers/net/arcnet/com20020-pci.c linux/drivers/net/arcnet/com20020-pci.c
--- v2.4.14/linux/drivers/net/arcnet/com20020-pci.c Mon Nov 5 15:55:30 2001
+++ linux/drivers/net/arcnet/com20020-pci.c Fri Nov 9 13:41:42 2001
@@ -83,7 +83,7 @@
X goto out_dev;
X }
X memset(lp, 0, sizeof(struct arcnet_local));
- pdev->driver_data = dev;
+ pci_set_drvdata(pdev, dev);
X
X ioaddr = pci_resource_start(pdev, 2);
X dev->base_addr = ioaddr;


@@ -128,7 +128,7 @@
X

X static void __devexit com20020pci_remove(struct pci_dev *pdev)
X {
- com20020_remove(pdev->driver_data);
+ com20020_remove(pci_get_drvdata(pdev));
X }
X
X static struct pci_device_id com20020pci_id_table[] __devinitdata = {
diff -u --recursive --new-file v2.4.14/linux/drivers/net/arlan.c linux/drivers/net/arlan.c
--- v2.4.14/linux/drivers/net/arlan.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/net/arlan.c Fri Nov 9 13:45:35 2001
@@ -8,6 +8,10 @@
X #include <linux/config.h>
X #include "arlan.h"
X
+#if BITS_PER_LONG != 32
+# error FIXME: this driver requires a 32-bit platform
+#endif
+
X static const char *arlan_version = "C.Jennigs 97 & Elmer....@ut.ee Oct'98, http://www.ylenurme.ee/~elmer/655/";
X
X struct net_device *arlan_device[MAX_ARLANS];
diff -u --recursive --new-file v2.4.14/linux/drivers/net/bmac.c linux/drivers/net/bmac.c
--- v2.4.14/linux/drivers/net/bmac.c Tue Oct 23 22:48:51 2001
+++ linux/drivers/net/bmac.c Wed Nov 14 15:16:31 2001
@@ -1659,7 +1659,7 @@
X MODULE_AUTHOR("Randy Gobbel/Paul Mackerras");
X MODULE_DESCRIPTION("PowerMac BMAC ethernet driver.");
X MODULE_LICENSE("GPL");
-
+EXPORT_NO_SYMBOLS;
X
X static void __exit bmac_cleanup (void)
X {
diff -u --recursive --new-file v2.4.14/linux/drivers/net/bonding.c linux/drivers/net/bonding.c
--- v2.4.14/linux/drivers/net/bonding.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/net/bonding.c Tue Nov 13 09:19:41 2001
@@ -4,11 +4,14 @@
X * Copyright 1999, Thomas Davis, tad...@lbl.gov.
X * Licensed under the GPL. Based on dummy.c, and eql.c devices.
X *
- * bond.c: a bonding/etherchannel/sun trunking net driver
+ * bonding.c: an Ethernet Bonding driver
X *
- * This is useful to talk to a Cisco 5500, running Etherchannel, aka:
- * Linux Channel Bonding
+ * This is useful to talk to a Cisco EtherChannel compatible equipment:
+ * Cisco 5500
X * Sun Trunking (Solaris)
+ * Alteon AceDirector Trunks
+ * Linux Bonding
+ * and probably many L2 switches ...
X *
X * How it works:
X * ifconfig bond0 ipaddress netmask up
@@ -21,280 +24,2019 @@
X * will release all slaves, marking them as down.
X *
X * ifenslave bond0 eth0
- * will attache eth0 to bond0 as a slave. eth0 hw mac address will either
+ * will attach eth0 to bond0 as a slave. eth0 hw mac address will either
X * a: be used as initial mac address
X * b: if a hw mac address already is there, eth0's hw mac address
- * will then be set from bond0.
+ * will then be set from bond0.
X *
X * v0.1 - first working version.
X * v0.2 - changed stats to be calculated by summing slaves stats.
+ *
+ * Changes:
+ * Arnaldo Carvalho de Melo <ac...@conectiva.com.br>
+ * - fix leaks on failure at bond_init
+ *
+ * 2000/09/30 - Willy Tarreau <willy at meta-x.org>
+ * - added trivial code to release a slave device.
+ * - fixed security bug (CAP_NET_ADMIN not checked)
+ * - implemented MII link monitoring to disable dead links :
+ * All MII capable slaves are checked every <miimon> milliseconds
+ * (100 ms seems good). This value can be changed by passing it to
+ * insmod. A value of zero disables the monitoring (default).
+ * - fixed an infinite loop in bond_xmit_roundrobin() when there's no
+ * good slave.
+ * - made the code hopefully SMP safe
+ *
+ * 2000/10/03 - Willy Tarreau <willy at meta-x.org>
+ * - optimized slave lists based on relevant suggestions from Thomas Davis
+ * - implemented active-backup method to obtain HA with two switches:
+ * stay as long as possible on the same active interface, while we
+ * also monitor the backup one (MII link status) because we want to know
+ * if we are able to switch at any time. ( pass "mode=1" to insmod )
+ * - lots of stress testings because we need it to be more robust than the
+ * wires ! :->
+ *
+ * 2000/10/09 - Willy Tarreau <willy at meta-x.org>
+ * - added up and down delays after link state change.
+ * - optimized the slaves chaining so that when we run forward, we never
+ * repass through the bond itself, but we can find it by searching
+ * backwards. Renders the deletion more difficult, but accelerates the
+ * scan.
+ * - smarter enslaving and releasing.
+ * - finer and more robust SMP locking
+ *
+ * 2000/10/17 - Willy Tarreau <willy at meta-x.org>
+ * - fixed two potential SMP race conditions
+ *
+ * 2000/10/18 - Willy Tarreau <willy at meta-x.org>
+ * - small fixes to the monitoring FSM in case of zero delays
+ * 2000/11/01 - Willy Tarreau <willy at meta-x.org>
+ * - fixed first slave not automatically used in trunk mode.
+ * 2000/11/10 : spelling of "EtherChannel" corrected.
+ * 2000/11/13 : fixed a race condition in case of concurrent accesses to ioctl().
+ * 2000/12/16 : fixed improper usage of rtnl_exlock_nowait().
+ *
+ * 2001/1/3 - Chad N. Tindel <ctindel at ieee dot org>
+ * - The bonding driver now simulates MII status monitoring, just like
+ * a normal network device. It will show that the link is down iff
+ * every slave in the bond shows that their links are down. If at least
+ * one slave is up, the bond's MII status will appear as up.
+ *
+ * 2001/2/7 - Chad N. Tindel <ctindel at ieee dot org>
+ * - Applications can now query the bond from user space to get
+ * information which may be useful. They do this by calling
+ * the BOND_INFO_QUERY ioctl. Once the app knows how many slaves
+ * are in the bond, it can call the BOND_SLAVE_INFO_QUERY ioctl to
+ * get slave specific information (# link failures, etc). See
+ * <linux/if_bonding.h> for more details. The structs of interest
+ * are ifbond and ifslave.
+ *
+ * 2001/4/5 - Chad N. Tindel <ctindel at ieee dot org>
+ * - Ported to 2.4 Kernel
X *
+ * 2001/5/2 - Jeffrey E. Mast <jeff at mastfamily dot com>
+ * - When a device is detached from a bond, the slave device is no longer
+ * left thinking that is has a master.
+ *
+ * 2001/5/16 - Jeffrey E. Mast <jeff at mastfamily dot com>
+ * - memset did not appropriately initialized the bond rw_locks. Used
+ * rwlock_init to initialize to unlocked state to prevent deadlock when
+ * first attempting a lock
+ * - Called SET_MODULE_OWNER for bond device
+ *
+ * 2001/5/17 - Tim Anderson <tsa at mvista.com>
+ * - 2 paths for releasing for slave release; 1 through ioctl
+ * and 2) through close. Both paths need to release the same way.
+ * - the free slave in bond release is changing slave status before
+ * the free. The netdev_set_master() is intended to change slave state
+ * so it should not be done as part of the release process.
+ * - Simple rule for slave state at release: only the active in A/B and
+ * only one in the trunked case.
+ *
+ * 2001/6/01 - Tim Anderson <tsa at mvista.com>
+ * - Now call dev_close when releasing a slave so it doesn't screw up
+ * out routing table.
+ *
+ * 2001/6/01 - Chad N. Tindel <ctindel at ieee dot org>
+ * - Added /proc support for getting bond and slave information.
+ * Information is in /proc/net/<bond device>/info.
+ * - Changed the locking when calling bond_close to prevent deadlock.
+ *
+ * 2001/8/05 - Janice Girouard <girouard at us.ibm.com>
+ * - correct problem where refcnt of slave is not incremented in bond_ioctl
+ * so the system hangs when halting.
+ * - correct locking problem when unable to malloc in bond_enslave.
+ * - adding bond_xmit_xor logic.
+ * - adding multiple bond device support.
+ *
+ * 2001/8/13 - Erik Habbinga <erik_habbinga at hp dot com>
+ * - correct locking problem with rtnl_exlock_nowait
+ *
+ * 2001/8/23 - Janice Girouard <girouard at us.ibm.com>
+ * - bzero initial dev_bonds, to correct oops
+ * - convert SIOCDEVPRIVATE to new MII ioctl calls
+ *
+ * 2001/9/13 - Takao Indoh <indou dot takao at jp dot fujitsu dot com>
+ * - Add the BOND_CHANGE_ACTIVE ioctl implementation
+ *
+ * 2001/9/14 - Mark Huth <mhuth at mvista dot com>
+ * - Change MII_LINK_READY to not check for end of auto-negotiation,
+ * but only for an up link.
+ *
+ * 2001/9/20 - Chad N. Tindel <ctindel at ieee dot org>
+ * - Add the device field to bonding_t. Previously the net_device
+ * corresponding to a bond wasn't available from the bonding_t
+ * structure.
+ *
+ * 2001/9/25 - Janice Girouard <girouard at us.ibm.com>
+ * - add arp_monitor for active backup mode
+ *
+ * 2001/10/23 - Takao Indoh <indou dot takao at jp dot fujitsu dot com>
+ * - Various memory leak fixes
X */
X
-#include <linux/module.h>
+#include <linux/config.h>
X #include <linux/kernel.h>
-#include <linux/netdevice.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/slab.h>
+#include <linux/string.h>
X #include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/socket.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <linux/rtnetlink.h>
+
X #include <linux/if_bonding.h>
+#include <linux/smp.h>
+#include <limits.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+
+/* monitor all links that often (in milliseconds). <=0 disables monitoring */
+#ifndef BOND_LINK_MON_INTERV
+#define BOND_LINK_MON_INTERV 0
+#endif
+
+#undef MII_LINK_UP
+#define MII_LINK_UP 0x04
+
+#undef MII_ENDOF_NWAY
+#define MII_ENDOF_NWAY 0x20
+
+#undef MII_LINK_READY
+/*#define MII_LINK_READY (MII_LINK_UP | MII_ENDOF_NWAY)*/
+#define MII_LINK_READY (MII_LINK_UP)
+
+#define MAX_BOND_ADDR 256
+
+#ifndef BOND_LINK_ARP_INTERV
+#define BOND_LINK_ARP_INTERV 0
+#endif
+
+static int arp_interval = BOND_LINK_ARP_INTERV;
+static char *arp_ip_target = NULL;
+static unsigned long arp_target = 0;
+static u32 my_ip = 0;
+char *arp_target_hw_addr = NULL;
+
+static int max_bonds = MAX_BONDS;
+static int miimon = BOND_LINK_MON_INTERV;
+static int mode = BOND_MODE_ROUNDROBIN;
+static int updelay = 0;
+static int downdelay = 0;
+
+static int first_pass = 1;
+int bond_cnt;
+static struct bonding *these_bonds = NULL;
+static struct net_device *dev_bonds = NULL;
+
+MODULE_PARM(max_bonds, "1-" __MODULE_STRING(INT_MAX) "i");
+MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
+MODULE_PARM(miimon, "i");
+MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
+MODULE_PARM(mode, "i");
+MODULE_PARM(arp_interval, "i");
+MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
+MODULE_PARM(arp_ip_target, "1-12s");
+MODULE_PARM_DESC(arp_ip_target, "arp target in n.n.n.n form");
+MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor");
+MODULE_PARM(updelay, "i");
+MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds");
+MODULE_PARM(downdelay, "i");
+MODULE_PARM_DESC(downdelay, "Delay before considering link down, in milliseconds");
+
+extern void arp_send( int type, int ptype, u32 dest_ip, struct net_device *dev,
+ u32 src_ip, unsigned char *dest_hw, unsigned char *src_hw,
+ unsigned char *target_hw);
+
+static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *dev);
+static int bond_xmit_xor(struct sk_buff *skb, struct net_device *dev);
+static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *dev);
+static struct net_device_stats *bond_get_stats(struct net_device *dev);
+static void bond_mii_monitor(struct net_device *dev);
+static void bond_arp_monitor(struct net_device *dev);
+static int bond_event(struct notifier_block *this, unsigned long event, void *ptr);
+static void bond_set_slave_inactive_flags(slave_t *slave);
+static void bond_set_slave_active_flags(slave_t *slave);
+static int bond_enslave(struct net_device *master, struct net_device *slave);
+static int bond_release(struct net_device *master, struct net_device *slave);
+static int bond_sethwaddr(struct net_device *master, struct net_device *slave);
+
+/*
+ * bond_get_info is the interface into the /proc filesystem. This is
+ * a different interface than the BOND_INFO_QUERY ioctl. That is done
+ * through the generic networking ioctl interface, and bond_info_query
+ * is the internal function which provides that information.


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

echo 'End of part 049'
echo 'File patch-2.4.15 is continued in part 050'
echo "050" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:17 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part041

#!/bin/sh -x
# this is part 041 of a 115 - part archive


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

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

X
X #include <linux/isicom.h>
X
-static int device_id[] = { 0x2028,
- 0x2051,
- 0x2052,
- 0x2053,
- 0x2054,
- 0x2055,
- 0x2056,
- 0x2057,
- 0x2058
- };
+static struct pci_device_id isicom_pci_tbl[] = {
+ { VENDOR_ID, 0x2028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { VENDOR_ID, 0x2051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { VENDOR_ID, 0x2052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { VENDOR_ID, 0x2053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { VENDOR_ID, 0x2054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { VENDOR_ID, 0x2055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { VENDOR_ID, 0x2056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { VENDOR_ID, 0x2057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { VENDOR_ID, 0x2058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
X
-static int isicom_refcount = 0;
+static int isicom_refcount;
X static int prev_card = 3; /* start servicing isi_card[0] */
-static struct isi_board * irq_to_board[16] = { NULL, };
+static struct isi_board * irq_to_board[16];
X static struct tty_driver isicom_normal, isicom_callout;
-static struct tty_struct * isicom_table[PORT_COUNT] = { NULL, };
-static struct termios * isicom_termios[PORT_COUNT] = { NULL, };
-static struct termios * isicom_termios_locked[PORT_COUNT] = { NULL, };
+static struct tty_struct * isicom_table[PORT_COUNT];
+static struct termios * isicom_termios[PORT_COUNT];
+static struct termios * isicom_termios_locked[PORT_COUNT];
X
X static struct isi_board isi_card[BOARD_COUNT];
X static struct isi_port isi_ports[PORT_COUNT];
@@ -997,7 +1000,7 @@
X }
X schedule();
X }
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
X remove_wait_queue(&port->open_wait, &wait);
X if (!tty_hung_up_p(filp))
X port->count++;
@@ -1202,7 +1205,7 @@
X port->tty = 0;
X if (port->blocked_open) {
X if (port->close_delay) {


- current->state = TASK_INTERRUPTIBLE;

+ set_current_state(TASK_INTERRUPTIBLE);
X #ifdef ISICOM_DEBUG
X printk(KERN_DEBUG "ISICOM: scheduling until time out.\n");
X #endif
@@ -1974,7 +1977,7 @@
X for (idx=0; idx < DEVID_COUNT; idx++) {
X dev = NULL;
X for (;;){
- if (!(dev = pci_find_device(VENDOR_ID, device_id[idx], dev)))
+ if (!(dev = pci_find_device(VENDOR_ID, isicom_pci_tbl[idx].device, dev)))
X break;
X if (card >= BOARD_COUNT)
X break;
@@ -1988,7 +1991,7 @@
X * space.
X */
X pciirq = dev->irq;
- printk(KERN_INFO "ISI PCI Card(Device ID 0x%x)\n", device_id[idx]);
+ printk(KERN_INFO "ISI PCI Card(Device ID 0x%x)\n", isicom_pci_tbl[idx].device);
X /*
X * allot the first empty slot in the array
X */
@@ -2035,7 +2038,7 @@
X void cleanup_module(void)
X {
X re_schedule = 0;


- current->state = TASK_INTERRUPTIBLE;

+ set_current_state(TASK_INTERRUPTIBLE);
X schedule_timeout(HZ);
X
X remove_bh(ISICOM_BH);
diff -u --recursive --new-file v2.4.14/linux/drivers/char/joystick/cs461x.c linux/drivers/char/joystick/cs461x.c
--- v2.4.14/linux/drivers/char/joystick/cs461x.c Sun Sep 23 11:40:57 2001
+++ linux/drivers/char/joystick/cs461x.c Fri Nov 9 13:41:42 2001
@@ -158,7 +158,7 @@
X
X static int cs461x_free(struct pci_dev *pdev)
X {
- struct gameport *port = (struct gameport *)pdev->driver_data;
+ struct gameport *port = pci_get_drvdata(pdev);
X if(port){
X gameport_unregister_port(port);
X kfree(port);
@@ -284,7 +284,7 @@
X }
X memset(port, 0, sizeof(struct gameport));
X
- pdev->driver_data = port;
+ pci_set_drvdata(pdev, port);
X
X port->open = cs461x_gameport_open;
X port->read = cs461x_gameport_read;
diff -u --recursive --new-file v2.4.14/linux/drivers/char/joystick/emu10k1-gp.c linux/drivers/char/joystick/emu10k1-gp.c
--- v2.4.14/linux/drivers/char/joystick/emu10k1-gp.c Sun Sep 23 11:40:57 2001
+++ linux/drivers/char/joystick/emu10k1-gp.c Fri Nov 9 13:41:42 2001
@@ -86,7 +86,7 @@
X port->gameport.io = ioport;
X port->size = iolen;
X port->dev = pdev;
- pdev->driver_data = port;
+ pci_set_drvdata(pdev, port);
X
X gameport_register_port(&port->gameport);
X
@@ -98,7 +98,7 @@
X
X static void __devexit emu_remove(struct pci_dev *pdev)
X {
- struct emu *port = (struct emu *)pdev->driver_data;
+ struct emu *port = pci_get_drvdata(pdev);
X gameport_unregister_port(&port->gameport);
X release_region(port->gameport.io, port->size);
X kfree(port);
diff -u --recursive --new-file v2.4.14/linux/drivers/char/joystick/pcigame.c linux/drivers/char/joystick/pcigame.c
--- v2.4.14/linux/drivers/char/joystick/pcigame.c Sun Sep 23 11:40:57 2001
+++ linux/drivers/char/joystick/pcigame.c Fri Nov 9 13:41:42 2001
@@ -133,7 +133,7 @@
X pcigame->data = pcigame_data + id->driver_data;
X
X pcigame->dev = dev;
- dev->driver_data = pcigame;
+ pci_set_drvdata(dev, pcigame);
X
X pcigame->gameport.private = pcigame;
X pcigame->gameport.fuzz = 64;
@@ -163,7 +163,7 @@
X
X static void __devexit pcigame_remove(struct pci_dev *dev)
X {
- struct pcigame *pcigame = dev->driver_data;
+ struct pcigame *pcigame = pci_get_drvdata(dev);
X gameport_unregister_port(&pcigame->gameport);
X iounmap(pcigame->base);
X kfree(pcigame);
diff -u --recursive --new-file v2.4.14/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- v2.4.14/linux/drivers/char/pc_keyb.c Sun Sep 23 11:40:57 2001
+++ linux/drivers/char/pc_keyb.c Fri Nov 9 14:01:21 2001
@@ -34,6 +34,7 @@
X #include <linux/vt_kern.h>
X #include <linux/smp_lock.h>
X #include <linux/kd.h>
+#include <linux/pm.h>
X
X #include <asm/keyboard.h>
X #include <asm/bitops.h>
@@ -397,29 +398,32 @@
X return 0200;
X }
X
-void pckbd_pm_resume(void)
+int pckbd_pm_resume(struct pm_dev *dev, pm_request_t rqst, void *data)
X {
X #if defined CONFIG_PSMOUSE


X unsigned long flags;
X

- if (queue) { /* Aux port detected */
- if (aux_count == 0) { /* Mouse not in use */
- spin_lock_irqsave(&kbd_controller_lock, flags);
- /*
- * Dell Lat. C600 A06 enables mouse after resume.
- * When user touches the pad, it posts IRQ 12
- * (which we do not process), thus holding keyboard.
- */
- kbd_write_command(KBD_CCMD_MOUSE_DISABLE);
- /* kbd_write_cmd(AUX_INTS_OFF); */ /* Config & lock */
- kb_wait();
- kbd_write_command(KBD_CCMD_WRITE_MODE);
- kb_wait();
- kbd_write_output(AUX_INTS_OFF);
- spin_unlock_irqrestore(&kbd_controller_lock, flags);
- }
+ if (rqst == PM_RESUME) {
+ if (queue) { /* Aux port detected */
+ if (aux_count == 0) { /* Mouse not in use */
+ spin_lock_irqsave(&kbd_controller_lock, flags);
+ /*
+ * Dell Lat. C600 A06 enables mouse after resume.
+ * When user touches the pad, it posts IRQ 12
+ * (which we do not process), thus holding keyboard.
+ */
+ kbd_write_command(KBD_CCMD_MOUSE_DISABLE);
+ /* kbd_write_cmd(AUX_INTS_OFF); */ /* Config & lock */
+ kb_wait();
+ kbd_write_command(KBD_CCMD_WRITE_MODE);
+ kb_wait();
+ kbd_write_output(AUX_INTS_OFF);
+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
+ }
+ }
X }
-#endif
+#endif


+ return 0;
X }
X

X
diff -u --recursive --new-file v2.4.14/linux/drivers/char/random.c linux/drivers/char/random.c
--- v2.4.14/linux/drivers/char/random.c Mon Nov 5 15:55:29 2001
+++ linux/drivers/char/random.c Fri Nov 9 14:01:21 2001
@@ -406,10 +406,6 @@
X *
X *****************************************************************/
X
-#ifndef MIN
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
X /*
X * Unfortunately, while the GCC optimizer for the i386 understands how
X * to optimize a static rotate left of x bits, it doesn't know how to
@@ -1360,7 +1356,7 @@
X #endif
X
X /* Copy data to destination buffer */
- i = MIN(nbytes, HASH_BUFFER_SIZE*sizeof(__u32)/2);
+ i = min(nbytes, HASH_BUFFER_SIZE*sizeof(__u32)/2);
X if (flags & EXTRACT_ENTROPY_USER) {
X i -= copy_to_user(buf, (__u8 const *)tmp, i);
X if (!i) {
@@ -1587,7 +1583,7 @@
X size_t c = count;
X
X while (c > 0) {
- bytes = MIN(c, sizeof(buf));
+ bytes = min(c, sizeof(buf));
X
X bytes -= copy_from_user(&buf, p, bytes);
X if (!bytes) {
diff -u --recursive --new-file v2.4.14/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
--- v2.4.14/linux/drivers/char/rtc.c Sun Sep 23 11:40:57 2001
+++ linux/drivers/char/rtc.c Tue Nov 13 09:16:05 2001
@@ -79,9 +79,11 @@
X #endif
X
X static unsigned long rtc_port;
-static int rtc_irq;
+static int rtc_irq = PCI_IRQ_NONE;
X #endif
X
+static int rtc_has_irq = 1;
+
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
@@ -198,6 +200,9 @@
X unsigned long data;
X ssize_t retval;
X
+ if (rtc_has_irq == 0)
+ return -EIO;
+
X if (count < sizeof(unsigned long))
X return -EINVAL;
X
@@ -244,6 +249,22 @@
X {
X struct rtc_time wtime;
X
+#if RTC_IRQ
+ if (rtc_has_irq == 0) {
+ switch (cmd) {
+ case RTC_AIE_OFF:
+ case RTC_AIE_ON:
+ case RTC_PIE_OFF:
+ case RTC_PIE_ON:
+ case RTC_UIE_OFF:
+ case RTC_UIE_ON:
+ case RTC_IRQP_READ:
+ case RTC_IRQP_SET:


+ return -EINVAL;
+ };
+ }

+#endif
+
X switch (cmd) {
X #if RTC_IRQ
X case RTC_AIE_OFF: /* Mask alarm int. enab. bit */
@@ -412,15 +433,18 @@
X yrs = 73;
X }
X #endif
+ /* These limits and adjustments are independant of
+ * whether the chip is in binary mode or not.
+ */
+ if (yrs > 169) {
+ spin_unlock_irq(&rtc_lock);
+ return -EINVAL;
+ }
+ if (yrs >= 100)
+ yrs -= 100;
+
X if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
X || RTC_ALWAYS_BCD) {
- if (yrs > 169) {
- spin_unlock_irq(&rtc_lock);
- return -EINVAL;
- }
- if (yrs >= 100)
- yrs -= 100;
-
X BIN_TO_BCD(sec);
X BIN_TO_BCD(min);
X BIN_TO_BCD(hrs);
@@ -550,13 +574,16 @@
X static int rtc_release(struct inode *inode, struct file *file)
X {
X #if RTC_IRQ
+ unsigned char tmp;
+
+ if (rtc_has_irq == 0)
+ goto no_irq;
+
X /*
X * Turn off all interrupts once the device is no longer
X * in use, and clear the data.
X */
X
- unsigned char tmp;
-
X spin_lock_irq(&rtc_lock);
X tmp = CMOS_READ(RTC_CONTROL);
X tmp &= ~RTC_PIE;
@@ -574,6 +601,7 @@
X if (file->f_flags & FASYNC) {
X rtc_fasync (-1, file, 0);
X }
+no_irq:
X #endif
X
X spin_lock_irq (&rtc_lock);
@@ -592,6 +620,9 @@
X {
X unsigned long l;
X
+ if (rtc_has_irq == 0)
+ return 0;
+
X poll_wait(file, &rtc_wait, wait);
X
X spin_lock_irq (&rtc_lock);
@@ -669,12 +700,17 @@
X return -EIO;
X
X found:
+ if (rtc_irq == PCI_IRQ_NONE) {
+ rtc_has_irq = 0;
+ goto no_irq;
+ }
+
X /*
X * XXX Interrupt pin #7 in Espresso is shared between RTC and
X * PCI Slot 2 INTA# (and some INTx# in Slot 1). SA_INTERRUPT here
X * is asking for trouble with add-on boards. Change to SA_SHIRQ.
X */
- if(request_irq(rtc_irq, rtc_interrupt, SA_INTERRUPT, "rtc", (void *)&rtc_port)) {
+ if (request_irq(rtc_irq, rtc_interrupt, SA_INTERRUPT, "rtc", (void *)&rtc_port)) {
X /*
X * Standard way for sparc to print irq's is to use
X * __irq_itoa(). I think for EBus it's ok to use %d.
@@ -682,6 +718,7 @@
X printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq);
X return -EIO;
X }
+no_irq:
X #else
X if (check_region (RTC_PORT (0), RTC_IO_EXTENT))
X {
@@ -712,8 +749,10 @@
X
X uip_watchdog = jiffies;
X if (rtc_is_updating() != 0)
- while (jiffies - uip_watchdog < 2*HZ/100)
+ while (jiffies - uip_watchdog < 2*HZ/100) {
X barrier();
+ cpu_relax();
+ }
X
X spin_lock_irq(&rtc_lock);
X year = CMOS_READ(RTC_YEAR);
@@ -766,11 +805,13 @@
X misc_deregister(&rtc_dev);
X
X #ifdef __sparc__
- free_irq (rtc_irq, &rtc_port);
+ if (rtc_has_irq)
+ free_irq (rtc_irq, &rtc_port);
X #else
X release_region (RTC_PORT (0), RTC_IO_EXTENT);
X #if RTC_IRQ
- free_irq (RTC_IRQ, NULL);
+ if (rtc_has_irq)
+ free_irq (RTC_IRQ, NULL);
X #endif
X #endif /* __sparc__ */
X }
@@ -946,8 +987,10 @@
X */
X
X if (rtc_is_updating() != 0)
- while (jiffies - uip_watchdog < 2*HZ/100)
+ while (jiffies - uip_watchdog < 2*HZ/100) {
X barrier();
+ cpu_relax();
+ }
X
X /*
X * Only the values that we read from the RTC are set. We leave
diff -u --recursive --new-file v2.4.14/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.4.14/linux/drivers/char/serial.c Mon Nov 5 15:55:29 2001
+++ linux/drivers/char/serial.c Fri Nov 9 14:12:55 2001
@@ -85,6 +85,11 @@
X * SERIAL_PARANOIA_CHECK
X * Check the magic number for the async_structure where
X * ever possible.
+ *
+ * CONFIG_SERIAL_ACPI
+ * Enable support for serial console port and serial
+ * debug port as defined by the SPCR and DBGP tables in
+ * ACPI 2.0.
X */
X
X #include <linux/config.h>
@@ -113,6 +118,10 @@
X #endif
X #endif
X
+#ifdef CONFIG_SERIAL_ACPI
+#define ENABLE_SERIAL_ACPI
+#endif
+
X #if defined(CONFIG_ISAPNP)|| (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE))
X #ifndef ENABLE_SERIAL_PNP
X #define ENABLE_SERIAL_PNP
@@ -1766,13 +1775,11 @@
X if (I_IGNPAR(info->tty))
X info->ignore_status_mask |= UART_LSR_OE;
X }
-#if 0 /* breaks serial console during boot stage */
X /*
X * !!! ignore all characters if CREAD is not set
X */
X if ((cflag & CREAD) == 0)
X info->ignore_status_mask |= UART_LSR_DR;
-#endif
X save_flags(flags); cli();
X if (uart_config[info->state->type].flags & UART_STARTECH) {
X serial_outp(info, UART_LCR, 0xBF);
@@ -2243,7 +2250,7 @@
X ((CIRC_CNT(info->xmit.head, info->xmit.tail,
X SERIAL_XMIT_SIZE) > 0) &&
X !info->tty->stopped && !info->tty->hw_stopped))
- result &= TIOCSER_TEMT;
+ result &= ~TIOCSER_TEMT;
X
X if (copy_to_user(value, &result, sizeof(int)))
X return -EFAULT;
@@ -2355,7 +2362,7 @@
X
X autoconfig(info->state);
X if ((info->state->flags & ASYNC_AUTO_IRQ) &&
- (info->state->port != 0) &&
+ (info->state->port != 0 || info->state->iomem_base != 0) &&
X (info->state->type != PORT_UNKNOWN)) {
X irq = detect_uart_irq(info->state);
X if (irq > 0)
@@ -3384,6 +3391,10 @@
X " ISAPNP"
X #define SERIAL_OPT
X #endif
+#ifdef ENABLE_SERIAL_ACPI
+ " SERIAL_ACPI"
+#define SERIAL_OPT
+#endif
X #ifdef SERIAL_OPT
X " enabled\n";
X #else
@@ -5475,13 +5486,22 @@
X continue;
X if ( (state->flags & ASYNC_BOOT_AUTOCONF)
X && (state->flags & ASYNC_AUTO_IRQ)
- && (state->port != 0))
+ && (state->port != 0 || state->iomem_base != 0))
X state->irq = detect_uart_irq(state);
- printk(KERN_INFO "ttyS%02d%s at 0x%04lx (irq = %d) is a %s\n",
- state->line + SERIAL_DEV_OFFSET,
- (state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
- state->port, state->irq,
- uart_config[state->type].name);
+ if (state->io_type == SERIAL_IO_MEM) {
+ printk(KERN_INFO"ttyS%02d%s at 0x%px (irq = %d) is a %s\n",
+ state->line + SERIAL_DEV_OFFSET,
+ (state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
+ state->iomem_base, state->irq,
+ uart_config[state->type].name);
+ }
+ else {
+ printk(KERN_INFO "ttyS%02d%s at 0x%04lx (irq = %d) is a %s\n",
+ state->line + SERIAL_DEV_OFFSET,
+ (state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
+ state->port, state->irq,
+ uart_config[state->type].name);
+ }
X tty_register_devfs(&serial_driver, 0,
X serial_driver.minor_start + state->line);
X tty_register_devfs(&callout_driver, 0,
diff -u --recursive --new-file v2.4.14/linux/drivers/char/serial_tx3912.c linux/drivers/char/serial_tx3912.c
--- v2.4.14/linux/drivers/char/serial_tx3912.c Sun Sep 23 11:40:57 2001
+++ linux/drivers/char/serial_tx3912.c Fri Nov 9 14:01:21 2001
@@ -20,7 +20,7 @@
X #include <linux/console.h>
X #include <linux/fs.h>
X #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
X #include <linux/module.h>
X #include <linux/delay.h>
X #include <linux/pm.h>
diff -u --recursive --new-file v2.4.14/linux/drivers/char/specialix.c linux/drivers/char/specialix.c
--- v2.4.14/linux/drivers/char/specialix.c Sun Sep 23 11:40:57 2001
+++ linux/drivers/char/specialix.c Fri Nov 9 14:01:21 2001
@@ -969,7 +969,10 @@
X if (bp->flags & SX_BOARD_ACTIVE)
X return 0;
X
- error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT, "specialix IO8+", bp);
+ if (bp->flags & SX_BOARD_IS_PCI)
+ error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT | SA_SHIRQ, "specialix IO8+", bp);
+ else
+ error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT, "specialix IO8+", bp);
X
X if (error)
X return error;
diff -u --recursive --new-file v2.4.14/linux/drivers/char/sx.c linux/drivers/char/sx.c
--- v2.4.14/linux/drivers/char/sx.c Sun Sep 23 11:40:57 2001
+++ linux/drivers/char/sx.c Fri Nov 9 14:01:21 2001
@@ -257,6 +257,11 @@
X #define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
X #endif
X
+static struct pci_device_id sx_pci_tbl[] = {
+ { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, PCI_ANY_ID, PCI_ANY_ID },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
X
X /* Configurable options:
X (Don't be too sure that it'll work if you toggle them) */
diff -u --recursive --new-file v2.4.14/linux/drivers/char/vt.c linux/drivers/char/vt.c
--- v2.4.14/linux/drivers/char/vt.c Mon Nov 5 15:55:30 2001
+++ linux/drivers/char/vt.c Fri Nov 16 10:08:28 2001
@@ -24,7 +24,6 @@
X #include <linux/major.h>
X #include <linux/fs.h>
X #include <linux/console.h>
-#include <linux/irq.h>
X
X #include <asm/io.h>
X #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.14/linux/drivers/hotplug/Config.in linux/drivers/hotplug/Config.in
--- v2.4.14/linux/drivers/hotplug/Config.in Wed Dec 31 16:00:00 1969
+++ linux/drivers/hotplug/Config.in Fri Nov 9 14:01:21 2001
@@ -0,0 +1,12 @@
+#
+# PCI Hotplug support
+#
+mainmenu_option next_comment
+comment 'PCI Hotplug Support'
+
+dep_tristate 'Support for PCI Hotplug (EXPERIMENTAL)' CONFIG_HOTPLUG_PCI $CONFIG_DDFS $CONFIG_EXPERIMENTAL
+
+dep_tristate ' Compaq PCI Hotplug driver' CONFIG_HOTPLUG_PCI_COMPAQ $CONFIG_HOTPLUG_PCI
+dep_mbool ' Save configuration into NVRAM on Compaq servers' CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM $CONFIG_HOTPLUG_PCI_COMPAQ
+
+endmenu
diff -u --recursive --new-file v2.4.14/linux/drivers/hotplug/Makefile linux/drivers/hotplug/Makefile
--- v2.4.14/linux/drivers/hotplug/Makefile Wed Dec 31 16:00:00 1969
+++ linux/drivers/hotplug/Makefile Fri Nov 9 14:01:21 2001
@@ -0,0 +1,34 @@
+#
+# Makefile for the Linux kernel pci hotplug controller drivers.
+#
+
+O_TARGET := vmlinux-obj.o
+
+list-multi := cpqphp.o pci_hotplug.o
+
+export-objs := pci_hotplug_core.o pci_hotplug_util.o
+
+obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o
+obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o
+
+pci_hotplug-objs := pci_hotplug_core.o \
+ pci_hotplug_util.o
+
+cpqphp-objs := cpqphp_core.o \
+ cpqphp_ctrl.o \
+ cpqphp_proc.o \
+ cpqphp_pci.o
+
+ifeq ($(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM),y)
+ cpqphp-objs += cpqphp_nvram.o
+endif
+
+
+include $(TOPDIR)/Rules.make
+
+pci_hotplug.o: $(pci_hotplug-objs)
+ $(LD) -r -o $@ $(pci_hotplug-objs)
+
+cpqphp.o: $(cpqphp-objs)
+ $(LD) -r -o $@ $(cpqphp-objs)
+
diff -u --recursive --new-file v2.4.14/linux/drivers/hotplug/cpqphp.h linux/drivers/hotplug/cpqphp.h
--- v2.4.14/linux/drivers/hotplug/cpqphp.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/hotplug/cpqphp.h Fri Nov 9 14:01:21 2001
@@ -0,0 +1,751 @@


+/*
+ * Compaq Hot Plug Controller Driver

+ *


+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (gr...@kroah.com)
+ * Copyright (c) 2001 IBM

+ *
+ * All rights reserved.
+ *

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


+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or (at

+ * your option) any later version.
+ *


+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or

+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.


+ *
+ * You should have received a copy of the GNU General Public License

+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gr...@kroah.com>
+ *
+ */

+#ifndef _CPQPHP_H
+#define _CPQPHP_H
+
+#include "pci_hotplug.h"
+#include <asm/io.h> /* for read? and write? functions */
+
+
+#if !defined(CONFIG_HOTPLUG_PCI_COMPAQ_MODULE)
+ #define MY_NAME "cpqphp.o"


+#else
+ #define MY_NAME THIS_MODULE->name
+#endif
+

+#define dbg(fmt, arg...) do { if (cpqhp_debug) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0)


+#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
+
+
+

+struct smbios_system_slot {
+ u8 type;
+ u8 length;
+ u16 handle;
+ u8 name_string_num;
+ u8 slot_type;
+ u8 slot_width;
+ u8 slot_current_usage;
+ u8 slot_length;
+ u16 slot_number;
+ u8 properties1;
+ u8 properties2;
+} __attribute__ ((packed));
+
+/* offsets to the smbios generic type based on the above structure layout */
+enum smbios_system_slot_offsets {
+ SMBIOS_SLOT_GENERIC_TYPE = offsetof(struct smbios_system_slot, type),
+ SMBIOS_SLOT_GENERIC_LENGTH = offsetof(struct smbios_system_slot, length),
+ SMBIOS_SLOT_GENERIC_HANDLE = offsetof(struct smbios_system_slot, handle),
+ SMBIOS_SLOT_NAME_STRING_NUM = offsetof(struct smbios_system_slot, name_string_num),
+ SMBIOS_SLOT_TYPE = offsetof(struct smbios_system_slot, slot_type),
+ SMBIOS_SLOT_WIDTH = offsetof(struct smbios_system_slot, slot_width),
+ SMBIOS_SLOT_CURRENT_USAGE = offsetof(struct smbios_system_slot, slot_current_usage),
+ SMBIOS_SLOT_LENGTH = offsetof(struct smbios_system_slot, slot_length),
+ SMBIOS_SLOT_NUMBER = offsetof(struct smbios_system_slot, slot_number),
+ SMBIOS_SLOT_PROPERTIES1 = offsetof(struct smbios_system_slot, properties1),
+ SMBIOS_SLOT_PROPERTIES2 = offsetof(struct smbios_system_slot, properties2),
+};
+
+struct smbios_generic {
+ u8 type;
+ u8 length;
+ u16 handle;
+} __attribute__ ((packed));
+
+/* offsets to the smbios generic type based on the above structure layout */
+enum smbios_generic_offsets {
+ SMBIOS_GENERIC_TYPE = offsetof(struct smbios_generic, type),
+ SMBIOS_GENERIC_LENGTH = offsetof(struct smbios_generic, length),
+ SMBIOS_GENERIC_HANDLE = offsetof(struct smbios_generic, handle),
+};
+
+struct smbios_entry_point {
+ char anchor[4];
+ u8 ep_checksum;
+ u8 ep_length;
+ u8 major_version;
+ u8 minor_version;
+ u16 max_size_entry;
+ u8 ep_rev;
+ u8 reserved[5];
+ char int_anchor[5];
+ u8 int_checksum;
+ u16 st_length;
+ u32 st_address;
+ u16 number_of_entrys;
+ u8 bcd_rev;
+} __attribute__ ((packed));
+
+/* offsets to the smbios entry point based on the above structure layout */
+enum smbios_entry_point_offsets {
+ ANCHOR = offsetof(struct smbios_entry_point, anchor[0]),
+ EP_CHECKSUM = offsetof(struct smbios_entry_point, ep_checksum),
+ EP_LENGTH = offsetof(struct smbios_entry_point, ep_length),
+ MAJOR_VERSION = offsetof(struct smbios_entry_point, major_version),
+ MINOR_VERSION = offsetof(struct smbios_entry_point, minor_version),
+ MAX_SIZE_ENTRY = offsetof(struct smbios_entry_point, max_size_entry),
+ EP_REV = offsetof(struct smbios_entry_point, ep_rev),
+ INT_ANCHOR = offsetof(struct smbios_entry_point, int_anchor[0]),
+ INT_CHECKSUM = offsetof(struct smbios_entry_point, int_checksum),
+ ST_LENGTH = offsetof(struct smbios_entry_point, st_length),
+ ST_ADDRESS = offsetof(struct smbios_entry_point, st_address),
+ NUMBER_OF_ENTRYS = offsetof(struct smbios_entry_point, number_of_entrys),
+ BCD_REV = offsetof(struct smbios_entry_point, bcd_rev),
+};
+
+struct ctrl_reg { /* offset */
+ u8 slot_RST; /* 0x00 */
+ u8 slot_enable; /* 0x01 */
+ u16 misc; /* 0x02 */
+ u32 led_control; /* 0x04 */
+ u32 int_input_clear; /* 0x08 */
+ u32 int_mask; /* 0x0a */
+ u8 reserved0; /* 0x10 */
+ u8 reserved1; /* 0x11 */
+ u8 reserved2; /* 0x12 */
+ u8 gen_output_AB; /* 0x13 */
+ u32 non_int_input; /* 0x14 */
+ u32 reserved3; /* 0x18 */
+ u32 reserved4; /* 0x1a */
+ u32 reserved5; /* 0x20 */
+ u8 reserved6; /* 0x24 */
+ u8 reserved7; /* 0x25 */
+ u16 reserved8; /* 0x26 */
+ u8 slot_mask; /* 0x28 */
+ u8 reserved9; /* 0x29 */
+ u8 reserved10; /* 0x2a */
+ u8 reserved11; /* 0x2b */
+ u8 slot_SERR; /* 0x2c */
+ u8 slot_power; /* 0x2d */
+} __attribute__ ((packed));
+
+/* offsets to the controller registers based on the above structure layout */
+enum ctrl_offsets {
+ SLOT_RST = offsetof(struct ctrl_reg, slot_RST),
+ SLOT_ENABLE = offsetof(struct ctrl_reg, slot_enable),
+ MISC = offsetof(struct ctrl_reg, misc),
+ LED_CONTROL = offsetof(struct ctrl_reg, led_control),
+ INT_INPUT_CLEAR = offsetof(struct ctrl_reg, int_input_clear),
+ INT_MASK = offsetof(struct ctrl_reg, int_mask),
+ CTRL_RESERVED0 = offsetof(struct ctrl_reg, reserved0),
+ CTRL_RESERVED1 = offsetof(struct ctrl_reg, reserved1),
+ CTRL_RESERVED2 = offsetof(struct ctrl_reg, reserved1),
+ GEN_OUTPUT_AB = offsetof(struct ctrl_reg, gen_output_AB),
+ NON_INT_INPUT = offsetof(struct ctrl_reg, non_int_input),
+ CTRL_RESERVED3 = offsetof(struct ctrl_reg, reserved3),
+ CTRL_RESERVED4 = offsetof(struct ctrl_reg, reserved4),
+ CTRL_RESERVED5 = offsetof(struct ctrl_reg, reserved5),
+ CTRL_RESERVED6 = offsetof(struct ctrl_reg, reserved6),
+ CTRL_RESERVED7 = offsetof(struct ctrl_reg, reserved7),
+ CTRL_RESERVED8 = offsetof(struct ctrl_reg, reserved8),
+ SLOT_MASK = offsetof(struct ctrl_reg, slot_mask),
+ CTRL_RESERVED9 = offsetof(struct ctrl_reg, reserved9),
+ CTRL_RESERVED10 = offsetof(struct ctrl_reg, reserved10),
+ CTRL_RESERVED11 = offsetof(struct ctrl_reg, reserved11),
+ SLOT_SERR = offsetof(struct ctrl_reg, slot_SERR),
+ SLOT_POWER = offsetof(struct ctrl_reg, slot_power),
+};
+
+struct hrt {
+ char sig0;
+ char sig1;
+ char sig2;
+ char sig3;
+ u16 unused_IRQ;
+ u16 PCIIRQ;
+ u8 number_of_entries;
+ u8 revision;
+ u16 reserved1;
+ u32 reserved2;
+} __attribute__ ((packed));
+
+/* offsets to the hotplug resource table registers based on the above structure layout */
+enum hrt_offsets {
+ SIG0 = offsetof(struct hrt, sig0),
+ SIG1 = offsetof(struct hrt, sig1),
+ SIG2 = offsetof(struct hrt, sig2),
+ SIG3 = offsetof(struct hrt, sig3),
+ UNUSED_IRQ = offsetof(struct hrt, unused_IRQ),
+ PCIIRQ = offsetof(struct hrt, PCIIRQ),
+ NUMBER_OF_ENTRIES = offsetof(struct hrt, number_of_entries),
+ REVISION = offsetof(struct hrt, revision),
+ HRT_RESERVED1 = offsetof(struct hrt, reserved1),
+ HRT_RESERVED2 = offsetof(struct hrt, reserved2),
+};
+
+struct slot_rt {
+ u8 dev_func;
+ u8 primary_bus;
+ u8 secondary_bus;
+ u8 max_bus;
+ u16 io_base;
+ u16 io_length;
+ u16 mem_base;
+ u16 mem_length;
+ u16 pre_mem_base;
+ u16 pre_mem_length;
+} __attribute__ ((packed));
+
+/* offsets to the hotplug slot resource table registers based on the above structure layout */
+enum slot_rt_offsets {
+ DEV_FUNC = offsetof(struct slot_rt, dev_func),
+ PRIMARY_BUS = offsetof(struct slot_rt, primary_bus),
+ SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus),
+ MAX_BUS = offsetof(struct slot_rt, max_bus),
+ IO_BASE = offsetof(struct slot_rt, io_base),
+ IO_LENGTH = offsetof(struct slot_rt, io_length),
+ MEM_BASE = offsetof(struct slot_rt, mem_base),
+ MEM_LENGTH = offsetof(struct slot_rt, mem_length),
+ PRE_MEM_BASE = offsetof(struct slot_rt, pre_mem_base),
+ PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length),
+};
+
+struct pci_func {
+ struct pci_func *next;


+ u8 bus;
+ u8 device;
+ u8 function;

+ u8 is_a_board;
+ u16 status;
+ u8 configured;
+ u8 switch_save;
+ u8 presence_save;
+ u32 base_length[0x06];
+ u8 base_type[0x06];
+ u16 reserved2;
+ u32 config_space[0x20];
+ struct pci_resource *mem_head;
+ struct pci_resource *p_mem_head;
+ struct pci_resource *io_head;
+ struct pci_resource *bus_head;
+ struct timer_list *p_task_event;
+ struct pci_dev* pci_dev;
+};
+
+#define SLOT_MAGIC 0x67267321
+struct slot {
+ u32 magic;
+ struct slot *next;


+ u8 bus;
+ u8 device;

+ u8 number;
+ u8 is_a_board;
+ u8 configured;
+ u8 state;
+ u8 switch_save;
+ u8 presence_save;
+ u32 capabilities;
+ u16 reserved2;
+ struct timer_list task_event;
+ u8 hp_slot;
+ struct controller *ctrl;
+ void *p_sm_slot;
+ struct hotplug_slot *hotplug_slot;
+};
+
+struct pci_resource {
+ struct pci_resource * next;
+ u32 base;
+ u32 length;
+};
+
+struct event_info {
+ u32 event_type;


+ u8 hp_slot;
+};
+

+struct controller {
+ struct controller *next;
+ u32 ctrl_int_comp;
+ struct semaphore crit_sect; /* critical section semaphore */
+ void *hpc_reg; /* cookie for our pci controller location */
+ struct pci_resource *mem_head;
+ struct pci_resource *p_mem_head;
+ struct pci_resource *io_head;
+ struct pci_resource *bus_head;
+ struct pci_dev *pci_dev;
+ struct pci_ops *pci_ops;
+ struct proc_dir_entry* proc_entry;
+ struct proc_dir_entry* proc_entry2;
+ struct event_info event_queue[10];
+ struct slot *slot;
+ u8 next_event;
+ u8 interrupt;


+ u8 bus;
+ u8 device;
+ u8 function;

+ u8 rev;
+ u8 slot_device_offset;
+ u8 first_slot;
+ u8 add_support;
+ u8 push_flag;
+ u8 speed; /* 0 = 33MHz, 1 = 66MHz */
+ u8 speed_capability; /* 0 = 33MHz, 1 = 66MHz */
+ u8 push_button; /* 0 = no pushbutton, 1 = pushbutton present */
+ u8 slot_switch_type; /* 0 = no switch, 1 = switch present */
+ u8 defeature_PHP; /* 0 = PHP not supported, 1 = PHP supported */
+ u8 alternate_base_address; /* 0 = not supported, 1 = supported */
+ u8 pci_config_space; /* Index/data access to working registers 0 = not supported, 1 = supported */
+ u8 pcix_speed_capability; /* PCI-X */
+ u8 pcix_support; /* PCI-X */
+ u16 vendor_id;
+ char proc_name[20];
+ char proc_name2[20];
+ struct tq_struct int_task_event;
+ wait_queue_head_t queue; /* sleep & wake process */
+};
+
+#define CTRL_SPEED_33MHz 0
+#define CTRL_SPEED_66MHz 1
+
+struct irq_mapping {
+ u8 barber_pole;
+ u8 valid_INT;
+ u8 interrupt[4];
+};
+
+struct resource_lists {
+ struct pci_resource *mem_head;
+ struct pci_resource *p_mem_head;
+ struct pci_resource *io_head;
+ struct pci_resource *bus_head;
+ struct irq_mapping *irqs;
+};
+
+#define ROM_PHY_ADDR 0x0F0000
+#define ROM_PHY_LEN 0x00ffff
+
+#define PCI_HPC_ID 0xA0F7
+#define PCI_SUB_HPC_ID 0xA2F7
+#define PCI_SUB_HPC_ID2 0xA2F8
+#define PCI_SUB_HPC_ID3 0xA2F9
+#define PCI_SUB_HPC_ID_INTC 0xA2FA
+
+#define INT_BUTTON_IGNORE 0
+#define INT_PRESENCE_ON 1
+#define INT_PRESENCE_OFF 2
+#define INT_SWITCH_CLOSE 3
+#define INT_SWITCH_OPEN 4
+#define INT_POWER_FAULT 5
+#define INT_POWER_FAULT_CLEAR 6
+#define INT_BUTTON_PRESS 7
+#define INT_BUTTON_RELEASE 8
+#define INT_BUTTON_CANCEL 9
+
+#define STATIC_STATE 0
+#define BLINKINGON_STATE 1
+#define BLINKINGOFF_STATE 2
+#define POWERON_STATE 3
+#define POWEROFF_STATE 4
+
+#define PCISLOT_INTERLOCK_CLOSED 0x00000001
+#define PCISLOT_ADAPTER_PRESENT 0x00000002
+#define PCISLOT_POWERED 0x00000004
+#define PCISLOT_66_MHZ_OPERATION 0x00000008
+#define PCISLOT_64_BIT_OPERATION 0x00000010
+#define PCISLOT_REPLACE_SUPPORTED 0x00000020
+#define PCISLOT_ADD_SUPPORTED 0x00000040
+#define PCISLOT_INTERLOCK_SUPPORTED 0x00000080
+#define PCISLOT_66_MHZ_SUPPORTED 0x00000100
+#define PCISLOT_64_BIT_SUPPORTED 0x00000200
+
+
+
+#define PCI_TO_PCI_BRIDGE_CLASS 0x00060400
+
+
+#define INTERLOCK_OPEN 0x00000002
+#define ADD_NOT_SUPPORTED 0x00000003
+#define CARD_FUNCTIONING 0x00000005
+#define ADAPTER_NOT_SAME 0x00000006
+#define NO_ADAPTER_PRESENT 0x00000009
+#define NOT_ENOUGH_RESOURCES 0x0000000B
+#define DEVICE_TYPE_NOT_SUPPORTED 0x0000000C
+#define POWER_FAILURE 0x0000000E
+
+#define REMOVE_NOT_SUPPORTED 0x00000003
+
+
+/*
+ * error Messages
+ */
+#define msg_initialization_err "Initialization failure, error=%d\n"
+#define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n"
+#define msg_HPC_non_compaq_or_intel "The PCI hot plug controller is not supported by this driver.\n"
+#define msg_HPC_not_supported "this system is not supported by this version of cpqphpd. Upgrade to a newer version of cpqphpd\n"
+#define msg_unable_to_save "unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n"
+#define msg_button_on "PCI slot #%d - powering on due to button press.\n"
+#define msg_button_off "PCI slot #%d - powering off due to button press.\n"
+#define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n"
+#define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n"
+
+
+/* Proc functions for the hotplug controller info */
+#ifdef CONFIG_PROC_FS
+extern int cpqhp_proc_init_ctrl (void);
+extern int cpqhp_proc_destroy_ctrl (void);
+extern int cpqhp_proc_create_ctrl (struct controller *ctrl);
+extern int cpqhp_proc_remove_ctrl (struct controller *ctrl);
+#else
+static inline int cpqhp_proc_init_ctrl (void)


+{
+ return 0;
+}

+static inline int cpqhp_proc_destroy_ctrl (void)


+{
+ return 0;
+}

+static inline int cpqhp_proc_create_ctrl (struct controller *ctrl)


+{
+ return 0;
+}

+static inline int cpqhp_proc_remove_ctrl (struct controller *ctrl)


+{
+ return 0;
+}

+#endif
+
+
+/* controller functions */
+extern void cpqhp_pushbutton_thread (unsigned long event_pointer);
+extern void cpqhp_ctrl_intr (int IRQ, struct controller *ctrl_input, struct pt_regs *regs);
+extern int cpqhp_find_available_resources (struct controller *ctrl, void *rom_start);
+extern int cpqhp_event_start_thread (void);
+extern void cpqhp_event_stop_thread (void);
+extern struct pci_func *cpqhp_slot_create (unsigned char busnumber);
+extern struct pci_func *cpqhp_slot_find (unsigned char bus, unsigned char device, unsigned char index);
+extern int cpqhp_process_SI (struct controller *ctrl, struct pci_func *func);
+extern int cpqhp_process_SS (struct controller *ctrl, struct pci_func *func);
+extern int cpqhp_hardware_test (struct controller *ctrl, int test_num);
+
+/* resource functions */
+extern int cpqhp_resource_sort_and_combine (struct pci_resource **head);
+
+/* pci functions */
+extern int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
+extern int cpqhp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot);
+extern int cpqhp_save_config (struct controller *ctrl, int busnumber, int is_hot_plug);
+extern int cpqhp_save_base_addr_length (struct controller *ctrl, struct pci_func * func);
+extern int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func);
+extern int cpqhp_configure_board (struct controller *ctrl, struct pci_func * func);
+extern int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot);
+extern int cpqhp_valid_replace (struct controller *ctrl, struct pci_func * func);
+extern void cpqhp_destroy_board_resources (struct pci_func * func);
+extern int cpqhp_return_board_resources (struct pci_func * func, struct resource_lists * resources);
+extern void cpqhp_destroy_resource_list (struct resource_lists * resources);
+extern int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func);
+extern int cpqhp_unconfigure_device (struct pci_func* func);
+
+
+/* Global variables */
+extern int cpqhp_debug;
+extern struct controller *cpqhp_ctrl_list;
+extern struct pci_func *cpqhp_slot_list[256];
+
+/* these can be gotten rid of, but for debugging they are purty */
+extern u8 cpqhp_nic_irq;
+extern u8 cpqhp_disk_irq;
+
+


+
+/* inline functions */
+
+

+/* Inline functions to check the sanity of a pointer that is passed to us */
+static inline int slot_paranoia_check (struct slot *slot, const char *function)
+{
+ if (!slot) {
+ dbg("%s - slot == NULL", function);
+ return -1;
+ }
+ if (slot->magic != SLOT_MAGIC) {
+ dbg("%s - bad magic number for slot", function);
+ return -1;
+ }
+ if (!slot->hotplug_slot) {
+ dbg("%s - slot->hotplug_slot == NULL!", function);
+ return -1;


+ }
+ return 0;
+}
+

+static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function)


+{
+ struct slot *slot;
+

+ if (!hotplug_slot) {
+ dbg("%s - hotplug_slot == NULL\n", function);


+ return NULL;
+ }
+

+ slot = (struct slot *)hotplug_slot->private;
+ if (slot_paranoia_check (slot, function))
+ return NULL;
+ return slot;
+}
+
+/*
+ * return_resource
+ *
+ * Puts node back in the resource list pointed to by head
+ *
+ */
+static inline void return_resource (struct pci_resource **head, struct pci_resource *node)
+{
+ if (!node || !head)
+ return;
+ node->next = *head;
+ *head = node;
+}
+
+static inline void set_SOGO (struct controller *ctrl)
+{
+ u16 misc;


+
+ misc = readw(ctrl->hpc_reg + MISC);

+ misc = (misc | 0x0001) & 0xFFFB;


+ writew(misc, ctrl->hpc_reg + MISC);

+}
+
+
+static inline void amber_LED_on (struct controller *ctrl, u8 slot)
+{
+ u32 led_control;
+
+ led_control = readl(ctrl->hpc_reg + LED_CONTROL);
+ led_control |= (0x01010000L << slot);
+ writel(led_control, ctrl->hpc_reg + LED_CONTROL);
+}
+
+
+static inline void amber_LED_off (struct controller *ctrl, u8 slot)
+{
+ u32 led_control;
+
+ led_control = readl(ctrl->hpc_reg + LED_CONTROL);
+ led_control &= ~(0x01010000L << slot);
+ writel(led_control, ctrl->hpc_reg + LED_CONTROL);
+}
+
+
+static inline int read_amber_LED (struct controller *ctrl, u8 slot)
+{
+ u32 led_control;
+
+ led_control = readl(ctrl->hpc_reg + LED_CONTROL);
+ led_control &= (0x01010000L << slot);
+
+ return led_control ? 1 : 0;
+}
+
+
+static inline void green_LED_on (struct controller *ctrl, u8 slot)
+{
+ u32 led_control;
+
+ led_control = readl(ctrl->hpc_reg + LED_CONTROL);
+ led_control |= 0x0101L << slot;
+ writel(led_control, ctrl->hpc_reg + LED_CONTROL);
+}
+
+static inline void green_LED_off (struct controller *ctrl, u8 slot)
+{
+ u32 led_control;
+
+ led_control = readl(ctrl->hpc_reg + LED_CONTROL);
+ led_control &= ~(0x0101L << slot);
+ writel(led_control, ctrl->hpc_reg + LED_CONTROL);
+}
+
+
+static inline void green_LED_blink (struct controller *ctrl, u8 slot)
+{
+ u32 led_control;
+
+ led_control = readl(ctrl->hpc_reg + LED_CONTROL);
+ led_control |= (0x0001L << slot);
+ writel(led_control, ctrl->hpc_reg + LED_CONTROL);
+}
+
+
+static inline void slot_disable (struct controller *ctrl, u8 slot)
+{
+ u8 slot_enable;
+
+ slot_enable = readb(ctrl->hpc_reg + SLOT_ENABLE);
+ slot_enable &= ~(0x01 << slot);
+ writeb(slot_enable, ctrl->hpc_reg + SLOT_ENABLE);
+}
+
+
+static inline void slot_enable (struct controller *ctrl, u8 slot)
+{
+ u8 slot_enable;
+
+ slot_enable = readb(ctrl->hpc_reg + SLOT_ENABLE);
+ slot_enable |= (0x01 << slot);
+ writeb(slot_enable, ctrl->hpc_reg + SLOT_ENABLE);
+}
+
+
+static inline u8 is_slot_enabled (struct controller *ctrl, u8 slot)
+{
+ u8 slot_enable;
+
+ slot_enable = readb(ctrl->hpc_reg + SLOT_ENABLE);
+ slot_enable &= (0x01 << slot);
+ return slot_enable ? 1 : 0;
+}
+
+
+static inline u8 read_slot_enable (struct controller *ctrl)
+{
+ return readb(ctrl->hpc_reg + SLOT_ENABLE);
+}
+
+
+static inline u8 get_controller_speed (struct controller *ctrl)
+{
+ u16 misc;


+
+ misc = readw(ctrl->hpc_reg + MISC);

+ return (misc & 0x0800) ? 1 : 0;
+}
+
+
+static inline void enable_slot_power (struct controller *ctrl, u8 slot)
+{
+ u8 slot_power;
+
+ slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
+ slot_power |= (0x01 << slot);
+ writeb(slot_power, ctrl->hpc_reg + SLOT_POWER);
+}
+
+static inline void disable_slot_power (struct controller *ctrl, u8 slot)
+{
+ u8 slot_power;
+
+ slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
+ slot_power &= ~(0x01 << slot);
+ writeb(slot_power, ctrl->hpc_reg + SLOT_POWER);
+}
+
+
+static inline int cpq_get_attention_status (struct controller *ctrl, struct slot *slot)
+{
+ u8 hp_slot;


+
+ if (slot == NULL)

+ return 1;
+
+ hp_slot = slot->device - ctrl->slot_device_offset;
+
+ return read_amber_LED (ctrl, hp_slot);
+}
+
+
+static inline int get_slot_enabled (struct controller *ctrl, struct slot *slot)
+{
+ u8 hp_slot;


+
+ if (slot == NULL)

+ return 1;
+
+ hp_slot = slot->device - ctrl->slot_device_offset;
+
+ return is_slot_enabled (ctrl, hp_slot);
+}
+
+
+static inline int cpq_get_latch_status (struct controller *ctrl, struct slot *slot)
+{
+ u32 status;
+ u8 hp_slot;
+


+ if (slot == NULL)

+ return 1;
+
+ hp_slot = slot->device - ctrl->slot_device_offset;
+ dbg(__FUNCTION__": slot->device = %d, ctrl->slot_device_offset = %d \n", slot->device, ctrl->slot_device_offset);
+
+ status = (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot));
+
+ return(status == 0) ? 1 : 0;
+}
+
+
+static inline int get_presence_status (struct controller *ctrl, struct slot *slot)
+{
+ int presence_save = 0;
+ u8 hp_slot;
+ u32 tempdword;


+
+ if (slot == NULL)

+ return 0;
+
+ hp_slot = slot->device - ctrl->slot_device_offset;
+


+ tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);

+ presence_save = (int) ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> hp_slot) & 0x02;
+
+ return presence_save;
+}
+
+#define SLOT_NAME_SIZE 10
+
+static inline void make_slot_name (char *buffer, int buffer_size, struct slot *slot)
+{
+ snprintf (buffer, buffer_size, "%d", slot->number);
+}
+
+
+static inline int wait_for_ctrl_irq (struct controller *ctrl)
+{
+ DECLARE_WAITQUEUE(wait, current);


+ int retval = 0;
+

+ dbg(__FUNCTION__" - start\n");
+ add_wait_queue(&ctrl->queue, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ /* Sleep for up to 1 second to wait for the LED to change. */
+ schedule_timeout(1*HZ);
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&ctrl->queue, &wait);
+ if (signal_pending(current))
+ retval = -EINTR;
+
+ dbg(__FUNCTION__" - end\n");


+ return retval;
+}
+

+#endif
+
diff -u --recursive --new-file v2.4.14/linux/drivers/hotplug/cpqphp_core.c linux/drivers/hotplug/cpqphp_core.c
--- v2.4.14/linux/drivers/hotplug/cpqphp_core.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/hotplug/cpqphp_core.c Fri Nov 9 14:01:21 2001
@@ -0,0 +1,1439 @@


+/*
+ * Compaq Hot Plug Controller Driver

+ *


+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (gr...@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.
+ *

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


+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or (at

+ * your option) any later version.
+ *


+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or

+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.


+ *
+ * You should have received a copy of the GNU General Public License

+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gr...@kroah.com>

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

+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include "cpqphp.h"
+#include "cpqphp_nvram.h"

+#include "../../arch/i386/kernel/pci-i386.h" /* horrible hack showing how processor dependant we are... */
+
+
+/* Global variables */
+int cpqhp_debug;
+struct controller *cpqhp_ctrl_list; /* = NULL */
+struct pci_func *cpqhp_slot_list[256];


+
+/* local variables */

+static void *smbios_table;
+static void *smbios_start;
+static void *cpqhp_rom_start;
+static u8 power_mode;
+static int debug;
+
+#define DRIVER_VERSION "0.9.6"
+#define DRIVER_AUTHOR "Dan Zink <dan....@compaq.com>, Greg Kroah-Hartman <gr...@kroah.com>"
+#define DRIVER_DESC "Compaq Hot Plug PCI Controller Driver"


+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+

+MODULE_PARM(power_mode, "b");
+MODULE_PARM_DESC(power_mode, "Power mode enabled or not");


+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+

+#define CPQHPC_MODULE_MINOR 208
+
+static int one_time_init (void);
+static int set_attention_status (struct hotplug_slot *slot, u8 value);
+static int process_SI (struct hotplug_slot *slot);
+static int process_SS (struct hotplug_slot *slot);
+static int hardware_test (struct hotplug_slot *slot, u32 value);
+static int get_power_status (struct hotplug_slot *slot, u8 *value);
+static int get_attention_status (struct hotplug_slot *slot, u8 *value);
+static int get_latch_status (struct hotplug_slot *slot, u8 *value);
+static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
+
+static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = {
+ owner: THIS_MODULE,
+ set_attention_status: set_attention_status,
+ enable_slot: process_SI,
+ disable_slot: process_SS,
+ hardware_test: hardware_test,
+ get_power_status: get_power_status,
+ get_attention_status: get_attention_status,
+ get_latch_status: get_latch_status,
+ get_adapter_status: get_adapter_status,
+};
+
+
+static inline int is_slot64bit (struct slot *slot)
+{
+ if (!slot || !slot->p_sm_slot)
+ return 0;
+
+ if (readb(slot->p_sm_slot + SMBIOS_SLOT_WIDTH) == 0x06)
+ return 1;


+
+ return 0;
+}
+

+static inline int is_slot66mhz (struct slot *slot)
+{
+ if (!slot || !slot->p_sm_slot)
+ return 0;
+
+ if (readb(slot->p_sm_slot + SMBIOS_SLOT_TYPE) == 0x0E)
+ return 1;


+
+ return 0;
+}
+

+/**
+ * detect_SMBIOS_pointer - find the system Management BIOS Table in the specified region of memory.
+ *
+ * @begin: begin pointer for region to be scanned.
+ * @end: end pointer for region to be scanned.
+ *
+ * Returns pointer to the head of the SMBIOS tables (or NULL)
+ *
+ */
+static void * detect_SMBIOS_pointer(void *begin, void *end)
+{
+ void *fp;
+ void *endp;
+ u8 temp1, temp2, temp3, temp4;
+ int status = 0;
+
+ endp = (end - sizeof(u32) + 1);
+
+ for (fp = begin; fp <= endp; fp += 16) {
+ temp1 = readb(fp);
+ temp2 = readb(fp+1);
+ temp3 = readb(fp+2);
+ temp4 = readb(fp+3);
+ if (temp1 == '_' &&
+ temp2 == 'S' &&
+ temp3 == 'M' &&
+ temp4 == '_') {
+ status = 1;
+ break;
+ }
+ }
+
+ if (!status)
+ fp = NULL;
+
+ dbg("Discovered SMBIOS Entry point at %p\n", fp);
+
+ return fp;
+}
+
+/**
+ * init_SERR - Initializes the per slot SERR generation.
+ *
+ * For unexpected switch opens
+ *
+ */
+static int init_SERR(struct controller * ctrl)
+{
+ u32 tempdword;
+ u32 number_of_slots;
+ u8 physical_slot;
+
+ if (!ctrl)
+ return 1;
+
+ tempdword = ctrl->first_slot;
+
+ number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
+ // Loop through slots
+ while (number_of_slots) {
+ physical_slot = tempdword;
+ writeb(0, ctrl->hpc_reg + SLOT_SERR);
+ tempdword++;
+ number_of_slots--;
+ }


+
+ return 0;
+}
+

+
+/* nice debugging output */
+static int pci_print_IRQ_route (void)
+{
+ struct irq_routing_table *routing_table;
+ int len;
+ int loop;
+
+ u8 tbus, tdevice, tslot;
+
+ routing_table = pcibios_get_irq_routing_table();
+ if (routing_table == NULL) {
+ err("No BIOS Routing Table??? Not good\n");


+ return -ENOMEM;
+ }
+

+ len = (routing_table->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
+ // Make sure I got at least one entry


+ if (len == 0) {

+ kfree(routing_table);


+ return -1;
+ }
+

+ dbg("bus dev func slot\n");
+
+ for (loop = 0; loop < len; ++loop) {
+ tbus = routing_table->slots[loop].bus;
+ tdevice = routing_table->slots[loop].devfn;
+ tslot = routing_table->slots[loop].slot;
+ dbg("%d %d %d %d\n", tbus, tdevice >> 3, tdevice & 0x7, tslot);
+
+ }
+ kfree(routing_table);


+ return 0;
+}
+

+
+/*
+ * get_subsequent_smbios_entry
+ *
+ * Gets the first entry if previous == NULL
+ * Otherwise, returns the next entry
+ * Uses global SMBIOS Table pointer
+ *
+ * @curr: %NULL or pointer to previously returned structure
+ *
+ * returns a pointer to an SMBIOS structure or NULL if none found
+ */
+static void * get_subsequent_smbios_entry(void *smbios_start, void *smbios_table, void *curr)
+{
+ u8 bail = 0;
+ u8 previous_byte = 1;
+ void *p_temp;
+ void *p_max;
+
+ if (!smbios_table || !curr)
+ return(NULL);
+
+ // set p_max to the end of the table
+ p_max = smbios_start + readw(smbios_table + ST_LENGTH);
+
+ p_temp = curr;
+ p_temp += readb(curr + SMBIOS_GENERIC_LENGTH);
+
+ while ((p_temp < p_max) && !bail) {
+ // Look for the double NULL terminator
+ // The first condition is the previous byte and the second is the curr
+ if (!previous_byte && !(readb(p_temp))) {
+ bail = 1;
+ }
+
+ previous_byte = readb(p_temp);
+ p_temp++;
+ }
+
+ if (p_temp < p_max) {
+ return p_temp;
+ } else {
+ return NULL;


+ }
+}
+
+
+/**

+ * get_SMBIOS_entry
+ *
+ * @type:SMBIOS structure type to be returned
+ * @previous: %NULL or pointer to previously returned structure
+ *
+ * Gets the first entry of the specified type if previous == NULL
+ * Otherwise, returns the next entry of the given type.
+ * Uses global SMBIOS Table pointer
+ * Uses get_subsequent_smbios_entry
+ *
+ * returns a pointer to an SMBIOS structure or %NULL if none found
+ */
+static void *get_SMBIOS_entry (void *smbios_start, void *smbios_table, u8 type, void * previous)
+{
+ if (!smbios_table)
+ return NULL;
+
+ if (!previous) {
+ previous = smbios_start;
+ } else {
+ previous = get_subsequent_smbios_entry(smbios_start, smbios_table, previous);
+ }
+
+ while (previous) {
+ if (readb(previous + SMBIOS_GENERIC_TYPE) != type) {
+ previous = get_subsequent_smbios_entry(smbios_start, smbios_table, previous);


+ } else {
+ break;
+ }
+ }
+

+ return previous;
+}
+
+
+static int ctrl_slot_setup (struct controller * ctrl, void *smbios_start, void *smbios_table)
+{
+ struct slot *new_slot;
+ u8 number_of_slots;
+ u8 slot_device;
+ u8 slot_number;
+ u8 ctrl_slot;
+ u32 tempdword;
+ void *slot_entry= NULL;
+ int result;
+
+ dbg(__FUNCTION__"\n");
+


+ tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
+

+ number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
+ slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
+ slot_number = ctrl->first_slot;
+
+ while (number_of_slots) {
+ new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL);
+ if (!new_slot)
+ return -ENOMEM;
+
+ memset(new_slot, 0, sizeof(struct slot));
+ new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL);
+ if (!new_slot->hotplug_slot) {
+ kfree (new_slot);
+ return -ENOMEM;
+ }
+ memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot));
+
+ new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+ if (!new_slot->hotplug_slot->info) {
+ kfree (new_slot->hotplug_slot);
+ kfree (new_slot);
+ return -ENOMEM;
+ }
+ memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info));
+ new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL);
+ if (!new_slot->hotplug_slot->name) {
+ kfree (new_slot->hotplug_slot->info);
+ kfree (new_slot->hotplug_slot);
+ kfree (new_slot);


+ return -ENOMEM;
+ }
+

+ new_slot->magic = SLOT_MAGIC;
+ new_slot->ctrl = ctrl;
+ new_slot->bus = ctrl->bus;
+ new_slot->device = slot_device;
+ new_slot->number = slot_number;
+ dbg("slot->number = %d\n",new_slot->number);
+
+ slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, slot_entry);
+
+ while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) != new_slot->number)) {
+ slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, slot_entry);
+ }
+
+ new_slot->p_sm_slot = slot_entry;
+
+ init_timer(&new_slot->task_event);
+ new_slot->task_event.expires = jiffies + 5 * HZ;
+ new_slot->task_event.function = cpqhp_pushbutton_thread;
+
+ //FIXME: these capabilities aren't used but if they are
+ // they need to be correctly implemented
+ new_slot->capabilities |= PCISLOT_REPLACE_SUPPORTED;
+ new_slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED;
+
+ if (is_slot64bit(new_slot))
+ new_slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
+ if (is_slot66mhz(new_slot))
+ new_slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;


+ if (ctrl->speed == 1)

+ new_slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
+
+ ctrl_slot = slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);
+
+ // Check presence
+ new_slot->capabilities |= ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;
+ // Check the switch state
+ new_slot->capabilities |= ((~tempdword & 0xFF) >> ctrl_slot) & 0x01;
+ // Check the slot enable
+ new_slot->capabilities |= ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
+
+ /* register this slot with the hotplug pci core */
+ new_slot->hotplug_slot->private = new_slot;
+ make_slot_name (new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);
+ new_slot->hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
+
+ new_slot->hotplug_slot->info->power_status = get_slot_enabled(ctrl, new_slot);
+ new_slot->hotplug_slot->info->attention_status = cpq_get_attention_status(ctrl, new_slot);
+ new_slot->hotplug_slot->info->latch_status = cpq_get_latch_status(ctrl, new_slot);
+ new_slot->hotplug_slot->info->adapter_status = get_presence_status(ctrl, new_slot);
+
+ dbg ("registering bus %d, dev %d, number %d, ctrl->slot_device_offset %d, slot %d\n",
+ new_slot->bus, new_slot->device, new_slot->number, ctrl->slot_device_offset, slot_number);
+ result = pci_hp_register (new_slot->hotplug_slot);
+ if (result) {
+ err ("pci_hp_register failed with error %d\n", result);


+ return result;
+ }
+

+ new_slot->next = ctrl->slot;
+ ctrl->slot = new_slot;
+
+ number_of_slots--;
+ slot_device++;
+ slot_number++;
+ }
+
+ return(0);
+}
+
+
+static int ctrl_slot_cleanup (struct controller * ctrl)
+{
+ struct slot *old_slot, *next_slot;
+
+ old_slot = ctrl->slot;
+ ctrl->slot = NULL;
+
+ while (old_slot) {
+ next_slot = old_slot->next;
+ pci_hp_deregister (old_slot->hotplug_slot);
+ kfree(old_slot->hotplug_slot);
+ kfree(old_slot);
+ old_slot = next_slot;
+ }
+
+ //Free IRQ associated with hot plug device
+ free_irq(ctrl->interrupt, ctrl);
+ //Unmap the memory
+ iounmap(ctrl->hpc_reg);
+ //Finally reclaim PCI mem
+ release_mem_region(pci_resource_start(ctrl->pci_dev, 0),
+ pci_resource_len(ctrl->pci_dev, 0));
+


+ return(0);
+}
+
+

+//============================================================================
+// function: get_slot_mapping
+//
+// Description: Attempts to determine a logical slot mapping for a PCI
+// device. Won't work for more than one PCI-PCI bridge
+// in a slot.
+//
+// Input: u8 bus_num - bus number of PCI device
+// u8 dev_num - device number of PCI device
+// u8 *slot - Pointer to u8 where slot number will
+// be returned
+//
+// Output: SUCCESS or FAILURE
+//=============================================================================
+static int get_slot_mapping (struct pci_ops *ops, u8 bus_num, u8 dev_num, u8 *slot)
+{
+ struct irq_routing_table *PCIIRQRoutingInfoLength;
+ u32 work;
+ long len;
+ long loop;
+
+ u8 tbus, tdevice, tslot, bridgeSlot;
+
+ dbg(__FUNCTION__" %p, %d, %d, %p\n", ops, bus_num, dev_num, slot);
+
+ bridgeSlot = 0xFF;
+
+ PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();
+
+ len = (PCIIRQRoutingInfoLength->size -
+ sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
+ // Make sure I got at least one entry


+ if (len == 0) {

+ if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength );


+ return -1;
+ }
+

+
+ for (loop = 0; loop < len; ++loop) {
+ tbus = PCIIRQRoutingInfoLength->slots[loop].bus;
+ tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn >> 3;
+ tslot = PCIIRQRoutingInfoLength->slots[loop].slot;
+
+ if ((tbus == bus_num) && (tdevice == dev_num)) {
+ *slot = tslot;
+
+ if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength );
+ return 0;
+ } else {
+ // Didn't get a match on the target PCI device. Check if the
+ // current IRQ table entry is a PCI-to-PCI bridge device. If so,
+ // and it's secondary bus matches the bus number for the target
+ // device, I need to save the bridge's slot number. If I can't
+ // find an entry for the target device, I will have to assume it's
+ // on the other side of the bridge, and assign it the bridge's slot.
+ pci_read_config_dword_nodev (ops, tbus, tdevice, 0, PCI_REVISION_ID, &work);
+
+ if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
+ pci_read_config_dword_nodev (ops, tbus, tdevice, 0, PCI_PRIMARY_BUS, &work);
+ // See if bridge's secondary bus matches target bus.
+ if (((work >> 8) & 0x000000FF) == (long) bus_num) {
+ bridgeSlot = tslot;


+ }
+ }
+ }
+
+ }
+
+

+ // If we got here, we didn't find an entry in the IRQ mapping table
+ // for the target PCI device. If we did determine that the target
+ // device is on the other side of a PCI-to-PCI bridge, return the
+ // slot number for the bridge.
+ if (bridgeSlot != 0xFF) {
+ *slot = bridgeSlot;
+ if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength );
+ return 0;
+ }
+ if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength );
+ // Couldn't find an entry in the routing table for this PCI device


+ return -1;
+}
+

+
+/**
+ * cpqhp_set_attention_status - Turns the Amber LED for a slot on or off
+ *
+ */
+static int cpqhp_set_attention_status (struct controller *ctrl, struct pci_func *func, u32 status)


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

echo 'End of part 041'
echo 'File patch-2.4.15 is continued in part 042'
echo "042" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:16 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part040

#!/bin/sh -x
# this is part 040 of a 115 - part archive


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

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

+ acpi_ser_p->signature[0],
+ acpi_ser_p->signature[1],
+ acpi_ser_p->signature[2],
+ acpi_ser_p->signature[3]);
+ printk(" length = %d\n", acpi_ser_p->length);
+ printk(" Rev = %d\n", acpi_ser_p->rev);
+ printk(" Interface type = %d\n", acpi_ser_p->intfc_type);
+ printk(" Base address = 0x%lX\n", iobase);
+ printk(" IRQ = %d\n", acpi_ser_p->irq);
+ printk(" Global System Int = %d\n", global_sys_irq);
+ printk(" Baud rate = ");
+ switch (acpi_ser_p->baud) {
+ case ACPI_SERIAL_BAUD_9600:
+ printk("9600\n");
+ break;
+
+ case ACPI_SERIAL_BAUD_19200:
+ printk("19200\n");
+ break;
+
+ case ACPI_SERIAL_BAUD_57600:
+ printk("57600\n");
+ break;
+
+ case ACPI_SERIAL_BAUD_115200:
+ printk("115200\n");


+ break;
+
+ default:

+ printk("Huh (%d)\n", acpi_ser_p->baud);
+ break;
+
+ }
+ if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_PCICONF_SPACE) {
+ printk(" PCI serial port:\n");
+ printk(" Bus %d, Device %d, Vendor ID 0x%x, Dev ID 0x%x\n",
+ acpi_ser_p->pci_bus, acpi_ser_p->pci_dev,
+ acpi_ser_p->pci_vendor_id, acpi_ser_p->pci_dev_id);
+ }
+#endif
+
+ /*
+ * Now build a serial_req structure to update the entry in
+ * rs_table for the headless console port.
+ */
+ switch (acpi_ser_p->intfc_type) {
+ case ACPI_SERIAL_INTFC_16550:
+ serial_req.type = PORT_16550;
+ serial_req.baud_base = BASE_BAUD;
+ break;
+
+ case ACPI_SERIAL_INTFC_16450:
+ serial_req.type = PORT_16450;
+ serial_req.baud_base = BASE_BAUD;


+ break;
+
+ default:

+ serial_req.type = PORT_UNKNOWN;
+ break;
+ }
+ if (strncmp(acpi_ser_p->signature, ACPI_SPCRT_SIGNATURE,
+ ACPI_SIG_LEN) == 0) {
+ serial_req.line = ACPI_SERIAL_CONSOLE_PORT;
+ }
+ else if (strncmp(acpi_ser_p->signature, ACPI_DBGPT_SIGNATURE,
+ ACPI_SIG_LEN) == 0) {
+ serial_req.line = ACPI_SERIAL_DEBUG_PORT;
+ }
+ /*
+ * Check if this is an I/O mapped address or a memory mapped address
+ */
+ if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_MEM_SPACE) {
+ serial_req.port = 0;
+ serial_req.port_high = 0;
+ serial_req.iomem_base = (void *)ioremap(iobase, 64);
+ serial_req.io_type = SERIAL_IO_MEM;
+ }
+ else if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_IO_SPACE) {
+ serial_req.port = (unsigned long) iobase & 0xffffffff;
+ serial_req.port_high = (unsigned long)(((u64)iobase) >> 32);
+ serial_req.iomem_base = NULL;
+ serial_req.io_type = SERIAL_IO_PORT;
+ }
+ else if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_PCICONF_SPACE) {
+ printk("WARNING: No support for PCI serial console\n");
+ return;
+ }
+
+ /*
+ * If the table does not have IRQ information, use 0 for IRQ.
+ * This will force rs_init() to probe for IRQ.
+ */
+ if (acpi_ser_p->length < 53) {
+ serial_req.irq = 0;
+ }
+ else {
+ serial_req.flags = ASYNC_SKIP_TEST | ASYNC_BOOT_AUTOCONF |
+ ASYNC_AUTO_IRQ;
+ if (acpi_ser_p->int_type &
+ (ACPI_SERIAL_INT_APIC | ACPI_SERIAL_INT_SAPIC)) {
+ serial_req.irq = global_sys_irq;
+ }
+ else if (acpi_ser_p->int_type & ACPI_SERIAL_INT_PCAT) {
+ serial_req.irq = acpi_ser_p->irq;


+ }
+ else {
+ /*

+ * IRQ type not being set would mean UART will
+ * run in polling mode. Do not probe for IRQ in
+ * that case.
+ */
+ serial_req.flags = ASYNC_SKIP_TEST|ASYNC_BOOT_AUTOCONF;
+ }
+ }
+
+ serial_req.xmit_fifo_size = serial_req.custom_divisor = 0;
+ serial_req.close_delay = serial_req.hub6 = serial_req.closing_wait = 0;
+ serial_req.iomem_reg_shift = 0;
+ if (early_serial_setup(&serial_req) < 0) {
+ printk("early_serial_setup() for ACPI serial console port failed\n");
+ return;
+ }
+
+#ifdef SERIAL_DEBUG_ACPI
+ printk("Leaving setup_serial_acpi()\n");
+#endif
+}
diff -u --recursive --new-file v2.4.14/linux/drivers/char/agp/agp.h linux/drivers/char/agp/agp.h
--- v2.4.14/linux/drivers/char/agp/agp.h Tue Oct 9 17:06:51 2001
+++ linux/drivers/char/agp/agp.h Fri Nov 9 14:01:21 2001
@@ -170,12 +170,27 @@
X #ifndef PCI_DEVICE_ID_INTEL_810_0
X #define PCI_DEVICE_ID_INTEL_810_0 0x7120
X #endif
+#ifndef PCI_DEVICE_ID_INTEL_830_M_0
+#define PCI_DEVICE_ID_INTEL_830_M_0 0x3575
+#endif
+#ifndef PCI_DEVICE_ID_INTEL_830_M_1
+#define PCI_DEVICE_ID_INTEL_830_M_1 0x3577
+#endif
+#ifndef PCI_DEVICE_ID_INTEL_820_0
+#define PCI_DEVICE_ID_INTEL_820_0 0x2500
+#endif
X #ifndef PCI_DEVICE_ID_INTEL_840_0
X #define PCI_DEVICE_ID_INTEL_840_0 0x1a21
X #endif
+#ifndef PCI_DEVICE_ID_INTEL_845_0
+#define PCI_DEVICE_ID_INTEL_845_0 0x1a30
+#endif
X #ifndef PCI_DEVICE_ID_INTEL_850_0
X #define PCI_DEVICE_ID_INTEL_850_0 0x2530
X #endif
+#ifndef PCI_DEVICE_ID_INTEL_860_0
+#define PCI_DEVICE_ID_INTEL_860_0 0x2532
+#endif
X #ifndef PCI_DEVICE_ID_INTEL_810_DC100_0
X #define PCI_DEVICE_ID_INTEL_810_DC100_0 0x7122
X #endif
@@ -200,12 +215,6 @@
X #ifndef PCI_DEVICE_ID_INTEL_815_1
X #define PCI_DEVICE_ID_INTEL_815_1 0x1132
X #endif
-#ifndef PCI_DEVICE_ID_INTEL_830_M_0
-#define PCI_DEVICE_ID_INTEL_830_M_0 0x3575
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_830_M_1
-#define PCI_DEVICE_ID_INTEL_830_M_1 0x3577
-#endif
X #ifndef PCI_DEVICE_ID_INTEL_82443GX_1
X #define PCI_DEVICE_ID_INTEL_82443GX_1 0x71a1
X #endif
@@ -251,14 +260,42 @@
X #define INTEL_NBXCFG 0x50
X #define INTEL_ERRSTS 0x91
X
+/* intel i830 registers */
+#define I830_GMCH_CTRL 0x52
+#define I830_GMCH_ENABLED 0x4
+#define I830_GMCH_MEM_MASK 0x1
+#define I830_GMCH_MEM_64M 0x1
+#define I830_GMCH_MEM_128M 0
+#define I830_GMCH_GMS_MASK 0x70
+#define I830_GMCH_GMS_DISABLED 0x00
+#define I830_GMCH_GMS_LOCAL 0x10
+#define I830_GMCH_GMS_STOLEN_512 0x20
+#define I830_GMCH_GMS_STOLEN_1024 0x30
+#define I830_GMCH_GMS_STOLEN_8192 0x40
+#define I830_RDRAM_CHANNEL_TYPE 0x03010
+#define I830_RDRAM_ND(x) (((x) & 0x20) >> 5)
+#define I830_RDRAM_DDT(x) (((x) & 0x18) >> 3)
+
+/* intel i820 registers */
+#define INTEL_I820_RDCR 0x51
+#define INTEL_I820_ERRSTS 0xc8
+
X /* intel i840 registers */
X #define INTEL_I840_MCHCFG 0x50
-#define INTEL_I840_ERRSTS 0xc8
+#define INTEL_I840_ERRSTS 0xc8
+
+/* intel i845 registers */
+#define INTEL_I845_AGPM 0x51
+#define INTEL_I845_ERRSTS 0xc8
X
X /* intel i850 registers */
X #define INTEL_I850_MCHCFG 0x50
X #define INTEL_I850_ERRSTS 0xc8
X
+/* intel i860 registers */
+#define INTEL_I860_MCHCFG 0x50
+#define INTEL_I860_ERRSTS 0xc8
+
X /* intel i810 registers */
X #define I810_GMADDR 0x10
X #define I810_MMADDR 0x14
@@ -277,21 +314,7 @@
X #define I810_DRAM_ROW_0 0x00000001
X #define I810_DRAM_ROW_0_SDRAM 0x00000001
X
-/* intel i830 registers */
-#define I830_GMCH_CTRL 0x52
-#define I830_GMCH_ENABLED 0x4
-#define I830_GMCH_MEM_MASK 0x1
-#define I830_GMCH_MEM_64M 0x1
-#define I830_GMCH_MEM_128M 0
-#define I830_GMCH_GMS_MASK 0x70
-#define I830_GMCH_GMS_DISABLED 0x00
-#define I830_GMCH_GMS_LOCAL 0x10
-#define I830_GMCH_GMS_STOLEN_512 0x20
-#define I830_GMCH_GMS_STOLEN_1024 0x30
-#define I830_GMCH_GMS_STOLEN_8192 0x40
-#define I830_RDRAM_CHANNEL_TYPE 0x03010
-#define I830_RDRAM_ND(x) (((x) & 0x20) >> 5)
-#define I830_RDRAM_DDT(x) (((x) & 0x18) >> 3)
+
X
X /* VIA register */
X #define VIA_APBASE 0x10
diff -u --recursive --new-file v2.4.14/linux/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c
--- v2.4.14/linux/drivers/char/agp/agpgart_be.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/char/agp/agpgart_be.c Fri Nov 16 10:11:22 2001
@@ -387,8 +387,8 @@
X /*
X * Driver routines - start
X * Currently this module supports the following chipsets:
- * i810, i815, 440lx, 440bx, 440gx, i840, i850, via vp3, via mvp3,
- * via kx133, via kt133, amd irongate, amd 761, amd 762, ALi M1541,
+ * i810, i815, 440lx, 440bx, 440gx, i830, i840, i845, i850, i860, via vp3,
+ * via mvp3, via kx133, via kt133, amd irongate, amd 761, amd 762, ALi M1541,
X * and generic support for the SiS chipsets.
X */
X
@@ -645,6 +645,7 @@
X
X static void agp_generic_resume(void)
X {
+ return;
X }
X
X static int agp_generic_free_gatt_table(void)
@@ -1398,6 +1399,10 @@
X }
X
X #endif /* CONFIG_AGP_I810 */
+
+ #ifdef CONFIG_AGP_INTEL
+
+#endif /* CONFIG_AGP_I810 */
X
X #ifdef CONFIG_AGP_INTEL
X
@@ -1422,12 +1427,45 @@


X return 0;
X }
X

+
+static int intel_8xx_fetch_size(void)
+{
+ int i;
+ u8 temp;
+ aper_size_info_8 *values;
+
+ pci_read_config_byte(agp_bridge.dev, INTEL_APSIZE, &temp);
+ values = A_SIZE_8(agp_bridge.aperture_sizes);
+
+ for (i = 0; i < agp_bridge.num_aperture_sizes; i++) {
+ if (temp == values[i].size_value) {
+ agp_bridge.previous_size =
+ agp_bridge.current_size = (void *) (values + i);
+ agp_bridge.aperture_size_idx = i;
+ return values[i].size;
+ }
+ }
+
+ return 0;
+}
+
X static void intel_tlbflush(agp_memory * mem)
X {
X pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x2200);
X pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x2280);
X }
X
+
+static void intel_8xx_tlbflush(agp_memory * mem)
+{
+ u32 temp;
+ pci_read_config_dword(agp_bridge.dev, INTEL_AGPCTRL, &temp);
+ pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, temp & ~(1 << 7));
+ pci_read_config_dword(agp_bridge.dev, INTEL_AGPCTRL, &temp);
+ pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, temp | (1 << 7));
+}
+
+
X static void intel_cleanup(void)
X {
X u16 temp;
@@ -1440,6 +1478,20 @@
X previous_size->size_value);
X }
X
+
+static void intel_8xx_cleanup(void)
+{
+ u16 temp;
+ aper_size_info_8 *previous_size;
+
+ previous_size = A_SIZE_8(agp_bridge.previous_size);
+ pci_read_config_word(agp_bridge.dev, INTEL_NBXCFG, &temp);
+ pci_write_config_word(agp_bridge.dev, INTEL_NBXCFG, temp & ~(1 << 9));
+ pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE,
+ previous_size->size_value);
+}
+
+
X static int intel_configure(void)
X {
X u32 temp;
@@ -1472,17 +1524,70 @@


X return 0;
X }
X

+static void intel_820_tlbflush(agp_memory * mem)


+{
+ return;
+}
+

+static void intel_820_cleanup(void)
+{
+ u8 temp;
+ aper_size_info_8 *previous_size;
+
+ previous_size = A_SIZE_8(agp_bridge.previous_size);
+ pci_read_config_byte(agp_bridge.dev, INTEL_I820_RDCR, &temp);
+ pci_write_config_byte(agp_bridge.dev, INTEL_I820_RDCR,
+ temp & ~(1 << 1));
+ pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE,
+ previous_size->size_value);
+}
+
+
+static int intel_820_configure(void)
+{
+ u32 temp;
+ u8 temp2;
+ aper_size_info_8 *current_size;
+
+ current_size = A_SIZE_8(agp_bridge.current_size);
+
+ /* aperture size */
+ pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE,
+ current_size->size_value);
+
+ /* address to map to */
+ pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp);
+ agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+
+ /* attbase - aperture base */
+ pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE,
+ agp_bridge.gatt_bus_addr);
+
+ /* agpctrl */
+ pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000);
+
+ /* global enable aperture access */
+ /* This flag is not accessed through MCHCFG register as in */
+ /* i850 chipset. */
+ pci_read_config_byte(agp_bridge.dev, INTEL_I820_RDCR, &temp2);
+ pci_write_config_byte(agp_bridge.dev, INTEL_I820_RDCR,
+ temp2 | (1 << 1));
+ /* clear any possible AGP-related error conditions */
+ pci_write_config_word(agp_bridge.dev, INTEL_I820_ERRSTS, 0x001c);

+ return 0;
+}
+

X static int intel_840_configure(void)
X {
X u32 temp;
X u16 temp2;
- aper_size_info_16 *current_size;
+ aper_size_info_8 *current_size;
X
- current_size = A_SIZE_16(agp_bridge.current_size);
+ current_size = A_SIZE_8(agp_bridge.current_size);
X
X /* aperture size */
X pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE,
- (char)current_size->size_value);
+ current_size->size_value);
X
X /* address to map to */
X pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp);
@@ -1504,17 +1609,49 @@


X return 0;
X }
X

+static int intel_845_configure(void)
+{
+ u32 temp;
+ u8 temp2;
+ aper_size_info_8 *current_size;
+
+ current_size = A_SIZE_8(agp_bridge.current_size);
+
+ /* aperture size */
+ pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE,
+ current_size->size_value);
+
+ /* address to map to */
+ pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp);
+ agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+
+ /* attbase - aperture base */
+ pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE,
+ agp_bridge.gatt_bus_addr);
+
+ /* agpctrl */
+ pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000);
+
+ /* agpm */
+ pci_read_config_byte(agp_bridge.dev, INTEL_I845_AGPM, &temp2);
+ pci_write_config_byte(agp_bridge.dev, INTEL_I845_AGPM,
+ temp2 | (1 << 1));
+ /* clear any possible error conditions */
+ pci_write_config_word(agp_bridge.dev, INTEL_I845_ERRSTS, 0x001c);

+ return 0;
+}
+

X static int intel_850_configure(void)
X {
X u32 temp;
X u16 temp2;
- aper_size_info_16 *current_size;
+ aper_size_info_8 *current_size;
X
- current_size = A_SIZE_16(agp_bridge.current_size);
+ current_size = A_SIZE_8(agp_bridge.current_size);
X
X /* aperture size */
X pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE,
- (char)current_size->size_value);
+ current_size->size_value);
X
X /* address to map to */
X pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp);
@@ -1536,6 +1673,38 @@


X return 0;
X }
X

+static int intel_860_configure(void)
+{
+ u32 temp;
+ u16 temp2;
+ aper_size_info_8 *current_size;
+
+ current_size = A_SIZE_8(agp_bridge.current_size);
+
+ /* aperture size */
+ pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE,
+ current_size->size_value);
+
+ /* address to map to */
+ pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp);
+ agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+
+ /* attbase - aperture base */
+ pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE,
+ agp_bridge.gatt_bus_addr);
+
+ /* agpctrl */
+ pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000);
+
+ /* mcgcfg */
+ pci_read_config_word(agp_bridge.dev, INTEL_I860_MCHCFG, &temp2);
+ pci_write_config_word(agp_bridge.dev, INTEL_I860_MCHCFG,
+ temp2 | (1 << 9));
+ /* clear any possible AGP-related error conditions */
+ pci_write_config_word(agp_bridge.dev, INTEL_I860_ERRSTS, 0xf700);


+ return 0;
+}
+

X static unsigned long intel_mask_memory(unsigned long addr, int type)
X {
X /* Memory type is ignored */
@@ -1554,6 +1723,17 @@
X {0x00000017, 0}
X };
X
+static aper_size_info_8 intel_8xx_sizes[7] =
+{
+ {256, 65536, 6, 0},
+ {128, 32768, 5, 32},
+ {64, 16384, 4, 48},
+ {32, 8192, 3, 56},
+ {16, 4096, 2, 60},
+ {8, 2048, 1, 62},
+ {4, 1024, 0, 63}
+};
+
X static aper_size_info_16 intel_generic_sizes[7] =
X {
X {256, 65536, 6, 0},
@@ -1598,19 +1778,84 @@
X (void) pdev; /* unused */
X }
X
+
+static int __init intel_820_setup (struct pci_dev *pdev)
+{
+ agp_bridge.masks = intel_generic_masks;
+ agp_bridge.num_of_masks = 1;
+ agp_bridge.aperture_sizes = (void *) intel_8xx_sizes;
+ agp_bridge.size_type = U8_APER_SIZE;
+ agp_bridge.num_aperture_sizes = 7;
+ agp_bridge.dev_private_data = NULL;
+ agp_bridge.needs_scratch_page = FALSE;
+ agp_bridge.configure = intel_820_configure;
+ agp_bridge.fetch_size = intel_8xx_fetch_size;
+ agp_bridge.cleanup = intel_cleanup;
+ agp_bridge.tlb_flush = intel_820_tlbflush;
+ agp_bridge.mask_memory = intel_mask_memory;
+ agp_bridge.agp_enable = agp_generic_agp_enable;
+ agp_bridge.cache_flush = global_cache_flush;
+ agp_bridge.create_gatt_table = agp_generic_create_gatt_table;
+ agp_bridge.free_gatt_table = agp_generic_free_gatt_table;
+ agp_bridge.insert_memory = agp_generic_insert_memory;
+ agp_bridge.remove_memory = agp_generic_remove_memory;
+ agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
+ agp_bridge.free_by_type = agp_generic_free_by_type;
+ agp_bridge.agp_alloc_page = agp_generic_alloc_page;
+ agp_bridge.agp_destroy_page = agp_generic_destroy_page;


+
+ return 0;
+

+ (void) pdev; /* unused */
+}
+
+
X static int __init intel_840_setup (struct pci_dev *pdev)
X {
X agp_bridge.masks = intel_generic_masks;
X agp_bridge.num_of_masks = 1;
- agp_bridge.aperture_sizes = (void *) intel_generic_sizes;
- agp_bridge.size_type = U16_APER_SIZE;
+ agp_bridge.aperture_sizes = (void *) intel_8xx_sizes;
+ agp_bridge.size_type = U8_APER_SIZE;
X agp_bridge.num_aperture_sizes = 7;
X agp_bridge.dev_private_data = NULL;
X agp_bridge.needs_scratch_page = FALSE;
X agp_bridge.configure = intel_840_configure;
- agp_bridge.fetch_size = intel_fetch_size;
- agp_bridge.cleanup = intel_cleanup;
- agp_bridge.tlb_flush = intel_tlbflush;
+ agp_bridge.fetch_size = intel_8xx_fetch_size;
+ agp_bridge.cleanup = intel_8xx_cleanup;
+ agp_bridge.tlb_flush = intel_8xx_tlbflush;
+ agp_bridge.mask_memory = intel_mask_memory;
+ agp_bridge.agp_enable = agp_generic_agp_enable;
+ agp_bridge.cache_flush = global_cache_flush;
+ agp_bridge.create_gatt_table = agp_generic_create_gatt_table;
+ agp_bridge.free_gatt_table = agp_generic_free_gatt_table;
+ agp_bridge.insert_memory = agp_generic_insert_memory;
+ agp_bridge.remove_memory = agp_generic_remove_memory;
+ agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
+ agp_bridge.free_by_type = agp_generic_free_by_type;
+ agp_bridge.agp_alloc_page = agp_generic_alloc_page;
+ agp_bridge.agp_destroy_page = agp_generic_destroy_page;
+ agp_bridge.suspend = agp_generic_suspend;
+ agp_bridge.resume = agp_generic_resume;
+ agp_bridge.cant_use_aperture = 0;


+
+ return 0;
+

+ (void) pdev; /* unused */
+}
+
+static int __init intel_845_setup (struct pci_dev *pdev)
+{
+ agp_bridge.masks = intel_generic_masks;
+ agp_bridge.num_of_masks = 1;
+ agp_bridge.aperture_sizes = (void *) intel_8xx_sizes;
+ agp_bridge.size_type = U8_APER_SIZE;
+ agp_bridge.num_aperture_sizes = 7;
+ agp_bridge.dev_private_data = NULL;
+ agp_bridge.needs_scratch_page = FALSE;
+ agp_bridge.configure = intel_845_configure;
+ agp_bridge.fetch_size = intel_8xx_fetch_size;
+ agp_bridge.cleanup = intel_8xx_cleanup;
+ agp_bridge.tlb_flush = intel_8xx_tlbflush;
X agp_bridge.mask_memory = intel_mask_memory;
X agp_bridge.agp_enable = agp_generic_agp_enable;
X agp_bridge.cache_flush = global_cache_flush;
@@ -1635,15 +1880,15 @@
X {
X agp_bridge.masks = intel_generic_masks;
X agp_bridge.num_of_masks = 1;
- agp_bridge.aperture_sizes = (void *) intel_generic_sizes;
- agp_bridge.size_type = U16_APER_SIZE;
+ agp_bridge.aperture_sizes = (void *) intel_8xx_sizes;
+ agp_bridge.size_type = U8_APER_SIZE;
X agp_bridge.num_aperture_sizes = 7;
X agp_bridge.dev_private_data = NULL;
X agp_bridge.needs_scratch_page = FALSE;
X agp_bridge.configure = intel_850_configure;
- agp_bridge.fetch_size = intel_fetch_size;
- agp_bridge.cleanup = intel_cleanup;
- agp_bridge.tlb_flush = intel_tlbflush;
+ agp_bridge.fetch_size = intel_8xx_fetch_size;
+ agp_bridge.cleanup = intel_8xx_cleanup;
+ agp_bridge.tlb_flush = intel_8xx_tlbflush;
X agp_bridge.mask_memory = intel_mask_memory;
X agp_bridge.agp_enable = agp_generic_agp_enable;
X agp_bridge.cache_flush = global_cache_flush;
@@ -1664,6 +1909,39 @@
X (void) pdev; /* unused */
X }
X
+static int __init intel_860_setup (struct pci_dev *pdev)
+{
+ agp_bridge.masks = intel_generic_masks;
+ agp_bridge.num_of_masks = 1;
+ agp_bridge.aperture_sizes = (void *) intel_8xx_sizes;
+ agp_bridge.size_type = U8_APER_SIZE;
+ agp_bridge.num_aperture_sizes = 7;
+ agp_bridge.dev_private_data = NULL;
+ agp_bridge.needs_scratch_page = FALSE;
+ agp_bridge.configure = intel_860_configure;
+ agp_bridge.fetch_size = intel_8xx_fetch_size;
+ agp_bridge.cleanup = intel_8xx_cleanup;
+ agp_bridge.tlb_flush = intel_8xx_tlbflush;
+ agp_bridge.mask_memory = intel_mask_memory;
+ agp_bridge.agp_enable = agp_generic_agp_enable;
+ agp_bridge.cache_flush = global_cache_flush;
+ agp_bridge.create_gatt_table = agp_generic_create_gatt_table;
+ agp_bridge.free_gatt_table = agp_generic_free_gatt_table;
+ agp_bridge.insert_memory = agp_generic_insert_memory;
+ agp_bridge.remove_memory = agp_generic_remove_memory;
+ agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
+ agp_bridge.free_by_type = agp_generic_free_by_type;
+ agp_bridge.agp_alloc_page = agp_generic_alloc_page;
+ agp_bridge.agp_destroy_page = agp_generic_destroy_page;
+ agp_bridge.suspend = agp_generic_suspend;
+ agp_bridge.resume = agp_generic_resume;
+ agp_bridge.cant_use_aperture = 0;


+
+ return 0;
+

+ (void) pdev; /* unused */
+}
+
X #endif /* CONFIG_AGP_INTEL */
X
X #ifdef CONFIG_AGP_VIA
@@ -3103,6 +3381,8 @@
X agp_bridge.free_by_type = agp_generic_free_by_type;
X agp_bridge.agp_alloc_page = agp_generic_alloc_page;
X agp_bridge.agp_destroy_page = agp_generic_destroy_page;
+ agp_bridge.suspend = agp_generic_suspend;
+ agp_bridge.resume = agp_generic_resume;
X agp_bridge.cant_use_aperture = 0;
X
X pci_read_config_dword(agp_bridge.dev,
@@ -3215,6 +3495,12 @@
X "AMD",
X "Irongate",
X amd_irongate_setup },
+ { PCI_DEVICE_ID_AMD_762_0,
+ PCI_VENDOR_ID_AMD,
+ AMD_IRONGATE,
+ "AMD",
+ "AMD 760MP",
+ amd_irongate_setup },
X { PCI_DEVICE_ID_AMD_761_0,
X PCI_VENDOR_ID_AMD,
X AMD_761,
@@ -3260,6 +3546,12 @@
X "Intel",
X "i815",
X intel_generic_setup },
+ { PCI_DEVICE_ID_INTEL_820_0,
+ PCI_VENDOR_ID_INTEL,
+ INTEL_I820,
+ "Intel",
+ "i820",
+ intel_820_setup },
X { PCI_DEVICE_ID_INTEL_830_M_0,
X PCI_VENDOR_ID_INTEL,
X INTEL_I830_M,
@@ -3272,12 +3564,24 @@
X "Intel",
X "i840",
X intel_840_setup },
+ { PCI_DEVICE_ID_INTEL_845_0,
+ PCI_VENDOR_ID_INTEL,
+ INTEL_I845,
+ "Intel",
+ "i845",
+ intel_845_setup },
X { PCI_DEVICE_ID_INTEL_850_0,
X PCI_VENDOR_ID_INTEL,
X INTEL_I850,
X "Intel",
X "i850",
X intel_850_setup },
+ { PCI_DEVICE_ID_INTEL_860_0,
+ PCI_VENDOR_ID_INTEL,
+ INTEL_I860,
+ "Intel",
+ "i860",
+ intel_860_setup },
X { 0,
X PCI_VENDOR_ID_INTEL,
X INTEL_GENERIC,
@@ -3288,6 +3592,36 @@
X #endif /* CONFIG_AGP_INTEL */
X
X #ifdef CONFIG_AGP_SIS
+ { PCI_DEVICE_ID_SI_740,
+ PCI_VENDOR_ID_SI,
+ SIS_GENERIC,
+ "SiS",
+ "740",
+ sis_generic_setup },
+ { PCI_DEVICE_ID_SI_650,
+ PCI_VENDOR_ID_SI,
+ SIS_GENERIC,
+ "SiS",
+ "650",
+ sis_generic_setup },
+ { PCI_DEVICE_ID_SI_645,
+ PCI_VENDOR_ID_SI,
+ SIS_GENERIC,
+ "SiS",
+ "645",
+ sis_generic_setup },
+ { PCI_DEVICE_ID_SI_735,
+ PCI_VENDOR_ID_SI,
+ SIS_GENERIC,
+ "SiS",
+ "735",
+ sis_generic_setup },
+ { PCI_DEVICE_ID_SI_730,
+ PCI_VENDOR_ID_SI,
+ SIS_GENERIC,
+ "SiS",
+ "730",
+ sis_generic_setup },
X { PCI_DEVICE_ID_SI_630,
X PCI_VENDOR_ID_SI,
X SIS_GENERIC,
@@ -3312,11 +3646,11 @@
X "SiS",
X "530",
X sis_generic_setup },
- { PCI_DEVICE_ID_SI_735,
+ { PCI_DEVICE_ID_SI_550,
X PCI_VENDOR_ID_SI,
X SIS_GENERIC,
X "SiS",
- "735",
+ "550",
X sis_generic_setup },
X { 0,
X PCI_VENDOR_ID_SI,
@@ -3530,13 +3864,13 @@
X PCI_DEVICE_ID_INTEL_815_1,
X NULL);
X if (i810_dev == NULL) {
- printk(KERN_ERR PFX "Detected an "
+ printk(KERN_ERR PFX "agpgart: Detected an "
X "Intel i815, but could not find the"
X " secondary device. Assuming a "
X "non-integrated video card.\n");
X break;
X }
- printk(KERN_INFO PFX "Detected an Intel i815 "
+ printk(KERN_INFO PFX "agpgart: Detected an Intel i815 "
X "Chipset.\n");
X agp_bridge.type = INTEL_I810;
X return intel_i810_setup(i810_dev);
diff -u --recursive --new-file v2.4.14/linux/drivers/char/drm/ati_pcigart.h linux/drivers/char/drm/ati_pcigart.h
--- v2.4.14/linux/drivers/char/drm/ati_pcigart.h Thu Oct 18 13:48:13 2001
+++ linux/drivers/char/drm/ati_pcigart.h Thu Nov 22 11:46:37 2001
@@ -36,7 +36,7 @@
X #elif PAGE_SIZE == 4096
X # define ATI_PCIGART_TABLE_ORDER 3
X # define ATI_PCIGART_TABLE_PAGES (1 << 3)
-#elif
+#else
X # error - PAGE_SIZE not 8K or 4K
X #endif
X

@@ -57,7 +57,7 @@
X

X page = virt_to_page( address );
X
- for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
+ for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
X atomic_inc( &page->count );
X SetPageReserved( page );
X }


@@ -74,7 +74,7 @@
X

X page = virt_to_page( address );
X
- for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
+ for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
X atomic_dec( &page->count );
X ClearPageReserved( page );
X }
diff -u --recursive --new-file v2.4.14/linux/drivers/char/drm/drm_agpsupport.h linux/drivers/char/drm/drm_agpsupport.h
--- v2.4.14/linux/drivers/char/drm/drm_agpsupport.h Thu Oct 18 13:48:13 2001
+++ linux/drivers/char/drm/drm_agpsupport.h Thu Nov 22 11:46:37 2001


@@ -273,7 +273,9 @@
X

X #if LINUX_VERSION_CODE >= 0x020400
X case INTEL_I815: head->chipset = "Intel i815"; break;
+ case INTEL_I820: head->chipset = "Intel i820"; break;
X case INTEL_I840: head->chipset = "Intel i840"; break;
+ case INTEL_I845: head->chipset = "Intel i845"; break;
X case INTEL_I850: head->chipset = "Intel i850"; break;
X #endif
X
diff -u --recursive --new-file v2.4.14/linux/drivers/char/drm/drm_vm.h linux/drivers/char/drm/drm_vm.h
--- v2.4.14/linux/drivers/char/drm/drm_vm.h Mon Nov 5 15:55:29 2001
+++ linux/drivers/char/drm/drm_vm.h Thu Nov 22 11:46:37 2001
@@ -423,7 +423,7 @@
X unlock_kernel();
X
X vma->vm_ops = &DRM(vm_dma_ops);
- vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
+ vma->vm_flags |= VM_RESERVED; /* Don't swap */
X
X #if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
X /* In Linux 2.2.3 and above, this is
@@ -558,7 +558,7 @@
X #endif
X /* Don't let this area swap. Change when
X DRM_KERNEL advisory is supported. */
- vma->vm_flags |= VM_LOCKED;
+ vma->vm_flags |= VM_RESERVED;
X break;
X case _DRM_SCATTER_GATHER:
X vma->vm_ops = &DRM(vm_sg_ops);
@@ -567,12 +567,12 @@
X #else
X vma->vm_pte = (unsigned long)map;
X #endif
- vma->vm_flags |= VM_LOCKED;
+ vma->vm_flags |= VM_RESERVED;
X break;
X default:
X return -EINVAL; /* This should never happen. */
X }
- vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
+ vma->vm_flags |= VM_RESERVED; /* Don't swap */
X
X #if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
X /* In Linux 2.2.3 and above, this is
diff -u --recursive --new-file v2.4.14/linux/drivers/char/esp.c linux/drivers/char/esp.c
--- v2.4.14/linux/drivers/char/esp.c Sun Sep 23 11:40:57 2001
+++ linux/drivers/char/esp.c Fri Nov 9 14:01:21 2001
@@ -2123,7 +2123,7 @@
X
X if (info->blocked_open) {
X if (info->close_delay) {


- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);

X schedule_timeout(info->close_delay);
X }
X wake_up_interruptible(&info->open_wait);
@@ -2156,7 +2156,7 @@
X
X while ((serial_in(info, UART_ESI_STAT1) != 0x03) ||
X (serial_in(info, UART_ESI_STAT2) != 0xff)) {


- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);

X schedule_timeout(char_time);
X
X if (signal_pending(current))
@@ -2170,7 +2170,7 @@
X }
X
X restore_flags(flags);


- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
X }

X
X /*
@@ -2203,6 +2203,7 @@
X DECLARE_WAITQUEUE(wait, current);
X int retval;
X int do_clocal = 0;
+ unsigned long flags;
X
X /*
X * If the device is in the middle of being closed, then block
@@ -2274,12 +2275,14 @@
X printk("block_til_ready before block: ttys%d, count = %d\n",
X info->line, info->count);
X #endif
+ save_flags(flags);
X cli();
X if (!tty_hung_up_p(filp))
X info->count--;
- sti();
+ restore_flags(flags);
X info->blocked_open++;
X while (1) {
+ save_flags(flags);
X cli();
X if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
X (tty->termios->c_cflag & CBAUD)) {
@@ -2293,7 +2296,7 @@
X serial_out(info, UART_ESI_CMD2,
X scratch | UART_MCR_DTR | UART_MCR_RTS);
X }
- sti();
+ restore_flags(flags);
X set_current_state(TASK_INTERRUPTIBLE);
X if (tty_hung_up_p(filp) ||
X !(info->flags & ASYNC_INITIALIZED)) {
@@ -2326,7 +2329,7 @@
X #endif


X schedule();
X }
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);

X remove_wait_queue(&info->open_wait, &wait);
X if (!tty_hung_up_p(filp))
X info->count++;
diff -u --recursive --new-file v2.4.14/linux/drivers/char/hp_keyb.c linux/drivers/char/hp_keyb.c
--- v2.4.14/linux/drivers/char/hp_keyb.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/hp_keyb.c Fri Nov 9 14:01:21 2001
@@ -0,0 +1,519 @@
+/*
+ * linux/drivers/char/hp_keyb.c
+ * helper-functions for the keyboard/psaux driver for HP-PARISC workstations
+ *
+ * based on pc_keyb.c by Geert Uytterhoeven & Martin Mares
+ *
+ * 2000/10/26 Debacker Xavier <deba...@esiee.fr>
+ * Marteau Thomas <mart...@esiee.fr>
+ * Djoudi Malek <djo...@esiee.fr>
+ * - fixed some keysym defines
+ *
+ * 2001/04/28 Debacker Xavier <deba...@esiee.fr>
+ * - scancode translation rewritten in handle_at_scancode()


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

+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/ptrace.h>
+#include <linux/signal.h>
+#include <linux/timer.h>
+#include <linux/random.h>
+#include <linux/ctype.h>
+#include <linux/kbd_ll.h>
+#include <linux/init.h>
+
+#include <asm/bitops.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#define KBD_REPORT_ERR
+#define KBD_REPORT_UNKN
+
+#define KBD_ESCAPEE0 0xe0 /* in */
+#define KBD_ESCAPEE1 0xe1 /* in */
+
+#define ESCE0(x) (0xe000|(x))
+#define ESCE1(x) (0xe100|(x))
+
+#define KBD_BAT 0xaa /* in */
+#define KBD_SETLEDS 0xed /* out */
+#define KBD_ECHO 0xee /* in/out */
+#define KBD_BREAK 0xf0 /* in */
+#define KBD_TYPRATEDLY 0xf3 /* out */
+#define KBD_SCANENABLE 0xf4 /* out */
+#define KBD_DEFDISABLE 0xf5 /* out */
+#define KBD_DEFAULT 0xf6 /* out */
+#define KBD_ACK 0xfa /* in */
+#define KBD_DIAGFAIL 0xfd /* in */
+#define KBD_RESEND 0xfe /* in/out */
+#define KBD_RESET 0xff /* out */
+
+#define CODE_BREAK 1
+#define CODE_ESCAPEE0 2
+#define CODE_ESCAPEE1 4
+#define CODE_ESCAPE12 8
+
+#define K_NONE 0x7f
+#define K_ESC 0x01
+#define K_F1 0x3b
+#define K_F2 0x3c
+#define K_F3 0x3d
+#define K_F4 0x3e
+#define K_F5 0x3f
+#define K_F6 0x40
+#define K_F7 0x41
+#define K_F8 0x42
+#define K_F9 0x43
+#define K_F10 0x44
+#define K_F11 0x57
+#define K_F12 0x58
+#define K_PRNT 0x54
+#define K_SCRL 0x46
+#define K_BRK 0x77
+#define K_AGR 0x29
+#define K_1 0x02
+#define K_2 0x03
+#define K_3 0x04
+#define K_4 0x05
+#define K_5 0x06
+#define K_6 0x07
+#define K_7 0x08
+#define K_8 0x09
+#define K_9 0x0a
+#define K_0 0x0b
+#define K_MINS 0x0c
+#define K_EQLS 0x0d
+#define K_BKSP 0x0e
+#define K_INS 0x6e
+#define K_HOME 0x66
+#define K_PGUP 0x68
+#define K_NUML 0x45
+#define KP_SLH 0x62
+#define KP_STR 0x37
+#define KP_MNS 0x4a
+#define K_TAB 0x0f
+#define K_Q 0x10
+#define K_W 0x11
+#define K_E 0x12
+#define K_R 0x13
+#define K_T 0x14
+#define K_Y 0x15
+#define K_U 0x16
+#define K_I 0x17
+#define K_O 0x18
+#define K_P 0x19
+#define K_LSBK 0x1a
+#define K_RSBK 0x1b
+#define K_ENTR 0x1c
+#define K_DEL 111
+#define K_END 0x6b
+#define K_PGDN 0x6d
+#define KP_7 0x47
+#define KP_8 0x48
+#define KP_9 0x49
+#define KP_PLS 0x4e
+#define K_CAPS 0x3a
+#define K_A 0x1e
+#define K_S 0x1f
+#define K_D 0x20
+#define K_F 0x21
+#define K_G 0x22
+#define K_H 0x23
+#define K_J 0x24
+#define K_K 0x25
+#define K_L 0x26
+#define K_SEMI 0x27
+#define K_SQOT 0x28
+#define K_HASH K_NONE
+#define KP_4 0x4b
+#define KP_5 0x4c
+#define KP_6 0x4d
+#define K_LSFT 0x2a
+#define K_BSLH 0x2b
+#define K_Z 0x2c
+#define K_X 0x2d
+#define K_C 0x2e
+#define K_V 0x2f
+#define K_B 0x30
+#define K_N 0x31
+#define K_M 0x32
+#define K_COMA 0x33
+#define K_DOT 0x34
+#define K_FSLH 0x35
+#define K_RSFT 0x36
+#define K_UP 0x67
+#define KP_1 0x4f
+#define KP_2 0x50
+#define KP_3 0x51
+#define KP_ENT 0x60
+#define K_LCTL 0x1d
+#define K_LALT 0x38
+#define K_SPCE 0x39
+#define K_RALT 0x64
+#define K_RCTL 0x61
+#define K_LEFT 0x69
+#define K_DOWN 0x6c
+#define K_RGHT 0x6a
+#define KP_0 0x52
+#define KP_DOT 0x53
+
+static unsigned char keycode_translate[256] =
+{
+/* 00 */ K_NONE, K_F9 , K_NONE, K_F5 , K_F3 , K_F1 , K_F2 , K_F12 ,
+/* 08 */ K_NONE, K_F10 , K_F8 , K_F6 , K_F4 , K_TAB , K_AGR , K_NONE,
+/* 10 */ K_NONE, K_LALT, K_LSFT, K_NONE, K_LCTL, K_Q , K_1 , K_NONE,
+/* 18 */ K_NONE, K_NONE, K_Z , K_S , K_A , K_W , K_2 , K_NONE,
+/* 20 */ K_NONE, K_C , K_X , K_D , K_E , K_4 , K_3 , K_NONE,
+/* 28 */ K_NONE, K_SPCE, K_V , K_F , K_T , K_R , K_5 , K_NONE,
+/* 30 */ K_NONE, K_N , K_B , K_H , K_G , K_Y , K_6 , K_NONE,
+/* 38 */ K_NONE, K_NONE, K_M , K_J , K_U , K_7 , K_8 , K_NONE,
+/* 40 */ K_NONE, K_COMA, K_K , K_I , K_O , K_0 , K_9 , K_NONE,
+/* 48 */ K_NONE, K_DOT , K_FSLH, K_L , K_SEMI, K_P , K_MINS, K_NONE,
+/* 50 */ K_NONE, K_NONE, K_SQOT, K_NONE, K_LSBK, K_EQLS, K_NONE, K_NONE,
+/* 58 */ K_CAPS, K_RSFT, K_ENTR, K_RSBK, K_NONE, K_BSLH, K_NONE, K_NONE,
+/* 60 */ K_NONE, K_HASH, K_NONE, K_NONE, K_NONE, K_NONE, K_BKSP, K_NONE,
+/* 68 */ K_NONE, KP_1 , K_NONE, KP_4 , KP_7 , K_NONE, K_NONE, K_NONE,
+/* 70 */ KP_0 , KP_DOT, KP_2 , KP_5 , KP_6 , KP_8 , K_ESC , K_NUML,
+/* 78 */ K_F11 , KP_PLS, KP_3 , KP_MNS, KP_STR, KP_9 , K_SCRL, K_PRNT,
+/* 80 */ K_NONE, K_NONE, K_NONE, K_F7 , K_NONE, K_NONE, K_NONE, K_NONE,
+/* 88 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* 90 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* 98 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* a0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* a8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* b0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* b8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* c0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* c8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* d0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* d8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* e0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* e8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* f0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* f8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, KBD_RESEND, K_NONE
+};
+
+/* ----- the following code stolen from pc_keyb.c */
+
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char hp_ps2kbd_sysrq_xlate[128] =
+ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
+ "\r\000/"; /* 0x60 - 0x6f */
+#endif
+
+/*
+ * Translation of escaped scancodes to keycodes.
+ * This is now user-settable.
+ * The keycodes 1-88,96-111,119 are fairly standard, and
+ * should probably not be changed - changing might confuse X.
+ * X also interprets scancode 0x5d (KEY_Begin).
+ *
+ * For 1-88 keycode equals scancode.
+ */
+
+#define E0_KPENTER 96
+#define E0_RCTRL 97
+#define E0_KPSLASH 98
+#define E0_PRSCR 99
+#define E0_RALT 100
+#define E0_BREAK 101 /* (control-pause) */
+#define E0_HOME 102
+#define E0_UP 103
+#define E0_PGUP 104
+#define E0_LEFT 105
+#define E0_RIGHT 106
+#define E0_END 107
+#define E0_DOWN 108
+#define E0_PGDN 109
+#define E0_INS 110
+#define E0_DEL 111
+
+#define E1_PAUSE 119
+
+/*
+ * The keycodes below are randomly located in 89-95,112-118,120-127.
+ * They could be thrown away (and all occurrences below replaced by 0),
+ * but that would force many users to use the `setkeycodes' utility, where
+ * they needed not before. It does not matter that there are duplicates, as
+ * long as no duplication occurs for any single keyboard.
+ */
+#define SC_LIM 89 /* 0x59 == 89 */
+
+#define FOCUS_PF1 85 /* actual code! */
+#define FOCUS_PF2 89
+#define FOCUS_PF3 90
+#define FOCUS_PF4 91
+#define FOCUS_PF5 92
+#define FOCUS_PF6 93
+#define FOCUS_PF7 94
+#define FOCUS_PF8 95
+#define FOCUS_PF9 120
+#define FOCUS_PF10 121
+#define FOCUS_PF11 122
+#define FOCUS_PF12 123
+
+#define JAP_86 124
+/* t...@olivia.ping.dk:
+ * The four keys are located over the numeric keypad, and are
+ * labelled A1-A4. It's an rc930 keyboard, from
+ * Regnecentralen/RC International, Now ICL.
+ * Scancodes: 59, 5a, 5b, 5c.
+ */
+#define RGN1 124
+#define RGN2 125
+#define RGN3 126
+#define RGN4 127
+
+static unsigned char high_keys[128 - SC_LIM] = {
+ RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
+ 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */
+ 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */
+ FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */
+ FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */
+};
+
+/* BTC */
+#define E0_MACRO 112
+/* LK450 */
+#define E0_F13 113
+#define E0_F14 114
+#define E0_HELP 115
+#define E0_DO 116
+#define E0_F17 117
+#define E0_KPMINPLUS 118
+/*
+ * My OmniKey generates e0 4c for the "OMNI" key and the
+ * right alt key does nada. [kko...@nyx10.cs.du.edu]
+ */
+#define E0_OK 124
+/*
+ * New microsoft keyboard is rumoured to have
+ * e0 5b (left window button), e0 5c (right window button),
+ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
+ * [or: Windows_L, Windows_R, TaskMan]
+ */
+#define E0_MSLW 125
+#define E0_MSRW 126
+#define E0_MSTM 127
+
+static unsigned char e0_keys[128] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
+ 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
+ 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
+ E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
+ E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
+ E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
+ E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
+ 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
+ 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
+ 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
+};
+
+int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
+{
+ if (scancode < SC_LIM || scancode > 255 || keycode > 127)
+ return -EINVAL;
+ if (scancode < 128)
+ high_keys[scancode - SC_LIM] = keycode;
+ else
+ e0_keys[scancode - 128] = keycode;


+ return 0;
+}
+

+int pckbd_getkeycode(unsigned int scancode)
+{
+ return
+ (scancode < SC_LIM || scancode > 255) ? -EINVAL :
+ (scancode < 128) ? high_keys[scancode - SC_LIM] :
+ e0_keys[scancode - 128];
+}
+
+int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode)
+{
+ static int prev_scancode;
+
+ /* special prefix scancodes.. */
+ if (scancode == 0xe0 || scancode == 0xe1) {
+ prev_scancode = scancode;


+ return 0;
+ }
+

+ /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
+ if (scancode == 0x00 || scancode == 0xff) {
+ prev_scancode = 0;
+ return 0;
+ }
+ scancode &= 0x7f;
+
+ if (prev_scancode) {
+ /*
+ * usually it will be 0xe0, but a Pause key generates
+ * e1 1d 45 e1 9d c5 when pressed, and nothing when released
+ */
+ if (prev_scancode != 0xe0) {
+ if (prev_scancode == 0xe1 && scancode == 0x1d) {
+ prev_scancode = 0x100;
+ return 0;
+ } else if (prev_scancode == 0x100 && scancode == 0x45) {
+ *keycode = E1_PAUSE;
+ prev_scancode = 0;
+ } else {
+#ifdef KBD_REPORT_UNKN
+ if (!raw_mode)
+ printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
+#endif
+ prev_scancode = 0;
+ return 0;
+ }
+ } else {
+ prev_scancode = 0;
+ /*
+ * The keyboard maintains its own internal caps lock and
+ * num lock statuses. In caps lock mode E0 AA precedes make
+ * code and E0 2A follows break code. In num lock mode,
+ * E0 2A precedes make code and E0 AA follows break code.
+ * We do our own book-keeping, so we will just ignore these.
+ */
+ /*
+ * For my keyboard there is no caps lock mode, but there are
+ * both Shift-L and Shift-R modes. The former mode generates
+ * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
+ * So, we should also ignore the latter. - a...@cwi.nl
+ */
+ if (scancode == 0x2a || scancode == 0x36)
+ return 0;
+
+ if (e0_keys[scancode])
+ *keycode = e0_keys[scancode];
+ else {
+#ifdef KBD_REPORT_UNKN
+ if (!raw_mode)
+ printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
+ scancode);
+#endif


+ return 0;
+ }
+ }

+ } else if (scancode >= SC_LIM) {
+ /* This happens with the FOCUS 9000 keyboard
+ Its keys PF1..PF12 are reported to generate
+ 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
+ Moreover, unless repeated, they do not generate
+ key-down events, so we have to zero up_flag below */
+ /* Also, Japanese 86/106 keyboards are reported to
+ generate 0x73 and 0x7d for \ - and \ | respectively. */
+ /* Also, some Brazilian keyboard is reported to produce
+ 0x73 and 0x7e for \ ? and KP-dot, respectively. */
+
+ *keycode = high_keys[scancode - SC_LIM];
+
+ if (!*keycode) {
+ if (!raw_mode) {
+#ifdef KBD_REPORT_UNKN
+ printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
+ " - ignored\n", scancode);
+#endif


+ }
+ return 0;
+ }

+ } else
+ *keycode = scancode;
+

+ return 1;
+}
+

+/* ----- end of stolen part ------ */
+
+
+void kbd_reset_setup(void)
+{
+}
+
+void handle_at_scancode(int keyval)
+{
+ static int brk;
+ static int esc0;
+ static int esc1;
+ int scancode = 0;
+
+ switch (keyval) {
+ case KBD_BREAK :
+ /* sets the "release_key" bit when a key is
+ released. HP keyboard send f0 followed by
+ the keycode while AT keyboard send the keycode
+ with this bit set. */
+ brk = 0x80;
+ return;
+ case KBD_ESCAPEE0 :
+ /* 2chars sequence, commonly used to differenciate
+ the two ALT keys and the two ENTER keys and so
+ on... */
+ esc0 = 2; /* e0-xx are 2 chars */
+ scancode = keyval;
+ break;
+ case KBD_ESCAPEE1 :
+ /* 3chars sequence, only used by the Pause key. */
+ esc1 = 3; /* e1-xx-xx are 3 chars */
+ scancode = keyval;
+ break;
+#if 0
+ case KBD_RESEND :
+ /* dunno what to do when it happens. RFC */
+ printk(KERN_INFO "keyboard: KBD_RESEND received.\n");
+ return;
+#endif
+ case 0x14 :
+ /* translate e1-14-77-e1-f0-14-f0-77 to
+ e1-1d-45-e1-9d-c5 (the Pause key) */
+ if (esc1==2) scancode = brk | 0x1d;
+ break;
+ case 0x77 :
+ if (esc1==1) scancode = brk | 0x45;
+ break;
+ case 0x12 :
+ /* an extended key is e0-12-e0-xx e0-f0-xx-e0-f0-12
+ on HP, while it is e0-2a-e0-xx e0-(xx|80)-f0-aa
+ on AT. */
+ if (esc0==1) scancode = brk | 0x2a;


+ break;
+ }
+
+

+ /* translates HP scancodes to AT scancodes */
+ if (!scancode) scancode = brk | keycode_translate[keyval];
+
+
+ if (!scancode) printk(KERN_INFO "keyboard: unexpected key code %02x\n",keyval);
+
+ /* now behave like an AT keyboard */
+ handle_scancode(scancode,!(scancode&0x80));
+
+ if (esc0) esc0--;
+ if (esc1) esc1--;
+
+ /* release key bit must be unset for the next key */
+ brk = 0;
+}
+
diff -u --recursive --new-file v2.4.14/linux/drivers/char/hp_psaux.c linux/drivers/char/hp_psaux.c
--- v2.4.14/linux/drivers/char/hp_psaux.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/hp_psaux.c Fri Nov 9 14:01:21 2001
@@ -0,0 +1,551 @@
+/*
+ * LASI PS/2 keyboard/psaux driver for HP-PARISC workstations
+ *
+ * (c) Copyright 1999 The Puffin Group Inc.
+ * by Alex deVries <adev...@thepuffingroup.com>
+ * Copyright 1999, 2000 Philipp Rumpf <pru...@tux.org>
+ *
+ * 2000/10/26 Debacker Xavier (deba...@esiee.fr)
+ * Marteau Thomas (mart...@esiee.fr)
+ * Djoudi Malek (djo...@esiee.fr)
+ * fixed leds control
+ * implemented the psaux and controlled the mouse scancode based on pc_keyb.c


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

+#include <asm/hardware.h>
+#include <asm/keyboard.h>
+#include <asm/gsc.h>
+
+#include <linux/types.h>
+#include <linux/ptrace.h> /* interrupt.h wants struct pt_regs defined */
+#include <linux/interrupt.h>
+#include <linux/sched.h> /* for request_irq/free_irq */
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/pc_keyb.h>
+#include <linux/kbd_kern.h>
+
+/* mouse includes */
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+#include <linux/poll.h>
+
+/* HP specific LASI PS/2 keyboard and psaux constants */
+#define AUX_REPLY_ACK 0xFA /* Command byte ACK. */
+#define AUX_RECONNECT 0xAA /* scancode when ps2 device is plugged (back) in */
+
+#define LASI_PSAUX_OFFSET 0x0100 /* offset from keyboard to psaux port */
+
+#define LASI_ID 0x00 /* ID and reset port offsets */
+#define LASI_RESET 0x00
+#define LASI_RCVDATA 0x04 /* receive and transmit port offsets */
+#define LASI_XMTDATA 0x04
+#define LASI_CONTROL 0x08 /* see: control register bits */
+#define LASI_STATUS 0x0C /* see: status register bits */
+
+/* control register bits */
+#define LASI_CTRL_ENBL 0x01 /* enable interface */
+#define LASI_CTRL_LPBXR 0x02 /* loopback operation */
+#define LASI_CTRL_DIAG 0x20 /* directly control clock/data line */
+#define LASI_CTRL_DATDIR 0x40 /* data line direct control */
+#define LASI_CTRL_CLKDIR 0x80 /* clock line direct control */
+
+/* status register bits */
+#define LASI_STAT_RBNE 0x01
+#define LASI_STAT_TBNE 0x02
+#define LASI_STAT_TERR 0x04
+#define LASI_STAT_PERR 0x08
+#define LASI_STAT_CMPINTR 0x10
+#define LASI_STAT_DATSHD 0x40
+#define LASI_STAT_CLKSHD 0x80
+
+static void *lasikbd_hpa;
+static void *lasips2_hpa;
+
+
+static inline u8 read_input(void *hpa)
+{
+ return gsc_readb(hpa+LASI_RCVDATA);
+}
+
+static inline u8 read_control(void *hpa)
+{
+ return gsc_readb(hpa+LASI_CONTROL);
+}
+
+static inline void write_control(u8 val, void *hpa)
+{
+ gsc_writeb(val, hpa+LASI_CONTROL);
+}
+
+static inline u8 read_status(void *hpa)
+{
+ return gsc_readb(hpa+LASI_STATUS);
+}
+
+static int write_output(u8 val, void *hpa)
+{
+ int wait = 0;
+
+ while (read_status(hpa) & LASI_STAT_TBNE) {
+ wait++;
+ if (wait>10000) {
+ /* printk(KERN_WARNING "Lasi PS/2 transmit buffer timeout\n"); */


+ return 0;
+ }
+ }
+

+ if (wait)
+ printk(KERN_DEBUG "Lasi PS/2 wait %d\n", wait);
+
+ gsc_writeb(val, hpa+LASI_XMTDATA);
+


+ return 1;
+}
+

+/* This function is the PA-RISC adaptation of i386 source */
+
+static inline int aux_write_ack(u8 val)
+{
+ return write_output(val, lasikbd_hpa+LASI_PSAUX_OFFSET);
+}
+
+static void lasikbd_leds(unsigned char leds)
+{
+ write_output(KBD_CMD_SET_LEDS, lasikbd_hpa);
+ write_output(leds, lasikbd_hpa);
+ write_output(KBD_CMD_ENABLE, lasikbd_hpa);
+}
+
+#if 0
+/* this might become useful again at some point. not now -prumpf */
+int lasi_ps2_test(void *hpa)
+{
+ u8 control,c;
+ int i, ret = 0;
+
+ control = read_control(hpa);
+ write_control(control | LASI_CTRL_LPBXR | LASI_CTRL_ENBL, hpa);
+
+ for (i=0; i<256; i++) {
+ write_output(i, hpa);
+
+ while (!(read_status(hpa) & LASI_STAT_RBNE))
+ /* just wait */;
+
+ c = read_input(hpa);
+ if (c != i)
+ ret--;
+ }
+
+ write_control(control, hpa);


+
+ return ret;
+}

+#endif
+
+static int __init lasi_ps2_reset(void *hpa, int id)
+{
+ u8 control;
+ int ret = 1;
+
+ /* reset the interface */
+ gsc_writeb(0xff, hpa+LASI_RESET);
+ gsc_writeb(0x0 , hpa+LASI_RESET);
+
+ /* enable it */
+ control = read_control(hpa);
+ write_control(control | LASI_CTRL_ENBL, hpa);
+
+ /* initializes the leds at the default state */
+ if (id==0) {
+ write_output(KBD_CMD_SET_LEDS, hpa);
+ write_output(0, hpa);
+ ret = write_output(KBD_CMD_ENABLE, hpa);


+ }
+
+ return ret;
+}

+
+static int inited;
+
+static void lasi_ps2_init_hw(void)
+{
+ ++inited;
+}
+
+
+/* Greatly inspired by pc_keyb.c */
+
+/*
+ * Wait for keyboard controller input buffer to drain.
+ *
+ * Don't use 'jiffies' so that we don't depend on
+ * interrupts..
+ *
+ * Quote from PS/2 System Reference Manual:
+ *
+ * "Address hex 0060 and address hex 0064 should be written only when
+ * the input-buffer-full bit and output-buffer-full bit in the
+ * Controller Status register are set 0."
+ */
+#ifdef CONFIG_PSMOUSE
+
+static struct aux_queue *queue;
+static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
+static unsigned char mouse_reply_expected;
+static int aux_count;
+
+static int fasync_aux(int fd, struct file *filp, int on)


+{
+ int retval;
+

+ retval = fasync_helper(fd, filp, on, &queue->fasync);
+ if (retval < 0)
+ return retval;
+

+ return 0;
+}
+
+
+

+static inline void handle_mouse_scancode(unsigned char scancode)
+{
+ if (mouse_reply_expected) {
+ if (scancode == AUX_REPLY_ACK) {
+ mouse_reply_expected--;
+ return;
+ }
+ mouse_reply_expected = 0;
+ }
+ else if (scancode == AUX_RECONNECT) {
+ queue->head = queue->tail = 0; /* Flush input queue */
+ return;
+ }
+
+ add_mouse_randomness(scancode);
+ if (aux_count) {
+ int head = queue->head;
+
+ queue->buf[head] = scancode;
+ head = (head + 1) & (AUX_BUF_SIZE-1);
+
+ if (head != queue->tail) {
+ queue->head = head;
+ kill_fasync(&queue->fasync, SIGIO, POLL_IN);
+ wake_up_interruptible(&queue->proc_list);
+ }
+ }
+}
+
+static inline int queue_empty(void)
+{
+ return queue->head == queue->tail;
+}
+
+static unsigned char get_from_queue(void)
+{
+ unsigned char result;


+ unsigned long flags;
+

+ spin_lock_irqsave(&kbd_controller_lock, flags);
+ result = queue->buf[queue->tail];
+ queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
+


+ return result;
+}
+
+

+/*
+ * Write to the aux device.
+ */
+
+static ssize_t write_aux(struct file * file, const char * buffer,
+ size_t count, loff_t *ppos)
+{
+ ssize_t retval = 0;
+
+ if (count) {
+ ssize_t written = 0;
+
+ if (count > 32)
+ count = 32; /* Limit to 32 bytes. */
+ do {
+ char c;
+ get_user(c, buffer++);
+ written++;
+ } while (--count);
+ retval = -EIO;
+ if (written) {
+ retval = written;
+ file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
+ }
+ }
+
+ return retval;
+}
+
+
+
+static ssize_t read_aux(struct file * file, char * buffer,
+ size_t count, loff_t *ppos)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ ssize_t i = count;
+ unsigned char c;
+
+ if (queue_empty()) {
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ add_wait_queue(&queue->proc_list, &wait);
+repeat:
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (queue_empty() && !signal_pending(current)) {
+ schedule();
+ goto repeat;
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&queue->proc_list, &wait);
+ }
+ while (i > 0 && !queue_empty()) {
+ c = get_from_queue();
+ put_user(c, buffer++);
+ i--;
+ }
+ if (count-i) {
+ file->f_dentry->d_inode->i_atime = CURRENT_TIME;
+ return count-i;
+ }
+ if (signal_pending(current))
+ return -ERESTARTSYS;


+ return 0;
+}
+
+

+static int open_aux(struct inode * inode, struct file * file)
+{
+ if (aux_count++)
+ return 0;
+
+ queue->head = queue->tail = 0; /* Flush input queue */
+ aux_count = 1;
+ aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */


+
+ return 0;
+}
+
+

+/* No kernel lock held - fine */
+static unsigned int aux_poll(struct file *file, poll_table * wait)
+{
+
+ poll_wait(file, &queue->proc_list, wait);
+ if (!queue_empty())
+ return POLLIN | POLLRDNORM;


+ return 0;
+}
+
+

+static int release_aux(struct inode * inode, struct file * file)
+{
+ lock_kernel();
+ fasync_aux(-1, file, 0);
+ if (--aux_count) {
+ unlock_kernel();
+ return 0;
+ }
+ unlock_kernel();


+ return 0;
+}
+

+static struct file_operations psaux_fops = {
+ read: read_aux,
+ write: write_aux,
+ poll: aux_poll,
+ open: open_aux,
+ release: release_aux,
+ fasync: fasync_aux,
+};
+
+static struct miscdevice psaux_mouse = {
+ minor: PSMOUSE_MINOR,
+ name: "psaux",
+ fops: &psaux_fops,
+};
+
+#endif /* CONFIG_PSMOUSE */
+
+
+/* This function is looking at the PS2 controller and empty the two buffers */
+
+static u8 handle_lasikbd_event(void *hpa)
+{
+ u8 status_keyb,status_mouse,scancode,id;
+ extern void handle_at_scancode(int); /* in drivers/char/keyb_at.c */
+
+ /* Mask to get the base address of the PS/2 controller */
+ id = gsc_readb(hpa+LASI_ID) & 0x0f;
+
+ if (id==1)
+ hpa -= LASI_PSAUX_OFFSET;
+ lasikbd_hpa = hpa;
+
+
+ status_keyb = read_status(hpa);
+ status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);
+
+ while ((status_keyb|status_mouse) & LASI_STAT_RBNE){
+
+ while (status_keyb & LASI_STAT_RBNE) {
+
+ scancode = read_input(hpa);
+
+ /* XXX don't know if this is a valid fix, but filtering
+ * 0xfa avoids 'unknown scancode' errors on, eg, capslock
+ * on some keyboards.
+ */
+ if (inited && scancode != 0xfa)
+ handle_at_scancode(scancode);
+
+ status_keyb =read_status(hpa);
+ }
+
+#ifdef CONFIG_PSMOUSE
+ while (status_mouse & LASI_STAT_RBNE) {
+ scancode = read_input(hpa+LASI_PSAUX_OFFSET);
+ handle_mouse_scancode(scancode);
+ status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);
+ }
+ status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);
+#endif /* CONFIG_PSMOUSE */
+ status_keyb = read_status(hpa);
+ }
+
+ tasklet_schedule(&keyboard_tasklet);
+ return (status_keyb|status_mouse);


+}
+
+
+
+

+extern struct pt_regs *kbd_pt_regs;
+
+static void lasikbd_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+ lasips2_hpa = dev; /* save "hpa" for lasikbd_leds() */
+ kbd_pt_regs = regs;
+ handle_lasikbd_event(lasips2_hpa);
+}
+
+
+extern int pckbd_translate(unsigned char, unsigned char *, char);
+
+static struct kbd_ops gsc_ps2_kbd_ops = {
+ translate: pckbd_translate,
+ init_hw: lasi_ps2_init_hw,
+ leds: lasikbd_leds,
+#ifdef CONFIG_MAGIC_SYSRQ
+ sysrq_key: 0x54,
+ sysrq_xlate: hp_ps2kbd_sysrq_xlate,
+#endif


+};
+
+static int __init

+lasi_ps2_register(struct hp_device *d, struct pa_iodc_driver *dri)
+{
+ void *hpa = (void *) d->hpa;
+ unsigned int irq;
+ char *name;
+ int device_found;
+ u8 id;
+
+ id = gsc_readb(hpa+LASI_ID) & 0x0f;
+
+ switch (id) {
+ case 0:
+ name = "keyboard";
+ lasikbd_hpa = hpa;


+ break;
+ case 1:

+ name = "psaux";
+ break;
+ default:
+ printk(KERN_WARNING "%s: Unknown PS/2 port (id=%d) - ignored.\n",
+ __FUNCTION__, id );


+ return 0;
+ }
+

+ /* reset the PS/2 port */
+ device_found = lasi_ps2_reset(hpa,id);
+
+ /* allocate the irq and memory region for that device */
+ if (!(irq = busdevice_alloc_irq(d)))
+ return -ENODEV;
+
+ if (request_irq(irq, lasikbd_interrupt, 0, name, hpa))
+ return -ENODEV;
+
+ if (!request_mem_region((unsigned long)hpa, LASI_STATUS + 4, name))
+ return -ENODEV;
+
+ switch (id) {
+ case 0:
+ register_kbd_ops(&gsc_ps2_kbd_ops);


+ break;
+ case 1:

+#ifdef CONFIG_PSMOUSE
+ queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
+ if (!queue)
+ return -ENOMEM;
+
+ memset(queue, 0, sizeof(*queue));
+ queue->head = queue->tail = 0;
+ init_waitqueue_head(&queue->proc_list);
+
+ misc_register(&psaux_mouse);
+
+ aux_write_ack(AUX_ENABLE_DEV);
+ /* try it a second time, this will give status if the device is
+ * available */
+ device_found = aux_write_ack(AUX_ENABLE_DEV);
+ break;
+#else
+ /* return without printing any unnecessary and misleading info */
+ return 0;
+#endif
+ } /* of case */
+
+ printk(KERN_INFO "PS/2 %s controller at 0x%08lx (irq %d) found, "
+ "%sdevice attached.\n",
+ name, (unsigned long)hpa, irq,
+ device_found ? "":"no ");


+
+ return 0;
+}
+
+

+static struct pa_iodc_driver lasi_psaux_drivers_for[] __initdata = {
+ {HPHW_FIO, 0x0, 0,0x00084, 0, 0,
+ DRIVER_CHECK_HWTYPE + DRIVER_CHECK_SVERSION,
+ "Lasi psaux", "generic", (void *) lasi_ps2_register},
+ { 0, }
+};
+
+static int __init gsc_ps2_init(void)
+{
+ return pdc_register_driver(lasi_psaux_drivers_for);
+}
+
+module_init(gsc_ps2_init);
+
diff -u --recursive --new-file v2.4.14/linux/drivers/char/isicom.c linux/drivers/char/isicom.c
--- v2.4.14/linux/drivers/char/isicom.c Sun Sep 23 11:40:57 2001
+++ linux/drivers/char/isicom.c Fri Nov 9 14:01:21 2001
@@ -60,24 +60,27 @@


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

echo 'End of part 040'
echo 'File patch-2.4.15 is continued in part 041'
echo "041" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:20 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part044

#!/bin/sh -x
# this is part 044 of a 115 - part archive


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

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

+ if (rc)
+ return(rc);
+
+ resNode = resNode->next;
+ }
+
+ // Fill in the number of entries

+ p_ev_ctrl->bus_avail = loop;
+


+ ctrl = ctrl->next;
+ }

+
+ p_EV_header->num_of_ctrl = numCtrl;
+
+ // Now store the EV
+
+ temp_dword = usedbytes;
+
+ rc = access_EV(WRITE_EV, "CQTHPS", (u8*) buffer, &temp_dword);
+
+ dbg("usedbytes = 0x%x, length = 0x%x\n", usedbytes, temp_dword);


+
+ evbuffer_length = temp_dword;
+

+ if (rc) {
+ err(msg_unable_to_save);
+ return(1);
+ }
+


+ return(0);
+}
+
+

+void compaq_nvram_init (void *rom_start)
+{
+ if (rom_start) {
+ compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR);
+ }
+ dbg("int15 entry = %p\n", compaq_int15_entry_point);
+
+ /* initialize our int15 lock */
+ spin_lock_init(&int15_lock);
+}
+
+
+int compaq_nvram_load (void *rom_start, struct controller *ctrl)
+{
+ u8 bus, device, function;
+ u8 nummem, numpmem, numio, numbus;
+ u32 rc;
+ u8 *p_byte;


+ struct pci_resource *mem_node;
+ struct pci_resource *p_mem_node;
+ struct pci_resource *io_node;
+ struct pci_resource *bus_node;

+ struct ev_hrt_ctrl *p_ev_ctrl;


+ struct ev_hrt_header *p_EV_header;
+

+ if (!evbuffer_init) {
+ // Read the resource list information in from NVRAM
+ if (load_HRT(rom_start))
+ memset (evbuffer, 0, 1024);
+
+ evbuffer_init = 1;
+ }
+
+ // If we saved information in NVRAM, use it now
+ p_EV_header = (struct ev_hrt_header *) evbuffer;
+
+ // The following code is for systems where version 1.0 of this
+ // driver has been loaded, but doesn't support the hardware.
+ // In that case, the driver would incorrectly store something
+ // in NVRAM.
+ if ((p_EV_header->Version == 2) ||
+ ((p_EV_header->Version == 1) && !ctrl->push_flag)) {
+ p_byte = &(p_EV_header->next);
+
+ p_ev_ctrl = (struct ev_hrt_ctrl *) &(p_EV_header->next);
+
+ p_byte += 3;
+
+ if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+ return(2);
+
+ bus = p_ev_ctrl->bus;
+ device = p_ev_ctrl->device;
+ function = p_ev_ctrl->function;
+
+ while ((bus != ctrl->bus) || (device != ctrl->device)
+ || (function != ctrl->function)) {
+ nummem = p_ev_ctrl->mem_avail;
+ numpmem = p_ev_ctrl->p_mem_avail;
+ numio = p_ev_ctrl->io_avail;
+ numbus = p_ev_ctrl->bus_avail;
+
+ p_byte += 4;
+
+ if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+ return(2);
+
+ // Skip forward to the next entry
+ p_byte += (nummem + numpmem + numio + numbus) * 8;
+
+ if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+ return(2);
+
+ p_ev_ctrl = (struct ev_hrt_ctrl *) p_byte;
+
+ p_byte += 3;
+
+ if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+ return(2);
+
+ bus = p_ev_ctrl->bus;
+ device = p_ev_ctrl->device;
+ function = p_ev_ctrl->function;
+ }
+
+ nummem = p_ev_ctrl->mem_avail;
+ numpmem = p_ev_ctrl->p_mem_avail;
+ numio = p_ev_ctrl->io_avail;
+ numbus = p_ev_ctrl->bus_avail;
+
+ p_byte += 4;
+
+ if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+ return(2);
+
+ while (nummem--) {
+ mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+ if (!mem_node)
+ break;
+
+ mem_node->base = *(u32*)p_byte;
+ dbg("mem base = %8.8x\n",mem_node->base);
+ p_byte += 4;
+
+ if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+ return(2);
+
+ mem_node->length = *(u32*)p_byte;
+ dbg("mem length = %8.8x\n",mem_node->length);
+ p_byte += 4;
+
+ if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+ return(2);
+
+ mem_node->next = ctrl->mem_head;
+ ctrl->mem_head = mem_node;
+ }
+
+ while (numpmem--) {
+ p_mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+ if (!p_mem_node)
+ break;
+
+ p_mem_node->base = *(u32*)p_byte;
+ dbg("pre-mem base = %8.8x\n",p_mem_node->base);
+ p_byte += 4;
+
+ if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+ return(2);
+
+ p_mem_node->length = *(u32*)p_byte;
+ dbg("pre-mem length = %8.8x\n",p_mem_node->length);
+ p_byte += 4;
+
+ if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+ return(2);
+
+ p_mem_node->next = ctrl->p_mem_head;
+ ctrl->p_mem_head = p_mem_node;
+ }
+
+ while (numio--) {
+ io_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+ if (!io_node)
+ break;
+
+ io_node->base = *(u32*)p_byte;
+ dbg("io base = %8.8x\n",io_node->base);
+ p_byte += 4;
+
+ if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+ return(2);
+
+ io_node->length = *(u32*)p_byte;
+ dbg("io length = %8.8x\n",io_node->length);
+ p_byte += 4;
+
+ if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+ return(2);
+
+ io_node->next = ctrl->io_head;
+ ctrl->io_head = io_node;
+ }
+
+ while (numbus--) {
+ bus_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+ if (!bus_node)
+ break;
+
+ bus_node->base = *(u32*)p_byte;
+ p_byte += 4;
+
+ if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+ return(2);
+
+ bus_node->length = *(u32*)p_byte;
+ p_byte += 4;
+
+
+ if (p_byte > ((u8*)p_EV_header + evbuffer_length))
+ return(2);
+
+ bus_node->next = ctrl->bus_head;
+ ctrl->bus_head = bus_node;
+ }
+
+ // If all of the following fail, we don't have any resources for
+ // hot plug add
+ rc = 1;
+ rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
+ rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
+ rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head));
+ rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
+
+ if (rc) {
+ return(rc);
+ }
+ } else {
+ if ((evbuffer[0] != 0) && (!ctrl->push_flag)) {


+ return(1);
+ }
+ }
+

+ return 0;
+}
+
+

+int compaq_nvram_store (void *rom_start)
+{
+ int rc = 1;
+
+ if (rom_start == NULL)
+ return -ENODEV;
+
+ if (evbuffer_init) {
+ rc = store_HRT(rom_start);
+ if (rc) {
+ err(msg_unable_to_save);
+ }


+ }
+ return rc;
+}
+

diff -u --recursive --new-file v2.4.14/linux/drivers/hotplug/cpqphp_nvram.h linux/drivers/hotplug/cpqphp_nvram.h
--- v2.4.14/linux/drivers/hotplug/cpqphp_nvram.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/hotplug/cpqphp_nvram.h Fri Nov 9 14:01:22 2001
@@ -0,0 +1,57 @@


+/*
+ * Compaq Hot Plug Controller Driver
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (gr...@kroah.com)
+ *

+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gr...@kroah.com>
+ *
+ */
+

+#ifndef _CPQPHP_NVRAM_H
+#define _CPQPHP_NVRAM_H
+
+#ifndef CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM
+
+static inline void compaq_nvram_init (void *rom_start)


+{
+ return;
+}
+

+static inline int compaq_nvram_load (void *rom_start, struct controller *ctrl)


+{
+ return 0;
+}
+

+static inline int compaq_nvram_store (void *rom_start)


+{
+ return 0;
+}
+

+#else
+
+extern void compaq_nvram_init (void *rom_start);
+extern int compaq_nvram_load (void *rom_start, struct controller *ctrl);
+extern int compaq_nvram_store (void *rom_start);
+
+#endif
+
+#endif
+
diff -u --recursive --new-file v2.4.14/linux/drivers/hotplug/cpqphp_pci.c linux/drivers/hotplug/cpqphp_pci.c
--- v2.4.14/linux/drivers/hotplug/cpqphp_pci.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/hotplug/cpqphp_pci.c Fri Nov 9 14:01:22 2001
@@ -0,0 +1,1726 @@

+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/pci.h>


+#include "cpqphp.h"
+#include "cpqphp_nvram.h"
+#include "../../arch/i386/kernel/pci-i386.h" /* horrible hack showing how processor dependant we are... */
+
+

+u8 cpqhp_nic_irq;
+u8 cpqhp_disk_irq;
+
+static u16 unused_IRQ;
+
+
+static int is_pci_dev_in_use(struct pci_dev* dev)
+{
+ /*
+ * dev->driver will be set if the device is in use by a new-style
+ * driver -- otherwise, check the device's regions to see if any
+ * driver has claimed them
+ */
+
+ int i, inuse=0;
+
+ if (dev->driver) return 1; //assume driver feels responsible
+
+ for (i = 0; !dev->driver && !inuse && (i < 6); i++) {
+ if (!pci_resource_start(dev, i))
+ continue;
+
+ if (pci_resource_flags(dev, i) & IORESOURCE_IO)
+ inuse = check_region(pci_resource_start(dev, i),
+ pci_resource_len(dev, i));
+ else if (pci_resource_flags(dev, i) & IORESOURCE_MEM)
+ inuse = check_mem_region(pci_resource_start(dev, i),
+ pci_resource_len(dev, i));
+ }
+
+ return inuse;
+
+}
+
+
+static int pci_hp_remove_device(struct pci_dev *dev)
+{
+ if (is_pci_dev_in_use(dev)) {
+ err("***Cannot safely power down device -- "
+ "it appears to be in use***\n");
+ return -EBUSY;
+ }
+ pci_remove_device(dev);


+ return 0;
+}
+
+
+/*

+ * detect_HRT_floating_pointer
+ *
+ * find the Hot Plug Resource Table in the specified region of memory.
+ *
+ */
+static void *detect_HRT_floating_pointer(void *begin, void *end)


+{
+ void *fp;
+ void *endp;

+ u8 temp1, temp2, temp3, temp4;
+ int status = 0;
+
+ endp = (end - sizeof(struct hrt) + 1);


+
+ for (fp = begin; fp <= endp; fp += 16) {

+ temp1 = readb(fp + SIG0);
+ temp2 = readb(fp + SIG1);
+ temp3 = readb(fp + SIG2);
+ temp4 = readb(fp + SIG3);
+ if (temp1 == '$' &&
+ temp2 == 'H' &&
+ temp3 == 'R' &&
+ temp4 == 'T') {
+ status = 1;
+ break;
+ }
+ }


+
+ if (!status)
+ fp = NULL;
+

+ dbg("Discovered Hotplug Resource Table at %p\n", fp);
+ return fp;
+}
+
+static int configure_visit_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus)
+{
+ struct pci_bus* bus = wrapped_bus->bus;
+ struct pci_dev* dev = wrapped_dev->dev;
+ struct pci_func *temp_func;
+ int i=0;
+
+ //We need to fix up the hotplug function representation with the linux representation
+ do {
+ temp_func = cpqhp_slot_find(dev->bus->number, dev->devfn >> 3, i++);
+ } while (temp_func && (temp_func->function != (dev->devfn & 0x07)));
+
+ if (temp_func) {
+ temp_func->pci_dev = dev;
+ } else {
+ //We did not even find a hotplug rep of the function, create it
+ //This code might be taken out if we can guarantee the creation of functions
+ //in parallel (hotplug and Linux at the same time).
+ dbg("@@@@@@@@@@@ cpqhp_slot_create in "__FUNCTION__"\n");
+ temp_func = cpqhp_slot_create(bus->number);
+ if (temp_func == NULL)
+ return -ENOMEM;
+ temp_func->pci_dev = dev;
+ }
+
+ //Create /proc/bus/pci proc entry for this device and bus device is on
+ //Notify the drivers of the change
+ if (temp_func->pci_dev) {
+ pci_proc_attach_device(temp_func->pci_dev);
+ pci_announce_device_to_drivers(temp_func->pci_dev);


+ }
+
+ return 0;
+}
+
+

+static int unconfigure_visit_pci_dev_phase2 (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus)
+{
+ struct pci_dev* dev = wrapped_dev->dev;
+
+ struct pci_func *temp_func;
+ int i=0;
+
+ //We need to remove the hotplug function representation with the linux representation
+ do {
+ temp_func = cpqhp_slot_find(dev->bus->number, dev->devfn >> 3, i++);
+ if (temp_func) {
+ dbg("temp_func->function = %d\n", temp_func->function);
+ }
+ } while (temp_func && (temp_func->function != (dev->devfn & 0x07)));
+
+ //Now, remove the Linux Representation
+ if (dev) {
+ if (pci_hp_remove_device(dev) == 0) {
+ kfree(dev); //Now, remove
+ } else {
+ return -1; // problems while freeing, abort visitation
+ }
+ }
+
+ if (temp_func) {
+ temp_func->pci_dev = NULL;
+ } else {
+ dbg("No pci_func representation for bus, devfn = %d, %x\n", dev->bus->number, dev->devfn);


+ }
+
+ return 0;
+}
+
+

+static int unconfigure_visit_pci_bus_phase2 (struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_dev)
+{
+ struct pci_bus* bus = wrapped_bus->bus;
+
+ //The cleanup code for proc entries regarding buses should be in the kernel...
+ if (bus->procdir)
+ dbg("detach_pci_bus %s\n", bus->procdir->name);
+ pci_proc_detach_bus(bus);
+ // The cleanup code should live in the kernel...
+ bus->self->subordinate = NULL;
+ // unlink from parent bus
+ list_del(&bus->node);
+
+ // Now, remove
+ if (bus)
+ kfree(bus);


+
+ return 0;
+}
+
+

+static int unconfigure_visit_pci_dev_phase1 (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus)
+{
+ struct pci_dev* dev = wrapped_dev->dev;
+
+ dbg("attempting removal of driver for device (%x, %x, %x)\n", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+ //Now, remove the Linux Driver Representation
+ if (dev->driver) {
+ if (dev->driver->remove) {
+ dev->driver->remove(dev);
+ dbg("driver was properly removed\n");
+ }
+ dev->driver = NULL;
+ }
+
+ return is_pci_dev_in_use(dev);
+}
+
+
+static struct pci_visit configure_functions = {
+ visit_pci_dev: configure_visit_pci_dev,
+};
+
+
+static struct pci_visit unconfigure_functions_phase1 = {
+ post_visit_pci_dev: unconfigure_visit_pci_dev_phase1
+};
+
+static struct pci_visit unconfigure_functions_phase2 = {
+ post_visit_pci_bus: unconfigure_visit_pci_bus_phase2,
+ post_visit_pci_dev: unconfigure_visit_pci_dev_phase2
+};
+
+
+int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
+{
+ unsigned char bus;
+ struct pci_dev dev0;
+ struct pci_bus *child;
+ struct pci_dev* temp;
+ int rc = 0;
+
+ struct pci_dev_wrapped wrapped_dev;
+ struct pci_bus_wrapped wrapped_bus;


+ memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));

+ memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
+

+ memset(&dev0, 0, sizeof(struct pci_dev));
+
+ if (func->pci_dev == NULL)
+ func->pci_dev = pci_find_slot(func->bus, (func->device << 3) | (func->function & 0x7));
+
+ //Still NULL ? Well then scan for it !
+ if (func->pci_dev == NULL) {
+ dbg("INFO: pci_dev still null\n");
+ dev0.bus = ctrl->pci_dev->bus;
+ dev0.devfn = (func->device << 3) + (func->function & 0x7);
+ dev0.sysdata = ctrl->pci_dev->sysdata;
+
+ //this will generate pci_dev structures for all functions, but we will only call this case when lookup fails
+ func->pci_dev = pci_scan_slot(&dev0);
+ if (func->pci_dev == NULL) {
+ dbg("ERROR: pci_dev still null\n");


+ return 0;
+ }
+ }
+

+ if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
+ child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
+ pci_do_scan_bus(child);
+
+ }
+
+ temp = func->pci_dev;
+
+ if (temp) {
+ wrapped_dev.dev = temp;
+ wrapped_bus.bus = temp->bus;
+ rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus);


+ }
+ return rc;
+}
+
+

+int cpqhp_unconfigure_device(struct pci_func* func)
+{
+ int rc = 0;
+ int j;
+ struct pci_dev_wrapped wrapped_dev;
+ struct pci_bus_wrapped wrapped_bus;


+
+ memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));

+ memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
+

+ dbg(__FUNCTION__": bus/dev/func = %x/%x/%x\n",func->bus, func->device, func->function);
+
+ for (j=0; j<8 ; j++) {
+ struct pci_dev* temp = pci_find_slot(func->bus, (func->device << 3) | j);
+ if (temp) {
+ wrapped_dev.dev = temp;
+ wrapped_bus.bus = temp->bus;
+ rc = pci_visit_dev(&unconfigure_functions_phase1, &wrapped_dev, &wrapped_bus);
+ if (rc)
+ break;
+
+ rc = pci_visit_dev(&unconfigure_functions_phase2, &wrapped_dev, &wrapped_bus);
+ if (rc)
+ break;
+ }


+ }
+ return rc;
+}
+

+static int PCI_RefinedAccessConfig(struct pci_ops *ops, u8 bus, u8 device, u8 function, u8 offset, u32 *value)
+{
+ u32 vendID = 0;
+
+ if (pci_read_config_dword_nodev (ops, bus, device, function, PCI_VENDOR_ID, &vendID) == -1)
+ return -1;
+ if (vendID == 0xffffffff)
+ return -1;
+ return pci_read_config_dword_nodev (ops, bus, device, function, offset, value);
+}
+
+
+/*
+ * cpqhp_set_irq
+ *
+ * @bus_num: bus number of PCI device
+ * @dev_num: device number of PCI device
+ * @slot: pointer to u8 where slot number will be returned
+ */
+int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
+{
+ int rc;
+ u16 temp_word;
+ struct pci_dev fakedev;
+ struct pci_bus fakebus;
+
+ fakedev.devfn = dev_num << 3;
+ fakedev.bus = &fakebus;
+ fakebus.number = bus_num;
+ dbg(__FUNCTION__": dev %d, bus %d, pin %d, num %d\n",
+ dev_num, bus_num, int_pin, irq_num);
+ rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num);
+ dbg(__FUNCTION__":rc %d\n", rc);


+ if (rc)
+ return rc;
+

+ // set the Edge Level Control Register (ELCR)
+ temp_word = inb(0x4d0);
+ temp_word |= inb(0x4d1) << 8;
+
+ temp_word |= 0x01 << irq_num;
+
+ // This should only be for x86 as it sets the Edge Level Control Register
+ outb((u8) (temp_word & 0xFF), 0x4d0);
+ outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);


+
+ return 0;
+}
+
+
+/*

+ * WTF??? This function isn't in the code, yet a function calls it, but the
+ * compiler optimizes it away? strange. Here as a placeholder to keep the
+ * compiler happy.
+ */
+static int PCI_ScanBusNonBridge (u8 bus, u8 device)


+{
+ return 0;
+}
+

+static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev_num)
+{
+ u8 tdevice;
+ u32 work;
+ u8 tbus;
+
+ for (tdevice = 0; tdevice < 0x100; tdevice++) {
+ //Scan for access first
+ if (PCI_RefinedAccessConfig(ctrl->pci_ops, bus_num, tdevice >> 3, tdevice & 0x7, 0x08, &work) == -1)
+ continue;
+ dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice);
+ //Yep we got one. Not a bridge ?
+ if ((work >> 8) != PCI_TO_PCI_BRIDGE_CLASS) {
+ *dev_num = tdevice;
+ dbg("found it !\n");


+ return 0;
+ }
+ }

+ for (tdevice = 0; tdevice < 0x100; tdevice++) {
+ //Scan for access first
+ if (PCI_RefinedAccessConfig(ctrl->pci_ops, bus_num, tdevice >> 3, tdevice & 0x7, 0x08, &work) == -1)
+ continue;
+ dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice);
+ //Yep we got one. bridge ?


+ if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {

+ pci_read_config_byte_nodev (ctrl->pci_ops, tbus, tdevice, 0, PCI_SECONDARY_BUS, &tbus);
+ dbg("Recurse on bus_num %d tdevice %d\n", tbus, tdevice);
+ if (PCI_ScanBusNonBridge(tbus, tdevice) == 0)


+ return 0;
+ }
+ }
+

+ return -1;
+}
+

+
+static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot, u8 nobridge)


+{
+ struct irq_routing_table *PCIIRQRoutingInfoLength;

+ long len;
+ long loop;

+ u32 work;


+
+ u8 tbus, tdevice, tslot;
+

+ PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();
+
+ len = (PCIIRQRoutingInfoLength->size -
+ sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
+ // Make sure I got at least one entry
+ if (len == 0) {
+ if (PCIIRQRoutingInfoLength != NULL)

+ kfree(PCIIRQRoutingInfoLength );


+ return -1;
+ }
+

+ for (loop = 0; loop < len; ++loop) {
+ tbus = PCIIRQRoutingInfoLength->slots[loop].bus;

+ tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn;


+ tslot = PCIIRQRoutingInfoLength->slots[loop].slot;
+

+ if (tslot == slot) {
+ *bus_num = tbus;
+ *dev_num = tdevice;
+ pci_read_config_dword_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, PCI_VENDOR_ID, &work);
+ if (!nobridge || (work == 0xffffffff)) {


+ if (PCIIRQRoutingInfoLength != NULL)

+ kfree(PCIIRQRoutingInfoLength );


+ return 0;
+ }
+

+ dbg("bus_num %d dev_num %d func_num %d\n", *bus_num, *dev_num >> 3, *dev_num & 0x7);
+ pci_read_config_dword_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, PCI_CLASS_REVISION, &work);
+ dbg("work >> 8 (%x) = BRIDGE (%x)\n", work >> 8, PCI_TO_PCI_BRIDGE_CLASS);


+
+ if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {

+ pci_read_config_byte_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, PCI_SECONDARY_BUS, &tbus);
+ dbg("Scan bus for Non Bridge: bus %d\n", tbus);
+ if (PCI_ScanBusForNonBridge(ctrl, tbus, dev_num) == 0) {
+ *bus_num = tbus;


+ if (PCIIRQRoutingInfoLength != NULL)

+ kfree(PCIIRQRoutingInfoLength );
+ return 0;
+ }
+ } else {


+ if (PCIIRQRoutingInfoLength != NULL)

+ kfree(PCIIRQRoutingInfoLength );


+ return 0;
+ }
+
+ }

+ }
+ if (PCIIRQRoutingInfoLength != NULL)

+ kfree(PCIIRQRoutingInfoLength );


+ return -1;
+}
+

+
+int cpqhp_get_bus_dev (struct controller *ctrl, u8 * bus_num, u8 * dev_num, u8 slot)
+{
+ return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0); //plain (bridges allowed)
+}
+
+
+/* More PCI configuration routines; this time centered around hotplug controller */
+
+
+/*
+ * cpqhp_save_config
+ *
+ * Reads configuration for all slots in a PCI bus and saves info.
+ *
+ * Note: For non-hot plug busses, the slot # saved is the device #
+ *


+ * returns 0 if success
+ */

+int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug)
+{
+ long rc;
+ u8 class_code;
+ u8 header_type;
+ u32 ID;
+ u8 secondary_bus;
+ struct pci_func *new_slot;
+ int sub_bus;
+ int FirstSupported;
+ int LastSupported;
+ int max_functions;
+ int function;
+ u8 DevError;
+ int device = 0;
+ int cloop = 0;
+ int stop_it;
+ int index;
+
+ // Decide which slots are supported
+
+ if (is_hot_plug) {
+ //*********************************
+ // is_hot_plug is the slot mask
+ //*********************************
+ FirstSupported = is_hot_plug >> 4;
+ LastSupported = FirstSupported + (is_hot_plug & 0x0F) - 1;
+ } else {
+ FirstSupported = 0;
+ LastSupported = 0x1F;
+ }
+
+ // Save PCI configuration space for all devices in supported slots
+
+ for (device = FirstSupported; device <= LastSupported; device++) {
+ ID = 0xFFFFFFFF;
+ rc = pci_read_config_dword_nodev (ctrl->pci_ops, busnumber, device, 0, PCI_VENDOR_ID, &ID);
+
+ if (ID != 0xFFFFFFFF) { // device in slot
+ rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, 0, 0x0B, &class_code);


+ if (rc)
+ return rc;
+

+ rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, 0, PCI_HEADER_TYPE, &header_type);


+ if (rc)
+ return rc;
+

+ // If multi-function device, set max_functions to 8
+ if (header_type & 0x80)


+ max_functions = 8;
+ else
+ max_functions = 1;
+
+ function = 0;
+
+ do {

+ DevError = 0;
+
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // P-P Bridge
+ // Recurse the subordinate bus
+ // get the subordinate bus number
+ rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, function, PCI_SECONDARY_BUS, &secondary_bus);


+ if (rc) {
+ return rc;

+ } else {
+ sub_bus = (int) secondary_bus;
+
+ // Save secondary bus cfg spc
+ // with this recursive call.
+ rc = cpqhp_save_config(ctrl, sub_bus, 0);
+
+ if (rc)


+ return rc;
+ }
+ }
+

+ index = 0;
+ new_slot = cpqhp_slot_find(busnumber, device, index++);
+ while (new_slot &&
+ (new_slot->function != (u8) function))
+ new_slot = cpqhp_slot_find(busnumber, device, index++);
+
+ if (!new_slot) {


+ // Setup slot structure.

+ new_slot = cpqhp_slot_create(busnumber);


+
+ if (new_slot == NULL)

+ return(1);
+ }
+
+ new_slot->bus = (u8) busnumber;
+ new_slot->device = (u8) device;
+ new_slot->function = (u8) function;


+ new_slot->is_a_board = 1;

+ new_slot->switch_save = 0x10;
+ // In case of unsupported board
+ new_slot->status = DevError;
+ new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function);
+
+ for (cloop = 0; cloop < 0x20; cloop++) {
+ rc = pci_read_config_dword_nodev (ctrl->pci_ops, busnumber, device, function, cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));


+ if (rc)
+ return rc;
+ }
+

+ function++;
+
+ stop_it = 0;
+

+ // this loop skips to the next present function
+ // reading in Class Code and Header type.
+
+ while ((function < max_functions)&&(!stop_it)) {
+ rc = pci_read_config_dword_nodev (ctrl->pci_ops, busnumber, device, function, PCI_VENDOR_ID, &ID);
+ if (ID == 0xFFFFFFFF) { // nothing there.
+ function++;
+ } else { // Something there
+ rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, function, 0x0B, &class_code);


+ if (rc)
+ return rc;
+

+ rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, function, PCI_HEADER_TYPE, &header_type);


+ if (rc)
+ return rc;
+

+ stop_it++;
+ }
+ }
+
+ } while (function < max_functions);

+ } // End of IF (device in slot?)

+ else if (is_hot_plug) {


+ // Setup slot structure with entry for empty slot

+ new_slot = cpqhp_slot_create(busnumber);


+
+ if (new_slot == NULL) {

+ return(1);
+ }
+
+ new_slot->bus = (u8) busnumber;
+ new_slot->device = (u8) device;


+ new_slot->function = 0;

+ new_slot->is_a_board = 0;
+ new_slot->presence_save = 0;
+ new_slot->switch_save = 0;
+ }


+ } // End of FOR loop
+

+ return(0);
+}
+
+
+/*

+ * cpqhp_save_slot_config
+ *
+ * Saves configuration info for all PCI devices in a given slot
+ * including subordinate busses.
+ *


+ * returns 0 if success
+ */

+int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot)
+{
+ long rc;
+ u8 class_code;
+ u8 header_type;
+ u32 ID;
+ u8 secondary_bus;
+ int sub_bus;
+ int max_functions;
+ int function;
+ int cloop = 0;
+ int stop_it;


+
+ ID = 0xFFFFFFFF;
+

+ pci_read_config_dword_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, 0, PCI_VENDOR_ID, &ID);
+
+ if (ID != 0xFFFFFFFF) { // device in slot
+ pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, 0, 0x0B, &class_code);
+
+ pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, 0, PCI_HEADER_TYPE, &header_type);
+
+ if (header_type & 0x80) // Multi-function device


+ max_functions = 8;
+ else
+ max_functions = 1;
+
+ function = 0;
+
+ do {

+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge
+ // Recurse the subordinate bus
+ pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, PCI_SECONDARY_BUS, &secondary_bus);
+
+ sub_bus = (int) secondary_bus;
+
+ // Save the config headers for the secondary bus.
+ rc = cpqhp_save_config(ctrl, sub_bus, 0);


+
+ if (rc)
+ return(rc);
+

+ } // End of IF
+


+ new_slot->status = 0;
+

+ for (cloop = 0; cloop < 0x20; cloop++) {
+ pci_read_config_dword_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));


+ }
+
+ function++;
+
+ stop_it = 0;
+

+ // this loop skips to the next present function
+ // reading in the Class Code and the Header type.


+
+ while ((function < max_functions) && (!stop_it)) {

+ pci_read_config_dword_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, PCI_VENDOR_ID, &ID);
+
+ if (ID == 0xFFFFFFFF) { // nothing there.
+ function++;
+ } else { // Something there
+ pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, 0x0B, &class_code);
+
+ pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, PCI_HEADER_TYPE, &header_type);


+
+ stop_it++;
+ }
+ }
+
+ } while (function < max_functions);

+ } // End of IF (device in slot?)

+ else {
+ return(2);
+ }
+

+ return(0);
+}
+
+
+/*

+ * cpqhp_save_base_addr_length
+ *
+ * Saves the length of all base address registers for the
+ * specified slot. this is for hot plug REPLACE
+ *


+ * returns 0 if success
+ */

+int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func)
+{
+ u8 cloop;
+ u8 header_type;
+ u8 secondary_bus;
+ u8 type;
+ int sub_bus;


+ u32 temp_register;
+ u32 base;

+ u32 rc;
+ struct pci_func *next;
+ int index = 0;
+
+ func = cpqhp_slot_find(func->bus, func->device, index++);
+
+ while (func != NULL) {


+
+ // Check for Bridge

+ pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type);
+


+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {

+ // PCI-PCI Bridge
+ pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SECONDARY_BUS, &secondary_bus);
+
+ sub_bus = (int) secondary_bus;
+
+ next = cpqhp_slot_list[sub_bus];
+


+ while (next != NULL) {

+ rc = cpqhp_save_base_addr_length(ctrl, next);


+
+ if (rc)
+ return(rc);
+

+ next = next->next;
+ }
+

+ //FIXME: this loop is duplicated in the non-bridge case. The two could be rolled together
+ // Figure out IO and memory base lengths
+ for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
+ temp_register = 0xFFFFFFFF;
+ pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register);
+ pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base);
+
+ if (base) { // If this register is implemented
+ if (base & 0x01L) {
+ // IO base
+ // set base = amount of IO space requested
+ base = base & 0xFFFFFFFE;
+ base = (~base) + 1;
+
+ type = 1;
+ } else {
+ // memory base
+ base = base & 0xFFFFFFF0;
+ base = (~base) + 1;
+
+ type = 0;
+ }
+ } else {
+ base = 0x0L;
+ type = 0;
+ }
+
+ // Save information in slot structure
+ func->base_length[(cloop - 0x10) >> 2] =
+ base;
+ func->base_type[(cloop - 0x10) >> 2] = type;


+
+ } // End of base register loop
+
+

+ } else if ((header_type & 0x7F) == 0x00) { // PCI-PCI Bridge
+ // Figure out IO and memory base lengths


+ for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
+ temp_register = 0xFFFFFFFF;

+ pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register);
+ pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base);
+
+ if (base) { // If this register is implemented
+ if (base & 0x01L) {
+ // IO base
+ // base = amount of IO space requested
+ base = base & 0xFFFFFFFE;
+ base = (~base) + 1;
+
+ type = 1;
+ } else {
+ // memory base
+ // base = amount of memory space requested
+ base = base & 0xFFFFFFF0;
+ base = (~base) + 1;
+
+ type = 0;
+ }
+ } else {
+ base = 0x0L;
+ type = 0;
+ }
+
+ // Save information in slot structure
+ func->base_length[(cloop - 0x10) >> 2] = base;
+ func->base_type[(cloop - 0x10) >> 2] = type;


+
+ } // End of base register loop
+

+ } else { // Some other unknown header type
+ }
+
+ // find the next device in this slot
+ func = cpqhp_slot_find(func->bus, func->device, index++);
+ }
+


+ return(0);
+}
+
+
+/*

+ * cpqhp_save_used_resources
+ *
+ * Stores used resource information for existing boards. this is
+ * for boards that were in the system when this driver was loaded.
+ * this function is for hot plug ADD
+ *


+ * returns 0 if success
+ */

+int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
+{
+ u8 cloop;
+ u8 header_type;
+ u8 secondary_bus;
+ u8 temp_byte;
+ u8 b_base;
+ u8 b_length;
+ u16 command;
+ u16 save_command;
+ u16 w_base;
+ u16 w_length;
+ u32 temp_register;
+ u32 save_base;
+ u32 base;
+ int index = 0;


+ struct pci_resource *mem_node;
+ struct pci_resource *p_mem_node;
+ struct pci_resource *io_node;
+ struct pci_resource *bus_node;
+

+ func = cpqhp_slot_find(func->bus, func->device, index++);
+
+ while ((func != NULL) && func->is_a_board) {
+ // Save the command register
+ pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_COMMAND, &save_command);
+
+ // disable card
+ command = 0x00;
+ pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_COMMAND, command);
+
+ // Check for Bridge
+ pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type);
+
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge
+ // Clear Bridge Control Register
+ command = 0x00;
+ pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_BRIDGE_CONTROL, command);
+
+ pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SECONDARY_BUS, &secondary_bus);
+
+ pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SUBORDINATE_BUS, &temp_byte);
+
+ bus_node =(struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);


+ if (!bus_node)
+ return -ENOMEM;
+

+ bus_node->base = secondary_bus;
+ bus_node->length = temp_byte - secondary_bus + 1;
+
+ bus_node->next = func->bus_head;
+ func->bus_head = bus_node;
+
+ // Save IO base and Limit registers
+ pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_BASE, &b_base);
+
+ pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_LIMIT, &b_length);
+
+ if ((b_base <= b_length) && (save_command & 0x01)) {
+ io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ if (!io_node)
+ return -ENOMEM;
+
+ io_node->base = (b_base & 0xF0) << 8;
+ io_node->length = (b_length - b_base + 0x10) << 8;


+
+ io_node->next = func->io_head;
+ func->io_head = io_node;
+ }

+ // Save memory base and Limit registers
+ pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_BASE, &w_base);
+
+ pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, &w_length);
+
+ if ((w_base <= w_length) && (save_command & 0x02)) {
+ mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ if (!mem_node)
+ return -ENOMEM;
+
+ mem_node->base = w_base << 16;
+ mem_node->length = (w_length - w_base + 0x10) << 16;


+
+ mem_node->next = func->mem_head;
+ func->mem_head = mem_node;
+ }

+ // Save prefetchable memory base and Limit registers
+ pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_BASE, &w_base);
+
+ pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, &w_length);
+
+ if ((w_base <= w_length) && (save_command & 0x02)) {
+ p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ if (!p_mem_node)
+ return -ENOMEM;
+
+ p_mem_node->base = w_base << 16;
+ p_mem_node->length = (w_length - w_base + 0x10) << 16;


+
+ p_mem_node->next = func->p_mem_head;
+ func->p_mem_head = p_mem_node;
+ }

+ // Figure out IO and memory base lengths
+ for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
+ pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &save_base);
+
+ temp_register = 0xFFFFFFFF;
+ pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register);
+
+ pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base);
+
+ temp_register = base;
+
+ if (base) { // If this register is implemented
+ if (((base & 0x03L) == 0x01)
+ && (save_command & 0x01)) {
+ // IO base
+ // set temp_register = amount of IO space requested
+ temp_register = base & 0xFFFFFFFE;
+ temp_register = (~temp_register) + 1;
+
+ io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ if (!io_node)
+ return -ENOMEM;
+
+ io_node->base =
+ save_base & (~0x03L);
+ io_node->length = temp_register;


+
+ io_node->next = func->io_head;
+ func->io_head = io_node;
+ } else

+ if (((base & 0x0BL) == 0x08)
+ && (save_command & 0x02)) {
+ // prefetchable memory base
+ temp_register = base & 0xFFFFFFF0;
+ temp_register = (~temp_register) + 1;
+
+ p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ if (!p_mem_node)
+ return -ENOMEM;
+
+ p_mem_node->base = save_base & (~0x0FL);
+ p_mem_node->length = temp_register;


+
+ p_mem_node->next = func->p_mem_head;
+ func->p_mem_head = p_mem_node;
+ } else

+ if (((base & 0x0BL) == 0x00)
+ && (save_command & 0x02)) {
+ // prefetchable memory base
+ temp_register = base & 0xFFFFFFF0;
+ temp_register = (~temp_register) + 1;
+
+ mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ if (!mem_node)
+ return -ENOMEM;
+
+ mem_node->base = save_base & (~0x0FL);
+ mem_node->length = temp_register;


+
+ mem_node->next = func->mem_head;
+ func->mem_head = mem_node;
+ } else

+ return(1);


+ }
+ } // End of base register loop

+ } else if ((header_type & 0x7F) == 0x00) { // Standard header
+ // Figure out IO and memory base lengths


+ for (cloop = 0x10; cloop <= 0x24; cloop += 4) {

+ pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &save_base);
+
+ temp_register = 0xFFFFFFFF;
+ pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register);
+
+ pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base);
+
+ temp_register = base;
+
+ if (base) { // If this register is implemented
+ if (((base & 0x03L) == 0x01)
+ && (save_command & 0x01)) {
+ // IO base
+ // set temp_register = amount of IO space requested
+ temp_register = base & 0xFFFFFFFE;
+ temp_register = (~temp_register) + 1;
+
+ io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ if (!io_node)
+ return -ENOMEM;
+
+ io_node->base = save_base & (~0x01L);
+ io_node->length = temp_register;


+
+ io_node->next = func->io_head;
+ func->io_head = io_node;
+ } else

+ if (((base & 0x0BL) == 0x08)
+ && (save_command & 0x02)) {
+ // prefetchable memory base
+ temp_register = base & 0xFFFFFFF0;
+ temp_register = (~temp_register) + 1;
+
+ p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ if (!p_mem_node)
+ return -ENOMEM;
+
+ p_mem_node->base = save_base & (~0x0FL);
+ p_mem_node->length = temp_register;


+
+ p_mem_node->next = func->p_mem_head;
+ func->p_mem_head = p_mem_node;
+ } else

+ if (((base & 0x0BL) == 0x00)
+ && (save_command & 0x02)) {
+ // prefetchable memory base
+ temp_register = base & 0xFFFFFFF0;
+ temp_register = (~temp_register) + 1;
+
+ mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ if (!mem_node)
+ return -ENOMEM;
+
+ mem_node->base = save_base & (~0x0FL);
+ mem_node->length = temp_register;


+
+ mem_node->next = func->mem_head;
+ func->mem_head = mem_node;
+ } else

+ return(1);


+ }
+ } // End of base register loop

+ } else { // Some other unknown header type
+ }
+
+ // find the next device in this slot
+ func = cpqhp_slot_find(func->bus, func->device, index++);
+ }
+


+ return(0);
+}
+
+
+/*

+ * cpqhp_configure_board
+ *
+ * Copies saved configuration information to one slot.
+ * this is called recursively for bridge devices.
+ * this is for hot plug REPLACE!
+ *


+ * returns 0 if success
+ */

+int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func)
+{
+ int cloop;
+ u8 header_type;
+ u8 secondary_bus;
+ int sub_bus;
+ struct pci_func *next;
+ u32 temp;
+ u32 rc;
+ int index = 0;
+
+ func = cpqhp_slot_find(func->bus, func->device, index++);
+
+ while (func != NULL) {
+ // Start at the top of config space so that the control
+ // registers are programmed last
+ for (cloop = 0x3C; cloop > 0; cloop -= 4) {
+ pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, func->config_space[cloop >> 2]);
+ }
+
+ pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type);
+
+ // If this is a bridge device, restore subordinate devices
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge
+ pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SECONDARY_BUS, &secondary_bus);
+
+ sub_bus = (int) secondary_bus;
+
+ next = cpqhp_slot_list[sub_bus];
+


+ while (next != NULL) {

+ rc = cpqhp_configure_board(ctrl, next);
+
+ if (rc)
+ return rc;
+


+ next = next->next;
+ }

+ } else {
+
+ // Check all the base Address Registers to make sure
+ // they are the same. If not, the board is different.
+
+ for (cloop = 16; cloop < 40; cloop += 4) {
+ pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &temp);
+
+ if (temp != func->config_space[cloop >> 2]) {
+ dbg("Config space compare failure!!! offset = %x\n", cloop);
+ dbg("bus = %x, device = %x, function = %x\n", func->bus, func->device, func->function);
+ dbg("temp = %x, config space = %x\n\n", temp, func->config_space[cloop]);
+ return 1;
+ }
+ }
+ }
+


+ func->configured = 1;
+

+ func = cpqhp_slot_find(func->bus, func->device, index++);
+ }


+
+ return 0;
+}
+
+
+/*

+ * cpqhp_valid_replace
+ *
+ * this function checks to see if a board is the same as the
+ * one it is replacing. this check will detect if the device's
+ * vendor or device id's are the same
+ *
+ * returns 0 if the board is the same nonzero otherwise
+ */
+int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func)
+{
+ u8 cloop;
+ u8 header_type;
+ u8 secondary_bus;
+ u8 type;
+ u32 temp_register = 0;
+ u32 base;
+ u32 rc;
+ struct pci_func *next;
+ int index = 0;
+
+ if (!func->is_a_board)
+ return(ADD_NOT_SUPPORTED);
+
+ func = cpqhp_slot_find(func->bus, func->device, index++);
+
+ while (func != NULL) {
+ pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_VENDOR_ID, &temp_register);
+
+ // No adapter present
+ if (temp_register == 0xFFFFFFFF)
+ return(NO_ADAPTER_PRESENT);
+
+ if (temp_register != func->config_space[0])
+ return(ADAPTER_NOT_SAME);
+
+ // Check for same revision number and class code
+ pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_CLASS_REVISION, &temp_register);
+
+ // Adapter not the same
+ if (temp_register != func->config_space[0x08 >> 2])
+ return(ADAPTER_NOT_SAME);


+
+ // Check for Bridge

+ pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type);
+
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge
+ // In order to continue checking, we must program the
+ // bus registers in the bridge to respond to accesses
+ // for it's subordinate bus(es)
+
+ temp_register = func->config_space[0x18 >> 2];
+ pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PRIMARY_BUS, temp_register);
+
+ secondary_bus = (temp_register >> 8) & 0xFF;
+
+ next = cpqhp_slot_list[secondary_bus];
+


+ while (next != NULL) {

+ rc = cpqhp_valid_replace(ctrl, next);


+
+ if (rc)
+ return(rc);
+

+ next = next->next;
+ }
+
+ }
+ // Check to see if it is a standard config header
+ else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
+ // Check subsystem vendor and ID
+ pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SUBSYSTEM_VENDOR_ID, &temp_register);
+
+ if (temp_register != func->config_space[0x2C >> 2]) {
+ // If it's a SMART-2 and the register isn't filled
+ // in, ignore the difference because
+ // they just have an old rev of the firmware
+
+ if (!((func->config_space[0] == 0xAE100E11)
+ && (temp_register == 0x00L)))
+ return(ADAPTER_NOT_SAME);
+ }
+ // Figure out IO and memory base lengths


+ for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
+ temp_register = 0xFFFFFFFF;

+ pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register);
+
+ pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base);
+
+ if (base) { // If this register is implemented
+ if (base & 0x01L) {
+ // IO base
+ // set base = amount of IO space requested
+ base = base & 0xFFFFFFFE;
+ base = (~base) + 1;
+
+ type = 1;
+ } else {
+ // memory base
+ base = base & 0xFFFFFFF0;
+ base = (~base) + 1;
+
+ type = 0;
+ }
+ } else {
+ base = 0x0L;
+ type = 0;
+ }
+
+ // Check information in slot structure
+ if (func->base_length[(cloop - 0x10) >> 2] != base)
+ return(ADAPTER_NOT_SAME);
+
+ if (func->base_type[(cloop - 0x10) >> 2] != type)
+ return(ADAPTER_NOT_SAME);


+
+ } // End of base register loop
+

+ } // End of (type 0 config space) else
+ else {
+ // this is not a type 0 or 1 config space header so
+ // we don't know how to do it
+ return(DEVICE_TYPE_NOT_SUPPORTED);
+ }
+
+ // Get the next function
+ func = cpqhp_slot_find(func->bus, func->device, index++);
+ }
+
+


+ return(0);
+}
+
+
+/*

+ * cpqhp_find_available_resources
+ *
+ * Finds available memory, IO, and IRQ resources for programming
+ * devices which may be added to the system
+ * this function is for hot plug ADD!
+ *


+ * returns 0 if success
+ */

+int cpqhp_find_available_resources (struct controller *ctrl, void *rom_start)
+{
+ u8 temp;
+ u8 populated_slot;
+ u8 bridged_slot;
+ void *one_slot;
+ struct pci_func *func = NULL;
+ int i = 10, index;
+ u32 temp_dword, rc;


+ struct pci_resource *mem_node;
+ struct pci_resource *p_mem_node;
+ struct pci_resource *io_node;
+ struct pci_resource *bus_node;

+ void *rom_resource_table;
+
+ rom_resource_table = detect_HRT_floating_pointer(rom_start, rom_start+0xffff);
+ dbg("rom_resource_table = %p\n", rom_resource_table);
+
+ if (rom_resource_table == NULL) {
+ return -ENODEV;
+ }
+ // Sum all resources and setup resource maps
+ unused_IRQ = readl(rom_resource_table + UNUSED_IRQ);
+ dbg("unused_IRQ = %x\n", unused_IRQ);
+
+ temp = 0;
+ while (unused_IRQ) {
+ if (unused_IRQ & 1) {
+ cpqhp_disk_irq = temp;
+ break;
+ }
+ unused_IRQ = unused_IRQ >> 1;
+ temp++;
+ }
+
+ dbg("cpqhp_disk_irq= %d\n", cpqhp_disk_irq);
+ unused_IRQ = unused_IRQ >> 1;
+ temp++;
+
+ while (unused_IRQ) {
+ if (unused_IRQ & 1) {
+ cpqhp_nic_irq = temp;
+ break;
+ }
+ unused_IRQ = unused_IRQ >> 1;
+ temp++;
+ }
+
+ dbg("cpqhp_nic_irq= %d\n", cpqhp_nic_irq);
+ unused_IRQ = readl(rom_resource_table + PCIIRQ);
+
+ temp = 0;
+
+ if (!cpqhp_nic_irq) {
+ cpqhp_nic_irq = ctrl->interrupt;
+ }
+
+ if (!cpqhp_disk_irq) {
+ cpqhp_disk_irq = ctrl->interrupt;
+ }
+
+ dbg("cpqhp_disk_irq, cpqhp_nic_irq= %d, %d\n", cpqhp_disk_irq, cpqhp_nic_irq);
+
+ rc = compaq_nvram_load(rom_start, ctrl);
+ if (rc)
+ return rc;
+
+ one_slot = rom_resource_table + sizeof (struct hrt);
+
+ i = readb(rom_resource_table + NUMBER_OF_ENTRIES);
+ dbg("number_of_entries = %d\n", i);
+
+ if (!readb(one_slot + SECONDARY_BUS)) {
+ return(1);
+ }
+
+ dbg("dev|IO base|length|Mem base|length|Pre base|length|PB SB MB\n");
+
+ while (i && readb(one_slot + SECONDARY_BUS)) {
+ u8 dev_func = readb(one_slot + DEV_FUNC);
+ u8 primary_bus = readb(one_slot + PRIMARY_BUS);
+ u8 secondary_bus = readb(one_slot + SECONDARY_BUS);
+ u8 max_bus = readb(one_slot + MAX_BUS);
+ u16 io_base = readw(one_slot + IO_BASE);
+ u16 io_length = readw(one_slot + IO_LENGTH);
+ u16 mem_base = readw(one_slot + MEM_BASE);
+ u16 mem_length = readw(one_slot + MEM_LENGTH);
+ u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE);
+ u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH);
+
+ dbg("%2.2x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x |%2.2x %2.2x %2.2x\n",
+ dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length,
+ primary_bus, secondary_bus, max_bus);
+
+ // If this entry isn't for our controller's bus, ignore it
+ if (primary_bus != ctrl->bus) {
+ i--;
+ one_slot += sizeof (struct slot_rt);
+ continue;
+ }
+ // find out if this entry is for an occupied slot
+ pci_read_config_dword_nodev (ctrl->pci_ops, primary_bus, dev_func >> 3, dev_func & 0x07, PCI_VENDOR_ID, &temp_dword);
+
+ dbg("temp_D_word = %x\n", temp_dword);
+
+ if (temp_dword != 0xFFFFFFFF) {
+ index = 0;
+ func = cpqhp_slot_find(primary_bus, dev_func >> 3, 0);
+
+ while (func && (func->function != (dev_func & 0x07))) {
+ dbg("func = %p (bus, dev, fun) = (%d, %d, %d)\n", func, primary_bus, dev_func >> 3, index);
+ func = cpqhp_slot_find(primary_bus, dev_func >> 3, index++);
+ }
+
+ // If we can't find a match, skip this table entry
+ if (!func) {
+ i--;
+ one_slot += sizeof (struct slot_rt);
+ continue;
+ }
+ // this may not work and shouldn't be used
+ if (secondary_bus != primary_bus)
+ bridged_slot = 1;
+ else
+ bridged_slot = 0;
+
+ populated_slot = 1;
+ } else {
+ populated_slot = 0;
+ bridged_slot = 0;
+ }
+
+
+ // If we've got a valid IO base, use it
+
+ temp_dword = io_base + io_length;
+
+ if ((io_base) && (temp_dword < 0x10000)) {
+ io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ if (!io_node)
+ return -ENOMEM;
+
+ io_node->base = io_base;
+ io_node->length = io_length;
+
+ dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length);
+ dbg("populated slot =%d \n", populated_slot);
+ if (!populated_slot) {
+ io_node->next = ctrl->io_head;
+ ctrl->io_head = io_node;


+ } else {
+ io_node->next = func->io_head;
+ func->io_head = io_node;
+ }

+ }
+
+ // If we've got a valid memory base, use it
+ temp_dword = mem_base + mem_length;
+ if ((mem_base) && (temp_dword < 0x10000)) {
+ mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ if (!mem_node)
+ return -ENOMEM;
+
+ mem_node->base = mem_base << 16;
+
+ mem_node->length = mem_length << 16;
+
+ dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length);
+ dbg("populated slot =%d \n", populated_slot);
+ if (!populated_slot) {
+ mem_node->next = ctrl->mem_head;
+ ctrl->mem_head = mem_node;


+ } else {
+ mem_node->next = func->mem_head;
+ func->mem_head = mem_node;
+ }

+ }
+
+ // If we've got a valid prefetchable memory base, and
+ // the base + length isn't greater than 0xFFFF
+ temp_dword = pre_mem_base + pre_mem_length;
+ if ((pre_mem_base) && (temp_dword < 0x10000)) {
+ p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ if (!p_mem_node)
+ return -ENOMEM;
+
+ p_mem_node->base = pre_mem_base << 16;
+
+ p_mem_node->length = pre_mem_length << 16;
+ dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length);
+ dbg("populated slot =%d \n", populated_slot);
+
+ if (!populated_slot) {
+ p_mem_node->next = ctrl->p_mem_head;
+ ctrl->p_mem_head = p_mem_node;


+ } else {
+ p_mem_node->next = func->p_mem_head;
+ func->p_mem_head = p_mem_node;
+ }

+ }
+
+ // If we've got a valid bus number, use it
+ // The second condition is to ignore bus numbers on
+ // populated slots that don't have PCI-PCI bridges
+ if (secondary_bus && (secondary_bus != primary_bus)) {
+ bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);


+ if (!bus_node)
+ return -ENOMEM;
+

+ bus_node->base = secondary_bus;
+ bus_node->length = max_bus - secondary_bus + 1;
+ dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length);
+ dbg("populated slot =%d \n", populated_slot);
+ if (!populated_slot) {
+ bus_node->next = ctrl->bus_head;
+ ctrl->bus_head = bus_node;
+ } else {
+ bus_node->next = func->bus_head;
+ func->bus_head = bus_node;
+ }
+ }
+
+ i--;
+ one_slot += sizeof (struct slot_rt);
+ }
+
+ // If all of the following fail, we don't have any resources for
+ // hot plug add
+ rc = 1;
+ rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
+ rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
+ rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head));
+ rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head));


+
+ return(rc);
+}
+
+

+/*
+ * cpqhp_return_board_resources
+ *
+ * this routine returns all resources allocated to a board to
+ * the available pool.
+ *


+ * returns 0 if success
+ */

+int cpqhp_return_board_resources(struct pci_func * func, struct resource_lists * resources)
+{
+ int rc = 0;
+ struct pci_resource *node;
+ struct pci_resource *t_node;


+ dbg(__FUNCTION__"\n");
+

+ if (!func)
+ return(1);
+
+ node = func->io_head;
+ func->io_head = NULL;
+ while (node) {
+ t_node = node->next;
+ return_resource(&(resources->io_head), node);
+ node = t_node;
+ }
+
+ node = func->mem_head;
+ func->mem_head = NULL;
+ while (node) {
+ t_node = node->next;
+ return_resource(&(resources->mem_head), node);
+ node = t_node;
+ }
+
+ node = func->p_mem_head;
+ func->p_mem_head = NULL;
+ while (node) {
+ t_node = node->next;
+ return_resource(&(resources->p_mem_head), node);
+ node = t_node;
+ }
+
+ node = func->bus_head;
+ func->bus_head = NULL;
+ while (node) {
+ t_node = node->next;
+ return_resource(&(resources->bus_head), node);
+ node = t_node;
+ }
+
+ rc |= cpqhp_resource_sort_and_combine(&(resources->mem_head));
+ rc |= cpqhp_resource_sort_and_combine(&(resources->p_mem_head));
+ rc |= cpqhp_resource_sort_and_combine(&(resources->io_head));
+ rc |= cpqhp_resource_sort_and_combine(&(resources->bus_head));


+
+ return(rc);
+}
+
+

+/*
+ * cpqhp_destroy_resource_list


+ *
+ * Puts node back in the resource list pointed to by head

+ */
+void cpqhp_destroy_resource_list (struct resource_lists * resources)
+{
+ struct pci_resource *res, *tres;
+
+ res = resources->io_head;
+ resources->io_head = NULL;
+


+ while (res) {
+ tres = res;
+ res = res->next;
+ kfree(tres);
+ }
+

+ res = resources->mem_head;
+ resources->mem_head = NULL;
+


+ while (res) {
+ tres = res;
+ res = res->next;
+ kfree(tres);
+ }
+

+ res = resources->p_mem_head;
+ resources->p_mem_head = NULL;
+


+ while (res) {
+ tres = res;
+ res = res->next;
+ kfree(tres);
+ }
+

+ res = resources->bus_head;
+ resources->bus_head = NULL;
+


+ while (res) {
+ tres = res;
+ res = res->next;
+ kfree(tres);
+ }

+}
+
+
+/*
+ * cpqhp_destroy_board_resources


+ *
+ * Puts node back in the resource list pointed to by head

+ */
+void cpqhp_destroy_board_resources (struct pci_func * func)
+{
+ struct pci_resource *res, *tres;
+
+ res = func->io_head;
+ func->io_head = NULL;
+


+ while (res) {
+ tres = res;
+ res = res->next;
+ kfree(tres);
+ }
+

+ res = func->mem_head;
+ func->mem_head = NULL;
+


+ while (res) {
+ tres = res;
+ res = res->next;
+ kfree(tres);
+ }
+

+ res = func->p_mem_head;
+ func->p_mem_head = NULL;
+


+ while (res) {
+ tres = res;
+ res = res->next;
+ kfree(tres);
+ }
+

+ res = func->bus_head;
+ func->bus_head = NULL;
+


+ while (res) {
+ tres = res;
+ res = res->next;
+ kfree(tres);
+ }

+}
+
diff -u --recursive --new-file v2.4.14/linux/drivers/hotplug/cpqphp_proc.c linux/drivers/hotplug/cpqphp_proc.c
--- v2.4.14/linux/drivers/hotplug/cpqphp_proc.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/hotplug/cpqphp_proc.c Fri Nov 9 14:01:22 2001
@@ -0,0 +1,192 @@


+/*
+ * Compaq Hot Plug Controller Driver
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001 Greg Kroah-Hartman (gr...@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more

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

echo 'End of part 044'
echo 'File patch-2.4.15 is continued in part 045'
echo "045" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:35 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part059

#!/bin/sh -x
# this is part 059 of a 115 - part archive


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

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

+under Linux is contained in 2 files named sym_glue.h and sym_glue.c.
+Other drivers files are intended not to depend on the Operating System
+on which the driver is used.
+
+The history of this driver can be summerized as follows:
+
+1993: ncr driver written for 386bsd and FreeBSD by:
+ Wolfgang Stanglmeier <wo...@cologne.de>
+ Stefan Esser <s...@mi.Uni-Koeln.de>
+
+1996: port of the ncr driver to Linux-1.2.13 and rename it ncr53c8xx.
+ Gerard Roudier
+
+1998: new sym53c8xx driver for Linux based on LOAD/STORE instruction and that
+ adds full support for the 896 but drops support for early NCR devices.
+ Gerard Roudier
+
+1999: port of the sym53c8xx driver to FreeBSD and support for the LSI53C1010
+ 33 MHz and 66MHz Ultra-3 controllers. The new driver is named `sym'.
+ Gerard Roudier
+
+2000: Add support for early NCR devices to FreeBSD `sym' driver.
+ Break the driver into several sources and separate the OS glue
+ code from the core code that can be shared among different O/Ses.
+ Write a glue code for Linux.
+ Gerard Roudier
+
+This README file addresses the Linux version of the driver. Under FreeBSD,
+the driver documentation is the sym.8 man page.
+
+Information about new chips is available at LSILOGIC web server:
+
+ http://www.lsilogic.com/
+
+SCSI standard documentations are available at T10 site:
+
+ http://www.t10.org/
+
+Useful SCSI tools written by Eric Youngdale are part of most Linux
+distributions:
+ scsiinfo: command line tool
+ scsi-config: TCL/Tk tool using scsiinfo
+
+2. Supported chips and SCSI features
+
+The following features are supported for all chips:
+
+ Synchronous negotiation
+ Disconnection
+ Tagged command queuing
+ SCSI parity checking
+ PCI Master parity checking
+
+Other features depends on chip capabilities.
+The driver notably uses optimized SCRIPTS for devices that support
+LOAD/STORE and handles PHASE MISMATCH from SCRIPTS for devices that
+support the corresponding feature.
+
+The following table shows some characteristics of the chip family.
+
+ On board LOAD/STORE HARDWARE
+Chip SDMS BIOS Wide SCSI std. Max. sync SCRIPTS PHASE MISMATCH
+---- --------- ---- --------- ---------- ---------- --------------
+810 N N FAST10 10 MB/s N N
+810A N N FAST10 10 MB/s Y N
+815 Y N FAST10 10 MB/s N N
+825 Y Y FAST10 20 MB/s N N
+825A Y Y FAST10 20 MB/s Y N
+860 N N FAST20 20 MB/s Y N
+875 Y Y FAST20 40 MB/s Y N
+875A Y Y FAST20 40 MB/s Y Y
+876 Y Y FAST20 40 MB/s Y N
+895 Y Y FAST40 80 MB/s Y N
+895A Y Y FAST40 80 MB/s Y Y
+896 Y Y FAST40 80 MB/s Y Y
+897 Y Y FAST40 80 MB/s Y Y
+1510D Y Y FAST40 80 MB/s Y Y
+1010 Y Y FAST80 160 MB/s Y Y
+1010_66* Y Y FAST80 160 MB/s Y Y
+
+* Chip supports 33MHz and 66MHz PCI bus clock.
+
+
+Summary of other supported features:
+
+Module: allow to load the driver
+Memory mapped I/O: increases performance
+Control commands: write operations to the proc SCSI file system
+Debugging information: written to syslog (expert only)
+Scatter / gather
+Shared interrupt
+Boot setup commands
+Serial NVRAM: Symbios and Tekram formats
+
+
+3. Advantages of this driver for newer chips.
+
+3.1 Optimized SCSI SCRIPTS.
+
+All chips except the 810, 815 and 825, support new SCSI SCRIPTS instructions
+named LOAD and STORE that allow to move up to 1 DWORD from/to an IO register
+to/from memory much faster that the MOVE MEMORY instruction that is supported
+by the 53c7xx and 53c8xx family.
+
+The LOAD/STORE instructions support absolute and DSA relative addressing
+modes. The SCSI SCRIPTS had been entirely rewritten using LOAD/STORE instead
+of MOVE MEMORY instructions.
+
+Due to the lack of LOAD/STORE SCRIPTS instructions by earlier chips, this
+driver also incorporates a different SCRIPTS set based on MEMORY MOVE, in
+order to provide support for the entire SYM53C8XX chips family.
+
+3.2 New features appeared with the SYM53C896
+
+Newer chips (see above) allows handling of the phase mismatch context from
+SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor
+until the C code has saved the context of the transfer).
+
+The 896 and 1010 chips support 64 bit PCI transactions and addressing,
+while the 895A supports 32 bit PCI transactions and 64 bit addressing.
+The SCRIPTS processor of these chips is not true 64 bit, but uses segment
+registers for bit 32-63. Another interesting feature is that LOAD/STORE
+instructions that address the on-chip RAM (8k) remain internal to the chip.
+
+4. Memory mapped I/O versus normal I/O
+
+Memory mapped I/O has less latency than normal I/O and is the recommended
+way for doing IO with PCI devices. Memory mapped I/O seems to work fine on
+most hardware configurations, but some poorly designed chipsets may break
+this feature. A configuration option is provided for normal I/O to be
+used but the driver defaults to MMIO.
+
+5. Tagged command queueing
+
+Queuing more than 1 command at a time to a device allows it to perform
+optimizations based on actual head positions and its mechanical
+characteristics. This feature may also reduce average command latency.
+In order to really gain advantage of this feature, devices must have
+a reasonnable cache size (No miracle is to be expected for a low-end
+hard disk with 128 KB or less).
+Some kown old SCSI devices do not properly support tagged command queuing.
+Generally, firmware revisions that fix this kind of problems are available
+at respective vendor web/ftp sites.
+All I can say is that I never have had problem with tagged queuing using
+this driver and its predecessors. Hard disks that behaved correctly for
+me using tagged commands are the following:
+
+- IBM S12 0662
+- Conner 1080S
+- Quantum Atlas I
+- Quantum Atlas II
+- Seagate Cheetah I
+- Quantum Viking II
+- IBM DRVS
+- Quantum Atlas IV
+- Seagate Cheetah II
+
+If your controller has NVRAM, you can configure this feature per target
+from the user setup tool. The Tekram Setup program allows to tune the
+maximum number of queued commands up to 32. The Symbios Setup only allows
+to enable or disable this feature.
+
+The maximum number of simultaneous tagged commands queued to a device
+is currently set to 16 by default. This value is suitable for most SCSI
+disks. With large SCSI disks (>= 2GB, cache >= 512KB, average seek time
+<= 10 ms), using a larger value may give better performances.
+
+This driver supports up to 255 commands per device, and but using more than
+64 is generally not worth-while, unless you are using a very large disk or
+disk arrays. It is noticeable that most of recent hard disks seem not to
+accept more than 64 simultaneous commands. So, using more than 64 queued
+commands is probably just resource wasting.
+
+If your controller does not have NVRAM or if it is managed by the SDMS
+BIOS/SETUP, you can configure tagged queueing feature and device queue
+depths from the boot command-line. For example:
+
+ sym53c8xx=tags:4/t2t3q15-t4q7/t1u0q32
+
+will set tagged commands queue depths as follow:
+
+- target 2 all luns on controller 0 --> 15
+- target 3 all luns on controller 0 --> 15
+- target 4 all luns on controller 0 --> 7
+- target 1 lun 0 on controller 1 --> 32
+- all other target/lun --> 4
+
+In some special conditions, some SCSI disk firmwares may return a
+QUEUE FULL status for a SCSI command. This behaviour is managed by the
+driver using the following heuristic:
+
+- Each time a QUEUE FULL status is returned, tagged queue depth is reduced
+ to the actual number of disconnected commands.
+
+- Every 200 successfully completed SCSI commands, if allowed by the
+ current limit, the maximum number of queueable commands is incremented.
+
+Since QUEUE FULL status reception and handling is resource wasting, the
+driver notifies by default this problem to user by indicating the actual
+number of commands used and their status, as well as its decision on the
+device queue depth change.
+The heuristic used by the driver in handling QUEUE FULL ensures that the
+impact on performances is not too bad. You can get rid of the messages by
+setting verbose level to zero, as follow:
+
+1st method: boot your system using 'sym53c8xx=verb:0' option.
+2nd method: apply "setverbose 0" control command to the proc fs entry
+ corresponding to your controller after boot-up.
+
+6. Parity checking
+
+The driver supports SCSI parity checking and PCI bus master parity
+checking. These features must be enabled in order to ensure safe data
+transfers. However, some flawed devices or mother boards will have
+problems with parity. You can disable either PCI parity or SCSI parity
+checking by entering appropriate options from the boot command line.
+(See 10: Boot setup commands).
+
+7. Profiling information
+
+This driver does not provide profiling informations as did its predecessors.
+This feature was not this useful and added complexity to the code.
+As the driver code got more complex, I have decided to remove everything
+that didn't seem actually useful.
+
+8. Control commands
+
+Control commands can be sent to the driver with write operations to
+the proc SCSI file system. The generic command syntax is the
+following:
+
+ echo "<verb> <parameters>" >/proc/scsi/sym53c8xx/0
+ (assumes controller number is 0)
+
+Using "all" for "<target>" parameter with the commands below will
+apply to all targets of the SCSI chain (except the controller).
+
+Available commands:
+
+8.1 Set minimum synchronous period factor
+
+ setsync <target> <period factor>
+
+ target: target number
+ period: minimum synchronous period.
+ Maximum speed = 1000/(4*period factor) except for special
+ cases below.
+
+ Specify a period of 0, to force asynchronous transfer mode.
+
+ 9 means 12.5 nano-seconds synchronous period
+ 10 means 25 nano-seconds synchronous period
+ 11 means 30 nano-seconds synchronous period
+ 12 means 50 nano-seconds synchronous period
+
+8.2 Set wide size
+
+ setwide <target> <size>
+
+ target: target number
+ size: 0=8 bits, 1=16bits
+
+8.3 Set maximum number of concurrent tagged commands
+
+ settags <target> <tags>
+
+ target: target number
+ tags: number of concurrent tagged commands
+ must not be greater than configured (default: 16)
+
+8.4 Set debug mode
+
+ setdebug <list of debug flags>
+
+ Available debug flags:
+ alloc: print info about memory allocations (ccb, lcb)
+ queue: print info about insertions into the command start queue
+ result: print sense data on CHECK CONDITION status
+ scatter: print info about the scatter process
+ scripts: print info about the script binding process
+ tiny: print minimal debugging information
+ timing: print timing information of the NCR chip
+ nego: print information about SCSI negotiations
+ phase: print information on script interruptions
+
+ Use "setdebug" with no argument to reset debug flags.
+
+
+8.5 Set flag (no_disc)
+
+ setflag <target> <flag>
+
+ target: target number
+
+ For the moment, only one flag is available:
+
+ no_disc: not allow target to disconnect.
+
+ Do not specify any flag in order to reset the flag. For example:
+ - setflag 4
+ will reset no_disc flag for target 4, so will allow it disconnections.
+ - setflag all
+ will allow disconnection for all devices on the SCSI bus.
+
+
+8.6 Set verbose level
+
+ setverbose #level
+
+ The driver default verbose level is 1. This command allows to change
+ th driver verbose level after boot-up.
+
+8.7 Reset all logical units of a target
+
+ resetdev <target>
+
+ target: target number
+ The driver will try to send a BUS DEVICE RESET message to the target.
+
+8.8 Abort all tasks of all logical units of a target
+
+ cleardev <target>
+
+ target: target number
+ The driver will try to send a ABORT message to all the logical units
+ of the target.
+
+
+9. Configuration parameters
+
+Under kernel configuration tools (make menuconfig, for example), it is
+possible to change some default driver configuration parameters.
+If the firmware of all your devices is perfect enough, all the
+features supported by the driver can be enabled at start-up. However,
+if only one has a flaw for some SCSI feature, you can disable the
+support by the driver of this feature at linux start-up and enable
+this feature after boot-up only for devices that support it safely.
+
+Configuration parameters:
+
+Use normal IO (default answer: n)
+ Answer "y" if you suspect your mother board to not allow memory mapped I/O.
+ May slow down performance a little.
+
+Default tagged command queue depth (default answer: 16)
+ Entering 0 defaults to tagged commands not being used.
+ This parameter can be specified from the boot command line.
+
+Maximum number of queued commands (default answer: 32)
+ This option allows you to specify the maximum number of tagged commands
+ that can be queued to a device. The maximum supported value is 255.
+
+Synchronous transfers frequency (default answer: 80)
+ This option allows you to specify the frequency in MHz the driver
+ will use at boot time for synchronous data transfer negotiations.
+ 0 means "asynchronous data transfers".
+
+10. Boot setup commands
+
+10.1 Syntax
+
+Setup commands can be passed to the driver either at boot time or as a
+string variable using 'insmod'.
+
+A boot setup command for this driver begins with the driver name "sym53c8xx=".
+The kernel syntax parser then expects an optionnal list of integers separated
+with comma followed by an optional list of comma-separated strings.
+
+Example of boot setup command under lilo prompt:
+
+lilo: linux root=/dev/sda2 sym53c8xx=tags:4,sync:10,debug:0x200
+
+- enable tagged commands, up to 4 tagged commands queued.
+- set synchronous negotiation speed to 10 Mega-transfers / second.
+- set DEBUG_NEGO flag.
+
+Since comma seems not to be allowed when defining a string variable using
+'insmod', the driver also accepts <space> as option separator.
+The following command will install driver module with the same options as
+above.
+
+ insmod sym53c8xx.o sym53c8xx="tags:4 sync:10 debug:0x200"
+
+The integer list of arguments is discarded by the driver.
+
+Each string argument must be specified as "keyword:value". Only lower-case
+characters and digits are allowed.
+
+10.2 Available arguments
+
+10.2.1 Master parity checking
+ mpar:y enabled
+ mpar:n disabled
+
+10.2.2 Scsi parity checking
+ spar:y enabled
+ spar:n disabled
+
+10.2.3 Default number of tagged commands
+ tags:0 (or tags:1 ) tagged command queuing disabled
+ tags:#tags (#tags > 1) tagged command queuing enabled
+ #tags will be truncated to the max queued commands configuration parameter.
+ This option also allows to specify a command queue depth for each device
+ that support tagged command queueing.
+ Example:
+ sym53c8xx=tags:10/t2t3q16-t5q24/t1u2q32
+ will set devices queue depth as follow:
+ - controller #0 target #2 and target #3 -> 16 commands,
+ - controller #0 target #5 -> 24 commands,
+ - controller #1 target #1 logical unit #2 -> 32 commands,
+ - all other logical units (all targets, all controllers) -> 10 commands.
+
+10.2.4 Default synchronous period factor
+ sync:255 disabled (asynchronous transfer mode)
+ sync:#factor
+ #factor = 9 Ultra-3 SCSI 80 Mega-transfers / second (Wide only)
+ #factor = 10 Ultra-2 SCSI 40 Mega-transfers / second
+ #factor = 11 Ultra-2 SCSI 33 Mega-transfers / second
+ #factor < 25 Ultra SCSI 20 Mega-transfers / second
+ #factor < 50 Fast SCSI-2
+
+ In all cases, the driver will use the minimum transfer period supported by
+ controllers according to SYM53C8XX chip type.
+
+10.2.5 Verbosity level
+ verb:0 minimal
+ verb:1 normal
+ verb:2 too much
+
+10.2.6 Debug mode
+ debug:0 clear debug flags
+ debug:#x set debug flags
+ #x is an integer value combining the following power-of-2 values:
+ DEBUG_ALLOC 0x1
+ DEBUG_PHASE 0x2
+ DEBUG_POLL 0x4
+ DEBUG_QUEUE 0x8
+ DEBUG_RESULT 0x10
+ DEBUG_SCATTER 0x20
+ DEBUG_SCRIPT 0x40
+ DEBUG_TINY 0x80
+ DEBUG_TIMING 0x100
+ DEBUG_NEGO 0x200
+ DEBUG_TAGS 0x400
+ DEBUG_FREEZE 0x800
+ DEBUG_RESTART 0x1000
+
+ You can play safely with DEBUG_NEGO. However, some of these flags may
+ generate bunches of syslog messages.
+
+10.2.7 Burst max
+ burst:0 burst disabled
+ burst:255 get burst length from initial IO register settings.
+ burst:#x burst enabled (1<<#x burst transfers max)
+ #x is an integer value which is log base 2 of the burst transfers max.
+ By default the driver uses the maximum value supported by the chip.
+
+10.2.8 LED support
+ led:1 enable LED support
+ led:0 disable LED support
+ Donnot enable LED support if your scsi board does not use SDMS BIOS.
+ (See 'Configuration parameters')
+
+10.2.9 Max wide
+ wide:1 wide scsi enabled
+ wide:0 wide scsi disabled
+ Some scsi boards use a 875 (ultra wide) and only supply narrow connectors.
+ If you have connected a wide device with a 50 pins to 68 pins cable
+ converter, any accepted wide negotiation will break further data transfers.
+ In such a case, using "wide:0" in the bootup command will be helpfull.
+
+10.2.10 Differential mode
+ diff:0 never set up diff mode
+ diff:1 set up diff mode if BIOS set it
+ diff:2 always set up diff mode
+ diff:3 set diff mode if GPIO3 is not set
+
+10.2.11 IRQ mode
+ irqm:0 always open drain
+ irqm:1 same as initial settings (assumed BIOS settings)
+ irqm:2 always totem pole
+
+10.2.12 Reverse probe
+ revprob:n probe chip ids from the PCI configuration in this order:
+ 810, 815, 825, 860, 875, 885, 875A, 895, 896, 895A,
+ 1510D, 1010-33, 1010-66.
+ revprob:y probe chip ids in the reverse order.
+
+10.2.13 Fix up PCI configuration space
+ pcifix:<option bits>
+
+ Available option bits:
+ 0x0: No attempt to fix PCI configuration space registers values.
+ 0x1: Set PCI cache-line size register if not set.
+ 0x2: Set write and invalidate bit in PCI command register.
+
+10.2.14 Serial NVRAM
+ nvram:n do not look for serial NVRAM
+ nvram:y test controllers for onboard serial NVRAM
+ (alternate binary form)
+ mvram=<bits options>
+ 0x01 look for NVRAM (equivalent to nvram=y)
+ 0x02 ignore NVRAM "Synchronous negotiation" parameters for all devices
+ 0x04 ignore NVRAM "Wide negotiation" parameter for all devices
+ 0x08 ignore NVRAM "Scan at boot time" parameter for all devices
+ 0x80 also attach controllers set to OFF in the NVRAM (sym53c8xx only)
+
+10.2.15 Check SCSI BUS
+ buschk:<option bits>
+
+ Available option bits:
+ 0x0: No check.
+ 0x1: Check and donnot attach the controller on error.
+ 0x2: Check and just warn on error.
+
+10.2.16 Exclude a host from being attached
+ excl=<io_address>
+
+ Prevent host at a given io address from being attached.
+ For example 'sym53c8xx=excl:0xb400,excl:0xc000' indicate to the
+ driver not to attach hosts at address 0xb400 and 0xc000.
+
+10.2.17 Suggest a default SCSI id for hosts
+ hostid:255 no id suggested.
+ hostid:#x (0 < x < 7) x suggested for hosts SCSI id.
+
+ If a host SCSI id is available from the NVRAM, the driver will ignore
+ any value suggested as boot option. Otherwise, if a suggested value
+ different from 255 has been supplied, it will use it. Otherwise, it will
+ try to deduce the value previously set in the hardware and use value
+ 7 if the hardware value is zero.
+
+10.3 PCI configuration fix-up boot option
+
+pcifix:<option bits>
+
+Available option bits:
+ 0x1: Set PCI cache-line size register if not set.
+ 0x2: Set write and invalidate bit in PCI command register.
+
+Use 'pcifix:3' in order to allow the driver to fix both PCI features.
+
+Recent SYMBIOS 53C8XX scsi processors are able to use PCI read multiple
+and PCI write and invalidate commands. These features require the
+cache line size register to be properly set in the PCI configuration
+space of the chips. On the other hand, chips will use PCI write and
+invalidate commands only if the corresponding bit is set to 1 in the
+PCI command register.
+
+Not all PCI bioses set the PCI cache line register and the PCI write and
+invalidate bit in the PCI configuration space of 53C8XX chips.
+Optimized PCI accesses may be broken for some PCI/memory controllers or
+make problems with some PCI boards.
+
+10.4 Serial NVRAM support boot option
+
+nvram:n do not look for serial NVRAM
+nvram:y test controllers for onboard serial NVRAM
+
+This option can also been entered as an hexadecimal value that allows
+to control what information the driver will get from the NVRAM and what
+information it will ignore.
+For details see '17. Serial NVRAM support'.
+
+When this option is enabled, the driver tries to detect all boards using
+a Serial NVRAM. This memory is used to hold user set up parameters.
+
+The parameters the driver is able to get from the NVRAM depend on the
+data format used, as follow:
+
+ Tekram format Symbios format
+General and host parameters
+ Boot order N Y
+ Host SCSI ID Y Y
+ SCSI parity checking Y Y
+ Verbose boot messages N Y
+SCSI devices parameters
+ Synchronous transfer speed Y Y
+ Wide 16 / Narrow Y Y
+ Tagged Command Queuing enabled Y Y
+ Disconnections enabled Y Y
+ Scan at boot time N Y
+
+In order to speed up the system boot, for each device configured without
+the "scan at boot time" option, the driver forces an error on the
+first TEST UNIT READY command received for this device.
+
+Some SDMS BIOS revisions seem to be unable to boot cleanly with very fast
+hard disks. In such a situation you cannot configure the NVRAM with
+optimized parameters value.
+
+The 'nvram' boot option can be entered in hexadecimal form in order
+to ignore some options configured in the NVRAM, as follow:
+
+mvram=<bits options>
+ 0x01 look for NVRAM (equivalent to nvram=y)
+ 0x02 ignore NVRAM "Synchronous negotiation" parameters for all devices
+ 0x04 ignore NVRAM "Wide negotiation" parameter for all devices
+ 0x08 ignore NVRAM "Scan at boot time" parameter for all devices
+ 0x80 also attach controllers set to OFF in the NVRAM (sym53c8xx only)
+
+Option 0x80 is disabled by default.
+Result is that, by default (option not set), the sym53c8xx driver will not
+attach controllers set to OFF in the NVRAM.
+
+10.5 SCSI BUS checking boot option.
+
+When this option is set to a non-zero value, the driver checks SCSI lines
+logic state, 100 micro-seconds after having asserted the SCSI RESET line.
+The driver just reads SCSI lines and checks all lines read FALSE except RESET.
+Since SCSI devices shall release the BUS at most 800 nano-seconds after SCSI
+RESET has been asserted, any signal to TRUE may indicate a SCSI BUS problem.
+Unfortunately, the following common SCSI BUS problems are not detected:
+- Only 1 terminator installed.
+- Misplaced terminators.
+- Bad quality terminators.
+On the other hand, either bad cabling, broken devices, not conformant
+devices, ... may cause a SCSI signal to be wrong when te driver reads it.
+
+15. SCSI problem troubleshooting
+
+15.1 Problem tracking
+
+Most SCSI problems are due to a non conformant SCSI bus or too buggy
+devices. If infortunately you have SCSI problems, you can check the
+following things:
+
+- SCSI bus cables
+- terminations at both end of the SCSI chain
+- linux syslog messages (some of them may help you)
+
+If you donnot find the source of problems, you can configure the
+driver or devices in the NVRAM with minimal features.
+
+- only asynchronous data transfers
+- tagged commands disabled
+- disconnections not allowed
+
+Now, if your SCSI bus is ok, your system has every chance to work
+with this safe configuration but performances will not be optimal.
+
+If it still fails, then you can send your problem description to
+appropriate mailing lists or news-groups. Send me a copy in order to
+be sure I will receive it. Obviously, a bug in the driver code is
+possible.
+
+ My cyrrent email address: Gerard Roudier <grou...@free.fr>
+
+Allowing disconnections is important if you use several devices on
+your SCSI bus but often causes problems with buggy devices.
+Synchronous data transfers increases throughput of fast devices like
+hard disks. Good SCSI hard disks with a large cache gain advantage of
+tagged commands queuing.
+
+15.2 Understanding hardware error reports
+
+When the driver detects an unexpected error condition, it may display a
+message of the following pattern.
+
+sym0:1: ERROR (0:48) (1-21-65) (f/95/0) @ (script 7c0:19000000).
+sym0: script cmd = 19000000
+sym0: regdump: da 10 80 95 47 0f 01 07 75 01 81 21 80 01 09 00.
+
+Some fields in such a message may help you understand the cause of the
+problem, as follows:
+
+sym0:1: ERROR (0:48) (1-21-65) (f/95/0) @ (script 7c0:19000000).
+.....A.........B.C....D.E..F....G.H..I.......J.....K...L.......
+
+Field A : target number.
+ SCSI ID of the device the controller was talking with at the moment the
+ error occurs.
+
+Field B : DSTAT io register (DMA STATUS)
+ Bit 0x40 : MDPE Master Data Parity Error
+ Data parity error detected on the PCI BUS.
+ Bit 0x20 : BF Bus Fault
+ PCI bus fault condition detected
+ Bit 0x01 : IID Illegal Instruction Detected
+ Set by the chip when it detects an Illegal Instruction format
+ on some condition that makes an instruction illegal.
+ Bit 0x80 : DFE Dma Fifo Empty
+ Pure status bit that does not indicate an error.
+ If the reported DSTAT value contains a combination of MDPE (0x40),
+ BF (0x20), then the cause may be likely due to a PCI BUS problem.
+
+Field C : SIST io register (SCSI Interrupt Status)
+ Bit 0x08 : SGE SCSI GROSS ERROR
+ Indicates that the chip detected a severe error condition
+ on the SCSI BUS that prevents the SCSI protocol from functionning
+ properly.
+ Bit 0x04 : UDC Undexpected Disconnection
+ Indicates that the device released the SCSI BUS when the chip
+ was not expecting this to happen. A device may behave so to
+ indicate the SCSI initiator that an error condition not reportable using the SCSI protocol has occured.
+ Bit 0x02 : RST SCSI BUS Reset
+ Generally SCSI targets donnot reset the SCSI BUS, although any
+ device on the BUS can reset it at any time.
+ Bit 0x01 : PAR Parity
+ SCSI parity error detected.
+ On a faulty SCSI BUS, any error condition among SGE (0x08), UDC (0x04) and
+ PAR (0x01) may be detected by the chip. If your SCSI system sometimes
+ encounters such error conditions, especially SCSI GROSS ERROR, then a SCSI
+ BUS problem is likely the cause of these errors.
+
+For fields D,E,F,G and H, you may look into the sym53c8xx_defs.h file
+that contains some minimal comments on IO register bits.
+Field D : SOCL Scsi Output Control Latch
+ This register reflects the state of the SCSI control lines the
+ chip want to drive or compare against.
+Field E : SBCL Scsi Bus Control Lines
+ Actual value of control lines on the SCSI BUS.
+Field F : SBDL Scsi Bus Data Lines
+ Actual value of data lines on the SCSI BUS.
+Field G : SXFER SCSI Transfer
+ Contains the setting of the Synchronous Period for output and
+ the current Synchronous offset (offset 0 means asynchronous).
+Field H : SCNTL3 Scsi Control Register 3
+ Contains the setting of timing values for both asynchronous and
+ synchronous data transfers.
+Field I : SCNTL4 Scsi Control Register 4
+ Only meaninful for 53C1010 Ultra3 controllers.
+
+Understanding Fields J, K, L and dumps requires to have good knowledge of
+SCSI standards, chip cores functionnals and internal driver data structures.
+You are not required to decode and understand them, unless you want to help
+maintain the driver code.
+
+17. Serial NVRAM (added by Richard Waltham: dorm...@farsrobt.demon.co.uk)
+
+17.1 Features
+
+Enabling serial NVRAM support enables detection of the serial NVRAM included
+on Symbios and some Symbios compatible host adaptors, and Tekram boards. The
+serial NVRAM is used by Symbios and Tekram to hold set up parameters for the
+host adaptor and it's attached drives.
+
+The Symbios NVRAM also holds data on the boot order of host adaptors in a
+system with more than one host adaptor. This enables the order of scanning
+the cards for drives to be changed from the default used during host adaptor
+detection.
+
+This can be done to a limited extent at the moment using "reverse probe" but
+this only changes the order of detection of different types of cards. The
+NVRAM boot order settings can do this as well as change the order the same
+types of cards are scanned in, something "reverse probe" cannot do.
+
+Tekram boards using Symbios chips, DC390W/F/U, which have NVRAM are detected
+and this is used to distinguish between Symbios compatible and Tekram host
+adaptors. This is used to disable the Symbios compatible "diff" setting
+incorrectly set on Tekram boards if the CONFIG_SCSI_53C8XX_SYMBIOS_COMPAT
+configuration parameter is set enabling both Symbios and Tekram boards to be
+used together with the Symbios cards using all their features, including
+"diff" support. ("led pin" support for Symbios compatible cards can remain
+enabled when using Tekram cards. It does nothing useful for Tekram host
+adaptors but does not cause problems either.)
+
+
+17.2 Symbios NVRAM layout
+
+typical data at NVRAM address 0x100 (53c810a NVRAM)
+-----------------------------------------------------------
+00 00
+64 01
+8e 0b
+
+00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00
+
+04 00 0f 00 00 10 00 50 00 00 01 00 00 62
+04 00 03 00 00 10 00 58 00 00 01 00 00 63
+04 00 01 00 00 10 00 48 00 00 01 00 00 61
+00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+
+fe fe
+00 00
+00 00
+-----------------------------------------------------------
+NVRAM layout details
+
+NVRAM Address 0x000-0x0ff not used
+ 0x100-0x26f initialised data
+ 0x270-0x7ff not used
+
+general layout
+
+ header - 6 bytes,
+ data - 356 bytes (checksum is byte sum of this data)
+ trailer - 6 bytes
+ ---
+ total 368 bytes
+
+data area layout
+
+ controller set up - 20 bytes
+ boot configuration - 56 bytes (4x14 bytes)
+ device set up - 128 bytes (16x8 bytes)
+ unused (spare?) - 152 bytes (19x8 bytes)
+ ---
+ total 356 bytes
+
+-----------------------------------------------------------
+header
+
+00 00 - ?? start marker
+64 01 - byte count (lsb/msb excludes header/trailer)
+8e 0b - checksum (lsb/msb excludes header/trailer)
+-----------------------------------------------------------
+controller set up
+
+00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00
+ | | | |
+ | | | -- host ID
+ | | |
+ | | --Removable Media Support
+ | | 0x00 = none
+ | | 0x01 = Bootable Device
+ | | 0x02 = All with Media
+ | |
+ | --flag bits 2
+ | 0x00000001= scan order hi->low
+ | (default 0x00 - scan low->hi)
+ --flag bits 1
+ 0x00000001 scam enable
+ 0x00000010 parity enable
+ 0x00000100 verbose boot msgs
+
+remaining bytes unknown - they do not appear to change in my
+current set up for any of the controllers.
+
+default set up is identical for 53c810a and 53c875 NVRAM
+(Removable Media added Symbios BIOS version 4.09)
+-----------------------------------------------------------
+boot configuration
+
+boot order set by order of the devices in this table
+
+04 00 0f 00 00 10 00 50 00 00 01 00 00 62 -- 1st controller
+04 00 03 00 00 10 00 58 00 00 01 00 00 63 2nd controller
+04 00 01 00 00 10 00 48 00 00 01 00 00 61 3rd controller
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 4th controller
+ | | | | | | | |
+ | | | | | | ---- PCI io port adr
+ | | | | | --0x01 init/scan at boot time
+ | | | | --PCI device/function number (0xdddddfff)
+ | | ----- ?? PCI vendor ID (lsb/msb)
+ ----PCI device ID (lsb/msb)
+
+?? use of this data is a guess but seems reasonable
+
+remaining bytes unknown - they do not appear to change in my
+current set up
+
+default set up is identical for 53c810a and 53c875 NVRAM
+-----------------------------------------------------------
+device set up (up to 16 devices - includes controller)
+
+0f 00 08 08 64 00 0a 00 - id 0
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00 - id 15
+ | | | | | |
+ | | | | ----timeout (lsb/msb)
+ | | | --synch period (0x?? 40 Mtrans/sec- fast 40) (probably 0x28)
+ | | | (0x30 20 Mtrans/sec- fast 20)
+ | | | (0x64 10 Mtrans/sec- fast )
+ | | | (0xc8 5 Mtrans/sec)
+ | | | (0x00 asynchronous)
+ | | -- ?? max sync offset (0x08 in NVRAM on 53c810a)
+ | | (0x10 in NVRAM on 53c875)
+ | --device bus width (0x08 narrow)
+ | (0x10 16 bit wide)
+ --flag bits
+ 0x00000001 - disconnect enabled
+ 0x00000010 - scan at boot time
+ 0x00000100 - scan luns
+ 0x00001000 - queue tags enabled
+
+remaining bytes unknown - they do not appear to change in my
+current set up
+
+?? use of this data is a guess but seems reasonable
+(but it could be max bus width)
+
+default set up for 53c810a NVRAM
+default set up for 53c875 NVRAM - bus width - 0x10
+ - sync offset ? - 0x10
+ - sync period - 0x30
+-----------------------------------------------------------
+?? spare device space (32 bit bus ??)
+
+00 00 00 00 00 00 00 00 (19x8bytes)
+.
+.
+00 00 00 00 00 00 00 00
+
+default set up is identical for 53c810a and 53c875 NVRAM
+-----------------------------------------------------------
+trailer
+
+fe fe - ? end marker ?
+00 00
+00 00
+
+default set up is identical for 53c810a and 53c875 NVRAM
+-----------------------------------------------------------
+
+
+
+17.3 Tekram NVRAM layout
+
+nvram 64x16 (1024 bit)
+
+Drive settings
+
+Drive ID 0-15 (addr 0x0yyyy0 = device setup, yyyy = ID)
+ (addr 0x0yyyy1 = 0x0000)
+
+ x x x x x x x x x x x x x x x x
+ | | | | | | | | |
+ | | | | | | | | ----- parity check 0 - off
+ | | | | | | | | 1 - on
+ | | | | | | | |
+ | | | | | | | ------- sync neg 0 - off
+ | | | | | | | 1 - on
+ | | | | | | |
+ | | | | | | --------- disconnect 0 - off
+ | | | | | | 1 - on
+ | | | | | |
+ | | | | | ----------- start cmd 0 - off
+ | | | | | 1 - on
+ | | | | |
+ | | | | -------------- tagged cmds 0 - off
+ | | | | 1 - on
+ | | | |
+ | | | ---------------- wide neg 0 - off
+ | | | 1 - on
+ | | |
+ --------------------------- sync rate 0 - 10.0 Mtrans/sec
+ 1 - 8.0
+ 2 - 6.6
+ 3 - 5.7
+ 4 - 5.0
+ 5 - 4.0
+ 6 - 3.0
+ 7 - 2.0
+ 7 - 2.0
+ 8 - 20.0
+ 9 - 16.7
+ a - 13.9
+ b - 11.9
+
+Global settings
+
+Host flags 0 (addr 0x100000, 32)
+
+ x x x x x x x x x x x x x x x x
+ | | | | | | | | | | | |
+ | | | | | | | | ----------- host ID 0x00 - 0x0f
+ | | | | | | | |
+ | | | | | | | ----------------------- support for 0 - off
+ | | | | | | | > 2 drives 1 - on
+ | | | | | | |
+ | | | | | | ------------------------- support drives 0 - off
+ | | | | | | > 1Gbytes 1 - on
+ | | | | | |
+ | | | | | --------------------------- bus reset on 0 - off
+ | | | | | power on 1 - on
+ | | | | |
+ | | | | ----------------------------- active neg 0 - off
+ | | | | 1 - on
+ | | | |
+ | | | -------------------------------- imm seek 0 - off
+ | | | 1 - on
+ | | |
+ | | ---------------------------------- scan luns 0 - off
+ | | 1 - on
+ | |
+ -------------------------------------- removable 0 - disable
+ as BIOS dev 1 - boot device
+ 2 - all
+
+Host flags 1 (addr 0x100001, 33)
+
+ x x x x x x x x x x x x x x x x
+ | | | | | |
+ | | | --------- boot delay 0 - 3 sec
+ | | | 1 - 5
+ | | | 2 - 10
+ | | | 3 - 20
+ | | | 4 - 30
+ | | | 5 - 60
+ | | | 6 - 120
+ | | |
+ --------------------------- max tag cmds 0 - 2
+ 1 - 4
+ 2 - 8
+ 3 - 16
+ 4 - 32
+
+Host flags 2 (addr 0x100010, 34)
+
+ x x x x x x x x x x x x x x x x
+ |
+ ----- F2/F6 enable 0 - off ???
+ 1 - on ???
+
+checksum (addr 0x111111)
+
+checksum = 0x1234 - (sum addr 0-63)
+
+----------------------------------------------------------------------------
+
+default nvram data:
+
+0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
+0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
+0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
+0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
+
+0x0f07 0x0400 0x0001 0x0000 0x0000 0x0000 0x0000 0x0000
+0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
+0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
+0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0xfbbc
+
+
+===============================================================================
+End of Linux SYM-2 driver documentation file
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/Makefile linux/drivers/scsi/sym53c8xx_2/Makefile
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/Makefile Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/Makefile Fri Nov 9 15:22:54 2001
@@ -0,0 +1,16 @@
+# File: drivers/sym53c8xx/Makefile
+# Makefile for the NCR/SYMBIOS/LSI 53C8XX PCI SCSI controllers driver.
+
+list-multi := sym53c8xx.o
+sym53c8xx-objs := sym_fw.o sym_glue.o sym_hipd.o sym_malloc.o sym_misc.o sym_nvram.o
+obj-$(CONFIG_SCSI_SYM53C8XX_2) := sym53c8xx.o
+
+EXTRA_CFLAGS += -I.
+
+sym53c8xx.o: $(sym53c8xx-objs)
+ $(LD) -r -o $@ $(sym53c8xx-objs)
+
+include $(TOPDIR)/Rules.make
+
+clean:
+ rm -f *.o
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym53c8xx.h linux/drivers/scsi/sym53c8xx_2/sym53c8xx.h
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym53c8xx.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym53c8xx.h Fri Nov 9 15:22:54 2001
@@ -0,0 +1,370 @@
+/*
+ * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family
+ * of PCI-SCSI IO processors.
+ *
+ * Copyright (C) 1999-2001 Gerard Roudier <grou...@free.fr>
+ *
+ * This driver is derived from the Linux sym53c8xx driver.
+ * Copyright (C) 1998-2000 Gerard Roudier
+ *
+ * The sym53c8xx driver is derived from the ncr53c8xx driver that had been
+ * a port of the FreeBSD ncr driver to Linux-1.2.13.
+ *
+ * The original ncr driver has been written for 386bsd and FreeBSD by
+ * Wolfgang Stanglmeier <wo...@cologne.de>
+ * Stefan Esser <s...@mi.Uni-Koeln.de>
+ * Copyright (C) 1994 Wolfgang Stanglmeier
+ *
+ * Other major contributions:
+ *
+ * NVRAM detection and reading.
+ * Copyright (C) 1997 Richard Waltham <dorm...@farsrobt.demon.co.uk>
+ *
+ *-----------------------------------------------------------------------------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Where this Software is combined with software released under the terms of
+ * the GNU Public License ("GPL") and the terms of the GPL would require the
+ * combined work to also be released under the terms of the GPL, the terms
+ * and conditions of this License will apply in addition to those of the
+ * GPL with the exception of any terms or conditions of this License that
+ * conflict with, or are expressly prohibited by, the GPL.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef SYM53C8XX_H
+#define SYM53C8XX_H
+
+#if !defined(LINUX_VERSION_CODE)
+#include <linux/version.h>
+#endif
+#include <linux/config.h>
+
+/*
+ * Compatibility with ncr53c8xx and sym53c8xx configuration options.
+ */
+#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED
+#ifdef CONFIG_SCSI_NCR53C8XX_IOMAPPED
+#define CONFIG_SCSI_SYM53C8XX_IOMAPPED CONFIG_SCSI_NCR53C8XX_IOMAPPED
+#endif
+#endif
+
+#ifndef CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS
+#ifdef CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
+#define CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
+#endif
+#endif
+
+#ifndef CONFIG_SCSI_SYM53C8XX_MAX_TAGS
+#ifdef CONFIG_SCSI_NCR53C8XX_MAX_TAGS
+#define CONFIG_SCSI_SYM53C8XX_MAX_TAGS CONFIG_SCSI_NCR53C8XX_MAX_TAGS
+#endif
+#endif
+
+int sym53c8xx_detect(Scsi_Host_Template *tpnt);
+const char *sym53c8xx_info(struct Scsi_Host *host);
+
+int sym53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+
+int sym53c8xx_eh_abort_handler(Scsi_Cmnd *);
+int sym53c8xx_eh_device_reset_handler(Scsi_Cmnd *);
+int sym53c8xx_eh_bus_reset_handler(Scsi_Cmnd *);
+int sym53c8xx_eh_host_reset_handler(Scsi_Cmnd *);
+
+#ifdef MODULE
+int sym53c8xx_release(struct Scsi_Host *);
+#else
+#define sym53c8xx_release NULL
+#endif
+
+
+/*
+ * Host template defintion
+ */
+#if (LINUX_VERSION_CODE >= 0x020400) || defined(HOSTS_C) || defined(MODULE)
+
+#include <scsi/scsicam.h>
+
+#define SYM53C8XX { \
+ name: "sym53c8xx", \
+ detect: sym53c8xx_detect, \
+ release: sym53c8xx_release, \
+ info: sym53c8xx_info, \
+ queuecommand: sym53c8xx_queue_command, \
+ use_new_eh_code: 1, \
+ eh_abort_handler: sym53c8xx_eh_abort_handler, \
+ eh_device_reset_handler:sym53c8xx_eh_device_reset_handler, \
+ eh_bus_reset_handler: sym53c8xx_eh_bus_reset_handler, \
+ eh_host_reset_handler: sym53c8xx_eh_host_reset_handler, \
+ bios_param: scsicam_bios_param, \
+ can_queue: 0, \
+ this_id: 7, \
+ sg_tablesize: 0, \
+ cmd_per_lun: 0, \
+ use_clustering: DISABLE_CLUSTERING}
+
+#endif /* defined(HOSTS_C) || defined(MODULE) */
+
+/*
+ * Translate kernel configuration parameters
+ * into corresponding driver parameters.
+ */
+#if !defined(HOSTS_C)
+
+/*
+ * Use normal IO if configured. Forced for alpha and powerpc.
+ * Powerpc fails copying to on-chip RAM using memcpy_toio().
+ * Forced to MMIO for sparc.
+ */
+#if defined(__alpha__)
+#define SYM_CONF_IOMAPPED
+#elif defined(__powerpc__)
+#define SYM_CONF_IOMAPPED
+#define SYM_OPT_NO_BUS_MEMORY_MAPPING
+#elif defined(__sparc__)
+#undef SYM_CONF_IOMAPPED
+#elif defined(CONFIG_SCSI_SYM53C8XX_IOMAPPED)
+#define SYM_CONF_IOMAPPED
+#endif
+
+/*
+ * DMA addressing mode.
+ *
+ * 0 : 32 bit addressing for all chips.
+ * 1 : 40 bit addressing when supported by chip.
+ * 2 : 64 bit addressing when supported by chip,
+ * limited to 16 segments of 4 GB -> 64 GB max.
+ */
+#ifdef CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE
+#define SYM_CONF_DMA_ADDRESSING_MODE CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE
+#endif
+
+/*
+ * NCR PQS/PDS special device support.
+ */
+#if 1
+#define SYM_CONF_PQS_PDS_SUPPORT
+#endif
+
+/*
+ * NVRAM support.
+ */
+#if 1
+#define SYM_CONF_NVRAM_SUPPORT (1)
+#define SYM_SETUP_SYMBIOS_NVRAM (1)
+#define SYM_SETUP_TEKRAM_NVRAM (1)
+#endif
+
+/*
+ * These options are not tunable from 'make config'
+ */
+#if 1
+#define SYM_LINUX_PROC_INFO_SUPPORT
+#define SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT
+#define SYM_LINUX_USER_COMMAND_SUPPORT
+#define SYM_LINUX_USER_INFO_SUPPORT
+#define SYM_LINUX_DEBUG_CONTROL_SUPPORT
+#endif
+
+/*
+ * Also handle old NCR chips if not (0).
+ */
+#define SYM_CONF_GENERIC_SUPPORT (1)
+
+/*
+ * Allow tags from 2 to 256, default 8
+ */
+#ifndef CONFIG_SCSI_SYM53C8XX_MAX_TAGS
+#define CONFIG_SCSI_SYM53C8XX_MAX_TAGS (8)
+#endif
+
+#if CONFIG_SCSI_SYM53C8XX_MAX_TAGS < 2
+#define SYM_CONF_MAX_TAG (2)
+#elif CONFIG_SCSI_SYM53C8XX_MAX_TAGS > 256
+#define SYM_CONF_MAX_TAG (256)
+#else
+#define SYM_CONF_MAX_TAG CONFIG_SCSI_SYM53C8XX_MAX_TAGS
+#endif
+
+#ifndef CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS
+#define CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS SYM_CONF_MAX_TAG
+#endif
+
+/*
+ * Anyway, we configure the driver for at least 64 tags per LUN. :)
+ */
+#if SYM_CONF_MAX_TAG <= 64
+#define SYM_CONF_MAX_TAG_ORDER (6)
+#elif SYM_CONF_MAX_TAG <= 128
+#define SYM_CONF_MAX_TAG_ORDER (7)
+#else
+#define SYM_CONF_MAX_TAG_ORDER (8)
+#endif
+
+/*
+ * Sync transfer frequency at startup.
+ * Allow up to ULTRA-160. The driver will scale the value
+ * according to controller capabilities.
+ */
+#define CONFIG_SCSI_SYM53C8XX_DEFAULT_SYNC (9)
+
+/*
+ * Max number of SG entries.
+ */
+#define SYM_CONF_MAX_SG (96)
+
+/*
+ * Max number of LUNs per target.
+ */
+#if 1 /* defined CONFIG_SCSI_MULTI_LUN */
+#define CONFIG_SCSI_SYM53C8XX_MAX_LUN (16)
+#else
+#define CONFIG_SCSI_SYM53C8XX_MAX_LUN (1)
+#endif
+
+/*
+ * Driver setup structure.
+ *
+ * This structure is initialized from linux config options.
+ * It can be overridden at boot-up by the boot command line.
+ */
+struct sym_driver_setup {
+ u_char pci_parity;
+ u_char scsi_parity;
+ u_short max_tag;
+ u_char min_sync;
+ u_char burst_order;
+ u_char scsi_led;
+ u_char max_wide;
+ u_char scsi_diff;
+ u_char irq_mode;
+ u_char scsi_bus_check;
+ u_char host_id;
+ u_char max_offs;
+ u_char max_lun;
+ u_char pci_fix_up;
+
+ u_char reverse_probe;
+ u_char verbose;
+ u_short debug;
+ u_char settle_delay;
+ u_char use_nvram;
+ u_long excludes[8];
+ char tag_ctrl[100];
+};
+
+#define SYM_SETUP_PCI_PARITY sym_driver_setup.pci_parity
+#define SYM_SETUP_SCSI_PARITY sym_driver_setup.scsi_parity
+#define SYM_SETUP_MAX_TAG sym_driver_setup.max_tag
+#define SYM_SETUP_MIN_SYNC sym_driver_setup.min_sync
+#define SYM_SETUP_BURST_ORDER sym_driver_setup.burst_order
+#define SYM_SETUP_SCSI_LED sym_driver_setup.scsi_led
+#define SYM_SETUP_MAX_WIDE sym_driver_setup.max_wide
+#define SYM_SETUP_SCSI_DIFF sym_driver_setup.scsi_diff
+#define SYM_SETUP_IRQ_MODE sym_driver_setup.irq_mode
+#define SYM_SETUP_SCSI_BUS_CHECK sym_driver_setup.scsi_bus_check
+#define SYM_SETUP_HOST_ID sym_driver_setup.host_id
+#define SYM_SETUP_MAX_OFFS sym_driver_setup.max_offs
+#define SYM_SETUP_MAX_LUN sym_driver_setup.max_lun
+#define SYM_SETUP_PCI_FIX_UP sym_driver_setup.pci_fix_up
+
+/*
+ * Initial setup.
+ *
+ * Can be overriden at startup by a command line.
+ */
+#define SYM_LINUX_DRIVER_SETUP \
+{ \
+ 1, /* pci_parity */ \
+ 1, /* scsi_parity */ \
+ CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS, \
+ CONFIG_SCSI_SYM53C8XX_DEFAULT_SYNC, \
+ 7, /* burst_order */ \
+ 1, /* scsi_led */ \
+ 1, /* max_wide */ \
+ 1, /* scsi_diff */ \
+ 0, /* irq_mode */ \
+ 1, /* scsi_bus_check */ \
+ 7, /* host_id */ \
+ 62, /* max_offs */ \
+ CONFIG_SCSI_SYM53C8XX_MAX_LUN, \
+ 3, /* pci_fix_up */ \
+ 0, /* reverse_probe */ \
+ 0, /* verbose */ \
+ 0, /* debug */ \
+ 3, /* settle_delay */ \
+ 1, /* use_nvram */ \
+}
+
+/*
+ * Boot fail safe setup.
+ *
+ * Override initial setup from boot command line:
+ * sym53c8xx=safe:y
+ */
+#define SYM_LINUX_DRIVER_SAFE_SETUP \
+{ \
+ 0, /* pci_parity */ \
+ 0, /* scsi_parity */ \
+ 0, /* max_tag */ \
+ 50, /* min_sync */ \
+ 0, /* burst_order */ \
+ 0, /* scsi_led */ \
+ 1, /* max_wide */ \
+ 1, /* scsi_diff */ \
+ 0, /* irq_mode */ \
+ 2, /* scsi_bus_check */ \
+ 7, /* host_id */ \
+ 15, /* max_offs */ \
+ 1, /* max_lun */ \
+ 0, /* pci_fix_up */ \
+ 0, /* reverse_probe */ \
+ 2, /* verbose */ \
+ 0, /* debug */ \
+ 10, /* settle_delay */ \
+ 1, /* use_nvram */ \
+}
+
+/*
+ * This structure is initialized from linux config options.
+ * It can be overridden at boot-up by the boot command line.
+ */
+#ifdef SYM_GLUE_C
+struct sym_driver_setup
+ sym_driver_setup = SYM_LINUX_DRIVER_SETUP;
+#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
+u_int sym_debug_flags = 0;
+#endif
+#else
+extern struct sym_driver_setup sym_driver_setup;
+#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
+extern u_int sym_debug_flags;
+#endif
+#endif /* SYM_GLUE_C */
+
+#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
+#define DEBUG_FLAGS sym_debug_flags
+#endif
+#define boot_verbose sym_driver_setup.verbose
+
+#endif /* !defined(HOSTS_C) */
+
+#endif /* SYM53C8XX_H */
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_conf.h linux/drivers/scsi/sym53c8xx_2/sym_conf.h
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_conf.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym_conf.h Fri Nov 9 15:22:54 2001
@@ -0,0 +1,329 @@
+/*
+ * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family
+ * of PCI-SCSI IO processors.
+ *
+ * Copyright (C) 1999-2001 Gerard Roudier <grou...@free.fr>
+ *
+ * This driver is derived from the Linux sym53c8xx driver.
+ * Copyright (C) 1998-2000 Gerard Roudier
+ *
+ * The sym53c8xx driver is derived from the ncr53c8xx driver that had been
+ * a port of the FreeBSD ncr driver to Linux-1.2.13.
+ *
+ * The original ncr driver has been written for 386bsd and FreeBSD by
+ * Wolfgang Stanglmeier <wo...@cologne.de>
+ * Stefan Esser <s...@mi.Uni-Koeln.de>
+ * Copyright (C) 1994 Wolfgang Stanglmeier
+ *
+ * Other major contributions:
+ *
+ * NVRAM detection and reading.
+ * Copyright (C) 1997 Richard Waltham <dorm...@farsrobt.demon.co.uk>
+ *
+ *-----------------------------------------------------------------------------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Where this Software is combined with software released under the terms of
+ * the GNU Public License ("GPL") and the terms of the GPL would require the
+ * combined work to also be released under the terms of the GPL, the terms
+ * and conditions of this License will apply in addition to those of the
+ * GPL with the exception of any terms or conditions of this License that
+ * conflict with, or are expressly prohibited by, the GPL.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY


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

echo 'End of part 059'
echo 'File patch-2.4.15 is continued in part 060'
echo "060" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:24 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part048

#!/bin/sh -x
# this is part 048 of a 115 - part archive


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

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

X }
X
+ /* VG_CREATE now uses minor number in VG structure */
+ if (minor == -1) minor = vg_ptr->vg_number;
+
+ /* Validate it */
+ if (vg[VG_CHR(minor)] != NULL) {
+ P_IOCTL("lvm_do_vg_create ERROR: VG %d in use\n", minor);
+ kfree(vg_ptr);


+ return -EPERM;
+ }
+

X /* we are not that active so far... */
X vg_ptr->vg_status &= ~VG_ACTIVE;
- vg[VG_CHR(minor)] = vg_ptr;
- vg[VG_CHR(minor)]->pe_allocated = 0;
+ vg_ptr->pe_allocated = 0;
X
X if (vg_ptr->pv_max > ABS_MAX_PV) {
X printk(KERN_WARNING
X "%s -- Can't activate VG: ABS_MAX_PV too small\n",
X lvm_name);
X kfree(vg_ptr);
- vg[VG_CHR(minor)] = NULL;
X return -EPERM;
X }
+
X if (vg_ptr->lv_max > ABS_MAX_LV) {
X printk(KERN_WARNING
X "%s -- Can't activate VG: ABS_MAX_LV too small for %u\n",
X lvm_name, vg_ptr->lv_max);
X kfree(vg_ptr);
- vg_ptr = NULL;


X return -EPERM;
X }
X

+ /* create devfs and procfs entries */
+ lvm_fs_create_vg(vg_ptr);
+
+ vg[VG_CHR(minor)] = vg_ptr;
+
X /* get the physical volume structures */
X vg_ptr->pv_act = vg_ptr->pv_cur = 0;


X for (p = 0; p < vg_ptr->pv_max; p++) {

+ pv_t *pvp;
X /* user space address */
X if ((pvp = vg_ptr->pv[p]) != NULL) {
X ret = lvm_do_pv_create(pvp, vg_ptr, p);
@@ -1843,9 +1519,12 @@
X /* get the logical volume structures */
X vg_ptr->lv_cur = 0;
X for (l = 0; l < vg_ptr->lv_max; l++) {
+ lv_t *lvp;
X /* user space address */
X if ((lvp = vg_ptr->lv[l]) != NULL) {
X if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) {
+ P_IOCTL("ERROR: copying LV ptr %p (%d bytes)\n",
+ lvp, sizeof(lv_t));
X lvm_do_vg_remove(minor);
X return -EFAULT;
X }
@@ -1864,12 +1543,10 @@
X }
X }
X
- lvm_do_create_devfs_entry_of_vg ( vg_ptr);
-
X /* Second path to correct snapshot logical volumes which are not
X in place during first path above */
X for (l = 0; l < ls; l++) {
- lvp = snap_lv_ptr[l];
+ lv_t *lvp = snap_lv_ptr[l];
X if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) {
X lvm_do_vg_remove(minor);
X return -EFAULT;
@@ -1880,8 +1557,6 @@
X }
X }
X
- lvm_do_create_proc_entry_of_vg ( vg_ptr);
-
X vfree(snap_lv_ptr);
X
X vg_count++;
@@ -1913,7 +1588,6 @@
X if ( ret != 0) return ret;
X pv_ptr = vg_ptr->pv[p];
X vg_ptr->pe_total += pv_ptr->pe_total;
- lvm_do_create_proc_entry_of_pv(vg_ptr, pv_ptr);


X return 0;
X }
X }

@@ -1963,10 +1637,12 @@
X lv_t *lv_ptr = NULL;
X pv_t *pv_ptr = NULL;
X
+ if (vg_ptr == NULL) return -ENXIO;
+
X if (copy_from_user(vg_name, arg, sizeof(vg_name)) != 0)
X return -EFAULT;
X
- lvm_do_remove_proc_entry_of_vg ( vg_ptr);
+ lvm_fs_remove_vg(vg_ptr);
X
X strncpy ( vg_ptr->vg_name, vg_name, sizeof ( vg_name)-1);
X for ( l = 0; l < vg_ptr->lv_max; l++)
@@ -1988,7 +1664,7 @@
X strncpy(pv_ptr->vg_name, vg_name, NAME_LEN);
X }
X
- lvm_do_create_proc_entry_of_vg ( vg_ptr);
+ lvm_fs_create_vg(vg_ptr);
X
X return 0;
X } /* lvm_do_vg_rename */
@@ -2015,6 +1691,9 @@
X /* let's go inactive */
X vg_ptr->vg_status &= ~VG_ACTIVE;
X
+ /* remove from procfs and devfs */
+ lvm_fs_remove_vg(vg_ptr);
+
X /* free LVs */
X /* first free snapshot logical volumes */
X for (i = 0; i < vg_ptr->lv_max; i++) {
@@ -2042,11 +1721,6 @@
X }
X }
X
- devfs_unregister (ch_devfs_handle[vg_ptr->vg_number]);
- devfs_unregister (vg_devfs_handle[vg_ptr->vg_number]);
-
- lvm_do_remove_proc_entry_of_vg ( vg_ptr);
-
X P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__);
X kfree(vg_ptr);
X vg[VG_CHR(minor)] = NULL;
@@ -2063,66 +1737,112 @@
X * character device support function physical volume create
X */
X static int lvm_do_pv_create(pv_t *pvp, vg_t *vg_ptr, ulong p) {
- pv_t *pv_ptr = NULL;
+ pv_t *pv;
+ int err;
X
- pv_ptr = vg_ptr->pv[p] = kmalloc(sizeof(pv_t),GFP_KERNEL);
- if (pv_ptr == NULL) {
+ pv = kmalloc(sizeof(pv_t),GFP_KERNEL);
+ if (pv == NULL) {
X printk(KERN_CRIT
- "%s -- VG_CREATE: kmalloc error PV at line %d\n",
+ "%s -- PV_CREATE: kmalloc error PV at line %d\n",
X lvm_name, __LINE__);
X return -ENOMEM;
X }
- if (copy_from_user(pv_ptr, pvp, sizeof(pv_t)) != 0) {
+
+ memset(pv, 0, sizeof(*pv));
+
+ if (copy_from_user(pv, pvp, sizeof(pv_t)) != 0) {
+ P_IOCTL("lvm_do_pv_create ERROR: copy PV ptr %p (%d bytes)\n",
+ pvp, sizeof(pv_t));
+ kfree(pv);
X return -EFAULT;
X }
+
+ if ((err = _open_pv(pv))) {
+ kfree(pv);


+ return err;
+ }
+

X /* We don't need the PE list
X in kernel space as with LVs pe_t list (see below) */
- pv_ptr->pe = NULL;
- pv_ptr->pe_allocated = 0;
- pv_ptr->pv_status = PV_ACTIVE;
+ pv->pe = NULL;
+ pv->pe_allocated = 0;
+ pv->pv_status = PV_ACTIVE;
X vg_ptr->pv_act++;
X vg_ptr->pv_cur++;
+ lvm_fs_create_pv(vg_ptr, pv);
X
+ vg_ptr->pv[p] = pv;
X return 0;
X } /* lvm_do_pv_create() */
X
X
X /*
- * character device support function physical volume create
+ * character device support function physical volume remove
X */
X static int lvm_do_pv_remove(vg_t *vg_ptr, ulong p) {
- pv_t *pv_ptr = vg_ptr->pv[p];
+ pv_t *pv = vg_ptr->pv[p];
+
+ lvm_fs_remove_pv(vg_ptr, pv);
X
- lvm_do_remove_proc_entry_of_pv ( vg_ptr, pv_ptr);
- vg_ptr->pe_total -= pv_ptr->pe_total;
+ vg_ptr->pe_total -= pv->pe_total;
X vg_ptr->pv_cur--;
X vg_ptr->pv_act--;
-#ifdef LVM_GET_INODE
- lvm_clear_inode(pv_ptr->inode);
-#endif
- kfree(pv_ptr);
+
+ _close_pv(pv);
+ kfree(pv);
+
X vg_ptr->pv[p] = NULL;


X
X return 0;
X }

X
X
+static void __update_hardsectsize(lv_t *lv) {
+ int le, e;
+ int max_hardsectsize = 0, hardsectsize;
+
+ for (le = 0; le < lv->lv_allocated_le; le++) {
+ hardsectsize = get_hardsect_size(lv->lv_current_pe[le].dev);
+ if (hardsectsize == 0)
+ hardsectsize = 512;
+ if (hardsectsize > max_hardsectsize)
+ max_hardsectsize = hardsectsize;
+ }
+
+ /* only perform this operation on active snapshots */
+ if ((lv->lv_access & LV_SNAPSHOT) &&
+ (lv->lv_status & LV_ACTIVE)) {
+ for (e = 0; e < lv->lv_remap_end; e++) {
+ hardsectsize = get_hardsect_size( lv->lv_block_exception[e].rdev_new);
+ if (hardsectsize == 0)
+ hardsectsize = 512;
+ if (hardsectsize > max_hardsectsize)
+ max_hardsectsize = hardsectsize;
+ }
+ }
+
+ lvm_hardsectsizes[MINOR(lv->lv_dev)] = max_hardsectsize;
+}
+
X /*
X * character device support function logical volume create
X */
X static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
X {
- int e, ret, l, le, l_new, p, size;
+ int e, ret, l, le, l_new, p, size, activate = 1;
X ulong lv_status_save;
X lv_block_exception_t *lvbe = lv->lv_block_exception;
X vg_t *vg_ptr = vg[VG_CHR(minor)];
X lv_t *lv_ptr = NULL;
+ pe_t *pep;
X
- if ((pep = lv->lv_current_pe) == NULL) return -EINVAL;
- if (lv->lv_chunk_size > LVM_SNAPSHOT_MAX_CHUNK)
+ if (!(pep = lv->lv_current_pe))
X return -EINVAL;
X

- for (l = 0; l < vg_ptr->lv_max; l++) {

+ if (_sectors_to_k(lv->lv_chunk_size) > LVM_SNAPSHOT_MAX_CHUNK)
+ return -EINVAL;
+
+ for (l = 0; l < vg_ptr->lv_cur; l++) {
X if (vg_ptr->lv[l] != NULL &&
X strcmp(vg_ptr->lv[l]->lv_name, lv_name) == 0)
X return -EEXIST;
@@ -2151,23 +1871,26 @@
X
X lv_status_save = lv_ptr->lv_status;
X lv_ptr->lv_status &= ~LV_ACTIVE;
- lv_ptr->lv_snapshot_org = \
- lv_ptr->lv_snapshot_prev = \
+ lv_ptr->lv_snapshot_org = NULL;
+ lv_ptr->lv_snapshot_prev = NULL;
X lv_ptr->lv_snapshot_next = NULL;
X lv_ptr->lv_block_exception = NULL;
X lv_ptr->lv_iobuf = NULL;
+ lv_ptr->lv_COW_table_iobuf = NULL;
X lv_ptr->lv_snapshot_hash_table = NULL;
X lv_ptr->lv_snapshot_hash_table_size = 0;
X lv_ptr->lv_snapshot_hash_mask = 0;
- lv_ptr->lv_COW_table_page = NULL;
- init_MUTEX(&lv_ptr->lv_snapshot_sem);
+ init_rwsem(&lv_ptr->lv_lock);
+
X lv_ptr->lv_snapshot_use_rate = 0;
+
X vg_ptr->lv[l] = lv_ptr;
X
X /* get the PE structures from user space if this
- is no snapshot logical volume */
+ is not a snapshot logical volume */
X if (!(lv_ptr->lv_access & LV_SNAPSHOT)) {
X size = lv_ptr->lv_allocated_le * sizeof(pe_t);
+
X if ((lv_ptr->lv_current_pe = vmalloc(size)) == NULL) {
X printk(KERN_CRIT
X "%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte "
@@ -2179,6 +1902,8 @@
X return -ENOMEM;
X }
X if (copy_from_user(lv_ptr->lv_current_pe, pep, size)) {
+ P_IOCTL("ERROR: copying PE ptr %p (%d bytes)\n",
+ pep, sizeof(size));
X vfree(lv_ptr->lv_current_pe);
X kfree(lv_ptr);
X vg_ptr->lv[l] = NULL;
@@ -2200,6 +1925,15 @@
X vg_ptr->lv[LV_BLK(lv_ptr->lv_snapshot_minor)];
X if (lv_ptr->lv_snapshot_org != NULL) {
X size = lv_ptr->lv_remap_end * sizeof(lv_block_exception_t);
+
+ if(!size) {
+ printk(KERN_WARNING
+ "%s -- zero length exception table requested\n",
+ lvm_name);
+ kfree(lv_ptr);


+ return -EINVAL;
+ }
+

X if ((lv_ptr->lv_block_exception = vmalloc(size)) == NULL) {
X printk(KERN_CRIT
X "%s -- lvm_do_lv_create: vmalloc error LV_BLOCK_EXCEPTION "
@@ -2217,6 +1951,17 @@
X vg_ptr->lv[l] = NULL;
X return -EFAULT;
X }
+
+ if(lv_ptr->lv_block_exception[0].rsector_org ==
+ LVM_SNAPSHOT_DROPPED_SECTOR)
+ {
+ printk(KERN_WARNING
+ "%s -- lvm_do_lv_create: snapshot has been dropped and will not be activated\n",
+ lvm_name);
+ activate = 0;
+ }
+
+
X /* point to the original logical volume */
X lv_ptr = lv_ptr->lv_snapshot_org;
X
@@ -2250,10 +1995,13 @@
X lv_ptr->lv_block_exception[e].rsector_org, lv_ptr);
X /* need to fill the COW exception table data
X into the page for disk i/o */
- lvm_snapshot_fill_COW_page(vg_ptr, lv_ptr);
+ if(lvm_snapshot_fill_COW_page(vg_ptr, lv_ptr)) {
+ kfree(lv_ptr);
+ vg_ptr->lv[l] = NULL;
+ return -EINVAL;
+ }
X init_waitqueue_head(&lv_ptr->lv_snapshot_wait);
X } else {
- vfree(lv_ptr->lv_block_exception);
X kfree(lv_ptr);
X vg_ptr->lv[l] = NULL;
X return -EFAULT;
@@ -2275,21 +2023,7 @@
X vg_ptr->lv_cur++;
X lv_ptr->lv_status = lv_status_save;
X
- {
- char *lv_tmp, *lv_buf = lv->lv_name;
-
- strtok(lv->lv_name, "/"); /* /dev */
- while((lv_tmp = strtok(NULL, "/")) != NULL)
- lv_buf = lv_tmp;
-
- lv_devfs_handle[lv->lv_number] = devfs_register(
- vg_devfs_handle[vg_ptr->vg_number], lv_buf,
- DEVFS_FL_DEFAULT, LVM_BLK_MAJOR, lv->lv_number,
- S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
- &lvm_blk_dops, NULL);
- }
-
- lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
+ __update_hardsectsize(lv_ptr);
X
X /* optionally add our new snapshot LV */
X if (lv_ptr->lv_access & LV_SNAPSHOT) {
@@ -2302,7 +2036,7 @@
X fsync_dev_lockfs(org->lv_dev);
X #endif
X
- down(&org->lv_snapshot_sem);
+ down_write(&org->lv_lock);
X org->lv_access |= LV_SNAPSHOT_ORG;
X lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG; /* this can only hide an userspace bug */
X
@@ -2310,11 +2044,15 @@
X for (last = org; last->lv_snapshot_next; last = last->lv_snapshot_next);
X lv_ptr->lv_snapshot_prev = last;
X last->lv_snapshot_next = lv_ptr;
- up(&org->lv_snapshot_sem);
+ up_write(&org->lv_lock);
X }
X
X /* activate the logical volume */
- lv_ptr->lv_status |= LV_ACTIVE;
+ if(activate)
+ lv_ptr->lv_status |= LV_ACTIVE;
+ else
+ lv_ptr->lv_status &= ~LV_ACTIVE;
+
X if ( lv_ptr->lv_access & LV_WRITE)
X set_device_ro(lv_ptr->lv_dev, 0);
X else
@@ -2322,13 +2060,15 @@
X
X #ifdef LVM_VFS_ENHANCEMENT
X /* VFS function call to unlock the filesystem */


- if (lv_ptr->lv_access & LV_SNAPSHOT) {

+ if (lv_ptr->lv_access & LV_SNAPSHOT)
X unlockfs(lv_ptr->lv_snapshot_org->lv_dev);
- }
X #endif
X
X lv_ptr->vg = vg_ptr;
X
+ lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].de =
+ lvm_fs_create_lv(vg_ptr, lv_ptr);
+
X return 0;
X } /* lvm_do_lv_create() */
X
@@ -2366,13 +2106,15 @@
X lv_ptr->lv_snapshot_next != NULL)
X return -EPERM;
X
+ lvm_fs_remove_lv(vg_ptr, lv_ptr);
+
X if (lv_ptr->lv_access & LV_SNAPSHOT) {
X /*
X * Atomically make the the snapshot invisible
X * to the original lv before playing with it.
X */
X lv_t * org = lv_ptr->lv_snapshot_org;
- down(&org->lv_snapshot_sem);
+ down_write(&org->lv_lock);
X
X /* remove this snapshot logical volume from the chain */
X lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next;
@@ -2380,11 +2122,13 @@
X lv_ptr->lv_snapshot_next->lv_snapshot_prev =
X lv_ptr->lv_snapshot_prev;
X }
- up(&org->lv_snapshot_sem);
X
X /* no more snapshots? */
- if (!org->lv_snapshot_next)
+ if (!org->lv_snapshot_next) {
X org->lv_access &= ~LV_SNAPSHOT_ORG;
+ }
+ up_write(&org->lv_lock);
+
X lvm_snapshot_release(lv_ptr);
X
X /* Update the VG PE(s) used by snapshot reserve space. */
@@ -2404,6 +2148,7 @@
X /* reset generic hd */
X lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].start_sect = -1;
X lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].nr_sects = 0;
+ lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].de = 0;
X lvm_size[MINOR(lv_ptr->lv_dev)] = 0;
X
X /* reset VG/LV mapping */
@@ -2427,10 +2172,6 @@
X vfree(lv_ptr->lv_current_pe);
X }
X
- devfs_unregister(lv_devfs_handle[lv_ptr->lv_number]);
-
- lvm_do_remove_proc_entry_of_lv ( vg_ptr, lv_ptr);
-
X P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__);
X kfree(lv_ptr);
X vg_ptr->lv[l] = NULL;
@@ -2440,205 +2181,217 @@
X
X
X /*
- * character device support function logical volume extend / reduce
+ * logical volume extend / reduce
X */
-static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *lv)
-{
- ulong end, l, le, p, size, old_allocated_le;
- vg_t *vg_ptr = vg[VG_CHR(minor)];
- lv_t *lv_ptr;
- pe_t *pe;
-
- if ((pep = lv->lv_current_pe) == NULL) return -EINVAL;
-


- for (l = 0; l < vg_ptr->lv_max; l++) {

- if (vg_ptr->lv[l] != NULL &&
- strcmp(vg_ptr->lv[l]->lv_name, lv_name) == 0)
- break;
- }
- if (l == vg_ptr->lv_max) return -ENXIO;
- lv_ptr = vg_ptr->lv[l];
-
- /* check for active snapshot */
- if (lv->lv_access & LV_SNAPSHOT)
- {
- ulong e;
- lv_block_exception_t *lvbe, *lvbe_old;
- struct list_head * lvs_hash_table_old;
-
- if (lv->lv_block_exception == NULL) return -ENXIO;
- size = lv->lv_remap_end * sizeof ( lv_block_exception_t);
- if ((lvbe = vmalloc(size)) == NULL)
- {
- printk(KERN_CRIT
- "%s -- lvm_do_lv_extend_reduce: vmalloc error LV_BLOCK_EXCEPTION "
- "of %lu Byte at line %d\n",
- lvm_name, size, __LINE__);
- return -ENOMEM;
- }
- if (lv->lv_remap_end > lv_ptr->lv_remap_end)
- {
- if (copy_from_user(lvbe, lv->lv_block_exception, size))
- {
- vfree(lvbe);


- return -EFAULT;
- }
- }

-
- lvbe_old = lv_ptr->lv_block_exception;
- lvs_hash_table_old = lv_ptr->lv_snapshot_hash_table;
-
- /* we need to play on the safe side here... */
- down(&lv_ptr->lv_snapshot_org->lv_snapshot_sem);
- if (lv_ptr->lv_block_exception == NULL ||
- lv_ptr->lv_remap_ptr > lv_ptr->lv_remap_end)
- {
- up(&lv_ptr->lv_snapshot_org->lv_snapshot_sem);
- vfree(lvbe);
- return -EPERM;
- }
- memcpy(lvbe,
- lv_ptr->lv_block_exception,
- (lv->lv_remap_end > lv_ptr->lv_remap_end ?
- lv_ptr->lv_remap_ptr : lv->lv_remap_end) * sizeof(lv_block_exception_t));
-
- lv_ptr->lv_block_exception = lvbe;
- lv_ptr->lv_remap_end = lv->lv_remap_end;
- if (lvm_snapshot_alloc_hash_table(lv_ptr) != 0)
- {
- lvm_drop_snapshot(lv_ptr, "no memory for hash table");
- up(&lv_ptr->lv_snapshot_org->lv_snapshot_sem);
- vfree(lvbe_old);
- vfree(lvs_hash_table_old);
- return -ENOMEM;
- }
-
- for (e = 0; e < lv_ptr->lv_remap_ptr; e++)
- lvm_hash_link (lv_ptr->lv_block_exception + e,
- lv_ptr->lv_block_exception[e].rdev_org,
- lv_ptr->lv_block_exception[e].rsector_org, lv_ptr);
-
- up(&lv_ptr->lv_snapshot_org->lv_snapshot_sem);
-
- vfree(lvbe_old);
- vfree(lvs_hash_table_old);
-
- return 0;
- }
+static int __extend_reduce_snapshot(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) {
+ ulong size;
+ lv_block_exception_t *lvbe;
+
+ if (!new_lv->lv_block_exception)
+ return -ENXIO;
+
+ size = new_lv->lv_remap_end * sizeof(lv_block_exception_t);
+ if ((lvbe = vmalloc(size)) == NULL) {
+ printk(KERN_CRIT
+ "%s -- lvm_do_lv_extend_reduce: vmalloc "
+ "error LV_BLOCK_EXCEPTION of %lu Byte at line %d\n",
+ lvm_name, size, __LINE__);
+ return -ENOMEM;
+ }
X
+ if ((new_lv->lv_remap_end > old_lv->lv_remap_end) &&
+ (copy_from_user(lvbe, new_lv->lv_block_exception, size))) {
+ vfree(lvbe);
+ return -EFAULT;
+ }
+ new_lv->lv_block_exception = lvbe;
X
- /* we drop in here in case it is an original logical volume */
- if ((pe = vmalloc(size = lv->lv_current_le * sizeof(pe_t))) == NULL) {
- printk(KERN_CRIT
- "%s -- lvm_do_lv_extend_reduce: vmalloc error LV_CURRENT_PE "
- "of %lu Byte at line %d\n",
- lvm_name, size, __LINE__);
- return -ENOMEM;
- }
- /* get the PE structures from user space */
- if (copy_from_user(pe, pep, size)) {
- vfree(pe);
- return -EFAULT;
- }
+ if (lvm_snapshot_alloc_hash_table(new_lv)) {
+ vfree(new_lv->lv_block_exception);
+ return -ENOMEM;
+ }
X
- /* reduce allocation counters on PV(s) */
- for (le = 0; le < lv_ptr->lv_allocated_le; le++) {
- vg_ptr->pe_allocated--;
- for (p = 0; p < vg_ptr->pv_cur; p++) {
- if (vg_ptr->pv[p]->pv_dev ==
- lv_ptr->lv_current_pe[le].dev) {
- vg_ptr->pv[p]->pe_allocated--;


- break;
- }
- }
- }

+ return 0;
+}
X

+static int __extend_reduce(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) {
+ ulong size, l, p, end;
+ pe_t *pe;
+
+ /* allocate space for new pe structures */
+ size = new_lv->lv_current_le * sizeof(pe_t);
+ if ((pe = vmalloc(size)) == NULL) {
+ printk(KERN_CRIT
+ "%s -- lvm_do_lv_extend_reduce: "
+ "vmalloc error LV_CURRENT_PE of %lu Byte at line %d\n",
+ lvm_name, size, __LINE__);
+ return -ENOMEM;
+ }
X
- /* save pointer to "old" lv/pe pointer array */
- pep1 = lv_ptr->lv_current_pe;
- end = lv_ptr->lv_current_le;
-
- /* save open counter... */
- lv->lv_open = lv_ptr->lv_open;
- lv->lv_snapshot_prev = lv_ptr->lv_snapshot_prev;
- lv->lv_snapshot_next = lv_ptr->lv_snapshot_next;
- lv->lv_snapshot_org = lv_ptr->lv_snapshot_org;
+ /* get the PE structures from user space */
+ if (copy_from_user(pe, new_lv->lv_current_pe, size)) {
+ if(old_lv->lv_access & LV_SNAPSHOT)
+ vfree(new_lv->lv_snapshot_hash_table);
+ vfree(pe);


+ return -EFAULT;
+ }
X

- lv->lv_current_pe = pe;
+ new_lv->lv_current_pe = pe;
X
- /* save # of old allocated logical extents */
- old_allocated_le = lv_ptr->lv_allocated_le;
+ /* reduce allocation counters on PV(s) */
+ for (l = 0; l < old_lv->lv_allocated_le; l++) {
+ vg_ptr->pe_allocated--;
+ for (p = 0; p < vg_ptr->pv_cur; p++) {
+ if (vg_ptr->pv[p]->pv_dev ==
+ old_lv->lv_current_pe[l].dev) {
+ vg_ptr->pv[p]->pe_allocated--;


+ break;
+ }
+ }
+ }

X
- /* copy preloaded LV */
- memcpy((char *) lv_ptr, (char *) lv, sizeof(lv_t));
+ /* extend the PE count in PVs */
+ for (l = 0; l < new_lv->lv_allocated_le; l++) {
+ vg_ptr->pe_allocated++;
+ for (p = 0; p < vg_ptr->pv_cur; p++) {
+ if (vg_ptr->pv[p]->pv_dev ==
+ new_lv->lv_current_pe[l].dev) {
+ vg_ptr->pv[p]->pe_allocated++;


+ break;
+ }
+ }
+ }

X
- lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].start_sect = 0;
- lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].nr_sects = lv_ptr->lv_size;
- lvm_size[MINOR(lv_ptr->lv_dev)] = lv_ptr->lv_size >> 1;
- /* vg_lv_map array doesn't have to be changed here */
+ /* save availiable i/o statistic data */
+ if (old_lv->lv_stripes < 2) { /* linear logical volume */
+ end = min(old_lv->lv_current_le, new_lv->lv_current_le);
+ for (l = 0; l < end; l++) {
+ new_lv->lv_current_pe[l].reads +=
+ old_lv->lv_current_pe[l].reads;
X
- LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead);
+ new_lv->lv_current_pe[l].writes +=
+ old_lv->lv_current_pe[l].writes;
+ }
X
- /* save availiable i/o statistic data */
- /* linear logical volume */
- if (lv_ptr->lv_stripes < 2) {
- /* Check what last LE shall be used */
- if (end > lv_ptr->lv_current_le) end = lv_ptr->lv_current_le;
- for (le = 0; le < end; le++) {
- lv_ptr->lv_current_pe[le].reads += pep1[le].reads;
- lv_ptr->lv_current_pe[le].writes += pep1[le].writes;
- }
- /* striped logical volume */
- } else {
- uint i, j, source, dest, end, old_stripe_size, new_stripe_size;
+ } else { /* striped logical volume */
+ uint i, j, source, dest, end, old_stripe_size, new_stripe_size;
X
- old_stripe_size = old_allocated_le / lv_ptr->lv_stripes;
- new_stripe_size = lv_ptr->lv_allocated_le / lv_ptr->lv_stripes;
- end = old_stripe_size;
- if (end > new_stripe_size) end = new_stripe_size;
- for (i = source = dest = 0;
- i < lv_ptr->lv_stripes; i++) {
- for (j = 0; j < end; j++) {
- lv_ptr->lv_current_pe[dest + j].reads +=
- pep1[source + j].reads;
- lv_ptr->lv_current_pe[dest + j].writes +=
- pep1[source + j].writes;
- }
- source += old_stripe_size;
- dest += new_stripe_size;
- }
- }
+ old_stripe_size = old_lv->lv_allocated_le / old_lv->lv_stripes;
+ new_stripe_size = new_lv->lv_allocated_le / new_lv->lv_stripes;
+ end = min(old_stripe_size, new_stripe_size);
+
+ for (i = source = dest = 0;
+ i < new_lv->lv_stripes; i++) {
+ for (j = 0; j < end; j++) {
+ new_lv->lv_current_pe[dest + j].reads +=
+ old_lv->lv_current_pe[source + j].reads;
+ new_lv->lv_current_pe[dest + j].writes +=
+ old_lv->lv_current_pe[source + j].writes;
+ }
+ source += old_stripe_size;
+ dest += new_stripe_size;
+ }
+ }
X
- /* extend the PE count in PVs */
- for (le = 0; le < lv_ptr->lv_allocated_le; le++) {
- vg_ptr->pe_allocated++;
- for (p = 0; p < vg_ptr->pv_cur; p++) {
- if (vg_ptr->pv[p]->pv_dev ==
- lv_ptr->lv_current_pe[le].dev) {
- vg_ptr->pv[p]->pe_allocated++;


- break;
- }
- }
- }

+ return 0;
+}
X

- vfree ( pep1);
- pep1 = NULL;
+static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *new_lv)
+{
+ int r;
+ ulong l, e, size;
+ vg_t *vg_ptr = vg[VG_CHR(minor)];
+ lv_t *old_lv;
+ pe_t *pe;
+
+ if ((pe = new_lv->lv_current_pe) == NULL)
+ return -EINVAL;
+
+ for (l = 0; l < vg_ptr->lv_max; l++)
+ if (vg_ptr->lv[l] && !strcmp(vg_ptr->lv[l]->lv_name, lv_name))
+ break;
+
+ if (l == vg_ptr->lv_max)
+ return -ENXIO;
+
+ old_lv = vg_ptr->lv[l];
+
+ if (old_lv->lv_access & LV_SNAPSHOT) {
+ /* only perform this operation on active snapshots */
+ if (old_lv->lv_status & LV_ACTIVE)
+ r = __extend_reduce_snapshot(vg_ptr, old_lv, new_lv);
+ else
+ r = -EPERM;
+
+ } else
+ r = __extend_reduce(vg_ptr, old_lv, new_lv);
+
+ if(r)
+ return r;
+
+ /* copy relevent fields */
+ down_write(&old_lv->lv_lock);
+
+ if(new_lv->lv_access & LV_SNAPSHOT) {
+ size = (new_lv->lv_remap_end > old_lv->lv_remap_end) ?
+ old_lv->lv_remap_ptr : new_lv->lv_remap_end;
+ size *= sizeof(lv_block_exception_t);
+ memcpy(new_lv->lv_block_exception,
+ old_lv->lv_block_exception, size);
+
+ old_lv->lv_remap_end = new_lv->lv_remap_end;
+ old_lv->lv_block_exception = new_lv->lv_block_exception;
+ old_lv->lv_snapshot_hash_table =
+ new_lv->lv_snapshot_hash_table;
+ old_lv->lv_snapshot_hash_table_size =
+ new_lv->lv_snapshot_hash_table_size;
+ old_lv->lv_snapshot_hash_mask =
+ new_lv->lv_snapshot_hash_mask;
+
+ for (e = 0; e < new_lv->lv_remap_ptr; e++)
+ lvm_hash_link(new_lv->lv_block_exception + e,
+ new_lv->lv_block_exception[e].rdev_org,
+ new_lv->lv_block_exception[e].rsector_org,
+ new_lv);
+
+ } else {
+
+ vfree(old_lv->lv_current_pe);
+ vfree(old_lv->lv_snapshot_hash_table);
+
+ old_lv->lv_size = new_lv->lv_size;
+ old_lv->lv_allocated_le = new_lv->lv_allocated_le;
+ old_lv->lv_current_le = new_lv->lv_current_le;
+ old_lv->lv_current_pe = new_lv->lv_current_pe;
+ lvm_gendisk.part[MINOR(old_lv->lv_dev)].nr_sects =
+ old_lv->lv_size;
+ lvm_size[MINOR(old_lv->lv_dev)] = old_lv->lv_size >> 1;
+
+ if (old_lv->lv_access & LV_SNAPSHOT_ORG) {
+ lv_t *snap;
+ for(snap = old_lv->lv_snapshot_next; snap;


+ snap = snap->lv_snapshot_next) {

+ down_write(&snap->lv_lock);
+ snap->lv_current_pe = old_lv->lv_current_pe;
+ snap->lv_allocated_le =
+ old_lv->lv_allocated_le;
+ snap->lv_current_le = old_lv->lv_current_le;
+ snap->lv_size = old_lv->lv_size;
+
+ lvm_gendisk.part[MINOR(snap->lv_dev)].nr_sects
+ = old_lv->lv_size;
+ lvm_size[MINOR(snap->lv_dev)] =
+ old_lv->lv_size >> 1;
+ __update_hardsectsize(snap);
+ up_write(&snap->lv_lock);
+ }
+ }
+ }
X

- if (lv->lv_access & LV_SNAPSHOT_ORG)

- {
- /* Correct the snapshot size information */
- while ((lv_ptr = lv_ptr->lv_snapshot_next) != NULL)
- {
- lv_ptr->lv_current_pe = lv_ptr->lv_snapshot_org->lv_current_pe;
- lv_ptr->lv_allocated_le = lv_ptr->lv_snapshot_org->lv_allocated_le;
- lv_ptr->lv_current_le = lv_ptr->lv_snapshot_org->lv_current_le;
- lv_ptr->lv_size = lv_ptr->lv_snapshot_org->lv_size;
- lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].nr_sects = lv_ptr->lv_size;
- lvm_size[MINOR(lv_ptr->lv_dev)] = lv_ptr->lv_size >> 1;
- }
- }
+ __update_hardsectsize(old_lv);
+ up_write(&old_lv->lv_lock);
X
- return 0;
+ return 0;
X } /* lvm_do_lv_extend_reduce() */
X
X
@@ -2648,10 +2401,10 @@
X static int lvm_do_lv_status_byname(vg_t *vg_ptr, void *arg)
X {
X uint l;
- ulong size;
- lv_t lv;
- lv_t *lv_ptr;
X lv_status_byname_req_t lv_status_byname_req;
+ void *saved_ptr1;
+ void *saved_ptr2;
+ lv_t *lv_ptr;


X
X if (vg_ptr == NULL) return -ENXIO;

X if (copy_from_user(&lv_status_byname_req, arg,
@@ -2659,28 +2412,31 @@
X return -EFAULT;
X
X if (lv_status_byname_req.lv == NULL) return -EINVAL;
- if (copy_from_user(&lv, lv_status_byname_req.lv,
- sizeof(lv_t)) != 0)
- return -EFAULT;
X
X for (l = 0; l < vg_ptr->lv_max; l++) {
- lv_ptr = vg_ptr->lv[l];
- if (lv_ptr != NULL &&
+ if ((lv_ptr = vg_ptr->lv[l]) != NULL &&
X strcmp(lv_ptr->lv_name,
- lv_status_byname_req.lv_name) == 0) {
- if (copy_to_user(lv_status_byname_req.lv,
+ lv_status_byname_req.lv_name) == 0) {
+ /* Save usermode pointers */
+ if (copy_from_user(&saved_ptr1, &lv_status_byname_req.lv->lv_current_pe, sizeof(void*)) != 0)
+ return -EFAULT;
+ if (copy_from_user(&saved_ptr2, &lv_status_byname_req.lv->lv_block_exception, sizeof(void*)) != 0)
+ return -EFAULT;
+ if (copy_to_user(lv_status_byname_req.lv,
X lv_ptr,
X sizeof(lv_t)) != 0)
X return -EFAULT;
X
- if (lv.lv_current_pe != NULL) {
- size = lv_ptr->lv_allocated_le *
- sizeof(pe_t);
- if (copy_to_user(lv.lv_current_pe,
+ if (saved_ptr1 != NULL) {
+ if (copy_to_user(saved_ptr1,
X lv_ptr->lv_current_pe,
- size) != 0)
+ lv_ptr->lv_allocated_le *
+ sizeof(pe_t)) != 0)
X return -EFAULT;
X }
+ /* Restore usermode pointers */
+ if (copy_to_user(&lv_status_byname_req.lv->lv_current_pe, &saved_ptr1, sizeof(void*)) != 0)
+ return -EFAULT;


X return 0;
X }
X }

@@ -2693,34 +2449,44 @@
X */
X static int lvm_do_lv_status_byindex(vg_t *vg_ptr,void *arg)
X {
- ulong size;
- lv_t lv;
- lv_t *lv_ptr;
X lv_status_byindex_req_t lv_status_byindex_req;
+ void *saved_ptr1;
+ void *saved_ptr2;
+ lv_t *lv_ptr;


X
X if (vg_ptr == NULL) return -ENXIO;

X if (copy_from_user(&lv_status_byindex_req, arg,
X sizeof(lv_status_byindex_req)) != 0)
X return -EFAULT;
X
- if ((lvp = lv_status_byindex_req.lv) == NULL)
+ if (lv_status_byindex_req.lv == NULL)
+ return -EINVAL;
+ if (lv_status_byindex_req.lv_index <0 ||
+ lv_status_byindex_req.lv_index >= MAX_LV)
X return -EINVAL;
X if ( ( lv_ptr = vg_ptr->lv[lv_status_byindex_req.lv_index]) == NULL)
X return -ENXIO;
X
- if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0)
- return -EFAULT;
+ /* Save usermode pointers */
+ if (copy_from_user(&saved_ptr1, &lv_status_byindex_req.lv->lv_current_pe, sizeof(void*)) != 0)
+ return -EFAULT;
+ if (copy_from_user(&saved_ptr2, &lv_status_byindex_req.lv->lv_block_exception, sizeof(void*)) != 0)
+ return -EFAULT;
X
- if (copy_to_user(lvp, lv_ptr, sizeof(lv_t)) != 0)
+ if (copy_to_user(lv_status_byindex_req.lv, lv_ptr, sizeof(lv_t)) != 0)
X return -EFAULT;
-
- if (lv.lv_current_pe != NULL) {
- size = lv_ptr->lv_allocated_le * sizeof(pe_t);
- if (copy_to_user(lv.lv_current_pe,
- lv_ptr->lv_current_pe,
- size) != 0)
+ if (saved_ptr1 != NULL) {
+ if (copy_to_user(saved_ptr1,
+ lv_ptr->lv_current_pe,
+ lv_ptr->lv_allocated_le *
+ sizeof(pe_t)) != 0)
X return -EFAULT;
X }
+
+ /* Restore usermode pointers */
+ if (copy_to_user(&lv_status_byindex_req.lv->lv_current_pe, &saved_ptr1, sizeof(void *)) != 0)
+ return -EFAULT;
+
X return 0;
X } /* lvm_do_lv_status_byindex() */
X
@@ -2731,6 +2497,9 @@
X static int lvm_do_lv_status_bydev(vg_t * vg_ptr, void * arg) {
X int l;
X lv_status_bydev_req_t lv_status_bydev_req;
+ void *saved_ptr1;
+ void *saved_ptr2;
+ lv_t *lv_ptr;


X
X if (vg_ptr == NULL) return -ENXIO;

X if (copy_from_user(&lv_status_bydev_req, arg,
@@ -2743,10 +2512,26 @@
X }
X
X if ( l == vg_ptr->lv_max) return -ENXIO;
+ lv_ptr = vg_ptr->lv[l];
+
+ /* Save usermode pointers */
+ if (copy_from_user(&saved_ptr1, &lv_status_bydev_req.lv->lv_current_pe, sizeof(void*)) != 0)
+ return -EFAULT;
+ if (copy_from_user(&saved_ptr2, &lv_status_bydev_req.lv->lv_block_exception, sizeof(void*)) != 0)
+ return -EFAULT;
X
- if (copy_to_user(lv_status_bydev_req.lv,
- vg_ptr->lv[l], sizeof(lv_t)) != 0)
+ if (copy_to_user(lv_status_bydev_req.lv, lv_ptr, sizeof(lv_t)) != 0)
X return -EFAULT;
+ if (saved_ptr1 != NULL) {
+ if (copy_to_user(saved_ptr1,
+ lv_ptr->lv_current_pe,
+ lv_ptr->lv_allocated_le *
+ sizeof(pe_t)) != 0)
+ return -EFAULT;
+ }
+ /* Restore usermode pointers */
+ if (copy_to_user(&lv_status_bydev_req.lv->lv_current_pe, &saved_ptr1, sizeof(void *)) != 0)
+ return -EFAULT;
X
X return 0;
X } /* lvm_do_lv_status_bydev() */
@@ -2766,11 +2551,11 @@
X if ( (lv_ptr = vg_ptr->lv[l]) == NULL) continue;
X if (lv_ptr->lv_dev == lv->lv_dev)
X {
- lvm_do_remove_proc_entry_of_lv ( vg_ptr, lv_ptr);
+ lvm_fs_remove_lv(vg_ptr, lv_ptr);
X strncpy(lv_ptr->lv_name,
X lv_req->lv_name,
X NAME_LEN);
- lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
+ lvm_fs_create_lv(vg_ptr, lv_ptr);
X break;
X }
X }
@@ -2787,9 +2572,7 @@
X {
X uint p;
X pv_t *pv_ptr;
-#ifdef LVM_GET_INODE
- struct inode *inode_sav;
-#endif
+ struct block_device *bd;


X
X if (vg_ptr == NULL) return -ENXIO;

X if (copy_from_user(&pv_change_req, arg,
@@ -2801,20 +2584,17 @@
X if (pv_ptr != NULL &&
X strcmp(pv_ptr->pv_name,
X pv_change_req.pv_name) == 0) {
-#ifdef LVM_GET_INODE
- inode_sav = pv_ptr->inode;
-#endif
+
+ bd = pv_ptr->bd;
X if (copy_from_user(pv_ptr,
X pv_change_req.pv,
X sizeof(pv_t)) != 0)
X return -EFAULT;
+ pv_ptr->bd = bd;
X
X /* We don't need the PE list
X in kernel space as with LVs pe_t list */
X pv_ptr->pe = NULL;
-#ifdef LVM_GET_INODE
- pv_ptr->inode = inode_sav;
-#endif


X return 0;
X }
X }

@@ -2849,161 +2629,27 @@
X return -ENXIO;
X } /* lvm_do_pv_status() */
X
-
-
-/*
- * create a devfs entry for a volume group
- */
-void lvm_do_create_devfs_entry_of_vg ( vg_t *vg_ptr) {
- vg_devfs_handle[vg_ptr->vg_number] = devfs_mk_dir(0, vg_ptr->vg_name, NULL);
- ch_devfs_handle[vg_ptr->vg_number] = devfs_register(
- vg_devfs_handle[vg_ptr->vg_number] , "group",
- DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR, vg_ptr->vg_number,


- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
- &lvm_chr_fops, NULL);
-}
-

-
-/*
- * create a /proc entry for a logical volume
- */
-void lvm_do_create_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) {
- char *basename;
-
- if ( vg_ptr->lv_subdir_pde != NULL) {


- basename = strrchr(lv_ptr->lv_name, '/');

- if (basename == NULL) basename = lv_ptr->lv_name;
- else basename++;
- pde = create_proc_entry(basename, S_IFREG,
- vg_ptr->lv_subdir_pde);
- if ( pde != NULL) {
- pde->read_proc = lvm_proc_read_lv_info;
- pde->data = lv_ptr;


- }
- }
-}
-
-

-/*
- * remove a /proc entry for a logical volume
- */
-void lvm_do_remove_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) {
- char *basename;
-
- if ( vg_ptr->lv_subdir_pde != NULL) {


- basename = strrchr(lv_ptr->lv_name, '/');

- if (basename == NULL) basename = lv_ptr->lv_name;
- else basename++;
- remove_proc_entry(basename, vg_ptr->lv_subdir_pde);
- }


-}
-
-
X /*

- * create a /proc entry for a physical volume
+ * character device support function flush and invalidate all buffers of a PV
X */
-void lvm_do_create_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) {
- int offset = 0;
- char *basename;
- char buffer[NAME_LEN];
-
- basename = pv_ptr->pv_name;
- if (strncmp(basename, "/dev/", 5) == 0) offset = 5;
- strncpy(buffer, basename + offset, sizeof(buffer));
- basename = buffer;
- while ( ( basename = strchr ( basename, '/')) != NULL) *basename = '_';
- pde = create_proc_entry(buffer, S_IFREG, vg_ptr->pv_subdir_pde);
- if ( pde != NULL) {
- pde->read_proc = lvm_proc_read_pv_info;
- pde->data = pv_ptr;
- }
-}
-
-
-/*
- * remove a /proc entry for a physical volume
- */
-void lvm_do_remove_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) {
- char *basename;
-
- basename = strrchr(pv_ptr->pv_name, '/');
- if ( vg_ptr->pv_subdir_pde != NULL) {
- basename = strrchr(pv_ptr->pv_name, '/');
- if (basename == NULL) basename = pv_ptr->pv_name;
- else basename++;
- remove_proc_entry(basename, vg_ptr->pv_subdir_pde);
- }
-}
+static int lvm_do_pv_flush(void *arg)
+{
+ pv_flush_req_t pv_flush_req;
X
+ if (copy_from_user(&pv_flush_req, arg,
+ sizeof(pv_flush_req)) != 0)
+ return -EFAULT;
X
-/*
- * create a /proc entry for a volume group
- */
-void lvm_do_create_proc_entry_of_vg ( vg_t *vg_ptr) {
- int l, p;
- pv_t *pv_ptr;
- lv_t *lv_ptr;
+ fsync_dev(pv_flush_req.pv_dev);
+ invalidate_buffers(pv_flush_req.pv_dev);
X
- pde = create_proc_entry(vg_ptr->vg_name, S_IFDIR,
- lvm_proc_vg_subdir);
- if ( pde != NULL) {
- vg_ptr->vg_dir_pde = pde;
- pde = create_proc_entry("group", S_IFREG,
- vg_ptr->vg_dir_pde);
- if ( pde != NULL) {
- pde->read_proc = lvm_proc_read_vg_info;
- pde->data = vg_ptr;
- }
- pde = create_proc_entry(LVM_LV_SUBDIR, S_IFDIR,
- vg_ptr->vg_dir_pde);
- if ( pde != NULL) {
- vg_ptr->lv_subdir_pde = pde;
- for ( l = 0; l < vg_ptr->lv_max; l++) {
- if ( ( lv_ptr = vg_ptr->lv[l]) == NULL) continue;
- lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
- }
- }
- pde = create_proc_entry(LVM_PV_SUBDIR, S_IFDIR,
- vg_ptr->vg_dir_pde);
- if ( pde != NULL) {
- vg_ptr->pv_subdir_pde = pde;
- for ( p = 0; p < vg_ptr->pv_max; p++) {
- if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) continue;
- lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr);
- }
- }
- }


+ return 0;
X }
X

X /*
- * remove a /proc entry for a volume group
- */
-void lvm_do_remove_proc_entry_of_vg ( vg_t *vg_ptr) {
- int l, p;


- lv_t *lv_ptr;
- pv_t *pv_ptr;
-

- for ( l = 0; l < vg_ptr->lv_max; l++) {
- if ( ( lv_ptr = vg_ptr->lv[l]) == NULL) continue;
- lvm_do_remove_proc_entry_of_lv ( vg_ptr, vg_ptr->lv[l]);
- }
- for ( p = 0; p < vg_ptr->pv_max; p++) {
- if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) continue;
- lvm_do_remove_proc_entry_of_pv ( vg_ptr, vg_ptr->pv[p]);
- }
- if ( vg_ptr->vg_dir_pde != NULL) {
- remove_proc_entry(LVM_LV_SUBDIR, vg_ptr->vg_dir_pde);
- remove_proc_entry(LVM_PV_SUBDIR, vg_ptr->vg_dir_pde);
- remove_proc_entry("group", vg_ptr->vg_dir_pde);
- remove_proc_entry(vg_ptr->vg_name, lvm_proc_vg_subdir);
- }
-}
-
-
-/*
X * support function initialize gendisk variables
X */
-void __init lvm_geninit(struct gendisk *lvm_gdisk)
+static void __init lvm_geninit(struct gendisk *lvm_gdisk)
X {
X int i = 0;
X
@@ -3019,36 +2665,85 @@
X
X blk_size[MAJOR_NR] = lvm_size;
X blksize_size[MAJOR_NR] = lvm_blocksizes;
- hardsect_size[MAJOR_NR] = lvm_blocksizes;
+ hardsect_size[MAJOR_NR] = lvm_hardsectsizes;
X
X return;
X } /* lvm_gen_init() */
X
X
+
+/* Must have down_write(_pe_lock) when we enqueue buffers */
+static void _queue_io(struct buffer_head *bh, int rw) {
+ if (bh->b_reqnext) BUG();
+ bh->b_reqnext = _pe_requests;
+ _pe_requests = bh;
+}
+
+/* Must have down_write(_pe_lock) when we dequeue buffers */
+static struct buffer_head *_dequeue_io(void)
+{
+ struct buffer_head *bh = _pe_requests;
+ _pe_requests = NULL;
+ return bh;
+}
+
+/*
+ * We do not need to hold _pe_lock to flush buffers. bh should be taken from
+ * _pe_requests under down_write(_pe_lock), and then _pe_requests can be set
+ * NULL and we drop _pe_lock. Any new buffers defered at this time will be
+ * added to a new list, and the old buffers can have their I/O restarted
+ * asynchronously.
+ *
+ * If, for some reason, the same PE is locked again before all of these writes
+ * have finished, then these buffers will just be re-queued (i.e. no danger).
+ */


+static void _flush_io(struct buffer_head *bh)

+{
+ while (bh) {
+ struct buffer_head *next = bh->b_reqnext;
+ bh->b_reqnext = NULL;
+ /* resubmit this buffer head */
+ generic_make_request(WRITE, bh);
+ bh = next;
+ }
+}
+
X /*
- * return a pointer to a '-' padded uuid
+ * we must open the pv's before we use them
X */
-static char *lvm_show_uuid ( char *uuidstr) {
- int i, j;
- static char uuid[NAME_LEN] = { 0, };
+static int _open_pv(pv_t *pv) {
+ int err;
+ struct block_device *bd;
X
- memset ( uuid, 0, NAME_LEN);
+ if (!(bd = bdget(kdev_t_to_nr(pv->pv_dev))))
+ return -ENOMEM;
+
+ err = blkdev_get(bd, FMODE_READ|FMODE_WRITE, 0, BDEV_FILE);


+ if (err)
+ return err;

X
- i = 6;
- memcpy ( uuid, uuidstr, i);
- uuidstr += i;
+ pv->bd = bd;


+ return 0;
+}
X

- for ( j = 0; j < 6; j++) {
- uuid[i++] = '-';
- memcpy ( &uuid[i], uuidstr, 4);
- uuidstr += 4;
- i += 4;
+static void _close_pv(pv_t *pv) {
+ if (pv) {
+ struct block_device *bdev = pv->bd;
+ pv->bd = NULL;
+ if (bdev)
+ blkdev_put(bdev, BDEV_FILE);
X }
+}
X
- memcpy ( &uuid[i], uuidstr, 2 );


+static unsigned long _sectors_to_k(unsigned long sect)

+{
+ if(SECTOR_SIZE > 1024) {
+ return sect * (SECTOR_SIZE / 1024);
+ }
X
- return uuid;
+ return sect / (1024 / SECTOR_SIZE);
X }
X
X module_init(lvm_init);
X module_exit(lvm_cleanup);
+MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/md/multipath.c linux/drivers/md/multipath.c
--- v2.4.14/linux/drivers/md/multipath.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/md/multipath.c Mon Nov 12 09:51:56 2001
@@ -7,10 +7,7 @@
X *
X * MULTIPATH management functions.
X *
- * Better read-balancing code written by Mika Kuoppala <mi...@iki.fi>, 2000
- *
- * Fixes to reconstruction by Jakob Řstergaard" <ja...@ostenfeld.dk>
- * Various fixes by Neil Brown <ne...@cse.unsw.edu.au>
+ * derived from raid1.c.
X *
X * This program is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
@@ -33,6 +30,9 @@
X
X #define MAX_WORK_PER_DISK 128
X
+#define NR_RESERVED_BUFS 32
+
+
X /*
X * The following can be used to debug the driver
X */
@@ -53,147 +53,55 @@
X
X static int multipath_diskop(mddev_t *mddev, mdp_disk_t **d, int state);
X
-struct buffer_head *multipath_alloc_bh(multipath_conf_t *conf, int cnt)
-{
- /* return a linked list of "cnt" struct buffer_heads.
- * don't take any off the free list unless we know we can
- * get all we need, otherwise we could deadlock
- */
- struct buffer_head *bh=NULL;
-
- while(cnt) {
- struct buffer_head *t;
- md_spin_lock_irq(&conf->device_lock);
- if (conf->freebh_cnt >= cnt)
- while (cnt) {
- t = conf->freebh;
- conf->freebh = t->b_next;
- t->b_next = bh;
- bh = t;
- t->b_state = 0;
- conf->freebh_cnt--;
- cnt--;
- }
- md_spin_unlock_irq(&conf->device_lock);
- if (cnt == 0)
- break;
- t = (struct buffer_head *)kmalloc(sizeof(struct buffer_head), GFP_NOIO);
- if (t) {
- memset(t, 0, sizeof(*t));
- t->b_next = bh;
- bh = t;
- cnt--;
- } else {
- PRINTK("waiting for %d bh\n", cnt);
- wait_event(conf->wait_buffer, conf->freebh_cnt >= cnt);
- }
- }
- return bh;
-}
-
-static inline void multipath_free_bh(multipath_conf_t *conf, struct buffer_head *bh)
-{
- unsigned long flags;
- spin_lock_irqsave(&conf->device_lock, flags);
- while (bh) {
- struct buffer_head *t = bh;
- bh=bh->b_next;
- if (t->b_pprev == NULL)
- kfree(t);
- else {
- t->b_next= conf->freebh;
- conf->freebh = t;
- conf->freebh_cnt++;
- }
- }
- spin_unlock_irqrestore(&conf->device_lock, flags);
- wake_up(&conf->wait_buffer);
-}
-
-static int multipath_grow_bh(multipath_conf_t *conf, int cnt)
-{
- /* allocate cnt buffer_heads, possibly less if kalloc fails */
- int i = 0;
-
- while (i < cnt) {
- struct buffer_head *bh;
- bh = kmalloc(sizeof(*bh), GFP_KERNEL);
- if (!bh) break;
- memset(bh, 0, sizeof(*bh));
-
- md_spin_lock_irq(&conf->device_lock);
- bh->b_pprev = &conf->freebh;
- bh->b_next = conf->freebh;
- conf->freebh = bh;
- conf->freebh_cnt++;
- md_spin_unlock_irq(&conf->device_lock);
-
- i++;
- }
- return i;
-}
-
-static int multipath_shrink_bh(multipath_conf_t *conf, int cnt)
-{
- /* discard cnt buffer_heads, if we can find them */
- int i = 0;
X
- md_spin_lock_irq(&conf->device_lock);
- while ((i < cnt) && conf->freebh) {
- struct buffer_head *bh = conf->freebh;
- conf->freebh = bh->b_next;
- kfree(bh);
- i++;
- conf->freebh_cnt--;
- }
- md_spin_unlock_irq(&conf->device_lock);
- return i;
-}
-
X
X static struct multipath_bh *multipath_alloc_mpbh(multipath_conf_t *conf)
X {
- struct multipath_bh *r1_bh = NULL;
+ struct multipath_bh *mp_bh = NULL;
X
X do {
X md_spin_lock_irq(&conf->device_lock);
- if (conf->freer1) {
- r1_bh = conf->freer1;
- conf->freer1 = r1_bh->next_r1;
- r1_bh->next_r1 = NULL;
- r1_bh->state = 0;
- r1_bh->bh_req.b_state = 0;
+ if (!conf->freer1_blocked && conf->freer1) {
+ mp_bh = conf->freer1;
+ conf->freer1 = mp_bh->next_mp;
+ conf->freer1_cnt--;
+ mp_bh->next_mp = NULL;
+ mp_bh->state = (1 << MPBH_PreAlloc);
+ mp_bh->bh_req.b_state = 0;
X }
X md_spin_unlock_irq(&conf->device_lock);
- if (r1_bh)
- return r1_bh;
- r1_bh = (struct multipath_bh *) kmalloc(sizeof(struct multipath_bh),
+ if (mp_bh)
+ return mp_bh;
+ mp_bh = (struct multipath_bh *) kmalloc(sizeof(struct multipath_bh),
X GFP_NOIO);
- if (r1_bh) {
- memset(r1_bh, 0, sizeof(*r1_bh));
- return r1_bh;
- }
- wait_event(conf->wait_buffer, conf->freer1);
+ if (mp_bh) {
+ memset(mp_bh, 0, sizeof(*mp_bh));
+ return mp_bh;
+ }
+ conf->freer1_blocked = 1;
+ wait_disk_event(conf->wait_buffer,
+ !conf->freer1_blocked ||
+ conf->freer1_cnt > NR_RESERVED_BUFS/2
+ );
+ conf->freer1_blocked = 0;
X } while (1);
X }
X
-static inline void multipath_free_mpbh(struct multipath_bh *r1_bh)
+static inline void multipath_free_mpbh(struct multipath_bh *mp_bh)
X {
- struct buffer_head *bh = r1_bh->multipath_bh_list;
- multipath_conf_t *conf = mddev_to_conf(r1_bh->mddev);
-
- r1_bh->multipath_bh_list = NULL;
+ multipath_conf_t *conf = mddev_to_conf(mp_bh->mddev);
X
- if (test_bit(MPBH_PreAlloc, &r1_bh->state)) {
+ if (test_bit(MPBH_PreAlloc, &mp_bh->state)) {
X unsigned long flags;
X spin_lock_irqsave(&conf->device_lock, flags);
- r1_bh->next_r1 = conf->freer1;
- conf->freer1 = r1_bh;
+ mp_bh->next_mp = conf->freer1;
+ conf->freer1 = mp_bh;
+ conf->freer1_cnt++;
X spin_unlock_irqrestore(&conf->device_lock, flags);
+ wake_up(&conf->wait_buffer);
X } else {
- kfree(r1_bh);
+ kfree(mp_bh);
X }
- multipath_free_bh(conf, bh);
X }
X
X static int multipath_grow_mpbh (multipath_conf_t *conf, int cnt)
@@ -201,18 +109,15 @@
X int i = 0;
X
X while (i < cnt) {
- struct multipath_bh *r1_bh;
- r1_bh = (struct multipath_bh*)kmalloc(sizeof(*r1_bh), GFP_KERNEL);
- if (!r1_bh)
+ struct multipath_bh *mp_bh;
+ mp_bh = (struct multipath_bh*)kmalloc(sizeof(*mp_bh), GFP_KERNEL);
+ if (!mp_bh)
X break;
- memset(r1_bh, 0, sizeof(*r1_bh));
-
- md_spin_lock_irq(&conf->device_lock);
- set_bit(MPBH_PreAlloc, &r1_bh->state);
- r1_bh->next_r1 = conf->freer1;
- conf->freer1 = r1_bh;
- md_spin_unlock_irq(&conf->device_lock);
+ memset(mp_bh, 0, sizeof(*mp_bh));
+ set_bit(MPBH_PreAlloc, &mp_bh->state);
+ mp_bh->mddev = conf->mddev;
X
+ multipath_free_mpbh(mp_bh);
X i++;
X }
X return i;
@@ -222,29 +127,15 @@
X {
X md_spin_lock_irq(&conf->device_lock);
X while (conf->freer1) {
- struct multipath_bh *r1_bh = conf->freer1;
- conf->freer1 = r1_bh->next_r1;
- kfree(r1_bh);
+ struct multipath_bh *mp_bh = conf->freer1;
+ conf->freer1 = mp_bh->next_mp;
+ conf->freer1_cnt--;
+ kfree(mp_bh);
X }
X md_spin_unlock_irq(&conf->device_lock);
X }
X
X
-
-static inline void multipath_free_buf(struct multipath_bh *r1_bh)
-{
- unsigned long flags;
- struct buffer_head *bh = r1_bh->multipath_bh_list;
- multipath_conf_t *conf = mddev_to_conf(r1_bh->mddev);
- r1_bh->multipath_bh_list = NULL;
-
- spin_lock_irqsave(&conf->device_lock, flags);
- r1_bh->next_r1 = conf->freebuf;
- conf->freebuf = r1_bh;
- spin_unlock_irqrestore(&conf->device_lock, flags);
- multipath_free_bh(conf, bh);
-}
-
X static int multipath_map (mddev_t *mddev, kdev_t *rdev)
X {
X multipath_conf_t *conf = mddev_to_conf(mddev);
@@ -266,77 +157,45 @@
X return (-1);
X }
X
-static void multipath_reschedule_retry (struct multipath_bh *r1_bh)
+static void multipath_reschedule_retry (struct multipath_bh *mp_bh)


X {
X unsigned long flags;

- mddev_t *mddev = r1_bh->mddev;
+ mddev_t *mddev = mp_bh->mddev;
X multipath_conf_t *conf = mddev_to_conf(mddev);
X
X md_spin_lock_irqsave(&retry_list_lock, flags);
X if (multipath_retry_list == NULL)
X multipath_retry_tail = &multipath_retry_list;
- *multipath_retry_tail = r1_bh;
- multipath_retry_tail = &r1_bh->next_r1;
- r1_bh->next_r1 = NULL;
+ *multipath_retry_tail = mp_bh;
+ multipath_retry_tail = &mp_bh->next_mp;
+ mp_bh->next_mp = NULL;
X md_spin_unlock_irqrestore(&retry_list_lock, flags);
X md_wakeup_thread(conf->thread);
X }
X
X
-static void inline io_request_done(unsigned long sector, multipath_conf_t *conf, int phase)
-{
- unsigned long flags;
- spin_lock_irqsave(&conf->segment_lock, flags);
- if (sector < conf->start_active)
- conf->cnt_done--;
- else if (sector >= conf->start_future && conf->phase == phase)
- conf->cnt_future--;
- else if (!--conf->cnt_pending)
- wake_up(&conf->wait_ready);
-
- spin_unlock_irqrestore(&conf->segment_lock, flags);
-}
-
-static void inline sync_request_done (unsigned long sector, multipath_conf_t *conf)
-{
- unsigned long flags;
- spin_lock_irqsave(&conf->segment_lock, flags);
- if (sector >= conf->start_ready)
- --conf->cnt_ready;
- else if (sector >= conf->start_active) {
- if (!--conf->cnt_active) {
- conf->start_active = conf->start_ready;
- wake_up(&conf->wait_done);
- }
- }
- spin_unlock_irqrestore(&conf->segment_lock, flags);
-}
-
X /*
X * multipath_end_bh_io() is called when we have finished servicing a multipathed
X * operation and are ready to return a success/failure code to the buffer
X * cache layer.
X */
-static void multipath_end_bh_io (struct multipath_bh *r1_bh, int uptodate)
+static void multipath_end_bh_io (struct multipath_bh *mp_bh, int uptodate)
X {
- struct buffer_head *bh = r1_bh->master_bh;
-
- io_request_done(bh->b_rsector, mddev_to_conf(r1_bh->mddev),
- test_bit(MPBH_SyncPhase, &r1_bh->state));
+ struct buffer_head *bh = mp_bh->master_bh;
X
X bh->b_end_io(bh, uptodate);
- multipath_free_mpbh(r1_bh);
+ multipath_free_mpbh(mp_bh);
X }
X
X void multipath_end_request (struct buffer_head *bh, int uptodate)
X {
- struct multipath_bh * r1_bh = (struct multipath_bh *)(bh->b_private);
+ struct multipath_bh * mp_bh = (struct multipath_bh *)(bh->b_private);
X
X /*
X * this branch is our 'one multipath IO has finished' event handler:
X */
X if (!uptodate)
- md_error (r1_bh->mddev, bh->b_dev);
+ md_error (mp_bh->mddev, bh->b_dev);
X else
X /*
X * Set MPBH_Uptodate in our master buffer_head, so that
@@ -347,11 +206,11 @@
X * user-side. So if something waits for IO, then it will
X * wait for the 'master' buffer_head.
X */
- set_bit (MPBH_Uptodate, &r1_bh->state);
+ set_bit (MPBH_Uptodate, &mp_bh->state);
X
X
X if (uptodate) {
- multipath_end_bh_io(r1_bh, uptodate);
+ multipath_end_bh_io(mp_bh, uptodate);


X return;
X }
X /*

@@ -359,20 +218,13 @@
X */
X printk(KERN_ERR "multipath: %s: rescheduling block %lu\n",
X partition_name(bh->b_dev), bh->b_blocknr);
- multipath_reschedule_retry(r1_bh);
+ multipath_reschedule_retry(mp_bh);
X return;
X }
X
X /*
X * This routine returns the disk from which the requested read should
- * be done. It bookkeeps the last read position for every disk
- * in array and when new read requests come, the disk which last
- * position is nearest to the request, is chosen.
- *
- * TODO: now if there are 2 multipaths in the same 2 devices, performance
- * degrades dramatically because position is multipath, not device based.
- * This should be changed to be device based. Also atomic sequential
- * reads should be somehow balanced.
+ * be done.
X */
X
X static int multipath_read_balance (multipath_conf_t *conf)
@@ -391,7 +243,7 @@
X {
X multipath_conf_t *conf = mddev_to_conf(mddev);
X struct buffer_head *bh_req;
- struct multipath_bh * r1_bh;
+ struct multipath_bh * mp_bh;
X struct multipath_info *multipath;
X
X if (!buffer_locked(bh))
@@ -406,45 +258,25 @@
X if (rw == READA)
X rw = READ;
X
- r1_bh = multipath_alloc_mpbh (conf);
-
- spin_lock_irq(&conf->segment_lock);
- wait_event_lock_irq(conf->wait_done,
- bh->b_rsector < conf->start_active ||
- bh->b_rsector >= conf->start_future,
- conf->segment_lock);
- if (bh->b_rsector < conf->start_active)
- conf->cnt_done++;
- else {
- conf->cnt_future++;
- if (conf->phase)
- set_bit(MPBH_SyncPhase, &r1_bh->state);
- }
- spin_unlock_irq(&conf->segment_lock);
-
- /*
- * i think the read and write branch should be separated completely,
- * since we want to do read balancing on the read side for example.
- * Alternative implementations? :) --mingo
- */
+ mp_bh = multipath_alloc_mpbh (conf);
X
- r1_bh->master_bh = bh;
- r1_bh->mddev = mddev;
- r1_bh->cmd = rw;
+ mp_bh->master_bh = bh;
+ mp_bh->mddev = mddev;
+ mp_bh->cmd = rw;
X
X /*
X * read balancing logic:
X */
X multipath = conf->multipaths + multipath_read_balance(conf);
X
- bh_req = &r1_bh->bh_req;
+ bh_req = &mp_bh->bh_req;
X memcpy(bh_req, bh, sizeof(*bh));
X bh_req->b_blocknr = bh->b_rsector;
X bh_req->b_dev = multipath->dev;
X bh_req->b_rdev = multipath->dev;
X /* bh_req->b_rsector = bh->n_rsector; */
X bh_req->b_end_io = multipath_end_request;
- bh_req->b_private = r1_bh;
+ bh_req->b_private = mp_bh;
X generic_make_request (rw, bh_req);
X return 0;
X }
@@ -540,12 +372,10 @@
X mdp_disk_t *spare;
X mdp_super_t *sb = mddev->sb;
X
-// MD_BUG();
X spare = get_spare(mddev);
X if (spare) {
X err = multipath_diskop(mddev, &spare, DISKOP_SPARE_WRITE);
X printk("got DISKOP_SPARE_WRITE err: %d. (spare_faulty(): %d)\n", err, disk_faulty(spare));
-// MD_BUG();
X }
X if (!err && !disk_faulty(spare)) {
X multipath_diskop(mddev, &spare, DISKOP_SPARE_ACTIVE);
@@ -553,7 +383,6 @@
X mark_disk_active(spare);
X sb->active_disks++;
X sb->spare_disks--;
-// MD_BUG();
X }
X }
X }
@@ -697,7 +526,6 @@
X case DISKOP_SPARE_WRITE:
X sdisk = conf->multipaths + spare_disk;
X sdisk->operational = 1;
- sdisk->write_only = 1;
X break;
X /*
X * Deactivate a spare disk:
@@ -705,7 +533,6 @@
X case DISKOP_SPARE_INACTIVE:
X sdisk = conf->multipaths + spare_disk;
X sdisk->operational = 0;
- sdisk->write_only = 0;
X break;
X /*
X * Activate (mark read-write) the (now sync) spare disk,
@@ -757,10 +584,6 @@
X spare_rdev = find_rdev_nr(mddev, spare_desc->number);
X failed_rdev = find_rdev_nr(mddev, failed_desc->number);
X xchg_values(spare_rdev->desc_nr, failed_rdev->desc_nr);
-// if (failed_rdev->alias_device)
-// MD_BUG();
-// if (!spare_rdev->alias_device)
-// MD_BUG();
X spare_rdev->alias_device = 0;
X failed_rdev->alias_device = 1;
X
@@ -788,7 +611,6 @@
X * this really activates the spare.
X */
X fdisk->spare = 0;
- fdisk->write_only = 0;
X
X /*
X * if we activate a spare, we definitely replace a
@@ -828,10 +650,8 @@
X adisk->dev = MKDEV(added_desc->major,added_desc->minor);
X
X adisk->operational = 0;
- adisk->write_only = 0;
X adisk->spare = 1;
X adisk->used_slot = 1;
- adisk->head_position = 0;
X conf->nr_disks++;
X
X break;
@@ -865,7 +685,7 @@
X
X static void multipathd (void *data)
X {
- struct multipath_bh *r1_bh;
+ struct multipath_bh *mp_bh;
X struct buffer_head *bh;
X unsigned long flags;
X mddev_t *mddev;
@@ -874,31 +694,31 @@
X
X for (;;) {
X md_spin_lock_irqsave(&retry_list_lock, flags);
- r1_bh = multipath_retry_list;
- if (!r1_bh)
+ mp_bh = multipath_retry_list;
+ if (!mp_bh)
X break;
- multipath_retry_list = r1_bh->next_r1;
+ multipath_retry_list = mp_bh->next_mp;
X md_spin_unlock_irqrestore(&retry_list_lock, flags);
X
- mddev = r1_bh->mddev;
+ mddev = mp_bh->mddev;
X if (mddev->sb_dirty) {
X printk(KERN_INFO "dirty sb detected, updating.\n");
X mddev->sb_dirty = 0;
X md_update_sb(mddev);
X }
- bh = &r1_bh->bh_req;
+ bh = &mp_bh->bh_req;
X dev = bh->b_dev;
X
X multipath_map (mddev, &bh->b_dev);
X if (bh->b_dev == dev) {
X printk (IO_ERROR, partition_name(bh->b_dev), bh->b_blocknr);
- multipath_end_bh_io(r1_bh, 0);
+ multipath_end_bh_io(mp_bh, 0);
X } else {
X printk (REDIRECT_SECTOR,
X partition_name(bh->b_dev), bh->b_blocknr);
X bh->b_rdev = bh->b_dev;
X bh->b_rsector = bh->b_blocknr;
- generic_make_request (r1_bh->cmd, bh);
+ generic_make_request (mp_bh->cmd, bh);
X }
X }
X md_spin_unlock_irqrestore(&retry_list_lock, flags);
@@ -1016,7 +836,7 @@
X mdp_disk_t *desc, *desc2;
X mdk_rdev_t *rdev, *def_rdev = NULL;
X struct md_list_head *tmp;
- int start_recovery = 0, num_rdevs = 0;
+ int num_rdevs = 0;
X
X MOD_INC_USE_COUNT;
X
@@ -1072,12 +892,9 @@
X disk->number = desc->number;
X disk->raid_disk = desc->raid_disk;
X disk->dev = rdev->dev;
- disk->sect_limit = MAX_WORK_PER_DISK;
X disk->operational = 0;
- disk->write_only = 0;
X disk->spare = 1;
X disk->used_slot = 1;
- disk->head_position = 0;
X mark_disk_sync(desc);
X
X if (disk_active(desc)) {
@@ -1135,10 +952,7 @@
X conf->mddev = mddev;
X conf->device_lock = MD_SPIN_LOCK_UNLOCKED;
X
- conf->segment_lock = MD_SPIN_LOCK_UNLOCKED;
X init_waitqueue_head(&conf->wait_buffer);
- init_waitqueue_head(&conf->wait_done);
- init_waitqueue_head(&conf->wait_ready);
X
X if (!conf->working_disks) {
X printk(NONE_OPERATIONAL, mdidx(mddev));
@@ -1150,17 +964,17 @@
X * As a minimum, 1 mpbh and raid_disks buffer_heads
X * would probably get us by in tight memory situations,
X * but a few more is probably a good idea.
- * For now, try 16 mpbh and 16*raid_disks bufferheads


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

echo 'End of part 048'
echo 'File patch-2.4.15 is continued in part 049'
echo "049" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:30 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part054

#!/bin/sh -x
# this is part 054 of a 115 - part archive


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

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

+ * you get very close to transmitting back-to-back packets. With
+ * only one Tx buf, the transmitter sits idle while you reload the
+ * card, leaving a substantial gap between each transmitted packet.
+ */
+
+ if (ei_local->tx1 == 0)
+ {
+ output_page = ei_local->tx_start_page;
+ ei_local->tx1 = send_length;
+ if (ei_debug && ei_local->tx2 > 0)
+ printk(KERN_DEBUG "%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n",
+ dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing);
+ }
+ else if (ei_local->tx2 == 0)
+ {
+ output_page = ei_local->tx_start_page + TX_1X_PAGES;
+ ei_local->tx2 = send_length;
+ if (ei_debug && ei_local->tx1 > 0)
+ printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
+ dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing);
+ }
+ else
+ { /* We should never get here. */
+ if (ei_debug)
+ printk(KERN_DEBUG "%s: No Tx buffers free! tx1=%d tx2=%d last=%d\n",
+ dev->name, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
+ ei_local->irqlock = 0;
+ netif_stop_queue(dev);
+ outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+ spin_unlock(&ei_local->page_lock);
+ enable_irq(dev->irq);
+ ei_local->stat.tx_errors++;


+ return 1;
+ }
+

+ /*
+ * Okay, now upload the packet and trigger a send if the transmitter
+ * isn't already sending. If it is busy, the interrupt handler will
+ * trigger the send later, upon receiving a Tx done interrupt.
+ */
+
+ ei_block_output(dev, length, skb->data, output_page);
+ if (! ei_local->txing)
+ {
+ ei_local->txing = 1;
+ NS8390_trigger_send(dev, send_length, output_page);
+ dev->trans_start = jiffies;
+ if (output_page == ei_local->tx_start_page)
+ {
+ ei_local->tx1 = -1;
+ ei_local->lasttx = -1;
+ }
+ else
+ {
+ ei_local->tx2 = -1;
+ ei_local->lasttx = -2;
+ }
+ }
+ else ei_local->txqueue++;
+
+ if (ei_local->tx1 && ei_local->tx2)
+ netif_stop_queue(dev);
+ else
+ netif_start_queue(dev);
+
+#else /* EI_PINGPONG */
+
+ /*
+ * Only one Tx buffer in use. You need two Tx bufs to come close to
+ * back-to-back transmits. Expect a 20 -> 25% performance hit on
+ * reasonable hardware if you only use one Tx buffer.
+ */
+
+ ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
+ ei_local->txing = 1;
+ NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
+ dev->trans_start = jiffies;
+ netif_stop_queue(dev);
+
+#endif /* EI_PINGPONG */
+
+ /* Turn 8390 interrupts back on. */
+ ei_local->irqlock = 0;
+ outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+
+ spin_unlock(&ei_local->page_lock);
+ enable_irq(dev->irq);
+
+ DEV_KFREE_SKB (skb);
+ add_tx_bytes(&ei_local->stat, send_length);


+
+ return 0;
+}
+

+/**
+ * ei_interrupt - handle the interrupts from an 8390
+ * @irq: interrupt number
+ * @dev_id: a pointer to the net_device
+ * @regs: unused
+ *
+ * Handle the ether interface interrupts. We pull packets from
+ * the 8390 via the card specific functions and fire them at the networking
+ * stack. We also handle transmit completions and wake the transmit path if
+ * neccessary. We also update the counters and do other housekeeping as
+ * needed.
+ */
+
+static void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+ struct net_device *dev = dev_id;
+ long e8390_base;
+ int interrupts, nr_serviced = 0, i;
+ struct ei_device *ei_local;
+
+ if (dev == NULL)
+ {
+ printk ("net_interrupt(): irq %d for unknown device.\n", irq);
+ return;
+ }
+
+ e8390_base = dev->base_addr;
+ ei_local = (struct ei_device *) dev->priv;
+
+ /*
+ * Protect the irq test too.
+ */
+
+ spin_lock(&ei_local->page_lock);
+
+ if (ei_local->irqlock)
+ {
+#if 1 /* This might just be an interrupt for a PCI device sharing this line */
+ /* The "irqlock" check is only for testing. */
+ printk(ei_local->irqlock
+ ? "%s: Interrupted while interrupts are masked! isr=%#2x imr=%#2x.\n"
+ : "%s: Reentering the interrupt handler! isr=%#2x imr=%#2x.\n",
+ dev->name, inb_p(e8390_base + EN0_ISR),
+ inb_p(e8390_base + EN0_IMR));
+#endif
+ spin_unlock(&ei_local->page_lock);
+ return;
+ }
+
+ if (ei_debug > 3)
+ printk(KERN_DEBUG "%s: interrupt(isr=%#2.2x).\n", dev->name,
+ inb_p(e8390_base + EN0_ISR));
+
+ outb_p(0x00, e8390_base + EN0_ISR);
+ ei_local->irqlock = 1;
+
+ /* !!Assumption!! -- we stay in page 0. Don't break this. */
+ while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0
+ && ++nr_serviced < MAX_SERVICE)
+ {
+ if (!netif_running(dev) || (interrupts == 0xff)) {
+ if (ei_debug > 1)
+ printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name);
+ outb_p(interrupts, e8390_base + EN0_ISR);
+ interrupts = 0;
+ break;
+ }
+ /* AX88190 bug fix. */
+ outb_p(interrupts, e8390_base + EN0_ISR);
+ for (i = 0; i < 10; i++) {
+ if (!(inb(e8390_base + EN0_ISR) & interrupts))
+ break;
+ outb_p(0, e8390_base + EN0_ISR);
+ outb_p(interrupts, e8390_base + EN0_ISR);
+ }
+ if (interrupts & ENISR_OVER)
+ ei_rx_overrun(dev);
+ else if (interrupts & (ENISR_RX+ENISR_RX_ERR))
+ {
+ /* Got a good (?) packet. */
+ ei_receive(dev);
+ }
+ /* Push the next to-transmit packet through. */
+ if (interrupts & ENISR_TX)
+ ei_tx_intr(dev);
+ else if (interrupts & ENISR_TX_ERR)
+ ei_tx_err(dev);
+
+ if (interrupts & ENISR_COUNTERS)
+ {
+ ei_local->stat.rx_frame_errors += inb_p(e8390_base + EN0_COUNTER0);
+ ei_local->stat.rx_crc_errors += inb_p(e8390_base + EN0_COUNTER1);
+ ei_local->stat.rx_missed_errors+= inb_p(e8390_base + EN0_COUNTER2);
+ }
+ }
+
+ if (interrupts && ei_debug)
+ {
+ if (nr_serviced >= MAX_SERVICE)
+ {
+ /* 0xFF is valid for a card removal */
+ if(interrupts!=0xFF)
+ printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n",
+ dev->name, interrupts);
+ outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
+ } else {
+ printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts);
+ outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
+ }
+ }
+
+ /* Turn 8390 interrupts back on. */
+ ei_local->irqlock = 0;
+ outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+
+ spin_unlock(&ei_local->page_lock);
+ return;
+}
+
+/**
+ * ei_tx_err - handle transmitter error
+ * @dev: network device which threw the exception
+ *
+ * A transmitter error has happened. Most likely excess collisions (which
+ * is a fairly normal condition). If the error is one where the Tx will
+ * have been aborted, we try and send another one right away, instead of
+ * letting the failed packet sit and collect dust in the Tx buffer. This
+ * is a much better solution as it avoids kernel based Tx timeouts, and
+ * an unnecessary card reset.
+ *
+ * Called with lock held.
+ */
+
+static void ei_tx_err(struct net_device *dev)
+{
+ long e8390_base = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *) dev->priv;
+ unsigned char txsr = inb_p(e8390_base+EN0_TSR);
+ unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
+
+#ifdef VERBOSE_ERROR_DUMP
+ printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr);
+ if (txsr & ENTSR_ABT)
+ printk("excess-collisions ");
+ if (txsr & ENTSR_ND)
+ printk("non-deferral ");
+ if (txsr & ENTSR_CRS)
+ printk("lost-carrier ");
+ if (txsr & ENTSR_FU)
+ printk("FIFO-underrun ");
+ if (txsr & ENTSR_CDH)
+ printk("lost-heartbeat ");
+ printk("\n");
+#endif
+
+ if (tx_was_aborted)
+ ei_tx_intr(dev);
+ else
+ {
+ ei_local->stat.tx_errors++;
+ if (txsr & ENTSR_CRS) ei_local->stat.tx_carrier_errors++;
+ if (txsr & ENTSR_CDH) ei_local->stat.tx_heartbeat_errors++;
+ if (txsr & ENTSR_OWC) ei_local->stat.tx_window_errors++;
+ }
+}
+
+/**
+ * ei_tx_intr - transmit interrupt handler
+ * @dev: network device for which tx intr is handled
+ *
+ * We have finished a transmit: check for errors and then trigger the next
+ * packet to be sent. Called with lock held.
+ */
+
+static void ei_tx_intr(struct net_device *dev)
+{
+ long e8390_base = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *) dev->priv;
+ int status = inb(e8390_base + EN0_TSR);
+
+#ifdef EI_PINGPONG
+
+ /*
+ * There are two Tx buffers, see which one finished, and trigger
+ * the send of another one if it exists.
+ */
+ ei_local->txqueue--;
+
+ if (ei_local->tx1 < 0)
+ {
+ if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
+ printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n",
+ ei_local->name, ei_local->lasttx, ei_local->tx1);
+ ei_local->tx1 = 0;
+ if (ei_local->tx2 > 0)
+ {
+ ei_local->txing = 1;
+ NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
+ dev->trans_start = jiffies;
+ ei_local->tx2 = -1,
+ ei_local->lasttx = 2;
+ }
+ else ei_local->lasttx = 20, ei_local->txing = 0;
+ }
+ else if (ei_local->tx2 < 0)
+ {
+ if (ei_local->lasttx != 2 && ei_local->lasttx != -2)
+ printk("%s: bogus last_tx_buffer %d, tx2=%d.\n",
+ ei_local->name, ei_local->lasttx, ei_local->tx2);
+ ei_local->tx2 = 0;
+ if (ei_local->tx1 > 0)
+ {
+ ei_local->txing = 1;
+ NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
+ dev->trans_start = jiffies;
+ ei_local->tx1 = -1;
+ ei_local->lasttx = 1;
+ }
+ else
+ ei_local->lasttx = 10, ei_local->txing = 0;
+ }
+// else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
+// dev->name, ei_local->lasttx);
+
+#else /* EI_PINGPONG */
+ /*
+ * Single Tx buffer: mark it free so another packet can be loaded.
+ */
+ ei_local->txing = 0;
+#endif
+
+ /* Minimize Tx latency: update the statistics after we restart TXing. */
+ if (status & ENTSR_COL)
+ ei_local->stat.collisions++;
+ if (status & ENTSR_PTX)
+ ei_local->stat.tx_packets++;
+ else
+ {
+ ei_local->stat.tx_errors++;
+ if (status & ENTSR_ABT)
+ {
+ ei_local->stat.tx_aborted_errors++;
+ ei_local->stat.collisions += 16;
+ }
+ if (status & ENTSR_CRS)
+ ei_local->stat.tx_carrier_errors++;
+ if (status & ENTSR_FU)
+ ei_local->stat.tx_fifo_errors++;
+ if (status & ENTSR_CDH)
+ ei_local->stat.tx_heartbeat_errors++;
+ if (status & ENTSR_OWC)
+ ei_local->stat.tx_window_errors++;
+ }
+ netif_wake_queue(dev);
+}
+
+/**
+ * ei_receive - receive some packets
+ * @dev: network device with which receive will be run
+ *
+ * We have a good packet(s), get it/them out of the buffers.
+ * Called with lock held.
+ */
+
+static void ei_receive(struct net_device *dev)
+{
+ long e8390_base = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *) dev->priv;
+ unsigned char rxing_page, this_frame, next_frame;
+ unsigned short current_offset;
+ int rx_pkt_count = 0;
+ struct e8390_pkt_hdr rx_frame;
+
+ while (++rx_pkt_count < 10)
+ {
+ int pkt_len, pkt_stat;
+
+ /* Get the rx page (incoming packet pointer). */
+ rxing_page = inb_p(e8390_base + EN1_CURPAG -1);
+
+ /* Remove one frame from the ring. Boundary is always a page behind. */
+ this_frame = inb_p(e8390_base + EN0_BOUNDARY) + 1;
+ if (this_frame >= ei_local->stop_page)
+ this_frame = ei_local->rx_start_page;
+
+ /* Someday we'll omit the previous, iff we never get this message.
+ (There is at least one clone claimed to have a problem.)
+
+ Keep quiet if it looks like a card removal. One problem here
+ is that some clones crash in roughly the same way.
+ */
+ if (ei_debug > 0 && this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF))
+ printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n",
+ dev->name, this_frame, ei_local->current_page);
+
+ if (this_frame == rxing_page) /* Read all the frames? */
+ break; /* Done for now */
+
+ current_offset = this_frame << 8;
+ ei_get_8390_hdr(dev, &rx_frame, this_frame);
+
+ pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);
+ pkt_stat = rx_frame.status;
+
+ next_frame = this_frame + 1 + ((pkt_len+4)>>8);
+
+ if (pkt_len < 60 || pkt_len > 1518)
+ {
+ if (ei_debug)
+ printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n",
+ dev->name, rx_frame.count, rx_frame.status,
+ rx_frame.next);
+ ei_local->stat.rx_errors++;
+ ei_local->stat.rx_length_errors++;
+ }
+ else if ((pkt_stat & 0x0F) == ENRSR_RXOK)

+ {
+ struct sk_buff *skb;
+

+ skb = dev_alloc_skb(pkt_len+2);


+ if (skb == NULL)

+ {
+ if (ei_debug > 1)
+ printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n",
+ dev->name, pkt_len);
+ ei_local->stat.rx_dropped++;
+ break;
+ }
+ else
+ {
+ skb_reserve(skb,2); /* IP headers on 16 byte boundaries */
+ skb->dev = dev;
+ skb_put(skb, pkt_len); /* Make room */
+ ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
+ skb->protocol=eth_type_trans(skb,dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ ei_local->stat.rx_packets++;
+ add_rx_bytes(&ei_local->stat, pkt_len);
+ if (pkt_stat & ENRSR_PHY)
+ ei_local->stat.multicast++;
+ }
+ }
+ else
+ {
+ if (ei_debug)
+ printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+ dev->name, rx_frame.status, rx_frame.next,
+ rx_frame.count);
+ ei_local->stat.rx_errors++;
+ /* NB: The NIC counts CRC, frame and missed errors. */
+ if (pkt_stat & ENRSR_FO)
+ ei_local->stat.rx_fifo_errors++;
+ }
+ next_frame = rx_frame.next;
+
+ /* This _should_ never happen: it's here for avoiding bad clones. */
+ if (next_frame >= ei_local->stop_page) {
+ printk("%s: next frame inconsistency, %#2x\n", dev->name,
+ next_frame);
+ next_frame = ei_local->rx_start_page;
+ }
+ ei_local->current_page = next_frame;
+ outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
+ }


+
+ return;
+}
+

+/**
+ * ei_rx_overrun - handle receiver overrun
+ * @dev: network device which threw exception
+ *
+ * We have a receiver overrun: we have to kick the 8390 to get it started
+ * again. Problem is that you have to kick it exactly as NS prescribes in
+ * the updated datasheets, or "the NIC may act in an unpredictable manner."
+ * This includes causing "the NIC to defer indefinitely when it is stopped
+ * on a busy network." Ugh.
+ * Called with lock held. Don't call this with the interrupts off or your
+ * computer will hate you - it takes 10ms or so.
+ */
+
+static void ei_rx_overrun(struct net_device *dev)
+{
+ axnet_dev_t *info = (axnet_dev_t *)dev;
+ long e8390_base = dev->base_addr;
+ unsigned char was_txing, must_resend = 0;
+ struct ei_device *ei_local = (struct ei_device *) dev->priv;
+
+ /*
+ * Record whether a Tx was in progress and then issue the
+ * stop command.
+ */
+ was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
+ outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
+
+ if (ei_debug > 1)
+ printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name);
+ ei_local->stat.rx_over_errors++;
+
+ /*
+ * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
+ * Early datasheets said to poll the reset bit, but now they say that
+ * it "is not a reliable indicator and subsequently should be ignored."
+ * We wait at least 10ms.
+ */
+
+ mdelay(10);
+
+ /*
+ * Reset RBCR[01] back to zero as per magic incantation.
+ */
+ outb_p(0x00, e8390_base+EN0_RCNTLO);
+ outb_p(0x00, e8390_base+EN0_RCNTHI);
+
+ /*
+ * See if any Tx was interrupted or not. According to NS, this
+ * step is vital, and skipping it will cause no end of havoc.
+ */
+
+ if (was_txing)
+ {
+ unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
+ if (!tx_completed)
+ must_resend = 1;
+ }
+
+ /*
+ * Have to enter loopback mode and then restart the NIC before
+ * you are allowed to slurp packets up off the ring.
+ */
+ outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
+ outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
+
+ /*
+ * Clear the Rx ring of all the debris, and ack the interrupt.
+ */
+ ei_receive(dev);
+
+ /*
+ * Leave loopback mode, and resend any packet that got stopped.
+ */
+ outb_p(E8390_TXCONFIG | info->duplex_flag, e8390_base + EN0_TXCR);
+ if (must_resend)
+ outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
+}
+
+/*
+ * Collect the stats. This is called unlocked and from several contexts.
+ */
+
+static struct net_device_stats *get_stats(struct net_device *dev)
+{


+ long ioaddr = dev->base_addr;

+ struct ei_device *ei_local = (struct ei_device *) dev->priv;


+ unsigned long flags;
+

+ /* If the card is stopped, just return the present stats. */
+ if (!netif_running(dev))
+ return &ei_local->stat;
+
+ spin_lock_irqsave(&ei_local->page_lock,flags);
+ /* Read the counter registers, assuming we are in page 0. */
+ ei_local->stat.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0);
+ ei_local->stat.rx_crc_errors += inb_p(ioaddr + EN0_COUNTER1);
+ ei_local->stat.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+ return &ei_local->stat;
+}
+
+/**
+ * do_set_multicast_list - set/clear multicast filter
+ * @dev: net device for which multicast filter is adjusted
+ *
+ * Set or clear the multicast filter for this adaptor. May be called
+ * from a BH in 2.1.x. Must be called with lock held.
+ */
+
+static void do_set_multicast_list(struct net_device *dev)
+{
+ long e8390_base = dev->base_addr;
+
+ if(dev->flags&IFF_PROMISC)
+ outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
+ else if(dev->flags&IFF_ALLMULTI || dev->mc_list)
+ outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
+ else
+ outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
+}
+
+/*
+ * Called without lock held. This is invoked from user context and may
+ * be parallel to just about everything else. Its also fairly quick and
+ * not called too often. Must protect against both bh and irq users
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{


+ unsigned long flags;
+

+ spin_lock_irqsave(&((struct ei_device *)dev->priv)->page_lock, flags);
+ do_set_multicast_list(dev);
+ spin_unlock_irqrestore(&((struct ei_device *)dev->priv)->page_lock, flags);
+}
+
+/**
+ * ethdev_init - init rest of 8390 device struct
+ * @dev: network device structure to init
+ *
+ * Initialize the rest of the 8390 device structure. Do NOT __init
+ * this, as it is used by 8390 based modular drivers too.
+ */
+
+static int ethdev_init(struct net_device *dev)
+{
+ if (ei_debug > 1)
+ printk(version);
+
+ if (dev->priv == NULL)
+ {
+ struct ei_device *ei_local;
+
+ dev->priv = kmalloc(sizeof(struct ei_device), GFP_KERNEL);
+ if (dev->priv == NULL)
+ return -ENOMEM;
+ memset(dev->priv, 0, sizeof(struct ei_device));
+ ei_local = (struct ei_device *)dev->priv;
+ spin_lock_init(&ei_local->page_lock);
+ }
+
+ dev->hard_start_xmit = &ei_start_xmit;
+ dev->get_stats = get_stats;
+ dev->set_multicast_list = &set_multicast_list;
+
+ ether_setup(dev);


+
+ return 0;
+}
+
+
+

+/* This page of functions should be 8390 generic */
+/* Follow National Semi's recommendations for initializing the "NIC". */
+
+/**
+ * NS8390_init - initialize 8390 hardware
+ * @dev: network device to initialize
+ * @startp: boolean. non-zero value to initiate chip processing
+ *
+ * Must be called with lock held.
+ */
+
+static void NS8390_init(struct net_device *dev, int startp)
+{
+ axnet_dev_t *info = (axnet_dev_t *)dev;
+ long e8390_base = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *) dev->priv;
+ int i;
+ int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48;
+
+ if(sizeof(struct e8390_pkt_hdr)!=4)
+ panic("8390.c: header struct mispacked\n");
+ /* Follow National Semi's recommendations for initing the DP83902. */
+ outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */
+ outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */
+ /* Clear the remote byte count registers. */
+ outb_p(0x00, e8390_base + EN0_RCNTLO);
+ outb_p(0x00, e8390_base + EN0_RCNTHI);
+ /* Set to monitor and loopback mode -- this is vital!. */
+ outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */
+ outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
+ /* Set the transmit page and receive ring. */
+ outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
+ ei_local->tx1 = ei_local->tx2 = 0;
+ outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG);
+ outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/
+ ei_local->current_page = ei_local->rx_start_page; /* assert boundary+1 */
+ outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG);
+ /* Clear the pending interrupts and mask. */
+ outb_p(0xFF, e8390_base + EN0_ISR);
+ outb_p(0x00, e8390_base + EN0_IMR);
+
+ /* Copy the station address into the DS8390 registers. */
+
+ outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
+ for(i = 0; i < 6; i++)
+ {
+ outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
+ if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
+ printk(KERN_ERR "Hw. address read/write mismap %d\n",i);
+ }
+ /*
+ * Initialize the multicast list to accept-all. If we enable multicast
+ * the higher levels can do the filtering.
+ */
+ for (i = 0; i < 8; i++)
+ outb_p(0xff, e8390_base + EN1_MULT + i);
+
+ outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
+ outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
+
+ netif_start_queue(dev);
+ ei_local->tx1 = ei_local->tx2 = 0;
+ ei_local->txing = 0;
+
+ if (startp)
+ {
+ outb_p(0xff, e8390_base + EN0_ISR);
+ outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+ outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
+ outb_p(E8390_TXCONFIG | info->duplex_flag,
+ e8390_base + EN0_TXCR); /* xmit on. */
+ /* 3c503 TechMan says rxconfig only after the NIC is started. */
+ outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */
+ do_set_multicast_list(dev); /* (re)load the mcast table */
+ }
+}
+
+/* Trigger a transmit start, assuming the length is valid.
+ Always called with the page lock held */
+
+static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
+ int start_page)
+{
+ long e8390_base = dev->base_addr;
+ struct ei_device *ei_local __attribute((unused)) = (struct ei_device *) dev->priv;
+
+ if (inb_p(e8390_base) & E8390_TRANS)
+ {
+ printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n",
+ dev->name);
+ return;
+ }
+ outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
+ outb_p(length >> 8, e8390_base + EN0_TCNTHI);
+ outb_p(start_page, e8390_base + EN0_TPSR);
+ outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD);
+}
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/fmvj18x_cs.c linux/drivers/net/pcmcia/fmvj18x_cs.c
--- v2.4.14/linux/drivers/net/pcmcia/fmvj18x_cs.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/pcmcia/fmvj18x_cs.c Tue Nov 13 09:02:30 2001
@@ -1,5 +1,5 @@
X /*======================================================================
- fmvj18x_cs.c 2.2 2001/01/07
+ fmvj18x_cs.c 2.6 2001/09/17
X
X A fmvj18x (and its compatibles) PCMCIA client driver
X
@@ -23,8 +23,9 @@
X
X The author may be reached as bec...@scyld.com, or C/O
X Scyld Computing Corporation
- 410 Severn Ave., Suite 210, Annapolis MD 21403
-
+ 410 Severn Ave., Suite 210
+ Annapolis MD 21403
+
X ======================================================================*/
X
X #include <linux/module.h>
@@ -54,40 +55,27 @@
X #include <pcmcia/ciscode.h>
X #include <pcmcia/ds.h>
X
-/*
- All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
- you do not define PCMCIA_DEBUG at all, all the debug code will be
- left out. If you compile with PCMCIA_DEBUG=0, the debug code will
- be present but disabled -- but it can then be enabled for specific
- modules at load time with a 'pc_debug=#' option to insmod.
-*/
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-#else
-#define DEBUG(n, args...)
-#endif
+/*====================================================================*/
+
+/* Module parameters */
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
X
X /* Bit map of interrupts to choose from */
X /* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
-static u_int irq_mask = 0xdeb8;
+INT_MODULE_PARM(irq_mask, 0xdeb8);
X static int irq_list[4] = { -1 };
+MODULE_PARM(irq_list, "1-4i");
X
X /* SRAM configuration */
X /* 0:4KB*2 TX buffer else:8KB*2 TX buffer */
-static int sram_config;
+INT_MODULE_PARM(sram_config, 0);
X
-MODULE_PARM(irq_mask, "i");
-MODULE_PARM(irq_list, "1-4i");
-MODULE_PARM(sram_config, "i");
-
-/*====================================================================*/
-/*
- driver version infomation
- */
X #ifdef PCMCIA_DEBUG
-static char *version = "fmvj18x_cs.c 2.2 2001/01/07";
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version = "fmvj18x_cs.c 2.6 2001/09/17";
+#else
+#define DEBUG(n, args...)
X #endif
X
X /*====================================================================*/
@@ -454,7 +442,9 @@
X break;
X case MANFID_FUJITSU:
X if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10302)
- cardtype = MBH10302;
+ /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302),
+ but these are MBH10304 based card. */
+ cardtype = MBH10304;
X else if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304)
X cardtype = MBH10304;
X else
@@ -476,7 +466,7 @@
X cardtype = XXX10304; /* MBH10304 with buggy CIS */
X link->conf.ConfigIndex = 0x20;
X } else {
- cardtype = MBH10302;
+ cardtype = MBH10302; /* NextCom NC5310, etc. */
X link->conf.ConfigIndex = 1;
X }
X break;
@@ -518,17 +508,17 @@
X
X ioaddr = dev->base_addr;
X
- /* Power On chip and select bank 0 */
- if(cardtype == UNGERMANN)
- outb(BANK_0U, ioaddr + CONFIG_1);
- else
- outb(BANK_0, ioaddr + CONFIG_1);
-
X /* Reset controller */
X if( sram_config == 0 )
X outb(CONFIG0_RST, ioaddr + CONFIG_0);
X else
X outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
+
+ /* Power On chip and select bank 0 */
+ if(cardtype == UNGERMANN)
+ outb(BANK_0U, ioaddr + CONFIG_1);
+ else
+ outb(BANK_0, ioaddr + CONFIG_1);
X
X /* Set hardware address */
X switch (cardtype) {
@@ -937,18 +927,18 @@
X
X DEBUG(4, "fjn_reset(%s) called.\n",dev->name);
X
+ /* Reset controller */
+ if( sram_config == 0 )
+ outb(CONFIG0_RST, ioaddr + CONFIG_0);
+ else
+ outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
+
X /* Power On chip and select bank 0 */
X if( lp->cardtype == UNGERMANN)
X outb(BANK_0U, ioaddr + CONFIG_1);
X else
X outb(BANK_0, ioaddr + CONFIG_1);
X
- /* Reset buffers */
- if( sram_config == 0 )
- outb(CONFIG0_RST, ioaddr + CONFIG_0);
- else
- outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
-
X /* Set Tx modes */
X outb(D_TX_MODE, ioaddr + TX_MODE);
X /* set Rx modes */
@@ -975,7 +965,7 @@
X outb(BANK_2, ioaddr + CONFIG_1);
X
X /* set 16col ctrl bits */
- if( lp->cardtype == TDK )
+ if( lp->cardtype == TDK || lp->cardtype == CONTEC)
X outb(TDK_AUTO_MODE, ioaddr + COL_CTRL);
X else
X outb(AUTO_MODE, ioaddr + COL_CTRL);


@@ -1257,4 +1247,3 @@
X }

X restore_flags(flags);
X }
-MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/nmclan_cs.c linux/drivers/net/pcmcia/nmclan_cs.c
--- v2.4.14/linux/drivers/net/pcmcia/nmclan_cs.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/pcmcia/nmclan_cs.c Tue Nov 13 09:02:30 2001
@@ -385,32 +385,31 @@
X "Auto", "10baseT", "BNC",
X };
X
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-#else
-#define DEBUG(n, args...)
-#endif
-
X /* ----------------------------------------------------------------------------
X Parameters
X These are the parameters that can be set during loading with
X 'insmod'.
X ---------------------------------------------------------------------------- */
X
-/* 0=auto, 1=10baseT, 2 = 10base2, default=auto */
-static int if_port;
+MODULE_DESCRIPTION("New Media PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
X
-/* Bit map of interrupts to choose from */
-static u_int irq_mask = 0xdeb8;
-static int irq_list[4] = { -1 };
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
X
-MODULE_PARM(if_port, "i");
-MODULE_PARM(irq_mask, "i");
+static int irq_list[4] = { -1 };
X MODULE_PARM(irq_list, "1-4i");
-MODULE_LICENSE("GPL");
X
+/* 0=auto, 1=10baseT, 2 = 10base2, default=auto */
+INT_MODULE_PARM(if_port, 0);
+/* Bit map of interrupts to choose from */
+INT_MODULE_PARM(irq_mask, 0xdeb8);
+
+#ifdef PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+#else
+#define DEBUG(n, args...)
+#endif
X
X /* ----------------------------------------------------------------------------
X Function Prototypes
@@ -1290,9 +1289,10 @@


X skb->protocol = eth_type_trans(skb, dev);
X

X netif_rx(skb); /* Send the packet to the upper (protocol) layers. */
+
X dev->last_rx = jiffies;
X lp->linux_stats.rx_packets++;
- lp->linux_stats.rx_bytes += pkt_len;
+ lp->linux_stats.rx_bytes += skb->len;
X outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */
X continue;
X } else {
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/pcnet_cs.c linux/drivers/net/pcmcia/pcnet_cs.c
--- v2.4.14/linux/drivers/net/pcmcia/pcnet_cs.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/pcmcia/pcnet_cs.c Tue Nov 13 09:02:30 2001


@@ -11,7 +11,7 @@
X

X Copyright (C) 1999 David A. Hinds -- dah...@users.sourceforge.net
X
- pcnet_cs.c 1.132 2001/02/09 03:13:29
+ pcnet_cs.c 1.144 2001/11/07 04:06:56
X
X The network driver code is based on Donald Becker's NE2000 code:
X
@@ -20,7 +20,7 @@
X Director, National Security Agency. This software may be used and
X distributed according to the terms of the GNU General Public License,
X incorporated herein by reference.
- Donald Becker may be reached at bec...@scyld.com.
+ Donald Becker may be reached at bec...@scyld.com
X
X Based also on Keith Moore's changes to Don Becker's code, for IBM
X CCAE support. Drivers merged back together, and shared-memory
@@ -39,6 +39,7 @@
X #include <linux/delay.h>
X #include <asm/io.h>
X #include <asm/system.h>
+#include <asm/byteorder.h>
X
X #include <linux/netdevice.h>
X #include <../drivers/net/8390.h>
@@ -72,14 +73,18 @@
X MODULE_PARM(pc_debug, "i");
X #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
X static char *version =
-"pcnet_cs.c 1.132 2001/02/09 03:13:29 (David Hinds)";
+"pcnet_cs.c 1.144 2001/11/07 04:06:56 (David Hinds)";
X #else
X #define DEBUG(n, args...)
X #endif
X
X /*====================================================================*/
X
-/* Parameters that can be set with 'insmod' */
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dah...@users.sourceforge.net>");
+MODULE_DESCRIPTION("NE2000 compatible PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
X
X #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
X
@@ -94,6 +99,7 @@
X INT_MODULE_PARM(delay_output, 0); /* pause after xmit? */
X INT_MODULE_PARM(delay_time, 4); /* in usec */
X INT_MODULE_PARM(use_shmem, -1); /* use shared memory? */
+INT_MODULE_PARM(full_duplex, 0); /* full duplex? */
X
X /* Ugh! Let the user hardwire the hardware address for queer cards */
X static int hw_addr[6] = { 0, /* ... */ };
@@ -101,13 +107,14 @@
X
X /*====================================================================*/
X
+static void mii_phy_probe(struct net_device *dev);
X static void pcnet_config(dev_link_t *link);
X static void pcnet_release(u_long arg);
X static int pcnet_event(event_t event, int priority,
X event_callback_args_t *args);
X static int pcnet_open(struct net_device *dev);
X static int pcnet_close(struct net_device *dev);
-static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
X static void ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs);
X static void ei_watchdog(u_long arg);
X static void pcnet_reset_8390(struct net_device *dev);
@@ -140,6 +147,12 @@
X #define HAS_MII 0x40
X #define USE_SHMEM 0x80 /* autodetected */
X
+#define AM79C9XX_HOME_PHY 0x00006B90 /* HomePNA PHY */
+#define AM79C9XX_ETH_PHY 0x00006B70 /* 10baseT PHY */
+#define MII_PHYID_REV_MASK 0xfffffff0
+#define MII_PHYID_REG1 0x02
+#define MII_PHYID_REG2 0x03
+
X static hw_info_t hw_info[] = {
X { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT },
X { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 },
@@ -216,7 +229,10 @@
X caddr_t base;
X struct timer_list watchdog;
X int stale, fast_poll;
+ u_char phy_id;
+ u_char eth_phy, pna_phy;
X u_short link_status;
+ u_long mii_reset;
X } pcnet_dev_t;
X
X /*======================================================================
@@ -518,8 +534,8 @@
X dev->dev_addr[i] = j & 0xff;
X dev->dev_addr[i+1] = j >> 8;
X }
- printk(KERN_INFO "pcnet_cs: sorry, the AX88190 chipset is not "
- "supported.\n");
+ printk(KERN_NOTICE "pcnet_cs: this is an AX88190 card!\n");
+ printk(KERN_NOTICE "pcnet_cs: use axnet_cs instead.\n");
X return NULL;
X }
X
@@ -749,10 +765,13 @@
X link->state &= ~DEV_CONFIG_PENDING;
X
X if (info->flags & (IS_DL10019|IS_DL10022)) {
- dev->do_ioctl = &do_ioctl;
+ u_char id = inb(dev->base_addr + 0x1a);
+ dev->do_ioctl = &ei_ioctl;
+ mii_phy_probe(dev);
X printk(KERN_INFO "%s: NE2000 (DL100%d rev %02x): ",
- dev->name, ((info->flags & IS_DL10022) ? 22 : 19),
- inb(dev->base_addr + 0x1a));
+ dev->name, ((info->flags & IS_DL10022) ? 22 : 19), id);
+ if (info->pna_phy)
+ printk("PNA, ");
X } else
X printk(KERN_INFO "%s: NE2000 Compatible: ", dev->name);
X printk("io %#3lx, irq %d,", dev->base_addr, dev->irq);
@@ -954,15 +973,44 @@
X outb_p(tmp, nic_base + PCNET_MISC);
X }
X if (info->flags & IS_DL10022) {
- mdio_reset(nic_base + DLINK_GPIO, 0);
- /* Restart MII autonegotiation */
- mdio_write(nic_base + DLINK_GPIO, 0, 0, 0x0000);
- mdio_write(nic_base + DLINK_GPIO, 0, 0, 0x1200);
+ if (info->flags & HAS_MII) {
+ mdio_reset(nic_base + DLINK_GPIO, info->eth_phy);
+ /* Restart MII autonegotiation */
+ mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
+ mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
+ info->mii_reset = jiffies;
+ } else {
+ outb(full_duplex ? 4 : 0, nic_base + DLINK_DIAG);
+ }
X }
X }
X
X /*====================================================================*/
X
+static void mii_phy_probe(struct net_device *dev)
+{
+ pcnet_dev_t *info = (pcnet_dev_t *)dev;
+ ioaddr_t mii_addr = dev->base_addr + DLINK_GPIO;
+ int i;
+ u_int tmp, phyid;
+
+ for (i = 31; i >= 0; i--) {
+ tmp = mdio_read(mii_addr, i, 1);
+ if ((tmp == 0) || (tmp == 0xffff))
+ continue;
+ tmp = mdio_read(mii_addr, i, MII_PHYID_REG1);
+ phyid = tmp << 16;
+ phyid |= mdio_read(mii_addr, i, MII_PHYID_REG2);
+ phyid &= MII_PHYID_REV_MASK;
+ DEBUG(0, "%s: MII at %d is 0x%08x\n", dev->name, i, phyid);
+ if (phyid == AM79C9XX_HOME_PHY) {
+ info->pna_phy = i;
+ } else if (phyid != AM79C9XX_ETH_PHY) {
+ info->eth_phy = i;
+ }
+ }
+}
+
X static int pcnet_open(struct net_device *dev)
X {
X pcnet_dev_t *info = (pcnet_dev_t *)dev;
@@ -979,6 +1027,7 @@
X set_misc_reg(dev);
X request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev);
X
+ info->phy_id = info->eth_phy;
X info->link_status = 0x00;
X info->watchdog.function = &ei_watchdog;
X info->watchdog.data = (u_long)info;
@@ -1074,6 +1123,7 @@
X pcnet_dev_t *info = (pcnet_dev_t *)(arg);
X struct net_device *dev = &info->dev;
X ioaddr_t nic_base = dev->base_addr;
+ ioaddr_t mii_addr = nic_base + DLINK_GPIO;
X u_short link;
X
X if (!netif_device_present(dev)) goto reschedule;
@@ -1097,35 +1147,57 @@
X if (!(info->flags & HAS_MII))
X goto reschedule;
X
- link = mdio_read(dev->base_addr + DLINK_GPIO, 0, 1);
+ mdio_read(mii_addr, info->phy_id, 1);
+ link = mdio_read(mii_addr, info->phy_id, 1);
X if (!link || (link == 0xffff)) {
- printk(KERN_INFO "%s: MII is missing!\n", dev->name);
- info->flags &= ~HAS_MII;
+ if (info->eth_phy) {
+ info->phy_id = info->eth_phy = 0;
+ } else {
+ printk(KERN_INFO "%s: MII is missing!\n", dev->name);
+ info->flags &= ~HAS_MII;
+ }
X goto reschedule;
X }
X
X link &= 0x0004;
X if (link != info->link_status) {
- u_short p = mdio_read(dev->base_addr + DLINK_GPIO, 0, 5);
+ u_short p = mdio_read(mii_addr, info->phy_id, 5);
X printk(KERN_INFO "%s: %s link beat\n", dev->name,
X (link) ? "found" : "lost");
X if (link && (info->flags & IS_DL10022)) {
X /* Disable collision detection on full duplex links */
- outb((p & 0x0140) ? 4 : 0, dev->base_addr + DLINK_DIAG);
+ outb((p & 0x0140) ? 4 : 0, nic_base + DLINK_DIAG);
X }
X if (link) {
- if (p)
- printk(KERN_INFO "%s: autonegotiation complete: "
- "%sbaseT-%cD selected\n", dev->name,
- ((p & 0x0180) ? "100" : "10"),
- ((p & 0x0140) ? 'F' : 'H'));
- else
- printk(KERN_INFO "%s: link partner did not autonegotiate\n",
- dev->name);
+ if (info->phy_id == info->eth_phy) {
+ if (p)
+ printk(KERN_INFO "%s: autonegotiation complete: "
+ "%sbaseT-%cD selected\n", dev->name,
+ ((p & 0x0180) ? "100" : "10"),
+ ((p & 0x0140) ? 'F' : 'H'));
+ else
+ printk(KERN_INFO "%s: link partner did not "
+ "autonegotiate\n", dev->name);
+ }
X NS8390_init(dev, 1);
X }
X info->link_status = link;
X }
+ if (info->pna_phy && (jiffies - info->mii_reset > 6*HZ)) {
+ link = mdio_read(mii_addr, info->eth_phy, 1) & 0x0004;
+ if (((info->phy_id == info->pna_phy) && link) ||
+ ((info->phy_id != info->pna_phy) && !link)) {
+ /* isolate this MII and try flipping to the other one */
+ mdio_write(mii_addr, info->phy_id, 0, 0x0400);
+ info->phy_id ^= info->pna_phy ^ info->eth_phy;
+ printk(KERN_INFO "%s: switched to %s transceiver\n", dev->name,
+ (info->phy_id == info->eth_phy) ? "ethernet" : "PNA");
+ mdio_write(mii_addr, info->phy_id, 0,
+ (info->phy_id == info->eth_phy) ? 0x1000 : 0);
+ info->link_status = 0;
+ info->mii_reset = jiffies;
+ }
+ }
X
X reschedule:
X info->watchdog.expires = jiffies + HZ;
@@ -1134,20 +1206,21 @@
X
X /*====================================================================*/
X
-static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
X {
+ pcnet_dev_t *info = (pcnet_dev_t *)dev;
X u16 *data = (u16 *)&rq->ifr_data;
- ioaddr_t addr = dev->base_addr + DLINK_GPIO;
+ ioaddr_t mii_addr = dev->base_addr + DLINK_GPIO;
X switch (cmd) {
X case SIOCDEVPRIVATE:
- data[0] = 0;
+ data[0] = info->phy_id;
X case SIOCDEVPRIVATE+1:
- data[3] = mdio_read(addr, data[0], data[1] & 0x1f);
+ data[3] = mdio_read(mii_addr, data[0], data[1] & 0x1f);
X return 0;
X case SIOCDEVPRIVATE+2:
X if (!capable(CAP_NET_ADMIN))
X return -EPERM;
- mdio_write(addr, data[0], data[1] & 0x1f, data[2]);
+ mdio_write(mii_addr, data[0], data[1] & 0x1f, data[2]);
X return 0;
X }
X return -EOPNOTSUPP;
@@ -1522,4 +1595,3 @@
X
X module_init(init_pcnet_cs);
X module_exit(exit_pcnet_cs);
-MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/smc91c92_cs.c linux/drivers/net/pcmcia/smc91c92_cs.c
--- v2.4.14/linux/drivers/net/pcmcia/smc91c92_cs.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/pcmcia/smc91c92_cs.c Tue Nov 13 09:02:30 2001


@@ -8,7 +8,7 @@
X

X Copyright (C) 1999 David A. Hinds -- dah...@users.sourceforge.net
X
- smc91c92_cs.c 1.106 2001/02/07 00:19:58
+ smc91c92_cs.c 1.113 2001/10/13 00:08:53
X
X This driver contains code written by Donald Becker
X (bec...@scyld.com), Rowan Hughes (x-c...@jcu.edu.au),
@@ -56,19 +56,14 @@
X
X /*====================================================================*/
X
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-static const char *version =
-"smc91c92_cs.c 0.09 1996/8/4 Donald Becker, bec...@scyld.com.\n";
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-#else
-#define DEBUG(n, args...)
-#endif
-
X static char *if_names[] = { "auto", "10baseT", "10base2"};
X
-/* Parameters that can be set with 'insmod' */
+/* Module parameters */
+
+MODULE_DESCRIPTION("SMC 91c92 series PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
+
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
X
X /*
X Transceiver/media type.
@@ -76,16 +71,23 @@
X 1 = 10baseT (and autoselect if #define AUTOSELECT),
X 2 = AUI/10base2,
X */
-static int if_port;
+INT_MODULE_PARM(if_port, 0);
X
X /* Bit map of interrupts to choose from. */
-static u_int irq_mask = 0xdeb8;
+INT_MODULE_PARM(irq_mask, 0xdeb8);
X static int irq_list[4] = { -1 };
-
-MODULE_PARM(if_port, "i");
-MODULE_PARM(irq_mask, "i");
X MODULE_PARM(irq_list, "1-4i");
-MODULE_LICENSE("GPL");
+
+#ifdef PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+static const char *version =
+"smc91c92_cs.c 0.09 1996/8/4 Donald Becker, bec...@scyld.com.\n";
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+#else
+#define DEBUG(n, args...)
+#endif
+
+/*====================================================================*/
X
X /* Operational parameter that usually are not changed. */
X
@@ -118,7 +120,8 @@
X int watchdog, tx_err;
X u_short media_status;
X u_short fast_poll;
- u_long last_rx;
+ u_short link_status;
+ int phy_id;
X };
X
X /* Special definitions for Megahertz multifunction cards */
@@ -246,6 +249,7 @@
X #define MULTICAST2 2
X #define MULTICAST4 4
X #define MULTICAST6 6
+#define MGMT 8
X #define REVISION 0x0a
X
X /* Transmit status bits. */
@@ -287,6 +291,9 @@
X static void smc_set_xcvr(struct net_device *dev, int if_port);
X static void smc_reset(struct net_device *dev);
X static void media_check(u_long arg);
+static void mdio_sync(ioaddr_t addr);
+static int mdio_read(ioaddr_t addr, int phy_id, int loc);
+static void mdio_write(ioaddr_t addr, int phy_id, int loc, int value);
X
X /*======================================================================


X
@@ -908,7 +915,8 @@

X cisparse_t parse;
X u_short buf[32];
X char *name;
- int i, rev;
+ int i, j, rev;
+ ioaddr_t ioaddr;
X
X DEBUG(0, "smc91c92_config(0x%p)\n", link);
X
@@ -1006,9 +1014,10 @@
X dev->irq);
X for (i = 0; i < 6; i++)
X printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
+
+ ioaddr = dev->base_addr;
X if (rev > 0) {
X u_long mir, mcr;
- ioaddr_t ioaddr = dev->base_addr;
X SMC_SELECT_BANK(0);
X mir = inw(ioaddr + MEMINFO) & 0xff;
X if (mir == 0xff) mir++;
@@ -1030,6 +1039,23 @@
X "MII" : if_names[dev->if_port]);
X }
X
+ if (smc->cfg & CFG_MII_SELECT) {
+ SMC_SELECT_BANK(3);
+
+ for (i = 0; i < 32; i++) {
+ j = mdio_read(dev->base_addr + MGMT, i, 1);
+ if ((j != 0) && (j != 0xffff)) break;
+ }
+ smc->phy_id = (i < 32) ? i : -1;
+ if (i < 32) {
+ DEBUG(0, " MII transceiver at index %d, status %x.\n", i, j);
+ } else {
+ printk(KERN_NOTICE " No MII transceivers found!\n");
+ }
+
+ SMC_SELECT_BANK(0);
+ }
+
X return;
X
X config_undo:
@@ -1088,7 +1114,8 @@
X dev_link_t *link = args->client_data;
X struct smc_private *smc = link->priv;
X struct net_device *dev = &smc->dev;
-
+ int i;
+
X DEBUG(1, "smc91c92_event(0x%06x)\n", event);
X
X switch (event) {
@@ -1130,6 +1157,16 @@
X set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
X set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
X }
+ if (((smc->manfid == MANFID_OSITECH) &&
+ (smc->cardid == PRODID_OSITECH_SEVEN)) ||
+ ((smc->manfid == MANFID_PSION) &&
+ (smc->cardid == PRODID_PSION_NET100))) {
+ /* Download the Seven of Diamonds firmware */
+ for (i = 0; i < sizeof(__Xilinx7OD); i++) {
+ outb(__Xilinx7OD[i], link->io.BasePort1+2);
+ udelay(50);
+ }
+ }
X if (link->open) {
X smc_reset(dev);
X netif_device_attach(dev);
@@ -1141,6 +1178,63 @@
X } /* smc91c92_event */
X
X /*======================================================================
+
+ MII interface support for SMC91cXX based cards
+======================================================================*/
+
+#define MDIO_SHIFT_CLK 0x04
+#define MDIO_DATA_OUT 0x01
+#define MDIO_DIR_WRITE 0x08
+#define MDIO_DATA_WRITE0 (MDIO_DIR_WRITE)
+#define MDIO_DATA_WRITE1 (MDIO_DIR_WRITE | MDIO_DATA_OUT)
+#define MDIO_DATA_READ 0x02
+
+static void mdio_sync(ioaddr_t addr)
+{
+ int bits;
+ for (bits = 0; bits < 32; bits++) {
+ outb(MDIO_DATA_WRITE1, addr);
+ outb(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
+ }
+}
+
+static int mdio_read(ioaddr_t addr, int phy_id, int loc)
+{
+ u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
+ int i, retval = 0;
+
+ mdio_sync(addr);
+ for (i = 13; i >= 0; i--) {
+ int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+ outb(dat, addr);
+ outb(dat | MDIO_SHIFT_CLK, addr);
+ }
+ for (i = 19; i > 0; i--) {
+ outb(0, addr);
+ retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0);
+ outb(MDIO_SHIFT_CLK, addr);
+ }
+ return (retval>>1) & 0xffff;
+}
+
+static void mdio_write(ioaddr_t addr, int phy_id, int loc, int value)
+{
+ u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
+ int i;
+
+ mdio_sync(addr);
+ for (i = 31; i >= 0; i--) {
+ int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+ outb(dat, addr);
+ outb(dat | MDIO_SHIFT_CLK, addr);
+ }
+ for (i = 1; i >= 0; i--) {
+ outb(0, addr);
+ outb(MDIO_SHIFT_CLK, addr);
+ }
+}
+
+/*======================================================================
X
X The driver core code, most of which should be common with a
X non-PCMCIA implementation.
@@ -1501,7 +1595,6 @@
X if (status & IM_RCV_INT) {
X /* Got a packet(s). */
X smc_rx(dev);
- smc->last_rx = jiffies;
X }
X if (status & IM_TX_INT) {
X smc_tx_err(dev);
@@ -1844,6 +1937,17 @@
X TCR_ENABLE | TCR_PAD_EN, ioaddr + TCR);
X set_rx_mode(dev);
X
+ if (smc->cfg & CFG_MII_SELECT) {
+ SMC_SELECT_BANK(3);
+
+ /* Reset MII */
+ mdio_write(ioaddr + MGMT, smc->phy_id, 0, 0x8000);
+
+ /* Restart MII autonegotiation */
+ mdio_write(ioaddr + MGMT, smc->phy_id, 0, 0x0000);
+ mdio_write(ioaddr + MGMT, smc->phy_id, 0, 0x1200);
+ }
+
X /* Enable interrupts. */
X SMC_SELECT_BANK(2);
X outw((IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT) << 8,
@@ -1862,18 +1966,20 @@
X struct net_device *dev = &smc->dev;
X ioaddr_t ioaddr = dev->base_addr;
X u_short i, media, saved_bank;
+ ioaddr_t mii_addr = dev->base_addr + MGMT;
+ u_short link;
+
+ saved_bank = inw(ioaddr + BANK_SELECT);
X
X if (!netif_device_present(dev))
X goto reschedule;
X
- saved_bank = inw(ioaddr + BANK_SELECT);
X SMC_SELECT_BANK(2);
X i = inw(ioaddr + INTERRUPT);
X SMC_SELECT_BANK(0);
X media = inw(ioaddr + EPH) & EPH_LINK_OK;
X SMC_SELECT_BANK(1);
X media |= (inw(ioaddr + CONFIG) & CFG_AUI_SELECT) ? 2 : 1;
- SMC_SELECT_BANK(saved_bank);
X
X /* Check for pending interrupt with watchdog flag set: with
X this, we can limp along even if the interrupt is blocked */
@@ -1887,14 +1993,42 @@
X smc->fast_poll--;
X smc->media.expires = jiffies + 1;
X add_timer(&smc->media);
+ SMC_SELECT_BANK(saved_bank);
X return;
X }
X
+ if (smc->cfg & CFG_MII_SELECT) {
+ if (smc->phy_id < 0)
+ goto reschedule;
+
+ SMC_SELECT_BANK(3);
+ link = mdio_read(mii_addr, smc->phy_id, 1);
+ if (!link || (link == 0xffff)) {
+ printk(KERN_INFO "%s: MII is missing!\n", dev->name);
+ smc->phy_id = -1;
+ goto reschedule;
+ }
+
+ link &= 0x0004;
+ if (link != smc->link_status) {
+ u_short p = mdio_read(mii_addr, smc->phy_id, 5);
+ printk(KERN_INFO "%s: %s link beat\n", dev->name,
+ (link) ? "found" : "lost");
+ if (link) {
+ printk(KERN_INFO "%s: autonegotiation complete: "
+ "%sbaseT-%cD selected\n", dev->name,
+ ((p & 0x0180) ? "100" : "10"),
+ (((p & 0x0100) || ((p & 0x1c0) == 0x40)) ? 'F' : 'H'));
+ }
+ smc->link_status = link;
+ }
+ }
+
X if (smc->cfg & CFG_MII_SELECT)
X goto reschedule;
X
X /* Ignore collisions unless we've had no rx's recently */
- if (jiffies - smc->last_rx > HZ) {
+ if (jiffies - dev->last_rx > HZ) {
X if (smc->tx_err || (smc->media_status & EPH_16COL))
X media |= EPH_16COL;
X }
@@ -1930,6 +2064,7 @@
X reschedule:
X smc->media.expires = jiffies + HZ;
X add_timer(&smc->media);
+ SMC_SELECT_BANK(saved_bank);
X }
X
X /*====================================================================*/
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/wavelan_cs.c linux/drivers/net/pcmcia/wavelan_cs.c
--- v2.4.14/linux/drivers/net/pcmcia/wavelan_cs.c Tue Oct 23 22:48:51 2001
+++ linux/drivers/net/pcmcia/wavelan_cs.c Fri Nov 9 15:22:54 2001
@@ -4838,4 +4838,4 @@
X
X module_init(init_wavelan_cs);
X module_exit(exit_wavelan_cs);


-MODULE_LICENSE("BSD without advertisement clause");

+MODULE_LICENSE("Dual BSD/GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/xirc2ps_cs.c linux/drivers/net/pcmcia/xirc2ps_cs.c
--- v2.4.14/linux/drivers/net/pcmcia/xirc2ps_cs.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/pcmcia/xirc2ps_cs.c Tue Nov 13 09:02:30 2001
@@ -5,6 +5,11 @@
X * This driver supports various Xircom CreditCard Ethernet adapters
X * including the CE2, CE IIps, RE-10, CEM28, CEM33, CE33, CEM56,
X * CE3-100, CE3B, RE-100, REM10BT, and REM56G-100.
+ *
+ * 2000-09-24 <psh...@icon.co.za> The Xircom CE3B-100 may not
+ * autodetect the media properly. In this case use the
+ * if_port=1 (for 10BaseT) or if_port=4 (for 100BaseT) options
+ * to force the media type.
X *
X * Written originally by Werner Koch based on David Hinds' skeleton of the
X * PCMCIA driver.
@@ -246,7 +251,10 @@
X #define XIR_CBE 14 /* (prodid 1) cardbus ethernet: not supported */
X /*====================================================================*/
X
-/* Parameters that can be set with 'insmod' */
+/* Module parameters */
+
+MODULE_DESCRIPTION("Xircom PCMCIA ethernet driver");
+MODULE_LICENSE("Dual MPL/GPL");
X
X #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
X
@@ -382,7 +390,6 @@
X static void do_powerdown(struct net_device *dev);
X static int do_stop(struct net_device *dev);
X
-
X /*=============== Helper functions =========================*/
X static void
X flush_stale_links(void)
@@ -1441,7 +1448,7 @@
X lp->stats.rx_fifo_errors++; /* okay ? */
X DEBUG(3, "%s: Alignment error\n", dev->name);
X }
-
+
X /* clear the received/dropped/error packet */
X PutWord(XIRCREG0_DO, 0x8000); /* issue cmd: skip_rx_packet */
X
@@ -1926,6 +1933,12 @@
X unsigned control, status, linkpartner;
X int i;
X
+ if (if_port == 4 || if_port == 1) { /* force 100BaseT or 10BaseT */
+ dev->if_port = if_port;
+ local->probe_port = 0;


+ return 1;
+ }
+

X status = mii_rd(ioaddr, 0, 1);
X if ((status & 0xff00) != 0x7800)
X return 0; /* No MII */
@@ -2090,4 +2103,3 @@
X
X __setup("xirc2ps_cs=", setup_xirc2ps_cs);
X #endif
-MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/xircom_cb.c linux/drivers/net/pcmcia/xircom_cb.c
--- v2.4.14/linux/drivers/net/pcmcia/xircom_cb.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/pcmcia/xircom_cb.c Fri Nov 9 13:41:42 2001
@@ -319,7 +319,7 @@
X */
X static void __devexit xircom_remove(struct pci_dev *pdev)
X {


- struct net_device *dev = pdev->driver_data;
+ struct net_device *dev = pci_get_drvdata(pdev);

X struct xircom_private *card;
X enter();
X
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/xircom_tulip_cb.c linux/drivers/net/pcmcia/xircom_tulip_cb.c
--- v2.4.14/linux/drivers/net/pcmcia/xircom_tulip_cb.c Mon Nov 5 15:55:30 2001
+++ linux/drivers/net/pcmcia/xircom_tulip_cb.c Fri Nov 9 13:41:42 2001
@@ -1701,7 +1701,7 @@
X #ifdef CONFIG_PM
X static int xircom_suspend(struct pci_dev *pdev, u32 state)


X {
- struct net_device *dev = pdev->driver_data;
+ struct net_device *dev = pci_get_drvdata(pdev);

X struct xircom_private *tp = dev->priv;
X printk(KERN_INFO "xircom_suspend(%s)\n", dev->name);
X if (tp->open)
@@ -1712,7 +1712,7 @@
X
X static int xircom_resume(struct pci_dev *pdev)
X {


- struct net_device *dev = pdev->driver_data;
+ struct net_device *dev = pci_get_drvdata(pdev);

X struct xircom_private *tp = dev->priv;
X printk(KERN_INFO "xircom_resume(%s)\n", dev->name);
X
@@ -1734,7 +1734,7 @@
X
X static void __devexit xircom_remove_one(struct pci_dev *pdev)
X {


- struct net_device *dev = pdev->driver_data;
+ struct net_device *dev = pci_get_drvdata(pdev);
X

X printk(KERN_INFO "xircom_remove_one(%s)\n", dev->name);
X unregister_netdev(dev);
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c
--- v2.4.14/linux/drivers/net/pcnet32.c Tue Oct 23 22:48:51 2001
+++ linux/drivers/net/pcnet32.c Sun Nov 11 10:09:33 2001
@@ -53,13 +53,6 @@
X static struct pci_device_id pcnet32_pci_tbl[] __devinitdata = {
X { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
X { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-/* this id is never reached as the match above occurs first.
- * However it clearly has significance, so let's not remove it
- * until we know what that significance is. -jgarzik
- */
-#if 0
- { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0x1014, 0x2000, 0, 0, 0 },
-#endif
X { 0, }
X };
X
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pppoe.c linux/drivers/net/pppoe.c
--- v2.4.14/linux/drivers/net/pppoe.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/pppoe.c Fri Nov 9 14:02:24 2001
@@ -5,7 +5,7 @@
X * PPPoE --- PPP over Ethernet (RFC 2516)
X *
X *
- * Version: 0.6.8
+ * Version: 0.6.9
X *
X * 030700 : Fixed connect logic to allow for disconnect.
X * 270700 : Fixed potential SMP problems; we must protect against
@@ -29,6 +29,8 @@
X * the original skb that was passed in on success, never on
X * failure. Delete the copy of the skb on failure to avoid
X * a memory leak.
+ * 081001 : Misc. cleanup (licence string, non-blocking, prevent
+ * reference of device on close).
X *
X * Author: Michal Ostrowski <most...@speakeasy.net>
X * Contributors:
@@ -349,7 +351,7 @@
X
X if (relay_po == NULL)
X goto abort_kfree;
-
+
X if ((relay_po->sk->state & PPPOX_CONNECTED) == 0)
X goto abort_put;
X
@@ -543,13 +545,12 @@
X po = sk->protinfo.pppox;
X if (po->pppoe_pa.sid) {
X delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
- po->pppoe_pa.sid = 0 ;
X }
X
X if (po->pppoe_dev)
- dev_put(po->pppoe_dev);
+ dev_put(po->pppoe_dev);
X
- po->pppoe_dev = NULL ;
+ po->pppoe_dev = NULL;
X
X sock_orphan(sk);
X sock->sk = NULL;
@@ -944,7 +945,8 @@
X goto end;
X }
X
- skb = skb_recv_datagram(sk, flags, 0, &error);
+ skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
+ flags & MSG_DONTWAIT, &error);
X
X if (error < 0) {
X goto end;
@@ -1077,3 +1079,7 @@
X
X module_init(pppoe_init);
X module_exit(pppoe_exit);
+
+MODULE_AUTHOR("Michal Ostrowski <most...@speakeasy.net>");
+MODULE_DESCRIPTION("PPP over Ethernet driver");
+MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pppox.c linux/drivers/net/pppox.c
--- v2.4.14/linux/drivers/net/pppox.c Wed Jul 25 17:10:21 2001
+++ linux/drivers/net/pppox.c Fri Nov 9 14:02:24 2001
@@ -158,3 +158,7 @@
X
X module_init(pppox_init);
X module_exit(pppox_exit);
+
+MODULE_AUTHOR("Michal Ostrowski <most...@speakeasy.net>");
+MODULE_DESCRIPTION("PPP over Ethernet driver (generic socket layer)");
+MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/net/rrunner.c linux/drivers/net/rrunner.c
--- v2.4.14/linux/drivers/net/rrunner.c Wed Jul 25 17:10:21 2001
+++ linux/drivers/net/rrunner.c Fri Nov 9 13:45:35 2001
@@ -826,7 +826,7 @@
X case E_RX_IDLE:
X printk(KERN_WARNING "%s: RX data not moving\n",
X dev->name);
- break;
+ goto drop;
X case E_WATCHDOG:
X printk(KERN_INFO "%s: The watchdog is here to see "
X "us\n", dev->name);
@@ -912,15 +912,43 @@
X case E_RX_PAR_ERR:
X printk(KERN_WARNING "%s: Receive parity error\n",
X dev->name);
- break;
+ goto drop;
X case E_RX_LLRC_ERR:
X printk(KERN_WARNING "%s: Receive LLRC error\n",
X dev->name);
- break;
+ goto drop;
X case E_PKT_LN_ERR:
X printk(KERN_WARNING "%s: Receive packet length "
X "error\n", dev->name);
- break;
+ goto drop;
+ case E_DTA_CKSM_ERR:
+ printk(KERN_WARNING "%s: Data checksum error\n",
+ dev->name);
+ goto drop;
+ case E_SHT_BST:
+ printk(KERN_WARNING "%s: Unexpected short burst "
+ "error\n", dev->name);
+ goto drop;
+ case E_STATE_ERR:
+ printk(KERN_WARNING "%s: Recv. state transition"
+ " error\n", dev->name);
+ goto drop;
+ case E_UNEXP_DATA:


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

echo 'End of part 054'
echo 'File patch-2.4.15 is continued in part 055'
echo "055" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:36 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part060

#!/bin/sh -x
# this is part 060 of a 115 - part archive


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

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

+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+

+#ifndef SYM_CONF_H
+#define SYM_CONF_H
+
+/*-------------------------------------------------------------------
+ * Static configuration.
+ *-------------------------------------------------------------------
+ */
+
+/*
+ * Also support early NCR 810, 815 and 825 chips.
+ */
+#ifndef SYM_CONF_GENERIC_SUPPORT
+#define SYM_CONF_GENERIC_SUPPORT (1)
+#endif
+
+/*
+ * Use Normal IO instead of MMIO.
+ */
+/* #define SYM_CONF_IOMAPPED */
+
+/*
+ * Max tags for a device (logical unit)
+ * We use a power of 2, (7) means 2<<7=128
+ * Maximum is 8 -> 256 tags
+ */
+#ifndef SYM_CONF_MAX_TAG_ORDER
+#define SYM_CONF_MAX_TAG_ORDER (6)
+#endif
+
+/*
+ * Max number of scatter/gather entries for en IO.
+ * Each entry costs 8 bytes in the internal CCB data structure.
+ */
+#ifndef SYM_CONF_MAX_SG
+#define SYM_CONF_MAX_SG (33)
+#endif
+
+/*
+ * Max number of targets.
+ * Maximum is 16 and you are advised not to change this value.
+ */
+#ifndef SYM_CONF_MAX_TARGET
+#define SYM_CONF_MAX_TARGET (16)
+#endif
+
+/*
+ * Max number of logical units.
+ * SPI-2 allows up to 64 logical units, but in real life, target
+ * that implements more that 7 logical units are pretty rare.
+ * Anyway, the cost of accepting up to 64 logical unit is low in
+ * this driver, thus going with the maximum is acceptable.
+ */
+#ifndef SYM_CONF_MAX_LUN
+#define SYM_CONF_MAX_LUN (64)
+#endif
+
+/*
+ * Max number of IO control blocks queued to the controller.
+ * Each entry needs 8 bytes and the queues are allocated contiguously.
+ * Since we donnot want to allocate more than a page, the theorical
+ * maximum is PAGE_SIZE/8. For safety, we announce a bit less to the
+ * access method. :)
+ * When not supplied, as it is suggested, the driver compute some
+ * good value for this parameter.
+ */
+/* #define SYM_CONF_MAX_START (PAGE_SIZE/8 - 16) */
+
+/*
+ * Support for NVRAM.
+ */
+#ifndef SYM_CONF_NVRAM_SUPPORT
+#define SYM_CONF_NVRAM_SUPPORT (1)
+#endif
+
+/*
+ * Support for Immediate Arbitration.
+ * Not advised.
+ */
+/* #define SYM_CONF_IARB_SUPPORT */
+
+/*
+ * Support for some PCI fix-ups (or assumed so).
+ */
+#define SYM_CONF_PCI_FIX_UP
+
+/*
+ * Number of lists for the optimization of the IO timeout handling.
+ * Not used under FreeBSD and Linux.
+ */
+#ifndef SYM_CONF_TIMEOUT_ORDER_MAX
+#define SYM_CONF_TIMEOUT_ORDER_MAX (8)
+#endif
+
+/*
+ * How the driver handles DMA addressing of user data.


+ * 0 : 32 bit addressing

+ * 1 : 40 bit addressing

+ * 2 : 64 bit addressing using segment registers
+ */
+#ifndef SYM_CONF_DMA_ADDRESSING_MODE
+#define SYM_CONF_DMA_ADDRESSING_MODE (0)
+#endif
+
+/*-------------------------------------------------------------------
+ * Configuration that could be dynamic if it was possible
+ * to pass arguments to the driver.
+ *-------------------------------------------------------------------
+ */
+
+/*
+ * HOST default scsi id.
+ */
+#ifndef SYM_SETUP_HOST_ID
+#define SYM_SETUP_HOST_ID 7
+#endif
+
+/*
+ * Max synchronous transfers.
+ */
+#ifndef SYM_SETUP_MIN_SYNC
+#define SYM_SETUP_MIN_SYNC (9)
+#endif
+
+/*
+ * Max wide order.
+ */
+#ifndef SYM_SETUP_MAX_WIDE
+#define SYM_SETUP_MAX_WIDE (1)
+#endif
+
+/*
+ * Max SCSI offset.
+ */
+#ifndef SYM_SETUP_MAX_OFFS
+#define SYM_SETUP_MAX_OFFS (63)
+#endif
+
+/*
+ * Default number of tags.
+ */
+#ifndef SYM_SETUP_MAX_TAG
+#define SYM_SETUP_MAX_TAG (1<<SYM_CONF_MAX_TAG_ORDER)
+#endif
+
+/*
+ * SYMBIOS NVRAM format support.
+ */
+#ifndef SYM_SETUP_SYMBIOS_NVRAM
+#define SYM_SETUP_SYMBIOS_NVRAM (1)
+#endif
+
+/*
+ * TEKRAM NVRAM format support.
+ */
+#ifndef SYM_SETUP_TEKRAM_NVRAM


+#define SYM_SETUP_TEKRAM_NVRAM (1)
+#endif
+
+/*

+ * PCI parity checking.
+ * It should not be an option, but some poor or broken
+ * PCI-HOST bridges have been reported to make problems
+ * when this feature is enabled.
+ * Setting this option to 0 tells the driver not to
+ * enable the checking against PCI parity.
+ */
+#ifndef SYM_SETUP_PCI_PARITY
+#define SYM_SETUP_PCI_PARITY (2)
+#endif
+
+/*
+ * SCSI parity checking.
+ */
+#ifndef SYM_SETUP_SCSI_PARITY
+#define SYM_SETUP_SCSI_PARITY (1)
+#endif
+
+/*
+ * SCSI activity LED.
+ */
+#ifndef SYM_SETUP_SCSI_LED
+#define SYM_SETUP_SCSI_LED (0)
+#endif
+
+/*
+ * SCSI High Voltage Differential support.
+ *
+ * HVD/LVD/SE capable controllers (895, 895A, 896, 1010)
+ * report the actual SCSI BUS mode from the STEST4 IO
+ * register.
+ *
+ * But for HVD/SE only capable chips (825a, 875, 885),
+ * the driver uses some heuristic to probe against HVD.
+ * Normally, the chip senses the DIFFSENS signal and
+ * should switch its BUS tranceivers to high impedance
+ * in situation of the driver having been wrong about
+ * the actual BUS mode. May-be, the BUS mode probing of
+ * the driver is safe, but, given that it may be partially
+ * based on some previous IO register settings, it
+ * cannot be stated so. Thus, decision has been taken
+ * to require a user option to be set for the DIFF probing
+ * to be applied for the 825a, 875 and 885 chips.
+ *
+ * This setup option works as follows:
+ *
+ * 0 -> HVD only supported for 895, 895A, 896, 1010.
+ * 1 -> HVD probed for 825A, 875, 885.
+ * 2 -> HVD assumed for 825A, 875, 885 (not advised).
+ */
+#ifndef SYM_SETUP_SCSI_DIFF
+#define SYM_SETUP_SCSI_DIFF (0)
+#endif
+
+/*
+ * IRQ mode.
+ */
+#ifndef SYM_SETUP_IRQ_MODE
+#define SYM_SETUP_IRQ_MODE (0)
+#endif
+
+/*
+ * Check SCSI BUS signal on reset.
+ */
+#ifndef SYM_SETUP_SCSI_BUS_CHECK
+#define SYM_SETUP_SCSI_BUS_CHECK (1)
+#endif
+
+/*
+ * Max burst for PCI (1<<value)
+ * 7 means: (1<<7) = 128 DWORDS.
+ */
+#ifndef SYM_SETUP_BURST_ORDER
+#define SYM_SETUP_BURST_ORDER (7)
+#endif
+
+/*
+ * Only relevant if IARB support configured.
+ * - Max number of successive settings of IARB hints.
+ * - Set IARB on arbitration lost.
+ */
+#define SYM_CONF_IARB_MAX 3
+#define SYM_CONF_SET_IARB_ON_ARB_LOST 1
+
+/*
+ * Returning wrong residuals may make problems.
+ * When zero, this define tells the driver to
+ * always return 0 as transfer residual.
+ * Btw, all my testings of residuals have succeeded.
+ */
+#define SYM_SETUP_RESIDUAL_SUPPORT 1
+
+/*
+ * Supported maximum number of LUNs to announce to
+ * the access method.
+ * The driver supports up to 64 LUNs per target as
+ * required by SPI-2/SPI-3. However some SCSI devices
+ * designed prior to these specifications or not being
+ * conformant may be highly confused when they are
+ * asked about a LUN > 7.
+ */
+#ifndef SYM_SETUP_MAX_LUN
+#define SYM_SETUP_MAX_LUN (8)
+#endif
+
+/*
+ * Bits indicating what kind of fix-ups we want.
+ *
+ * Bit 0 (1) : cache line size configuration register.
+ * Bit 1 (2) : MWI bit in command register.
+ * Bit 2 (4) : latency timer if seems too low.
+ */
+
+#ifndef SYM_SETUP_PCI_FIX_UP
+#define SYM_SETUP_PCI_FIX_UP (3)
+#endif
+
+#endif /* SYM_CONF_H */
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_defs.h linux/drivers/scsi/sym53c8xx_2/sym_defs.h
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_defs.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym_defs.h Fri Nov 9 15:22:54 2001
@@ -0,0 +1,957 @@

+#ifndef SYM_DEFS_H
+#define SYM_DEFS_H
+
+/*
+ * Vendor.
+ */
+#define PCI_VENDOR_NCR 0x1000
+
+/*
+ * PCI device identifier of SYMBIOS chips.
+ */
+#define PCI_ID_SYM53C810 1
+#define PCI_ID_SYM53C810AP 5
+#define PCI_ID_SYM53C815 4
+#define PCI_ID_SYM53C820 2
+#define PCI_ID_SYM53C825 3
+#define PCI_ID_SYM53C860 6
+#define PCI_ID_SYM53C875 0xf
+#define PCI_ID_SYM53C875_2 0x8f
+#define PCI_ID_SYM53C885 0xd
+#define PCI_ID_SYM53C895 0xc
+#define PCI_ID_SYM53C896 0xb
+#define PCI_ID_SYM53C895A 0x12
+#define PCI_ID_SYM53C875A 0x13
+#define PCI_ID_LSI53C1010 0x20
+#define PCI_ID_LSI53C1010_2 0x21
+#define PCI_ID_LSI53C1510D 0xa
+
+/*
+ * SYM53C8XX device features descriptor.
+ */
+struct sym_pci_chip {
+ u_short device_id;
+ u_short revision_id;
+ char *name;
+ u_char burst_max; /* log-base-2 of max burst */
+ u_char offset_max;
+ u_char nr_divisor;
+ u_char lp_probe_bit;
+ u_int features;
+#define FE_LED0 (1<<0)
+#define FE_WIDE (1<<1) /* Wide data transfers */
+#define FE_ULTRA (1<<2) /* Ultra speed 20Mtrans/sec */
+#define FE_ULTRA2 (1<<3) /* Ultra 2 - 40 Mtrans/sec */
+#define FE_DBLR (1<<4) /* Clock doubler present */
+#define FE_QUAD (1<<5) /* Clock quadrupler present */
+#define FE_ERL (1<<6) /* Enable read line */
+#define FE_CLSE (1<<7) /* Cache line size enable */
+#define FE_WRIE (1<<8) /* Write & Invalidate enable */
+#define FE_ERMP (1<<9) /* Enable read multiple */
+#define FE_BOF (1<<10) /* Burst opcode fetch */
+#define FE_DFS (1<<11) /* DMA fifo size */
+#define FE_PFEN (1<<12) /* Prefetch enable */
+#define FE_LDSTR (1<<13) /* Load/Store supported */
+#define FE_RAM (1<<14) /* On chip RAM present */
+#define FE_VARCLK (1<<15) /* Clock frequency may vary */
+#define FE_RAM8K (1<<16) /* On chip RAM sized 8Kb */
+#define FE_64BIT (1<<17) /* 64-bit PCI BUS interface */
+#define FE_IO256 (1<<18) /* Requires full 256 bytes in PCI space */
+#define FE_NOPM (1<<19) /* Scripts handles phase mismatch */
+#define FE_LEDC (1<<20) /* Hardware control of LED */
+#define FE_ULTRA3 (1<<21) /* Ultra 3 - 80 Mtrans/sec DT */
+#define FE_66MHZ (1<<22) /* 66MHz PCI support */
+#define FE_CRC (1<<23) /* CRC support */
+#define FE_DIFF (1<<24) /* SCSI HVD support */
+#define FE_DFBC (1<<25) /* Have DFBC register */
+#define FE_LCKFRQ (1<<26) /* Have LCKFRQ */
+#define FE_C10 (1<<27) /* Various C10 core (mis)features */
+#define FE_U3EN (1<<28) /* U3EN bit usable */
+#define FE_DAC (1<<29) /* Support PCI DAC (64 bit addressing) */
+#define FE_ISTAT1 (1<<30) /* Have ISTAT1, MBOX0, MBOX1 registers */
+
+#define FE_CACHE_SET (FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP)
+#define FE_CACHE0_SET (FE_CACHE_SET & ~FE_ERL)
+};
+
+/*
+ * Symbios NVRAM data format
+ */
+#define SYMBIOS_NVRAM_SIZE 368
+#define SYMBIOS_NVRAM_ADDRESS 0x100
+
+struct Symbios_nvram {
+/* Header 6 bytes */
+ u_short type; /* 0x0000 */
+ u_short byte_count; /* excluding header/trailer */
+ u_short checksum;
+
+/* Controller set up 20 bytes */
+ u_char v_major; /* 0x00 */
+ u_char v_minor; /* 0x30 */
+ u32 boot_crc;
+ u_short flags;
+#define SYMBIOS_SCAM_ENABLE (1)
+#define SYMBIOS_PARITY_ENABLE (1<<1)
+#define SYMBIOS_VERBOSE_MSGS (1<<2)
+#define SYMBIOS_CHS_MAPPING (1<<3)
+#define SYMBIOS_NO_NVRAM (1<<3) /* ??? */
+ u_short flags1;
+#define SYMBIOS_SCAN_HI_LO (1)
+ u_short term_state;
+#define SYMBIOS_TERM_CANT_PROGRAM (0)
+#define SYMBIOS_TERM_ENABLED (1)
+#define SYMBIOS_TERM_DISABLED (2)
+ u_short rmvbl_flags;
+#define SYMBIOS_RMVBL_NO_SUPPORT (0)
+#define SYMBIOS_RMVBL_BOOT_DEVICE (1)
+#define SYMBIOS_RMVBL_MEDIA_INSTALLED (2)
+ u_char host_id;
+ u_char num_hba; /* 0x04 */
+ u_char num_devices; /* 0x10 */
+ u_char max_scam_devices; /* 0x04 */
+ u_char num_valid_scam_devices; /* 0x00 */
+ u_char flags2;
+#define SYMBIOS_AVOID_BUS_RESET (1<<2)
+
+/* Boot order 14 bytes * 4 */
+ struct Symbios_host{
+ u_short type; /* 4:8xx / 0:nok */
+ u_short device_id; /* PCI device id */
+ u_short vendor_id; /* PCI vendor id */
+ u_char bus_nr; /* PCI bus number */
+ u_char device_fn; /* PCI device/function number << 3*/
+ u_short word8;
+ u_short flags;
+#define SYMBIOS_INIT_SCAN_AT_BOOT (1)
+ u_short io_port; /* PCI io_port address */
+ } host[4];
+
+/* Targets 8 bytes * 16 */
+ struct Symbios_target {
+ u_char flags;
+#define SYMBIOS_DISCONNECT_ENABLE (1)
+#define SYMBIOS_SCAN_AT_BOOT_TIME (1<<1)
+#define SYMBIOS_SCAN_LUNS (1<<2)
+#define SYMBIOS_QUEUE_TAGS_ENABLED (1<<3)
+ u_char rsvd;
+ u_char bus_width; /* 0x08/0x10 */
+ u_char sync_offset;
+ u_short sync_period; /* 4*period factor */
+ u_short timeout;
+ } target[16];
+/* Scam table 8 bytes * 4 */
+ struct Symbios_scam {
+ u_short id;
+ u_short method;
+#define SYMBIOS_SCAM_DEFAULT_METHOD (0)
+#define SYMBIOS_SCAM_DONT_ASSIGN (1)
+#define SYMBIOS_SCAM_SET_SPECIFIC_ID (2)
+#define SYMBIOS_SCAM_USE_ORDER_GIVEN (3)
+ u_short status;
+#define SYMBIOS_SCAM_UNKNOWN (0)
+#define SYMBIOS_SCAM_DEVICE_NOT_FOUND (1)
+#define SYMBIOS_SCAM_ID_NOT_SET (2)
+#define SYMBIOS_SCAM_ID_VALID (3)
+ u_char target_id;
+ u_char rsvd;
+ } scam[4];
+
+ u_char spare_devices[15*8];
+ u_char trailer[6]; /* 0xfe 0xfe 0x00 0x00 0x00 0x00 */
+};
+typedef struct Symbios_nvram Symbios_nvram;
+typedef struct Symbios_host Symbios_host;
+typedef struct Symbios_target Symbios_target;
+typedef struct Symbios_scam Symbios_scam;
+
+/*
+ * Tekram NvRAM data format.
+ */
+#define TEKRAM_NVRAM_SIZE 64
+#define TEKRAM_93C46_NVRAM_ADDRESS 0
+#define TEKRAM_24C16_NVRAM_ADDRESS 0x40
+
+struct Tekram_nvram {
+ struct Tekram_target {
+ u_char flags;
+#define TEKRAM_PARITY_CHECK (1)
+#define TEKRAM_SYNC_NEGO (1<<1)
+#define TEKRAM_DISCONNECT_ENABLE (1<<2)
+#define TEKRAM_START_CMD (1<<3)
+#define TEKRAM_TAGGED_COMMANDS (1<<4)
+#define TEKRAM_WIDE_NEGO (1<<5)
+ u_char sync_index;
+ u_short word2;
+ } target[16];
+ u_char host_id;
+ u_char flags;
+#define TEKRAM_MORE_THAN_2_DRIVES (1)
+#define TEKRAM_DRIVES_SUP_1GB (1<<1)
+#define TEKRAM_RESET_ON_POWER_ON (1<<2)
+#define TEKRAM_ACTIVE_NEGATION (1<<3)
+#define TEKRAM_IMMEDIATE_SEEK (1<<4)
+#define TEKRAM_SCAN_LUNS (1<<5)
+#define TEKRAM_REMOVABLE_FLAGS (3<<6) /* 0: disable; */
+ /* 1: boot device; 2:all */
+ u_char boot_delay_index;
+ u_char max_tags_index;
+ u_short flags1;
+#define TEKRAM_F2_F6_ENABLED (1)
+ u_short spare[29];
+};
+typedef struct Tekram_nvram Tekram_nvram;
+typedef struct Tekram_target Tekram_target;
+
+/*
+ * SYM53C8XX IO register data structure.
+ */
+struct sym_reg {
+/*00*/ u8 nc_scntl0; /* full arb., ena parity, par->ATN */
+
+/*01*/ u8 nc_scntl1; /* no reset */
+ #define ISCON 0x10 /* connected to scsi */
+ #define CRST 0x08 /* force reset */
+ #define IARB 0x02 /* immediate arbitration */
+
+/*02*/ u8 nc_scntl2; /* no disconnect expected */
+ #define SDU 0x80 /* cmd: disconnect will raise error */
+ #define CHM 0x40 /* sta: chained mode */
+ #define WSS 0x08 /* sta: wide scsi send [W]*/
+ #define WSR 0x01 /* sta: wide scsi received [W]*/
+
+/*03*/ u8 nc_scntl3; /* cnf system clock dependent */
+ #define EWS 0x08 /* cmd: enable wide scsi [W]*/
+ #define ULTRA 0x80 /* cmd: ULTRA enable */
+ /* bits 0-2, 7 rsvd for C1010 */
+
+/*04*/ u8 nc_scid; /* cnf host adapter scsi address */
+ #define RRE 0x40 /* r/w:e enable response to resel. */
+ #define SRE 0x20 /* r/w:e enable response to select */
+
+/*05*/ u8 nc_sxfer; /* ### Sync speed and count */
+ /* bits 6-7 rsvd for C1010 */
+
+/*06*/ u8 nc_sdid; /* ### Destination-ID */
+
+/*07*/ u8 nc_gpreg; /* ??? IO-Pins */
+
+/*08*/ u8 nc_sfbr; /* ### First byte received */
+
+/*09*/ u8 nc_socl;
+ #define CREQ 0x80 /* r/w: SCSI-REQ */
+ #define CACK 0x40 /* r/w: SCSI-ACK */
+ #define CBSY 0x20 /* r/w: SCSI-BSY */
+ #define CSEL 0x10 /* r/w: SCSI-SEL */
+ #define CATN 0x08 /* r/w: SCSI-ATN */
+ #define CMSG 0x04 /* r/w: SCSI-MSG */
+ #define CC_D 0x02 /* r/w: SCSI-C_D */
+ #define CI_O 0x01 /* r/w: SCSI-I_O */
+
+/*0a*/ u8 nc_ssid;
+
+/*0b*/ u8 nc_sbcl;
+
+/*0c*/ u8 nc_dstat;
+ #define DFE 0x80 /* sta: dma fifo empty */
+ #define MDPE 0x40 /* int: master data parity error */
+ #define BF 0x20 /* int: script: bus fault */
+ #define ABRT 0x10 /* int: script: command aborted */
+ #define SSI 0x08 /* int: script: single step */
+ #define SIR 0x04 /* int: script: interrupt instruct. */
+ #define IID 0x01 /* int: script: illegal instruct. */
+
+/*0d*/ u8 nc_sstat0;
+ #define ILF 0x80 /* sta: data in SIDL register lsb */
+ #define ORF 0x40 /* sta: data in SODR register lsb */
+ #define OLF 0x20 /* sta: data in SODL register lsb */
+ #define AIP 0x10 /* sta: arbitration in progress */
+ #define LOA 0x08 /* sta: arbitration lost */
+ #define WOA 0x04 /* sta: arbitration won */
+ #define IRST 0x02 /* sta: scsi reset signal */
+ #define SDP 0x01 /* sta: scsi parity signal */
+
+/*0e*/ u8 nc_sstat1;
+ #define FF3210 0xf0 /* sta: bytes in the scsi fifo */
+
+/*0f*/ u8 nc_sstat2;
+ #define ILF1 0x80 /* sta: data in SIDL register msb[W]*/
+ #define ORF1 0x40 /* sta: data in SODR register msb[W]*/
+ #define OLF1 0x20 /* sta: data in SODL register msb[W]*/
+ #define DM 0x04 /* sta: DIFFSENS mismatch (895/6 only) */
+ #define LDSC 0x02 /* sta: disconnect & reconnect */
+
+/*10*/ u8 nc_dsa; /* --> Base page */
+/*11*/ u8 nc_dsa1;
+/*12*/ u8 nc_dsa2;
+/*13*/ u8 nc_dsa3;
+
+/*14*/ u8 nc_istat; /* --> Main Command and status */
+ #define CABRT 0x80 /* cmd: abort current operation */
+ #define SRST 0x40 /* mod: reset chip */
+ #define SIGP 0x20 /* r/w: message from host to script */
+ #define SEM 0x10 /* r/w: message between host + script */
+ #define CON 0x08 /* sta: connected to scsi */
+ #define INTF 0x04 /* sta: int on the fly (reset by wr)*/
+ #define SIP 0x02 /* sta: scsi-interrupt */
+ #define DIP 0x01 /* sta: host/script interrupt */
+
+/*15*/ u8 nc_istat1; /* 896 only */
+ #define FLSH 0x04 /* sta: chip is flushing */
+ #define SCRUN 0x02 /* sta: scripts are running */
+ #define SIRQD 0x01 /* r/w: disable INT pin */
+
+/*16*/ u8 nc_mbox0; /* 896 only */
+/*17*/ u8 nc_mbox1; /* 896 only */
+
+/*18*/ u8 nc_ctest0;
+/*19*/ u8 nc_ctest1;
+
+/*1a*/ u8 nc_ctest2;
+ #define CSIGP 0x40
+ /* bits 0-2,7 rsvd for C1010 */
+
+/*1b*/ u8 nc_ctest3;
+ #define FLF 0x08 /* cmd: flush dma fifo */
+ #define CLF 0x04 /* cmd: clear dma fifo */
+ #define FM 0x02 /* mod: fetch pin mode */
+ #define WRIE 0x01 /* mod: write and invalidate enable */
+ /* bits 4-7 rsvd for C1010 */
+
+/*1c*/ u32 nc_temp; /* ### Temporary stack */
+
+/*20*/ u8 nc_dfifo;
+/*21*/ u8 nc_ctest4;
+ #define BDIS 0x80 /* mod: burst disable */
+ #define MPEE 0x08 /* mod: master parity error enable */
+
+/*22*/ u8 nc_ctest5;
+ #define DFS 0x20 /* mod: dma fifo size */
+ /* bits 0-1, 3-7 rsvd for C1010 */
+
+/*23*/ u8 nc_ctest6;
+
+/*24*/ u32 nc_dbc; /* ### Byte count and command */
+/*28*/ u32 nc_dnad; /* ### Next command register */
+/*2c*/ u32 nc_dsp; /* --> Script Pointer */
+/*30*/ u32 nc_dsps; /* --> Script pointer save/opcode#2 */
+
+/*34*/ u8 nc_scratcha; /* Temporary register a */
+/*35*/ u8 nc_scratcha1;
+/*36*/ u8 nc_scratcha2;
+/*37*/ u8 nc_scratcha3;
+
+/*38*/ u8 nc_dmode;
+ #define BL_2 0x80 /* mod: burst length shift value +2 */
+ #define BL_1 0x40 /* mod: burst length shift value +1 */
+ #define ERL 0x08 /* mod: enable read line */
+ #define ERMP 0x04 /* mod: enable read multiple */
+ #define BOF 0x02 /* mod: burst op code fetch */
+
+/*39*/ u8 nc_dien;
+/*3a*/ u8 nc_sbr;
+
+/*3b*/ u8 nc_dcntl; /* --> Script execution control */
+ #define CLSE 0x80 /* mod: cache line size enable */
+ #define PFF 0x40 /* cmd: pre-fetch flush */
+ #define PFEN 0x20 /* mod: pre-fetch enable */
+ #define SSM 0x10 /* mod: single step mode */
+ #define IRQM 0x08 /* mod: irq mode (1 = totem pole !) */
+ #define STD 0x04 /* cmd: start dma mode */
+ #define IRQD 0x02 /* mod: irq disable */
+ #define NOCOM 0x01 /* cmd: protect sfbr while reselect */
+ /* bits 0-1 rsvd for C1010 */
+
+/*3c*/ u32 nc_adder;
+
+/*40*/ u16 nc_sien; /* -->: interrupt enable */
+/*42*/ u16 nc_sist; /* <--: interrupt status */
+ #define SBMC 0x1000/* sta: SCSI Bus Mode Change (895/6 only) */
+ #define STO 0x0400/* sta: timeout (select) */
+ #define GEN 0x0200/* sta: timeout (general) */
+ #define HTH 0x0100/* sta: timeout (handshake) */
+ #define MA 0x80 /* sta: phase mismatch */
+ #define CMP 0x40 /* sta: arbitration complete */
+ #define SEL 0x20 /* sta: selected by another device */
+ #define RSL 0x10 /* sta: reselected by another device*/
+ #define SGE 0x08 /* sta: gross error (over/underflow)*/
+ #define UDC 0x04 /* sta: unexpected disconnect */
+ #define RST 0x02 /* sta: scsi bus reset detected */
+ #define PAR 0x01 /* sta: scsi parity error */
+
+/*44*/ u8 nc_slpar;
+/*45*/ u8 nc_swide;
+/*46*/ u8 nc_macntl;
+/*47*/ u8 nc_gpcntl;
+/*48*/ u8 nc_stime0; /* cmd: timeout for select&handshake*/
+/*49*/ u8 nc_stime1; /* cmd: timeout user defined */
+/*4a*/ u16 nc_respid; /* sta: Reselect-IDs */
+
+/*4c*/ u8 nc_stest0;
+
+/*4d*/ u8 nc_stest1;
+ #define SCLK 0x80 /* Use the PCI clock as SCSI clock */
+ #define DBLEN 0x08 /* clock doubler running */
+ #define DBLSEL 0x04 /* clock doubler selected */
+
+
+/*4e*/ u8 nc_stest2;
+ #define ROF 0x40 /* reset scsi offset (after gross error!) */
+ #define EXT 0x02 /* extended filtering */
+
+/*4f*/ u8 nc_stest3;
+ #define TE 0x80 /* c: tolerAnt enable */
+ #define HSC 0x20 /* c: Halt SCSI Clock */
+ #define CSF 0x02 /* c: clear scsi fifo */
+
+/*50*/ u16 nc_sidl; /* Lowlevel: latched from scsi data */
+/*52*/ u8 nc_stest4;
+ #define SMODE 0xc0 /* SCSI bus mode (895/6 only) */
+ #define SMODE_HVD 0x40 /* High Voltage Differential */
+ #define SMODE_SE 0x80 /* Single Ended */
+ #define SMODE_LVD 0xc0 /* Low Voltage Differential */
+ #define LCKFRQ 0x20 /* Frequency Lock (895/6 only) */
+ /* bits 0-5 rsvd for C1010 */
+
+/*53*/ u8 nc_53_;
+/*54*/ u16 nc_sodl; /* Lowlevel: data out to scsi data */
+/*56*/ u8 nc_ccntl0; /* Chip Control 0 (896) */
+ #define ENPMJ 0x80 /* Enable Phase Mismatch Jump */
+ #define PMJCTL 0x40 /* Phase Mismatch Jump Control */
+ #define ENNDJ 0x20 /* Enable Non Data PM Jump */
+ #define DISFC 0x10 /* Disable Auto FIFO Clear */
+ #define DILS 0x02 /* Disable Internal Load/Store */
+ #define DPR 0x01 /* Disable Pipe Req */
+
+/*57*/ u8 nc_ccntl1; /* Chip Control 1 (896) */
+ #define ZMOD 0x80 /* High Impedance Mode */
+ #define DDAC 0x08 /* Disable Dual Address Cycle */
+ #define XTIMOD 0x04 /* 64-bit Table Ind. Indexing Mode */
+ #define EXTIBMV 0x02 /* Enable 64-bit Table Ind. BMOV */
+ #define EXDBMV 0x01 /* Enable 64-bit Direct BMOV */
+
+/*58*/ u16 nc_sbdl; /* Lowlevel: data from scsi data */
+/*5a*/ u16 nc_5a_;
+
+/*5c*/ u8 nc_scr0; /* Working register B */
+/*5d*/ u8 nc_scr1;
+/*5e*/ u8 nc_scr2;
+/*5f*/ u8 nc_scr3;
+
+/*60*/ u8 nc_scrx[64]; /* Working register C-R */
+/*a0*/ u32 nc_mmrs; /* Memory Move Read Selector */
+/*a4*/ u32 nc_mmws; /* Memory Move Write Selector */
+/*a8*/ u32 nc_sfs; /* Script Fetch Selector */
+/*ac*/ u32 nc_drs; /* DSA Relative Selector */
+/*b0*/ u32 nc_sbms; /* Static Block Move Selector */
+/*b4*/ u32 nc_dbms; /* Dynamic Block Move Selector */
+/*b8*/ u32 nc_dnad64; /* DMA Next Address 64 */
+/*bc*/ u16 nc_scntl4; /* C1010 only */
+ #define U3EN 0x80 /* Enable Ultra 3 */
+ #define AIPCKEN 0x40 /* AIP checking enable */
+ /* Also enable AIP generation on C10-33*/
+ #define XCLKH_DT 0x08 /* Extra clock of data hold on DT edge */
+ #define XCLKH_ST 0x04 /* Extra clock of data hold on ST edge */
+ #define XCLKS_DT 0x02 /* Extra clock of data set on DT edge */
+ #define XCLKS_ST 0x01 /* Extra clock of data set on ST edge */
+/*be*/ u8 nc_aipcntl0; /* AIP Control 0 C1010 only */
+/*bf*/ u8 nc_aipcntl1; /* AIP Control 1 C1010 only */
+ #define DISAIP 0x08 /* Disable AIP generation C10-66 only */
+/*c0*/ u32 nc_pmjad1; /* Phase Mismatch Jump Address 1 */
+/*c4*/ u32 nc_pmjad2; /* Phase Mismatch Jump Address 2 */
+/*c8*/ u8 nc_rbc; /* Remaining Byte Count */
+/*c9*/ u8 nc_rbc1;
+/*ca*/ u8 nc_rbc2;
+/*cb*/ u8 nc_rbc3;
+
+/*cc*/ u8 nc_ua; /* Updated Address */
+/*cd*/ u8 nc_ua1;
+/*ce*/ u8 nc_ua2;
+/*cf*/ u8 nc_ua3;
+/*d0*/ u32 nc_esa; /* Entry Storage Address */
+/*d4*/ u8 nc_ia; /* Instruction Address */
+/*d5*/ u8 nc_ia1;
+/*d6*/ u8 nc_ia2;
+/*d7*/ u8 nc_ia3;
+/*d8*/ u32 nc_sbc; /* SCSI Byte Count (3 bytes only) */
+/*dc*/ u32 nc_csbc; /* Cumulative SCSI Byte Count */
+ /* Following for C1010 only */
+/*e0*/ u16 nc_crcpad; /* CRC Value */
+/*e2*/ u8 nc_crccntl0; /* CRC control register */
+ #define SNDCRC 0x10 /* Send CRC Request */
+/*e3*/ u8 nc_crccntl1; /* CRC control register */
+/*e4*/ u32 nc_crcdata; /* CRC data register */
+/*e8*/ u32 nc_e8_;
+/*ec*/ u32 nc_ec_;
+/*f0*/ u16 nc_dfbc; /* DMA FIFO byte count */
+};
+
+/*-----------------------------------------------------------
+ *
+ * Utility macros for the script.
+ *
+ *-----------------------------------------------------------
+ */
+
+#define REGJ(p,r) (offsetof(struct sym_reg, p ## r))
+#define REG(r) REGJ (nc_, r)
+
+/*-----------------------------------------------------------
+ *
+ * SCSI phases
+ *
+ *-----------------------------------------------------------
+ */
+
+#define SCR_DATA_OUT 0x00000000
+#define SCR_DATA_IN 0x01000000
+#define SCR_COMMAND 0x02000000
+#define SCR_STATUS 0x03000000
+#define SCR_DT_DATA_OUT 0x04000000
+#define SCR_DT_DATA_IN 0x05000000
+#define SCR_MSG_OUT 0x06000000
+#define SCR_MSG_IN 0x07000000
+/* DT phases are illegal for non Ultra3 mode */
+#define SCR_ILG_OUT 0x04000000
+#define SCR_ILG_IN 0x05000000
+
+/*-----------------------------------------------------------
+ *
+ * Data transfer via SCSI.
+ *
+ *-----------------------------------------------------------
+ *
+ * MOVE_ABS (LEN)
+ * <<start address>>
+ *
+ * MOVE_IND (LEN)
+ * <<dnad_offset>>
+ *
+ * MOVE_TBL
+ * <<dnad_offset>>
+ *
+ *-----------------------------------------------------------
+ */
+
+#define OPC_MOVE 0x08000000
+
+#define SCR_MOVE_ABS(l) ((0x00000000 | OPC_MOVE) | (l))
+/* #define SCR_MOVE_IND(l) ((0x20000000 | OPC_MOVE) | (l)) */
+#define SCR_MOVE_TBL (0x10000000 | OPC_MOVE)
+
+#define SCR_CHMOV_ABS(l) ((0x00000000) | (l))
+/* #define SCR_CHMOV_IND(l) ((0x20000000) | (l)) */
+#define SCR_CHMOV_TBL (0x10000000)
+
+#ifdef SYM_CONF_TARGET_ROLE_SUPPORT
+/* We steal the `indirect addressing' flag for target mode MOVE in scripts */
+
+#define OPC_TCHMOVE 0x08000000
+
+#define SCR_TCHMOVE_ABS(l) ((0x20000000 | OPC_TCHMOVE) | (l))
+#define SCR_TCHMOVE_TBL (0x30000000 | OPC_TCHMOVE)
+
+#define SCR_TMOV_ABS(l) ((0x20000000) | (l))
+#define SCR_TMOV_TBL (0x30000000)
+#endif
+
+struct sym_tblmove {
+ u32 size;


+ u32 addr;
+};
+

+/*-----------------------------------------------------------
+ *
+ * Selection
+ *
+ *-----------------------------------------------------------
+ *
+ * SEL_ABS | SCR_ID (0..15) [ | REL_JMP]
+ * <<alternate_address>>
+ *
+ * SEL_TBL | << dnad_offset>> [ | REL_JMP]
+ * <<alternate_address>>
+ *
+ *-----------------------------------------------------------
+ */
+
+#define SCR_SEL_ABS 0x40000000
+#define SCR_SEL_ABS_ATN 0x41000000
+#define SCR_SEL_TBL 0x42000000
+#define SCR_SEL_TBL_ATN 0x43000000
+
+#ifdef SYM_CONF_TARGET_ROLE_SUPPORT
+#define SCR_RESEL_ABS 0x40000000
+#define SCR_RESEL_ABS_ATN 0x41000000
+#define SCR_RESEL_TBL 0x42000000
+#define SCR_RESEL_TBL_ATN 0x43000000
+#endif
+
+struct sym_tblsel {
+ u_char sel_scntl4; /* C1010 only */
+ u_char sel_sxfer;
+ u_char sel_id;
+ u_char sel_scntl3;
+};
+
+#define SCR_JMP_REL 0x04000000
+#define SCR_ID(id) (((u32)(id)) << 16)
+
+/*-----------------------------------------------------------
+ *
+ * Waiting for Disconnect or Reselect
+ *
+ *-----------------------------------------------------------
+ *
+ * WAIT_DISC
+ * dummy: <<alternate_address>>
+ *
+ * WAIT_RESEL
+ * <<alternate_address>>
+ *
+ *-----------------------------------------------------------
+ */
+
+#define SCR_WAIT_DISC 0x48000000
+#define SCR_WAIT_RESEL 0x50000000
+
+#ifdef SYM_CONF_TARGET_ROLE_SUPPORT
+#define SCR_DISCONNECT 0x48000000
+#endif
+
+/*-----------------------------------------------------------
+ *
+ * Bit Set / Reset
+ *
+ *-----------------------------------------------------------
+ *
+ * SET (flags {|.. })
+ *
+ * CLR (flags {|.. })
+ *
+ *-----------------------------------------------------------
+ */
+
+#define SCR_SET(f) (0x58000000 | (f))
+#define SCR_CLR(f) (0x60000000 | (f))
+
+#define SCR_CARRY 0x00000400
+#define SCR_TRG 0x00000200
+#define SCR_ACK 0x00000040
+#define SCR_ATN 0x00000008
+
+
+/*-----------------------------------------------------------
+ *
+ * Memory to memory move
+ *
+ *-----------------------------------------------------------
+ *
+ * COPY (bytecount)
+ * << source_address >>
+ * << destination_address >>
+ *
+ * SCR_COPY sets the NO FLUSH option by default.
+ * SCR_COPY_F does not set this option.
+ *
+ * For chips which do not support this option,
+ * sym_fw_bind_script() will remove this bit.
+ *
+ *-----------------------------------------------------------
+ */
+
+#define SCR_NO_FLUSH 0x01000000
+
+#define SCR_COPY(n) (0xc0000000 | SCR_NO_FLUSH | (n))
+#define SCR_COPY_F(n) (0xc0000000 | (n))
+
+/*-----------------------------------------------------------
+ *
+ * Register move and binary operations
+ *
+ *-----------------------------------------------------------
+ *
+ * SFBR_REG (reg, op, data) reg = SFBR op data
+ * << 0 >>
+ *
+ * REG_SFBR (reg, op, data) SFBR = reg op data
+ * << 0 >>
+ *
+ * REG_REG (reg, op, data) reg = reg op data
+ * << 0 >>
+ *
+ *-----------------------------------------------------------
+ *
+ * On 825A, 875, 895 and 896 chips the content
+ * of SFBR register can be used as data (SCR_SFBR_DATA).
+ * The 896 has additionnal IO registers starting at
+ * offset 0x80. Bit 7 of register offset is stored in
+ * bit 7 of the SCRIPTS instruction first DWORD.
+ *
+ *-----------------------------------------------------------
+ */
+
+#define SCR_REG_OFS(ofs) ((((ofs) & 0x7f) << 16ul) + ((ofs) & 0x80))
+
+#define SCR_SFBR_REG(reg,op,data) \
+ (0x68000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+#define SCR_REG_SFBR(reg,op,data) \
+ (0x70000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+#define SCR_REG_REG(reg,op,data) \
+ (0x78000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+
+#define SCR_LOAD 0x00000000
+#define SCR_SHL 0x01000000
+#define SCR_OR 0x02000000
+#define SCR_XOR 0x03000000
+#define SCR_AND 0x04000000
+#define SCR_SHR 0x05000000
+#define SCR_ADD 0x06000000
+#define SCR_ADDC 0x07000000
+
+#define SCR_SFBR_DATA (0x00800000>>8ul) /* Use SFBR as data */
+
+/*-----------------------------------------------------------
+ *
+ * FROM_REG (reg) SFBR = reg
+ * << 0 >>
+ *
+ * TO_REG (reg) reg = SFBR
+ * << 0 >>
+ *
+ * LOAD_REG (reg, data) reg = <data>
+ * << 0 >>
+ *
+ * LOAD_SFBR(data) SFBR = <data>
+ * << 0 >>
+ *
+ *-----------------------------------------------------------
+ */
+
+#define SCR_FROM_REG(reg) \
+ SCR_REG_SFBR(reg,SCR_OR,0)
+
+#define SCR_TO_REG(reg) \
+ SCR_SFBR_REG(reg,SCR_OR,0)
+
+#define SCR_LOAD_REG(reg,data) \
+ SCR_REG_REG(reg,SCR_LOAD,data)
+
+#define SCR_LOAD_SFBR(data) \
+ (SCR_REG_SFBR (gpreg, SCR_LOAD, data))
+
+/*-----------------------------------------------------------
+ *
+ * LOAD from memory to register.
+ * STORE from register to memory.
+ *
+ * Only supported by 810A, 860, 825A, 875, 895 and 896.
+ *
+ *-----------------------------------------------------------
+ *
+ * LOAD_ABS (LEN)
+ * <<start address>>
+ *
+ * LOAD_REL (LEN) (DSA relative)
+ * <<dsa_offset>>
+ *
+ *-----------------------------------------------------------
+ */
+
+#define SCR_REG_OFS2(ofs) (((ofs) & 0xff) << 16ul)
+#define SCR_NO_FLUSH2 0x02000000
+#define SCR_DSA_REL2 0x10000000
+
+#define SCR_LOAD_R(reg, how, n) \
+ (0xe1000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
+
+#define SCR_STORE_R(reg, how, n) \
+ (0xe0000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
+
+#define SCR_LOAD_ABS(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2, n)
+#define SCR_LOAD_REL(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2, n)
+#define SCR_LOAD_ABS_F(reg, n) SCR_LOAD_R(reg, 0, n)
+#define SCR_LOAD_REL_F(reg, n) SCR_LOAD_R(reg, SCR_DSA_REL2, n)
+
+#define SCR_STORE_ABS(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2, n)
+#define SCR_STORE_REL(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2,n)
+#define SCR_STORE_ABS_F(reg, n) SCR_STORE_R(reg, 0, n)
+#define SCR_STORE_REL_F(reg, n) SCR_STORE_R(reg, SCR_DSA_REL2, n)
+
+
+/*-----------------------------------------------------------
+ *
+ * Waiting for Disconnect or Reselect
+ *
+ *-----------------------------------------------------------
+ *
+ * JUMP [ | IFTRUE/IFFALSE ( ... ) ]
+ * <<address>>
+ *
+ * JUMPR [ | IFTRUE/IFFALSE ( ... ) ]
+ * <<distance>>
+ *
+ * CALL [ | IFTRUE/IFFALSE ( ... ) ]
+ * <<address>>
+ *
+ * CALLR [ | IFTRUE/IFFALSE ( ... ) ]
+ * <<distance>>
+ *
+ * RETURN [ | IFTRUE/IFFALSE ( ... ) ]
+ * <<dummy>>
+ *
+ * INT [ | IFTRUE/IFFALSE ( ... ) ]
+ * <<ident>>
+ *
+ * INT_FLY [ | IFTRUE/IFFALSE ( ... ) ]
+ * <<ident>>
+ *
+ * Conditions:
+ * WHEN (phase)
+ * IF (phase)
+ * CARRYSET
+ * DATA (data, mask)
+ *
+ *-----------------------------------------------------------
+ */
+
+#define SCR_NO_OP 0x80000000
+#define SCR_JUMP 0x80080000
+#define SCR_JUMP64 0x80480000
+#define SCR_JUMPR 0x80880000
+#define SCR_CALL 0x88080000
+#define SCR_CALLR 0x88880000
+#define SCR_RETURN 0x90080000
+#define SCR_INT 0x98080000
+#define SCR_INT_FLY 0x98180000
+
+#define IFFALSE(arg) (0x00080000 | (arg))
+#define IFTRUE(arg) (0x00000000 | (arg))
+
+#define WHEN(phase) (0x00030000 | (phase))
+#define IF(phase) (0x00020000 | (phase))
+
+#define DATA(D) (0x00040000 | ((D) & 0xff))
+#define MASK(D,M) (0x00040000 | (((M ^ 0xff) & 0xff) << 8ul)|((D) & 0xff))
+
+#define CARRYSET (0x00200000)
+
+/*-----------------------------------------------------------
+ *
+ * SCSI constants.
+ *
+ *-----------------------------------------------------------
+ */
+
+/*
+ * Messages
+ */
+
+#define M_COMPLETE (0x00)
+#define M_EXTENDED (0x01)
+#define M_SAVE_DP (0x02)
+#define M_RESTORE_DP (0x03)
+#define M_DISCONNECT (0x04)
+#define M_ID_ERROR (0x05)
+#define M_ABORT (0x06)
+#define M_REJECT (0x07)
+#define M_NOOP (0x08)
+#define M_PARITY (0x09)
+#define M_LCOMPLETE (0x0a)
+#define M_FCOMPLETE (0x0b)
+#define M_RESET (0x0c)
+#define M_ABORT_TAG (0x0d)
+#define M_CLEAR_QUEUE (0x0e)
+#define M_INIT_REC (0x0f)
+#define M_REL_REC (0x10)
+#define M_TERMINATE (0x11)
+#define M_SIMPLE_TAG (0x20)
+#define M_HEAD_TAG (0x21)
+#define M_ORDERED_TAG (0x22)
+#define M_IGN_RESIDUE (0x23)
+#define M_IDENTIFY (0x80)
+
+#define M_X_MODIFY_DP (0x00)
+#define M_X_SYNC_REQ (0x01)
+#define M_X_WIDE_REQ (0x03)
+#define M_X_PPR_REQ (0x04)
+
+/*
+ * PPR protocol options
+ */
+#define PPR_OPT_IU (0x01)
+#define PPR_OPT_DT (0x02)
+#define PPR_OPT_QAS (0x04)
+#define PPR_OPT_MASK (0x07)
+
+/*
+ * Status
+ */
+
+#define S_GOOD (0x00)
+#define S_CHECK_COND (0x02)
+#define S_COND_MET (0x04)
+#define S_BUSY (0x08)
+#define S_INT (0x10)
+#define S_INT_COND_MET (0x14)
+#define S_CONFLICT (0x18)
+#define S_TERMINATED (0x20)
+#define S_QUEUE_FULL (0x28)
+#define S_ILLEGAL (0xff)
+
+#endif /* defined SYM_DEFS_H */
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_fw.c linux/drivers/scsi/sym53c8xx_2/sym_fw.c
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_fw.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym_fw.c Fri Nov 9 15:22:54 2001
@@ -0,0 +1,617 @@

+#ifdef __FreeBSD__
+#include <dev/sym/sym_glue.h>
+#else
+#include "sym_glue.h"
+#endif
+
+/*
+ * Macros used for all firmwares.
+ */
+#define SYM_GEN_A(s, label) ((short) offsetof(s, label)),
+#define SYM_GEN_B(s, label) ((short) offsetof(s, label)),
+#define SYM_GEN_Z(s, label) ((short) offsetof(s, label)),
+#define PADDR_A(label) SYM_GEN_PADDR_A(struct SYM_FWA_SCR, label)
+#define PADDR_B(label) SYM_GEN_PADDR_B(struct SYM_FWB_SCR, label)
+
+
+#if SYM_CONF_GENERIC_SUPPORT
+/*
+ * Allocate firmware #1 script area.
+ */
+#define SYM_FWA_SCR sym_fw1a_scr
+#define SYM_FWB_SCR sym_fw1b_scr
+#define SYM_FWZ_SCR sym_fw1z_scr
+#ifdef __FreeBSD__
+#include <dev/sym/sym_fw1.h>
+#else
+#include "sym_fw1.h"
+#endif
+static struct sym_fwa_ofs sym_fw1a_ofs = {
+ SYM_GEN_FW_A(struct SYM_FWA_SCR)
+};
+static struct sym_fwb_ofs sym_fw1b_ofs = {
+ SYM_GEN_FW_B(struct SYM_FWB_SCR)
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+ SYM_GEN_B(struct SYM_FWB_SCR, data_io)
+#endif
+};
+static struct sym_fwz_ofs sym_fw1z_ofs = {
+ SYM_GEN_FW_Z(struct SYM_FWZ_SCR)
+#ifdef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ SYM_GEN_Z(struct SYM_FWZ_SCR, start_ram)
+#endif
+};
+#undef SYM_FWA_SCR
+#undef SYM_FWB_SCR
+#undef SYM_FWZ_SCR
+#endif /* SYM_CONF_GENERIC_SUPPORT */
+
+/*
+ * Allocate firmware #2 script area.
+ */
+#define SYM_FWA_SCR sym_fw2a_scr
+#define SYM_FWB_SCR sym_fw2b_scr
+#define SYM_FWZ_SCR sym_fw2z_scr
+#ifdef __FreeBSD__
+#include <dev/sym/sym_fw2.h>
+#else
+#include "sym_fw2.h"
+#endif
+static struct sym_fwa_ofs sym_fw2a_ofs = {
+ SYM_GEN_FW_A(struct SYM_FWA_SCR)
+};
+static struct sym_fwb_ofs sym_fw2b_ofs = {
+ SYM_GEN_FW_B(struct SYM_FWB_SCR)
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+ SYM_GEN_B(struct SYM_FWB_SCR, data_io)
+#endif
+ SYM_GEN_B(struct SYM_FWB_SCR, start64)
+ SYM_GEN_B(struct SYM_FWB_SCR, pm_handle)
+};
+static struct sym_fwz_ofs sym_fw2z_ofs = {
+ SYM_GEN_FW_Z(struct SYM_FWZ_SCR)
+#ifdef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ SYM_GEN_Z(struct SYM_FWZ_SCR, start_ram)
+ SYM_GEN_Z(struct SYM_FWZ_SCR, start_ram64)
+#endif
+};
+#undef SYM_FWA_SCR
+#undef SYM_FWB_SCR
+#undef SYM_FWZ_SCR
+
+#undef SYM_GEN_A
+#undef SYM_GEN_B
+#undef SYM_GEN_Z
+#undef PADDR_A
+#undef PADDR_B
+
+#if SYM_CONF_GENERIC_SUPPORT
+/*
+ * Patch routine for firmware #1.
+ */
+static void
+sym_fw1_patch(hcb_p np)
+{
+ struct sym_fw1a_scr *scripta0;
+ struct sym_fw1b_scr *scriptb0;
+#ifdef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ struct sym_fw1z_scr *scriptz0 =
+ (struct sym_fw1z_scr *) np->scriptz0;
+#endif
+
+ scripta0 = (struct sym_fw1a_scr *) np->scripta0;
+ scriptb0 = (struct sym_fw1b_scr *) np->scriptb0;
+
+#ifdef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ /*
+ * Set up BUS physical address of SCRIPTS that is to
+ * be copied to on-chip RAM by the SCRIPTS processor.
+ */
+ scriptz0->scripta0_ba[0] = cpu_to_scr(vtobus(scripta0));
+#endif
+
+ /*
+ * Remove LED support if not needed.
+ */
+ if (!(np->features & FE_LED0)) {
+ scripta0->idle[0] = cpu_to_scr(SCR_NO_OP);
+ scripta0->reselected[0] = cpu_to_scr(SCR_NO_OP);
+ scripta0->start[0] = cpu_to_scr(SCR_NO_OP);
+ }
+
+#ifdef SYM_CONF_IARB_SUPPORT
+ /*
+ * If user does not want to use IMMEDIATE ARBITRATION
+ * when we are reselected while attempting to arbitrate,
+ * patch the SCRIPTS accordingly with a SCRIPT NO_OP.
+ */
+ if (!SYM_CONF_SET_IARB_ON_ARB_LOST)
+ scripta0->ungetjob[0] = cpu_to_scr(SCR_NO_OP);
+#endif
+ /*
+ * Patch some data in SCRIPTS.
+ * - start and done queue initial bus address.
+ * - target bus address table bus address.
+ */
+ scriptb0->startpos[0] = cpu_to_scr(np->squeue_ba);
+ scriptb0->done_pos[0] = cpu_to_scr(np->dqueue_ba);
+ scriptb0->targtbl[0] = cpu_to_scr(np->targtbl_ba);
+}
+#endif /* SYM_CONF_GENERIC_SUPPORT */
+
+/*
+ * Patch routine for firmware #2.
+ */
+static void
+sym_fw2_patch(hcb_p np)
+{
+ struct sym_fw2a_scr *scripta0;
+ struct sym_fw2b_scr *scriptb0;
+#ifdef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ struct sym_fw2z_scr *scriptz0 =
+ (struct sym_fw2z_scr *) np->scriptz0;
+#endif
+
+ scripta0 = (struct sym_fw2a_scr *) np->scripta0;
+ scriptb0 = (struct sym_fw2b_scr *) np->scriptb0;
+
+#ifdef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ /*
+ * Set up BUS physical address of SCRIPTS that is to
+ * be copied to on-chip RAM by the SCRIPTS processor.
+ */
+ scriptz0->scripta0_ba64[0] = /* Nothing is missing here */
+ scriptz0->scripta0_ba[0] = cpu_to_scr(vtobus(scripta0));
+ scriptz0->scriptb0_ba64[0] = cpu_to_scr(vtobus(scriptb0));
+ scriptz0->ram_seg64[0] = np->scr_ram_seg;
+#endif
+
+ /*
+ * Remove LED support if not needed.
+ */
+ if (!(np->features & FE_LED0)) {
+ scripta0->idle[0] = cpu_to_scr(SCR_NO_OP);
+ scripta0->reselected[0] = cpu_to_scr(SCR_NO_OP);
+ scripta0->start[0] = cpu_to_scr(SCR_NO_OP);
+ }
+
+#if SYM_CONF_DMA_ADDRESSING_MODE == 2
+ /*
+ * Remove useless 64 bit DMA specific SCRIPTS,
+ * when this feature is not available.
+ */
+ if (!np->use_dac) {
+ scripta0->is_dmap_dirty[0] = cpu_to_scr(SCR_NO_OP);
+ scripta0->is_dmap_dirty[1] = 0;
+ scripta0->is_dmap_dirty[2] = cpu_to_scr(SCR_NO_OP);
+ scripta0->is_dmap_dirty[3] = 0;
+ }
+#endif
+
+#ifdef SYM_CONF_IARB_SUPPORT
+ /*
+ * If user does not want to use IMMEDIATE ARBITRATION
+ * when we are reselected while attempting to arbitrate,
+ * patch the SCRIPTS accordingly with a SCRIPT NO_OP.
+ */
+ if (!SYM_CONF_SET_IARB_ON_ARB_LOST)
+ scripta0->ungetjob[0] = cpu_to_scr(SCR_NO_OP);
+#endif
+ /*
+ * Patch some variable in SCRIPTS.
+ * - start and done queue initial bus address.
+ * - target bus address table bus address.
+ */
+ scriptb0->startpos[0] = cpu_to_scr(np->squeue_ba);
+ scriptb0->done_pos[0] = cpu_to_scr(np->dqueue_ba);
+ scriptb0->targtbl[0] = cpu_to_scr(np->targtbl_ba);
+
+ /*
+ * Remove the load of SCNTL4 on reselection if not a C10.
+ */
+ if (!(np->features & FE_C10)) {
+ scripta0->resel_scntl4[0] = cpu_to_scr(SCR_NO_OP);
+ scripta0->resel_scntl4[1] = cpu_to_scr(0);
+ }
+
+ /*
+ * Remove a couple of work-arounds specific to C1010 if
+ * they are not desirable. See `sym_fw2.h' for more details.
+ */
+ if (!(np->device_id == PCI_ID_LSI53C1010_2 &&
+ np->revision_id < 0x1 &&
+ np->pciclk_khz < 60000)) {
+ scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP);
+ scripta0->datao_phase[1] = cpu_to_scr(0);
+ }
+ if (!(np->device_id == PCI_ID_LSI53C1010 &&
+ /* np->revision_id < 0xff */ 1)) {
+ scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP);
+ scripta0->sel_done[1] = cpu_to_scr(0);
+ }
+
+ /*
+ * Patch some other variables in SCRIPTS.
+ * These ones are loaded by the SCRIPTS processor.
+ */
+ scriptb0->pm0_data_addr[0] =
+ cpu_to_scr(np->scripta_ba +
+ offsetof(struct sym_fw2a_scr, pm0_data));
+ scriptb0->pm1_data_addr[0] =
+ cpu_to_scr(np->scripta_ba +
+ offsetof(struct sym_fw2a_scr, pm1_data));
+}
+
+/*
+ * Fill the data area in scripts.
+ * To be done for all firmwares.
+ */
+static void
+sym_fw_fill_data (u32 *in, u32 *out)
+{
+ int i;
+
+ for (i = 0; i < SYM_CONF_MAX_SG; i++) {
+ *in++ = SCR_CHMOV_TBL ^ SCR_DATA_IN;
+ *in++ = offsetof (struct sym_dsb, data[i]);
+ *out++ = SCR_CHMOV_TBL ^ SCR_DATA_OUT;
+ *out++ = offsetof (struct sym_dsb, data[i]);
+ }
+}
+
+/*
+ * Setup useful script bus addresses.
+ * To be done for all firmwares.
+ */
+static void
+sym_fw_setup_bus_addresses(hcb_p np, struct sym_fw *fw)
+{
+ u32 *pa;
+ u_short *po;
+ int i;
+
+ /*
+ * Build the bus address table for script A
+ * from the script A offset table.
+ */
+ po = (u_short *) fw->a_ofs;
+ pa = (u32 *) &np->fwa_bas;
+ for (i = 0 ; i < sizeof(np->fwa_bas)/sizeof(u32) ; i++)
+ pa[i] = np->scripta_ba + po[i];
+
+ /*
+ * Same for script B.
+ */
+ po = (u_short *) fw->b_ofs;
+ pa = (u32 *) &np->fwb_bas;
+ for (i = 0 ; i < sizeof(np->fwb_bas)/sizeof(u32) ; i++)
+ pa[i] = np->scriptb_ba + po[i];
+
+ /*
+ * Same for script Z.
+ */
+ po = (u_short *) fw->z_ofs;
+ pa = (u32 *) &np->fwz_bas;
+ for (i = 0 ; i < sizeof(np->fwz_bas)/sizeof(u32) ; i++)
+ pa[i] = np->scriptz_ba + po[i];
+}
+
+#if SYM_CONF_GENERIC_SUPPORT
+/*
+ * Setup routine for firmware #1.
+ */
+static void
+sym_fw1_setup(hcb_p np, struct sym_fw *fw)
+{
+ struct sym_fw1a_scr *scripta0;
+ struct sym_fw1b_scr *scriptb0;
+
+ scripta0 = (struct sym_fw1a_scr *) np->scripta0;
+ scriptb0 = (struct sym_fw1b_scr *) np->scriptb0;
+
+ /*
+ * Fill variable parts in scripts.
+ */
+ sym_fw_fill_data(scripta0->data_in, scripta0->data_out);
+
+ /*
+ * Setup bus addresses used from the C code..
+ */
+ sym_fw_setup_bus_addresses(np, fw);
+}
+#endif /* SYM_CONF_GENERIC_SUPPORT */
+
+/*
+ * Setup routine for firmware #2.
+ */
+static void
+sym_fw2_setup(hcb_p np, struct sym_fw *fw)
+{
+ struct sym_fw2a_scr *scripta0;
+ struct sym_fw2b_scr *scriptb0;
+
+ scripta0 = (struct sym_fw2a_scr *) np->scripta0;
+ scriptb0 = (struct sym_fw2b_scr *) np->scriptb0;
+
+ /*
+ * Fill variable parts in scripts.
+ */
+ sym_fw_fill_data(scripta0->data_in, scripta0->data_out);
+
+ /*
+ * Setup bus addresses used from the C code..
+ */
+ sym_fw_setup_bus_addresses(np, fw);
+}
+
+/*
+ * Allocate firmware descriptors.
+ */
+#if SYM_CONF_GENERIC_SUPPORT
+static struct sym_fw sym_fw1 = SYM_FW_ENTRY(sym_fw1, "NCR-generic");
+#endif /* SYM_CONF_GENERIC_SUPPORT */
+static struct sym_fw sym_fw2 = SYM_FW_ENTRY(sym_fw2, "LOAD/STORE-based");
+
+/*
+ * Find the most appropriate firmware for a chip.
+ */
+struct sym_fw *
+sym_find_firmware(struct sym_pci_chip *chip)
+{
+ if (chip->features & FE_LDSTR)
+ return &sym_fw2;
+#if SYM_CONF_GENERIC_SUPPORT
+ else if (!(chip->features & (FE_PFEN|FE_NOPM|FE_DAC)))
+ return &sym_fw1;
+#endif


+ else
+ return 0;

+}
+
+/*
+ * Bind a script to physical addresses.
+ */
+void sym_fw_bind_script (hcb_p np, u32 *start, int len)
+{
+ u32 opcode, new, old, tmp1, tmp2;
+ u32 *end, *cur;
+ int relocs;
+
+ cur = start;
+ end = start + len/4;
+
+ while (cur < end) {
+
+ opcode = *cur;
+
+ /*
+ * If we forget to change the length
+ * in scripts, a field will be
+ * padded with 0. This is an illegal
+ * command.
+ */
+ if (opcode == 0) {
+ printf ("%s: ERROR0 IN SCRIPT at %d.\n",
+ sym_name(np), (int) (cur-start));
+ MDELAY (10000);
+ ++cur;
+ continue;
+ };
+
+ /*
+ * We use the bogus value 0xf00ff00f ;-)
+ * to reserve data area in SCRIPTS.
+ */
+ if (opcode == SCR_DATA_ZERO) {
+ *cur++ = 0;
+ continue;
+ }
+
+ if (DEBUG_FLAGS & DEBUG_SCRIPT)
+ printf ("%d: <%x>\n", (int) (cur-start),
+ (unsigned)opcode);
+
+ /*
+ * We don't have to decode ALL commands
+ */
+ switch (opcode >> 28) {
+ case 0xf:
+ /*
+ * LOAD / STORE DSA relative, don't relocate.
+ */
+ relocs = 0;
+ break;
+ case 0xe:
+ /*
+ * LOAD / STORE absolute.
+ */
+ relocs = 1;
+ break;
+ case 0xc:
+ /*
+ * COPY has TWO arguments.
+ */
+ relocs = 2;
+ tmp1 = cur[1];
+ tmp2 = cur[2];
+ if ((tmp1 ^ tmp2) & 3) {
+ printf ("%s: ERROR1 IN SCRIPT at %d.\n",
+ sym_name(np), (int) (cur-start));
+ MDELAY (10000);
+ }
+ /*
+ * If PREFETCH feature not enabled, remove
+ * the NO FLUSH bit if present.
+ */
+ if ((opcode & SCR_NO_FLUSH) &&
+ !(np->features & FE_PFEN)) {
+ opcode = (opcode & ~SCR_NO_FLUSH);
+ }
+ break;
+ case 0x0:
+ /*
+ * MOVE/CHMOV (absolute address)
+ */
+ if (!(np->features & FE_WIDE))
+ opcode = (opcode | OPC_MOVE);
+ relocs = 1;
+ break;
+ case 0x1:
+ /*
+ * MOVE/CHMOV (table indirect)
+ */
+ if (!(np->features & FE_WIDE))
+ opcode = (opcode | OPC_MOVE);
+ relocs = 0;
+ break;
+#ifdef SYM_CONF_TARGET_ROLE_SUPPORT
+ case 0x2:
+ /*
+ * MOVE/CHMOV in target role (absolute address)
+ */
+ opcode &= ~0x20000000;
+ if (!(np->features & FE_WIDE))
+ opcode = (opcode & ~OPC_TCHMOVE);
+ relocs = 1;
+ break;
+ case 0x3:
+ /*
+ * MOVE/CHMOV in target role (table indirect)
+ */
+ opcode &= ~0x20000000;
+ if (!(np->features & FE_WIDE))
+ opcode = (opcode & ~OPC_TCHMOVE);
+ relocs = 0;
+ break;
+#endif
+ case 0x8:
+ /*
+ * JUMP / CALL
+ * dont't relocate if relative :-)
+ */
+ if (opcode & 0x00800000)
+ relocs = 0;
+ else if ((opcode & 0xf8400000) == 0x80400000)/*JUMP64*/
+ relocs = 2;
+ else
+ relocs = 1;
+ break;
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ relocs = 1;
+ break;
+ default:
+ relocs = 0;
+ break;
+ };
+
+ /*
+ * Scriptify:) the opcode.
+ */
+ *cur++ = cpu_to_scr(opcode);
+
+ /*
+ * If no relocation, assume 1 argument
+ * and just scriptize:) it.
+ */
+ if (!relocs) {
+ *cur = cpu_to_scr(*cur);
+ ++cur;
+ continue;
+ }
+
+ /*
+ * Otherwise performs all needed relocations.
+ */
+ while (relocs--) {
+ old = *cur;
+
+ switch (old & RELOC_MASK) {
+ case RELOC_REGISTER:
+ new = (old & ~RELOC_MASK) + np->mmio_ba;
+ break;
+ case RELOC_LABEL_A:
+ new = (old & ~RELOC_MASK) + np->scripta_ba;
+ break;
+ case RELOC_LABEL_B:
+ new = (old & ~RELOC_MASK) + np->scriptb_ba;
+ break;
+ case RELOC_SOFTC:
+ new = (old & ~RELOC_MASK) + np->hcb_ba;
+ break;
+ case 0:
+ /*
+ * Don't relocate a 0 address.
+ * They are mostly used for patched or
+ * script self-modified areas.
+ */
+ if (old == 0) {
+ new = old;
+ break;
+ }
+ /* fall through */
+ default:
+ new = 0;
+ panic("sym_fw_bind_script: "
+ "weird relocation %x\n", old);
+ break;
+ }
+
+ *cur++ = cpu_to_scr(new);
+ }
+ };
+}
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_fw.h linux/drivers/scsi/sym53c8xx_2/sym_fw.h
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_fw.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym_fw.h Fri Nov 9 15:22:54 2001
@@ -0,0 +1,232 @@

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

echo 'End of part 060'
echo 'File patch-2.4.15 is continued in part 061'
echo "061" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:27 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part051

#!/bin/sh -x
# this is part 051 of a 115 - part archive


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

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

X
- printk (KERN_INFO "%s: %s, %2x:%2x:%2x:%2x:%2x:%2x, IRQ %d\n",
+ printk (KERN_INFO "%s: %s, %02x:%02x:%02x:%02x:%02x:%02x, IRQ %d\n",
X dev->name, np->name,
X dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
X dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], irq);
@@ -297,7 +328,7 @@
X
X /* Check CRC */
X crc = ~get_crc (sromdata, 256 - 4);
- if (psrom->crc != ~get_crc (sromdata, 256 - 4)) {
+ if (psrom->crc != crc) {
X printk (KERN_ERR "%s: EEPROM data CRC error.\n", dev->name);
X return -1;
X }
@@ -590,7 +621,7 @@
X if (int_status & RxDMAComplete)
X receive_packet (dev);
X /* TxComplete interrupt */
- if (int_status & TxComplete) {
+ if (int_status & TxComplete || np->tx_full) {
X int tx_status = readl (ioaddr + TxStatus);
X if (tx_status & 0x01)
X tx_error (dev, tx_status);
@@ -715,8 +746,6 @@
X writel (readw (dev->base_addr + MACCtrl) | TxEnable, ioaddr + MACCtrl);
X }
X
-/* Every interrupts go into here to see if any packet need to process, this
- ensure Rx rings keep full in a critical cases of Rx rings ran out */
X static int
X receive_packet (struct net_device *dev)
X {
@@ -832,6 +861,7 @@
X {
X long ioaddr = dev->base_addr;
X struct netdev_private *np = dev->priv;
+ u16 macctrl;
X
X /* Stop the down counter and recovery the interrupt */
X if (int_status & IntRequested) {
@@ -845,15 +875,17 @@
X if (int_status & LinkEvent) {
X if (mii_wait_link (dev, 10) == 0) {
X printk (KERN_INFO "%s: Link up\n", dev->name);
- if (np->an_enable) {
- /* Auto-Negotiation mode */
+ if (np->phy_media)
+ mii_get_media_pcs (dev);
+ else
X mii_get_media (dev);
- if (np->full_duplex) {
- writew (readw (dev->base_addr + MACCtrl)
- | DuplexSelect,
- ioaddr + MACCtrl);
- }
- }
+ macctrl = 0;
+ macctrl |= (np->full_duplex) ? DuplexSelect : 0;
+ macctrl |= (np->tx_flow) ?
+ TxFlowControlEnable : 0;
+ macctrl |= (np->rx_flow) ?
+ RxFlowControlEnable : 0;
+ writew(macctrl, ioaddr + MACCtrl);
X } else {
X printk (KERN_INFO "%s: Link off\n", dev->name);
X }
@@ -1302,35 +1334,42 @@
X /* Auto-Negotiation not completed */
X return -1;
X }
- negotiate.image = mii_read (dev, phy_addr, MII_ANAR) &
- mii_read (dev, phy_addr, MII_ANLPAR);
+ negotiate.image = mii_read (dev, phy_addr, MII_ANAR) &
+ mii_read (dev, phy_addr, MII_ANLPAR);
X mscr.image = mii_read (dev, phy_addr, MII_MSCR);
X mssr.image = mii_read (dev, phy_addr, MII_MSSR);
X if (mscr.bits.media_1000BT_FD & mssr.bits.lp_1000BT_FD) {


X np->speed = 1000;

X np->full_duplex = 1;

- printk (KERN_INFO "Auto 1000BaseT, Full duplex.\n");
+ printk (KERN_INFO "Auto 1000 Mbps, Full duplex\n");
X } else if (mscr.bits.media_1000BT_HD & mssr.bits.lp_1000BT_HD) {


X np->speed = 1000;

X np->full_duplex = 0;

- printk (KERN_INFO "Auto 1000BaseT, Half duplex.\n");
+ printk (KERN_INFO "Auto 1000 Mbps, Half duplex\n");
X } else if (negotiate.bits.media_100BX_FD) {


X np->speed = 100;
X np->full_duplex = 1;

- printk (KERN_INFO "Auto 100BaseT, Full duplex.\n");
+ printk (KERN_INFO "Auto 100 Mbps, Full duplex\n");
X } else if (negotiate.bits.media_100BX_HD) {


X np->speed = 100;

X np->full_duplex = 0;
- printk (KERN_INFO "Auto 100BaseT, Half duplex.\n");
+ printk (KERN_INFO "Auto 100 Mbps, Half duplex\n");
X } else if (negotiate.bits.media_10BT_FD) {


X np->speed = 10;

X np->full_duplex = 1;
- printk (KERN_INFO "Auto 10BaseT, Full duplex.\n");
+ printk (KERN_INFO "Auto 10 Mbps, Full duplex\n");
X } else if (negotiate.bits.media_10BT_HD) {


X np->speed = 10;
X np->full_duplex = 0;

- printk (KERN_INFO "Auto 10BaseT, Half duplex.\n");
+ printk (KERN_INFO "Auto 10 Mbps, Half duplex\n");
X }
+ if (negotiate.bits.pause) {
+ np->tx_flow = 1;
+ np->rx_flow = 1;
+ } else if (negotiate.bits.asymmetric) {
+ np->rx_flow = 1;
+ }
+ /* else tx_flow, rx_flow = user select */
X } else {
X bmcr.image = mii_read (dev, phy_addr, MII_BMCR);
X if (bmcr.bits.speed100 == 1 && bmcr.bits.speed1000 == 0) {
@@ -1341,11 +1380,20 @@
X printk (KERN_INFO "Operating at 1000 Mbps, ");
X }
X if (bmcr.bits.duplex_mode) {
- printk ("Full duplex.\n");
+ printk ("Full duplex\n");
X } else {
- printk ("Half duplex.\n");
+ printk ("Half duplex\n");
X }
X }
+ if (np->tx_flow)
+ printk(KERN_INFO "Enable Tx Flow Control\n");
+ else
+ printk(KERN_INFO "Disable Tx Flow Control\n");
+ if (np->rx_flow)
+ printk(KERN_INFO "Enable Rx Flow Control\n");
+ else
+ printk(KERN_INFO "Disable Rx Flow Control\n");


+
X return 0;
X }
X

@@ -1363,7 +1411,7 @@
X
X /* Does user set speed? */
X if (np->an_enable) {
- /* Reset to enable Auto-Negotiation */
+ /* Advertise capabilities */
X bmsr.image = mii_read (dev, phy_addr, MII_BMSR);
X anar.image = mii_read (dev, phy_addr, MII_ANAR);
X anar.bits.media_100BX_FD = bmsr.bits.media_100BX_FD;
@@ -1371,24 +1419,23 @@
X anar.bits.media_100BT4 = bmsr.bits.media_100BT4;
X anar.bits.media_10BT_FD = bmsr.bits.media_10BT_FD;
X anar.bits.media_10BT_HD = bmsr.bits.media_10BT_HD;
+ anar.bits.pause = 1;
+ anar.bits.asymmetric = 1;
X mii_write (dev, phy_addr, MII_ANAR, anar.image);
X
X /* Enable Auto crossover */
X pscr.image = mii_read (dev, phy_addr, MII_PHY_SCR);
X pscr.bits.mdi_crossover_mode = 3; /* 11'b */
X mii_write (dev, phy_addr, MII_PHY_SCR, pscr.image);
+
X /* Soft reset PHY */
X mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET);
X bmcr.image = 0;
X bmcr.bits.an_enable = 1;
+ bmcr.bits.restart_an = 1;
X bmcr.bits.reset = 1;
X mii_write (dev, phy_addr, MII_BMCR, bmcr.image);
- /* Wait for Link up, link up need a certain time */
- if (mii_wait_link (dev, 3200) != 0) {
- printk (KERN_INFO "Link time out\n");
- }
- mdelay (1);
- mii_get_media (dev);
+ mdelay(1);
X } else {
X /* Force speed setting */
X /* 1) Disable Auto crossover */
@@ -1423,10 +1470,10 @@
X }
X if (np->full_duplex) {
X bmcr.bits.duplex_mode = 1;
- printk ("Full duplex. \n");
+ printk ("Full duplex\n");
X } else {
X bmcr.bits.duplex_mode = 0;
- printk ("Half duplex.\n");
+ printk ("Half duplex\n");
X }
X #if 0
X /* Set 1000BaseT Master/Slave setting */
@@ -1435,16 +1482,125 @@
X mscr.bits.cfg_value = 0;
X #endif
X mii_write (dev, phy_addr, MII_BMCR, bmcr.image);
+ mdelay(10);


+ }
+ return 0;
+}
X

- /* Wait for Link up, link up need a certain time */
- if (mii_wait_link (dev, 3200) != 0) {
- printk (KERN_INFO "Link time out\n");
+static int
+mii_get_media_pcs (struct net_device *dev)
+{
+ ANAR_PCS_t negotiate;
+ BMSR_t bmsr;
+ BMCR_t bmcr;
+ int phy_addr;
+ struct netdev_private *np;
+
+ np = dev->priv;
+ phy_addr = np->phy_addr;
+
+ bmsr.image = mii_read (dev, phy_addr, PCS_BMSR);
+ if (np->an_enable) {
+ if (!bmsr.bits.an_complete) {
+ /* Auto-Negotiation not completed */
+ return -1;
+ }
+ negotiate.image = mii_read (dev, phy_addr, PCS_ANAR) &
+ mii_read (dev, phy_addr, PCS_ANLPAR);


+ np->speed = 1000;

+ if (negotiate.bits.full_duplex) {
+ printk (KERN_INFO "Auto 1000 Mbps, Full duplex\n");


+ np->full_duplex = 1;

+ } else {
+ printk (KERN_INFO "Auto 1000 Mbps, half duplex\n");


+ np->full_duplex = 0;

+ }
+ if (negotiate.bits.pause) {
+ np->tx_flow = 1;
+ np->rx_flow = 1;
+ } else if (negotiate.bits.asymmetric) {
+ np->rx_flow = 1;
X }
- mii_get_media (dev);
+ /* else tx_flow, rx_flow = user select */
+ } else {
+ bmcr.image = mii_read (dev, phy_addr, PCS_BMCR);
+ printk (KERN_INFO "Operating at 1000 Mbps, ");
+ if (bmcr.bits.duplex_mode) {
+ printk ("Full duplex\n");
+ } else {
+ printk ("Half duplex\n");
+ }
+ }
+ if (np->tx_flow)
+ printk(KERN_INFO "Enable Tx Flow Control\n");
+ else
+ printk(KERN_INFO "Disable Tx Flow Control\n");
+ if (np->rx_flow)
+ printk(KERN_INFO "Enable Rx Flow Control\n");
+ else
+ printk(KERN_INFO "Disable Rx Flow Control\n");


+
+ return 0;
+}

+
+static int
+mii_set_media_pcs (struct net_device *dev)
+{
+ BMCR_t bmcr;
+ ESR_t esr;
+ ANAR_PCS_t anar;
+ int phy_addr;
+ struct netdev_private *np;
+ np = dev->priv;
+ phy_addr = np->phy_addr;
+
+ /* Auto-Negotiation? */
+ if (np->an_enable) {
+ /* Advertise capabilities */
+ esr.image = mii_read (dev, phy_addr, PCS_ESR);
+ anar.image = mii_read (dev, phy_addr, MII_ANAR);
+ anar.bits.half_duplex =
+ esr.bits.media_1000BT_HD | esr.bits.media_1000BX_HD;
+ anar.bits.full_duplex =
+ esr.bits.media_1000BT_FD | esr.bits.media_1000BX_FD;
+ anar.bits.pause = 1;
+ anar.bits.asymmetric = 1;
+ mii_write (dev, phy_addr, MII_ANAR, anar.image);
+
+ /* Soft reset PHY */
+ mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET);
+ bmcr.image = 0;
+ bmcr.bits.an_enable = 1;
+ bmcr.bits.restart_an = 1;
+ bmcr.bits.reset = 1;
+ mii_write (dev, phy_addr, MII_BMCR, bmcr.image);
+ mdelay(1);
+ } else {
+ /* Force speed setting */
+ /* PHY Reset */
+ bmcr.image = 0;
+ bmcr.bits.reset = 1;
+ mii_write (dev, phy_addr, MII_BMCR, bmcr.image);
+ mdelay(10);
+ bmcr.image = 0;
+ bmcr.bits.an_enable = 0;
+ if (np->full_duplex) {
+ bmcr.bits.duplex_mode = 1;
+ printk (KERN_INFO "Manual full duplex\n");
+ } else {
+ bmcr.bits.duplex_mode = 0;
+ printk (KERN_INFO "Manual half duplex\n");
+ }
+ mii_write (dev, phy_addr, MII_BMCR, bmcr.image);
+ mdelay(10);
+
+ /* Advertise nothing */
+ mii_write (dev, phy_addr, MII_ANAR, 0);


X }
X return 0;
X }
X

+
X static int
X rio_close (struct net_device *dev)
X {
@@ -1521,10 +1677,6 @@
X static int __init
X rio_init (void)
X {
-#ifdef MODULE
- printk ("%s", version);
-#endif
-
X return pci_module_init (&rio_driver);
X }
X
@@ -1542,5 +1694,7 @@
X Compile command:
X
X gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -c dl2x.c
+
+Read Documentation/networking/dl2k.txt for details.
X
X */
diff -u --recursive --new-file v2.4.14/linux/drivers/net/dl2k.h linux/drivers/net/dl2k.h
--- v2.4.14/linux/drivers/net/dl2k.h Sun Sep 23 11:40:58 2001
+++ linux/drivers/net/dl2k.h Mon Nov 19 15:19:42 2001
@@ -209,6 +209,11 @@
X RxDisable = 0x10000000,
X RxEnabled = 0x20000000,
X };
+
+enum ASICCtrl_LoWord_bits {
+ PhyMedia = 0x0080,
+};
+
X enum ASICCtrl_HiWord_bits {
X GlobalReset = 0x0001,
X RxReset = 0x0002,
@@ -277,6 +282,17 @@
X MII_ESR = 15,
X MII_PHY_SCR = 16,
X };
+/* PCS register */
+enum _pcs_reg {
+ PCS_BMCR = 0,
+ PCS_BMSR = 1,
+ PCS_ANAR = 4,
+ PCS_ANLPAR = 5,
+ PCS_ANER = 6,
+ PCS_ANNPT = 7,
+ PCS_ANLPRNP = 8,
+ PCS_ESR = 15,
+};
X
X /* Basic Mode Control Register */
X typedef union t_MII_BMCR {
@@ -533,6 +549,58 @@
X adm_isolate
X } MII_ADMIN_t, *PMII_ADMIN_t;
X
+/* Physical Coding Sublayer Management (PCS) */
+/* PCS control and status registers bitmap as the same as MII */
+/* PCS Extended Status register bitmap as the same as MII */
+/* PCS ANAR */
+typedef union t_PCS_ANAR {
+ u16 image;
+ struct {
+ u16 _bit_4_0:5; // bit 4:0
+ u16 full_duplex:1; // bit 5
+ u16 half_duplex:1; // bit 6
+ u16 asymmetric:1; // bit 7
+ u16 pause:1; // bit 8
+ u16 _bit_11_9:3; // bit 11:9
+ u16 remote_fault:2; // bit 13:12
+ u16 _bit_14:1; // bit 14
+ u16 next_page:1; // bit 15
+ } bits;
+} ANAR_PCS_t, *PANAR_PCS_t;
+
+enum _pcs_anar {
+ PCS_ANAR_NEXT_PAGE = 0x8000,
+ PCS_ANAR_REMOTE_FAULT = 0x3000,
+ PCS_ANAR_ASYMMETRIC = 0x0100,
+ PCS_ANAR_PAUSE = 0x0080,
+ PCS_ANAR_HALF_DUPLEX = 0x0040,
+ PCS_ANAR_FULL_DUPLEX = 0x0020,
+};
+/* PCS ANLPAR */
+typedef union t_PCS_ANLPAR {
+ u16 image;
+ struct {
+ u16 _bit_4_0:5; // bit 4:0
+ u16 full_duplex:1; // bit 5
+ u16 half_duplex:1; // bit 6
+ u16 asymmetric:1; // bit 7
+ u16 pause:1; // bit 8
+ u16 _bit_11_9:3; // bit 11:9
+ u16 remote_fault:2; // bit 13:12
+ u16 _bit_14:1; // bit 14
+ u16 next_page:1; // bit 15
+ } bits;
+} ANLPAR_PCS_t, *PANLPAR_PCS_t;
+
+enum _pcs_anlpar {
+ PCS_ANLPAR_NEXT_PAGE = PCS_ANAR_NEXT_PAGE,
+ PCS_ANLPAR_REMOTE_FAULT = PCS_ANAR_REMOTE_FAULT,
+ PCS_ANLPAR_ASYMMETRIC = PCS_ANAR_ASYMMETRIC,
+ PCS_ANLPAR_PAUSE = PCS_ANAR_PAUSE,
+ PCS_ANLPAR_HALF_DUPLEX = PCS_ANAR_HALF_DUPLEX,
+ PCS_ANLPAR_FULL_DUPLEX = PCS_ANAR_FULL_DUPLEX,
+};
+
X typedef struct t_SROM {
X u16 config_param; /* 0x00 */
X u16 asic_ctrl; /* 0x02 */
@@ -582,16 +650,19 @@
X spinlock_t lock;
X struct net_device_stats stats;
X unsigned int rx_buf_sz; /* Based on MTU+slack. */
- unsigned int tx_full:1; /* The Tx queue is full. */
- unsigned int full_duplex:1; /* Full-duplex operation requested. */
X unsigned int speed; /* Operating speed */
X unsigned int vlan; /* VLAN Id */
- unsigned int an_enable; /* Auto-Negotiated Enable */
X unsigned int chip_id; /* PCI table chip id */
- unsigned int jumbo;
- unsigned int int_count;
- unsigned int int_timeout;
- unsigned int coalesce:1;
+ unsigned int int_count; /* Maximum frames each RxDMAComplete intr */
+ unsigned int int_timeout; /* Wait time between RxDMAComplete intr */
+ unsigned int tx_full:1; /* The Tx queue is full. */
+ unsigned int full_duplex:1; /* Full-duplex operation requested. */
+ unsigned int an_enable:2; /* Auto-Negotiated Enable */
+ unsigned int jumbo:1; /* Jumbo frame enable */
+ unsigned int coalesce:1; /* Rx coalescing enable */
+ unsigned int tx_flow:1; /* Tx flow control enable */
+ unsigned int rx_flow:1; /* Rx flow control enable */
+ unsigned int phy_media:1; /* 1: fiber, 0: copper */
X struct netdev_desc *last_tx; /* Last Tx descriptor used. */
X unsigned long cur_rx, old_rx; /* Producer/consumer ring indices */
X unsigned long cur_tx, old_tx;
diff -u --recursive --new-file v2.4.14/linux/drivers/net/dmfe.c linux/drivers/net/dmfe.c
--- v2.4.14/linux/drivers/net/dmfe.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/net/dmfe.c Fri Nov 9 13:50:01 2001
@@ -1,6 +1,4 @@
X /*
- dmfe.c: Version 1.36p1 2001-05-12 for Linux kernel 2.4.x
-
X A Davicom DM9102/DM9102A/DM9102A+DM9801/DM9102A+DM9802 NIC fast
X ethernet driver for Linux.
X Copyright (C) 1997 Sten Wang
@@ -38,19 +36,33 @@
X
X Tobias Ringstrom <to...@unhappy.mine.nu> :
X Cleaned up and added SMP safety. Thanks go to Jeff Garzik,
- Andrew Morton and Frank Davis for the SMP safety fixes.
+ Andrew Morton and Frank Davis for the SMP safety fixes.
+
+ Vojtech Pavlik <voj...@suse.cz> :
+ Cleaned up pointer arithmetics.
+ Fixed a lot of 64bit issues.
+ Cleaned up printk()s a bit.
+ Fixed some obvious big endian problems.
+
+ Tobias Ringstrom <to...@unhappy.mine.nu> :
+ Use time_after for jiffies calculation. Added ethtool
+ support. Updated PCI resource allocation. Do not
+ forget to unmap PCI mapped skbs.
X
X TODO
X
X Implement pci_driver::suspend() and pci_driver::resume()
X power management methods.
X
- Check and fix on 64bit and big endian boxes.
+ Check on 64 bit boxes.
+ Check and fix on big endian boxes.
X
X Test and make sure PCI latency is now correct for all cases.
X */
X
-#define DMFE_VERSION "1.36p1 (May 12, 2001)"
+#define DRV_NAME "dmfe"
+#define DRV_VERSION "1.36.3"
+#define DRV_RELDATE "2001-11-06"
X
X #include <linux/module.h>
X
@@ -68,6 +80,7 @@
X #include <linux/version.h>
X #include <linux/netdevice.h>
X #include <linux/etherdevice.h>
+#include <linux/ethtool.h>
X #include <linux/skbuff.h>
X #include <linux/delay.h>
X #include <linux/spinlock.h>
@@ -76,10 +89,7 @@
X #include <asm/bitops.h>
X #include <asm/io.h>
X #include <asm/dma.h>
-
-#if BITS_PER_LONG == 64
-#error FIXME: driver does not support 64-bit platforms
-#endif
+#include <asm/uaccess.h>
X
X
X /* Board/System/Debug information/definition ---------------- */
@@ -130,9 +140,9 @@
X #define DMFE_TX_TIMEOUT ((3*HZ)/2) /* tx packet time-out time 1.5 s" */
X #define DMFE_TX_KICK (HZ/2) /* tx packet Kick-out time 0.5 s" */
X
-#define DMFE_DBUG(dbug_now, msg, value) if (dmfe_debug || (dbug_now)) printk(KERN_ERR "<DMFE>: %s %lx\n", (msg), (long) (value))
+#define DMFE_DBUG(dbug_now, msg, value) if (dmfe_debug || (dbug_now)) printk(KERN_ERR DRV_NAME ": %s %lx\n", (msg), (long) (value))
X
-#define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR "<DMFE>: Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
+#define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR DRV_NAME ": Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
X
X
X /* CR9 definition: SROM/MII */
@@ -160,26 +170,22 @@
X
X /* Structure/enum declaration ------------------------------- */
X struct tx_desc {
- u32 tdes0, tdes1, tdes2, tdes3;
- u32 tx_skb_ptr;
- u32 tx_buf_ptr;
- u32 next_tx_desc;
- u32 reserved;
-};
+ u32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */
+ char *tx_buf_ptr; /* Data for us */
+ struct tx_desc *next_tx_desc;
+} __attribute__(( aligned(32) ));
X
X struct rx_desc {
- u32 rdes0, rdes1, rdes2, rdes3;
- u32 rx_skb_ptr;
- u32 rx_buf_ptr;
- u32 next_rx_desc;
- u32 reserved;
-};
+ u32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */
+ struct sk_buff *rx_skb_ptr; /* Data for us */
+ struct rx_desc *next_rx_desc;
+} __attribute__(( aligned(32) ));
X
X struct dmfe_board_info {
X u32 chip_id; /* Chip vendor/Device ID */
X u32 chip_revision; /* Chip revision */
X struct DEVICE *next_dev; /* next device */
- struct pci_dev * net_dev; /* PCI device */
+ struct pci_dev *pdev; /* PCI device */
X spinlock_t lock;
X
X long ioaddr; /* I/O base address */
@@ -206,10 +212,10 @@
X struct rx_desc *first_rx_desc;
X struct rx_desc *rx_insert_ptr;
X struct rx_desc *rx_ready_ptr; /* packet come pointer */
- unsigned long tx_packet_cnt; /* transmitted packet count */
- unsigned long tx_queue_cnt; /* wait to send packet count */
- unsigned long rx_avail_cnt; /* available rx descriptor count */
- unsigned long interval_rx_cnt; /* rx packet count a callback time */
+ unsigned long tx_packet_cnt; /* transmitted packet count */
+ unsigned long tx_queue_cnt; /* wait to send packet count */
+ unsigned long rx_avail_cnt; /* available rx descriptor count */
+ unsigned long interval_rx_cnt; /* rx packet count a callback time */
X
X u16 HPNA_command; /* For HPNA register 16 */
X u16 HPNA_timer; /* For HPNA remote device check */
@@ -263,7 +269,8 @@
X /* Global variable declaration ----------------------------- */
X static int __devinitdata printed_version;


X static char version[] __devinitdata =

- KERN_INFO "Davicom DM9xxx net driver, version " DMFE_VERSION "\n";
+ KERN_INFO DRV_NAME ": Davicom DM9xxx net driver, version "
+ DRV_VERSION " (" DRV_RELDATE ")\n";
X
X static int dmfe_debug;
X static unsigned char dmfe_media_mode = DMFE_AUTO;
@@ -358,7 +365,7 @@
X static u16 read_srom_word(long ,int);
X static void dmfe_interrupt(int , void *, struct pt_regs *);
X static void dmfe_descriptor_init(struct dmfe_board_info *, unsigned long);
-static void allocated_rx_buffer(struct dmfe_board_info *);
+static void allocate_rx_buffer(struct dmfe_board_info *);
X static void update_cr6(u32, unsigned long);
X static void send_filter_frame(struct DEVICE * ,int);
X static void dm9132_id_table(struct DEVICE * ,int);
@@ -371,7 +378,7 @@
X static void dmfe_timer(unsigned long);
X static void dmfe_rx_packet(struct DEVICE *, struct dmfe_board_info *);
X static void dmfe_free_tx_pkt(struct DEVICE *, struct dmfe_board_info *);
-static void dmfe_reused_skb(struct dmfe_board_info *, struct sk_buff *);
+static void dmfe_reuse_skb(struct dmfe_board_info *, struct sk_buff *);
X static void dmfe_dynamic_reset(struct DEVICE *);
X static void dmfe_free_rxbuffer(struct dmfe_board_info *);
X static void dmfe_init_dm910x(struct DEVICE *);
@@ -391,31 +398,46 @@
X static int __devinit dmfe_init_one (struct pci_dev *pdev,


X const struct pci_device_id *ent)
X {

- unsigned long pci_iobase;
- u8 pci_irqline;
X struct dmfe_board_info *db; /* board information structure */
- int i;
X struct net_device *dev;
X u32 dev_rev, pci_pmr;
+ int i, err;
+
+ DMFE_DBUG(0, "dmfe_init_one()", 0);
X
X if (!printed_version++)
X printk(version);
X
- DMFE_DBUG(0, "dmfe_init_one()", 0);
+ /* Init network device */
+ dev = alloc_etherdev(sizeof(*db));
+ if (dev == NULL)
+ return -ENOMEM;
+ SET_MODULE_OWNER(dev);
+
+ if (pci_set_dma_mask(pdev, 0xffffffff)) {
+ printk(KERN_WARNING DRV_NAME ": 32-bit PCI DMA not available.\n");
+ err = -ENODEV;
+ goto err_out_free;
+ }
X
X /* Enable Master/IO access, Disable memory access */
- i = pci_enable_device(pdev);
- if (i)
- return i;
- pci_set_master(pdev);
+ err = pci_enable_device(pdev);
+ if (err)
+ goto err_out_free;
+
+ if (!pci_resource_start(pdev, 0)) {
+ printk(KERN_ERR DRV_NAME ": I/O base is zero\n");
+ err = -ENODEV;
+ goto err_out_disable;
+ }
X
- pci_iobase = pci_resource_start(pdev, 0);
- pci_irqline = pdev->irq;
+ /* Read Chip revision */
+ pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev);
X
- /* iobase check */
- if (pci_iobase == 0) {
- printk(KERN_ERR "<DMFE>: I/O base is zero\n");
- return -ENODEV;
+ if (pci_resource_len(pdev, 0) < (CHK_IO_SIZE(pdev, dev_rev)) ) {
+ printk(KERN_ERR DRV_NAME ": Allocated I/O size too small\n");
+ err = -ENODEV;
+ goto err_out_disable;
X }
X
X #if 0 /* pci_{enable_device,set_master} sets minimum latency for us now */
@@ -427,51 +449,32 @@
X pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);
X #endif
X
- /* Read Chip revision */
- pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev);
-
- /* Init network device */
- dev = alloc_etherdev(sizeof(*db));
- if (dev == NULL)
- return -ENOMEM;
- SET_MODULE_OWNER(dev);
-
- /* IO range check */
- if (pci_resource_len (pdev, 0) < (CHK_IO_SIZE(pdev, dev_rev)) ) {
- printk(KERN_ERR "<DMFE>: Allocated I/O size too small\n");
- goto err_out;
- }
-
- if (!request_region(pci_iobase,
- pci_resource_len (pdev, 0),
- dev->name)) {
- printk(KERN_ERR "<DMFE>: I/O conflict : IO=%lx Range=%x\n",
- pci_iobase, CHK_IO_SIZE(pdev, dev_rev));
- goto err_out;
+ if (pci_request_regions(pdev, DRV_NAME)) {
+ printk(KERN_ERR DRV_NAME ": Failed to request PCI regions\n");
+ err = -ENODEV;
+ goto err_out_disable;
X }
X
X /* Init system & device */
X db = dev->priv;
X
- /* Allocated Tx/Rx descriptor memory */
+ /* Allocate Tx/Rx descriptor memory */
X db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr);
X db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, &db->buf_pool_dma_ptr);
X
- db->first_tx_desc = (struct tx_desc *)db->desc_pool_ptr;
+ db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
X db->first_tx_desc_dma = db->desc_pool_dma_ptr;
X db->buf_pool_start = db->buf_pool_ptr;
X db->buf_pool_dma_start = db->buf_pool_dma_ptr;
X
- pdev->driver_data = dev;
-
X db->chip_id = ent->driver_data;
- db->ioaddr = pci_iobase;
+ db->ioaddr = pci_resource_start(pdev, 0);
X db->chip_revision = dev_rev;
X
- db->net_dev = pdev;
+ db->pdev = pdev;
X
- dev->base_addr = pci_iobase;
- dev->irq = pci_irqline;
+ dev->base_addr = db->ioaddr;
+ dev->irq = pdev->irq;
X pci_set_drvdata(pdev, dev);
X dev->open = &dmfe_open;
X dev->hard_start_xmit = &dmfe_start_xmit;
@@ -490,29 +493,37 @@
X
X /* read 64 word srom data */
X for (i = 0; i < 64; i++)
- ((u16 *) db->srom)[i] = read_srom_word(pci_iobase, i);
+ ((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, i));
X
X /* Set Node address */
X for (i = 0; i < 6; i++)
X dev->dev_addr[i] = db->srom[20 + i];
X
- i = register_netdev (dev);
- if (i) goto err_out;
-
- printk(KERN_INFO "%s: Davicom DM%04lx at 0x%lx,",
- dev->name,
- ent->driver_data >> 16,
- pci_iobase);
+ err = register_netdev (dev);
+ if (err)
+ goto err_out_res;
+
+ printk(KERN_INFO "%s: Davicom DM%04lx at pci%s,",
+ dev->name,
+ ent->driver_data >> 16,
+ pdev->slot_name);
X for (i = 0; i < 6; i++)
X printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
- printk(", IRQ %d\n", pci_irqline);
+ printk(", irq %d.\n", dev->irq);
+
+ pci_set_master(pdev);


X
X return 0;
X

-err_out:
+err_out_res:
+ pci_release_regions(pdev);
+err_out_disable:
+ pci_disable_device(pdev);
+err_out_free:
X pci_set_drvdata(pdev, NULL);
X kfree(dev);
- return -ENODEV;
+


+ return err;
X }
X

X
@@ -524,14 +535,13 @@
X DMFE_DBUG(0, "dmfe_remove_one()", 0);
X
X if (dev) {
- pci_free_consistent(db->net_dev, sizeof(struct tx_desc) *
+ pci_free_consistent(db->pdev, sizeof(struct tx_desc) *
X DESC_ALL_CNT + 0x20, db->desc_pool_ptr,
X db->desc_pool_dma_ptr);
- pci_free_consistent(db->net_dev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
+ pci_free_consistent(db->pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
X db->buf_pool_ptr, db->buf_pool_dma_ptr);
X unregister_netdev(dev);
- release_region(dev->base_addr,
- CHK_IO_SIZE(pdev, db->chip_revision));
+ pci_release_regions(pdev);
X kfree(dev); /* free board information */
X pci_set_drvdata(pdev, NULL);
X }
@@ -552,7 +562,7 @@
X
X DMFE_DBUG(0, "dmfe_open", 0);
X
- ret = request_irq(dev->irq, &dmfe_interrupt, SA_SHIRQ, dev->name, dev);
+ ret = request_irq(dev->irq, &dmfe_interrupt, SA_SHIRQ, dev->name, dev);
X if (ret)
X return ret;
X
@@ -683,7 +693,7 @@
X
X /* Too large packet check */
X if (skb->len > MAX_PACKET_SIZE) {
- printk(KERN_ERR "<DMFE>: big packet = %d\n", (u16)skb->len);
+ printk(KERN_ERR DRV_NAME ": big packet = %d\n", (u16)skb->len);
X dev_kfree_skb(skb);
X return 0;
X }
@@ -693,7 +703,7 @@
X /* No Tx resource check, it never happen nromally */
X if (db->tx_queue_cnt >= TX_FREE_DESC_CNT) {
X spin_unlock_irqrestore(&db->lock, flags);
- printk(KERN_ERR "<DMFE>: No Tx resource %ld\n", db->tx_queue_cnt);
+ printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n", db->tx_queue_cnt);


X return 1;
X }
X

@@ -702,11 +712,11 @@
X
X /* transmit this packet */
X txptr = db->tx_insert_ptr;
- memcpy( (char *) txptr->tx_buf_ptr, (char *) skb->data, skb->len);
+ memcpy(txptr->tx_buf_ptr, skb->data, skb->len);
X txptr->tdes1 = cpu_to_le32(0xe1000000 | skb->len);
X
X /* Point to next transmit free descriptor */
- db->tx_insert_ptr = (struct tx_desc *) txptr->next_tx_desc;
+ db->tx_insert_ptr = txptr->next_tx_desc;
X
X /* Transmit Packet Process */
X if ( (!db->tx_queue_cnt) && (db->tx_packet_cnt < TX_MAX_SEND_CNT) ) {
@@ -765,7 +775,7 @@
X
X #if 0
X /* show statistic counter */
- printk("<DMFE>: FU:%lx EC:%lx LC:%lx NC:%lx LOC:%lx TXJT:%lx RESET:%lx RCR8:%lx FAL:%lx TT:%lx\n",
+ printk(DRV_NAME ": FU:%lx EC:%lx LC:%lx NC:%lx LOC:%lx TXJT:%lx RESET:%lx RCR8:%lx FAL:%lx TT:%lx\n",
X db->tx_fifo_underrun, db->tx_excessive_collision,
X db->tx_late_collision, db->tx_no_carrier, db->tx_loss_carrier,
X db->tx_jabber_timeout, db->reset_count, db->reset_cr8,
@@ -822,9 +832,9 @@
X if ( (db->cr5_data & 0x40) && db->rx_avail_cnt )
X dmfe_rx_packet(dev, db);
X
- /* reallocated rx descriptor buffer */
+ /* reallocate rx descriptor buffer */
X if (db->rx_avail_cnt<RX_DESC_CNT)
- allocated_rx_buffer(db);
+ allocate_rx_buffer(db);
X
X /* Free the transmitted descriptor */
X if ( db->cr5_data & 0x01)
@@ -852,11 +862,13 @@
X {
X struct tx_desc *txptr;
X unsigned long ioaddr = dev->base_addr;
+ u32 tdes0;
X
X txptr = db->tx_remove_ptr;
X while(db->tx_packet_cnt) {
- /* printk("<DMFE>: tdes0=%x\n", txptr->tdes0); */
- if (txptr->tdes0 & 0x80000000)
+ tdes0 = le32_to_cpu(txptr->tdes0);
+ /* printk(DRV_NAME ": tdes0=%x\n", tdes0); */
+ if (tdes0 & 0x80000000)
X break;
X
X /* A packet sent completed */
@@ -864,38 +876,38 @@
X db->stats.tx_packets++;
X
X /* Transmit statistic counter */
- if ( txptr->tdes0 != 0x7fffffff ) {
- /* printk("<DMFE>: tdes0=%x\n", txptr->tdes0); */
- db->stats.collisions += (txptr->tdes0 >> 3) & 0xf;
- db->stats.tx_bytes += txptr->tdes1 & 0x7ff;
- if (txptr->tdes0 & TDES0_ERR_MASK) {
+ if ( tdes0 != 0x7fffffff ) {
+ /* printk(DRV_NAME ": tdes0=%x\n", tdes0); */
+ db->stats.collisions += (tdes0 >> 3) & 0xf;
+ db->stats.tx_bytes += le32_to_cpu(txptr->tdes1) & 0x7ff;
+ if (tdes0 & TDES0_ERR_MASK) {
X db->stats.tx_errors++;
X
- if (txptr->tdes0 & 0x0002) { /* UnderRun */
+ if (tdes0 & 0x0002) { /* UnderRun */
X db->tx_fifo_underrun++;
X if ( !(db->cr6_data & CR6_SFT) ) {
X db->cr6_data = db->cr6_data | CR6_SFT;
X update_cr6(db->cr6_data, db->ioaddr);
X }
X }
- if (txptr->tdes0 & 0x0100)
+ if (tdes0 & 0x0100)
X db->tx_excessive_collision++;
- if (txptr->tdes0 & 0x0200)
+ if (tdes0 & 0x0200)
X db->tx_late_collision++;
- if (txptr->tdes0 & 0x0400)
+ if (tdes0 & 0x0400)
X db->tx_no_carrier++;
- if (txptr->tdes0 & 0x0800)
+ if (tdes0 & 0x0800)
X db->tx_loss_carrier++;
- if (txptr->tdes0 & 0x4000)
+ if (tdes0 & 0x4000)
X db->tx_jabber_timeout++;
X }
X }
X
- txptr = (struct tx_desc *) txptr->next_tx_desc;
+ txptr = txptr->next_tx_desc;
X }/* End of while */
X
X /* Update TX remove pointer to next */
- db->tx_remove_ptr = (struct tx_desc *) txptr;
+ db->tx_remove_ptr = txptr;
X
X /* Send the Tx packet in queue */
X if ( (db->tx_packet_cnt < TX_MAX_SEND_CNT) && db->tx_queue_cnt ) {
@@ -921,49 +933,51 @@
X struct rx_desc *rxptr;
X struct sk_buff *skb;
X int rxlen;
+ u32 rdes0;
X
X rxptr = db->rx_ready_ptr;
X
X while(db->rx_avail_cnt) {
- if (rxptr->rdes0 & 0x80000000) /* packet owner check */
+ rdes0 = le32_to_cpu(rxptr->rdes0);
+ if (rdes0 & 0x80000000) /* packet owner check */
X break;
X
X db->rx_avail_cnt--;
X db->interval_rx_cnt++;
X
- if ( (rxptr->rdes0 & 0x300) != 0x300) {
+ pci_unmap_single(db->pdev, le32_to_cpu(rxptr->rdes2), RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE);
+ if ( (rdes0 & 0x300) != 0x300) {
X /* A packet without First/Last flag */
- /* reused this SKB */
- DMFE_DBUG(0, "Reused SK buffer, rdes0", rxptr->rdes0);
- dmfe_reused_skb(db, (struct sk_buff *) rxptr->rx_skb_ptr);
+ /* reuse this SKB */
+ DMFE_DBUG(0, "Reuse SK buffer, rdes0", rdes0);
+ dmfe_reuse_skb(db, rxptr->rx_skb_ptr);
X } else {
X /* A packet with First/Last flag */
- rxlen = ( (rxptr->rdes0 >> 16) & 0x3fff) - 4;
+ rxlen = ( (rdes0 >> 16) & 0x3fff) - 4;
X
X /* error summary bit check */
- if (rxptr->rdes0 & 0x8000) {
+ if (rdes0 & 0x8000) {
X /* This is a error packet */
- //printk("<DMFE>: rdes0: %lx\n", rxptr->rdes0);
+ //printk(DRV_NAME ": rdes0: %lx\n", rdes0);
X db->stats.rx_errors++;
- if (rxptr->rdes0 & 1)
+ if (rdes0 & 1)
X db->stats.rx_fifo_errors++;
- if (rxptr->rdes0 & 2)
+ if (rdes0 & 2)
X db->stats.rx_crc_errors++;
- if (rxptr->rdes0 & 0x80)
+ if (rdes0 & 0x80)
X db->stats.rx_length_errors++;
X }
X
- if ( !(rxptr->rdes0 & 0x8000) ||
+ if ( !(rdes0 & 0x8000) ||
X ((db->cr6_data & CR6_PM) && (rxlen>6)) ) {
- skb = (struct sk_buff *) rxptr->rx_skb_ptr;
+ skb = rxptr->rx_skb_ptr;
X
X /* Received Packet CRC check need or not */
X if ( (db->dm910x_chk_mode & 1) &&
X (cal_CRC(skb->tail, rxlen, 1) !=
- (*(unsigned long *) (skb->tail+rxlen) )
- ) ) {
+ (*(u32 *) (skb->tail+rxlen) ))) { /* FIXME (?) */
X /* Found a error received packet */
- dmfe_reused_skb(db, (struct sk_buff *) rxptr->rx_skb_ptr);
+ dmfe_reuse_skb(db, rxptr->rx_skb_ptr);
X db->dm910x_chk_mode = 3;
X } else {
X /* Good packet, send to upper layer */
@@ -971,11 +985,11 @@
X if ( (rxlen < RX_COPY_SIZE) &&
X ( (skb = dev_alloc_skb(rxlen + 2) )
X != NULL) ) {
- /* size less than COPY_SIZE, allocated a rxlen SKB */
+ /* size less than COPY_SIZE, allocate a rxlen SKB */
X skb->dev = dev;
X skb_reserve(skb, 2); /* 16byte align */
- memcpy(skb_put(skb, rxlen), ((struct sk_buff *) rxptr->rx_skb_ptr)->tail, rxlen);
- dmfe_reused_skb(db, (struct sk_buff *) rxptr->rx_skb_ptr);
+ memcpy(skb_put(skb, rxlen), rxptr->rx_skb_ptr->tail, rxlen);
+ dmfe_reuse_skb(db, rxptr->rx_skb_ptr);
X } else {
X skb->dev = dev;
X skb_put(skb, rxlen);
@@ -988,12 +1002,12 @@
X }
X } else {
X /* Reuse SKB buffer when the packet is error */
- DMFE_DBUG(0, "Reused SK buffer, rdes0", rxptr->rdes0);
- dmfe_reused_skb(db, (struct sk_buff *) rxptr->rx_skb_ptr);
+ DMFE_DBUG(0, "Reuse SK buffer, rdes0", rdes0);
+ dmfe_reuse_skb(db, rxptr->rx_skb_ptr);
X }
X }
X
- rxptr = (struct rx_desc *) rxptr->next_rx_desc;
+ rxptr = rxptr->next_rx_desc;
X }
X
X db->rx_ready_ptr = rxptr;
@@ -1051,19 +1065,57 @@
X
X
X /*
+ * Process the ethtool ioctl command
+ */
+
+static int dmfe_ethtool_ioctl(struct net_device *dev, void *useraddr)
+{
+ struct dmfe_board_info *db = dev->priv;
+ struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+ u32 ethcmd;
+
+ if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
+ return -EFAULT;
+
+ switch (ethcmd) {
+ case ETHTOOL_GDRVINFO:
+ strcpy(info.driver, DRV_NAME);
+ strcpy(info.version, DRV_VERSION);
+ if (db->pdev)
+ strcpy(info.bus_info, db->pdev->slot_name);
+ else
+ sprintf(info.bus_info, "EISA 0x%lx %d",
+ dev->base_addr, dev->irq);
+ if (copy_to_user(useraddr, &info, sizeof(info)))
+ return -EFAULT;


+ return 0;
+ }
+

+ return -EOPNOTSUPP;
+}
+
+
+/*
X * Process the upper socket ioctl command
X */
X
X static int dmfe_do_ioctl(struct DEVICE *dev, struct ifreq *ifr, int cmd)
X {
+ int retval = -EOPNOTSUPP;
X DMFE_DBUG(0, "dmfe_do_ioctl()", 0);
- return 0;
+
+ switch(cmd) {
+ case SIOCETHTOOL:
+ return dmfe_ethtool_ioctl(dev, (void*)ifr->ifr_data);


+ }
+
+ return retval;

X }
X
X
X /*
X * A periodic timer routine
- * Dynamic media sense, allocated Rx buffer...
+ * Dynamic media sense, allocate Rx buffer...
X */
X
X static void dmfe_timer(unsigned long data)
@@ -1109,11 +1161,11 @@
X
X /* TX polling kick monitor */
X if ( db->tx_packet_cnt &&
- ((jiffies - dev->trans_start) > DMFE_TX_KICK) ) {
+ time_after(jiffies, dev->trans_start + DMFE_TX_KICK) ) {
X outl(0x1, dev->base_addr + DCR1); /* Tx polling again */
X
X /* TX Timeout */
- if ( (jiffies - dev->trans_start) > DMFE_TX_TIMEOUT ) {
+ if ( time_after(jiffies, dev->trans_start + DMFE_TX_TIMEOUT) ) {
X db->reset_TXtimeout++;
X db->wait_reset = 1;
X printk(KERN_WARNING "%s: Tx timeout - resetting\n",
@@ -1244,35 +1296,36 @@
X
X /* free allocated rx buffer */
X while (db->rx_avail_cnt) {
- dev_kfree_skb( (void *) (db->rx_ready_ptr->rx_skb_ptr) );
- db->rx_ready_ptr = (struct rx_desc *) db->rx_ready_ptr->next_rx_desc;
+ dev_kfree_skb(db->rx_ready_ptr->rx_skb_ptr);
+ db->rx_ready_ptr = db->rx_ready_ptr->next_rx_desc;
X db->rx_avail_cnt--;
X }
X }
X
X
X /*
- * Reused the SK buffer
+ * Reuse the SK buffer
X */
X
-static void dmfe_reused_skb(struct dmfe_board_info *db, struct sk_buff * skb)
+static void dmfe_reuse_skb(struct dmfe_board_info *db, struct sk_buff * skb)
X {
X struct rx_desc *rxptr = db->rx_insert_ptr;
X
- if (!(rxptr->rdes0 & 0x80000000)) {
- rxptr->rx_skb_ptr = (u32) skb;
- rxptr->rdes2 = cpu_to_le32( pci_map_single(db->net_dev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+ if (!(rxptr->rdes0 & cpu_to_le32(0x80000000))) {
+ rxptr->rx_skb_ptr = skb;
+ rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+ wmb();
X rxptr->rdes0 = cpu_to_le32(0x80000000);
X db->rx_avail_cnt++;
- db->rx_insert_ptr = (struct rx_desc *) rxptr->next_rx_desc;
+ db->rx_insert_ptr = rxptr->next_rx_desc;
X } else
- DMFE_DBUG(0, "SK Buffer reused method error", db->rx_avail_cnt);
+ DMFE_DBUG(0, "SK Buffer reuse method error", db->rx_avail_cnt);
X }
X
X
X /*
X * Initialize transmit/Receive descriptor
- * Using Chain structure, and allocated Tx/Rx buffer
+ * Using Chain structure, and allocate Tx/Rx buffer
X */
X
X static void dmfe_descriptor_init(struct dmfe_board_info *db, unsigned long ioaddr)
@@ -1292,8 +1345,8 @@
X outl(db->first_tx_desc_dma, ioaddr + DCR4); /* TX DESC address */
X
X /* rx descriptor start pointer */
- db->first_rx_desc = (struct rx_desc *) ( (u32) db->first_tx_desc + sizeof(struct rx_desc) * TX_DESC_CNT );
- db->first_rx_desc_dma = ( db->first_tx_desc_dma + sizeof(struct rx_desc) * TX_DESC_CNT);
+ db->first_rx_desc = (void *)db->first_tx_desc + sizeof(struct tx_desc) * TX_DESC_CNT;
+ db->first_rx_desc_dma = db->first_tx_desc_dma + sizeof(struct tx_desc) * TX_DESC_CNT;
X db->rx_insert_ptr = db->first_rx_desc;
X db->rx_ready_ptr = db->first_rx_desc;
X outl(db->first_rx_desc_dma, ioaddr + DCR3); /* RX DESC address */
@@ -1303,18 +1356,18 @@
X tmp_buf_dma = db->buf_pool_dma_start;
X tmp_tx_dma = db->first_tx_desc_dma;
X for (tmp_tx = db->first_tx_desc, i = 0; i < TX_DESC_CNT; i++, tmp_tx++) {
- tmp_tx->tx_buf_ptr = (u32) tmp_buf;
+ tmp_tx->tx_buf_ptr = tmp_buf;
X tmp_tx->tdes0 = cpu_to_le32(0);
X tmp_tx->tdes1 = cpu_to_le32(0x81000000); /* IC, chain */
X tmp_tx->tdes2 = cpu_to_le32(tmp_buf_dma);
X tmp_tx_dma += sizeof(struct tx_desc);
X tmp_tx->tdes3 = cpu_to_le32(tmp_tx_dma);
- tmp_tx->next_tx_desc = (u32) ((u32) tmp_tx + sizeof(struct tx_desc));
- tmp_buf = (unsigned char *) ((u32) tmp_buf + TX_BUF_ALLOC);
+ tmp_tx->next_tx_desc = tmp_tx + 1;
+ tmp_buf = tmp_buf + TX_BUF_ALLOC;
X tmp_buf_dma = tmp_buf_dma + TX_BUF_ALLOC;
X }
X (--tmp_tx)->tdes3 = cpu_to_le32(db->first_tx_desc_dma);
- tmp_tx->next_tx_desc = (u32) db->first_tx_desc;
+ tmp_tx->next_tx_desc = db->first_tx_desc;
X
X /* Init Receive descriptor chain */
X tmp_rx_dma=db->first_rx_desc_dma;
@@ -1323,13 +1376,13 @@
X tmp_rx->rdes1 = cpu_to_le32(0x01000600);
X tmp_rx_dma += sizeof(struct rx_desc);
X tmp_rx->rdes3 = cpu_to_le32(tmp_rx_dma);
- tmp_rx->next_rx_desc = (u32) ((u32) tmp_rx + sizeof(struct rx_desc));
+ tmp_rx->next_rx_desc = tmp_rx + 1;
X }
X (--tmp_rx)->rdes3 = cpu_to_le32(db->first_rx_desc_dma);
- tmp_rx->next_rx_desc = (u32) db->first_rx_desc;
+ tmp_rx->next_rx_desc = db->first_rx_desc;
X
- /* pre-allocated Rx buffer */
- allocated_rx_buffer(db);
+ /* pre-allocate Rx buffer */
+ allocate_rx_buffer(db);
X }
X
X
@@ -1438,7 +1491,7 @@
X }
X
X /* prepare the setup frame */
- db->tx_insert_ptr = (struct tx_desc *) txptr->next_tx_desc;
+ db->tx_insert_ptr = txptr->next_tx_desc;
X txptr->tdes1 = cpu_to_le32(0x890000c0);
X
X /* Resource Check and Send the setup packet */
@@ -1457,10 +1510,10 @@
X
X /*
X * Allocate rx buffer,
- * As possible as allocated maxiumn Rx buffer
+ * As possible as allocate maxiumn Rx buffer
X */
X
-static void allocated_rx_buffer(struct dmfe_board_info *db)
+static void allocate_rx_buffer(struct dmfe_board_info *db)
X {
X struct rx_desc *rxptr;
X struct sk_buff *skb;
@@ -1470,10 +1523,11 @@
X while(db->rx_avail_cnt < RX_DESC_CNT) {
X if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL )
X break;
- rxptr->rx_skb_ptr = (u32) skb; /* FIXME */
- rxptr->rdes2 = cpu_to_le32( pci_map_single(db->net_dev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+ rxptr->rx_skb_ptr = skb; /* FIXME (?) */
+ rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+ wmb();
X rxptr->rdes0 = cpu_to_le32(0x80000000);
- rxptr = (struct rx_desc *) rxptr->next_rx_desc;
+ rxptr = rxptr->next_rx_desc;
X db->rx_avail_cnt++;
X }
X
@@ -1540,7 +1594,7 @@
X phy_mode = phy_read(db->ioaddr, db->phy_addr, 7, db->chip_id) & 0xf000;
X else /* DM9102/DM9102A */
X phy_mode = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id) & 0xf000;
- /* printk("<DMFE>: Phy_mode %x ",phy_mode); */
+ /* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */
X switch (phy_mode) {
X case 0x1000: db->op_mode = DMFE_10MHF; break;
X case 0x2000: db->op_mode = DMFE_10MFD; break;
@@ -1830,7 +1884,7 @@
X if ( ( (int) srom[18] & 0xff) == SROM_V41_CODE) {
X /* SROM V4.01 */
X /* Get NIC support media mode */
- db->NIC_capability = *(u16 *) (&srom[34]);
+ db->NIC_capability = le16_to_cpup(srom + 34);
X db->PHY_reg4 = 0;
X for (tmp_reg = 1; tmp_reg < 0x10; tmp_reg <<= 1) {
X switch( db->NIC_capability & tmp_reg ) {
@@ -1842,7 +1896,7 @@
X }
X
X /* Media Mode Force or not check */
- dmfe_mode = *( (int *) &srom[34]) & *( (int *) &srom[36] );
+ dmfe_mode = le32_to_cpup(srom + 34) & le32_to_cpup(srom + 36);
X switch(dmfe_mode) {
X case 0x4: dmfe_media_mode = DMFE_100MHF; break; /* 100MHF */
X case 0x2: dmfe_media_mode = DMFE_10MFD; break; /* 10MFD */
@@ -2024,7 +2078,7 @@
X MODULE_PARM_DESC(debug, "Davicom DM9xxx enable debugging (0-1)");
X MODULE_PARM_DESC(mode, "Davicom DM9xxx: Bit 0: 10/100Mbps, bit 2: duplex, bit 8: HomePNA");
X MODULE_PARM_DESC(SF_mode, "Davicom DM9xxx special function (bit 0: VLAN, bit 1 Flow Control, bit 2: TX pause packet)");
-
+
X /* Description:
X * when user used insmod to add module, system invoked init_module()
X * to initilize and register.
diff -u --recursive --new-file v2.4.14/linux/drivers/net/eepro.c linux/drivers/net/eepro.c
--- v2.4.14/linux/drivers/net/eepro.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/net/eepro.c Mon Nov 19 15:19:42 2001
@@ -8,7 +8,7 @@
X according to the terms of the GNU General Public License,


X incorporated herein by reference.

X
- The author may be reached at bao...@srs.gov
+ The author may be reached at bao...@srs.gov
X or 418 Hastings Place, Martinez, GA 30907.
X
X Things remaining to do:
@@ -23,26 +23,31 @@
X This is a compatibility hardware problem.
X
X Versions:
+ 0.13 irq sharing, rewrote probe function, fixed a nasty bug in
+ hardware_send_packet and a major cleanup (aris, 11/08/2001)
+ 0.12d fixing a problem with single card detected as eight eth devices
+ fixing a problem with sudden drop in card performance
+ (chris (as...@go2.pl), 10/29/2001)
X 0.12c fixing some problems with old cards (aris, 01/08/2001)
X 0.12b misc fixes (aris, 06/26/2000)
X 0.12a port of version 0.12a of 2.2.x kernels to 2.3.x
X (aris (ar...@conectiva.com.br), 05/19/2000)
X 0.11e some tweaks about multiple cards support (PdP, jul/aug 1999)
X 0.11d added __initdata, __init stuff; call spin_lock_init
- in eepro_probe1. Replaced "eepro" by dev->name. Augmented
- the code protected by spin_lock in interrupt routine
+ in eepro_probe1. Replaced "eepro" by dev->name. Augmented
+ the code protected by spin_lock in interrupt routine
X (PdP, 12/12/1998)
- 0.11c minor cleanup (PdP, RMC, 09/12/1998)
- 0.11b Pascal Dupuis (dup...@lei.ucl.ac.be): works as a module
- under 2.1.xx. Debug messages are flagged as KERN_DEBUG to
- avoid console flooding. Added locking at critical parts. Now
+ 0.11c minor cleanup (PdP, RMC, 09/12/1998)
+ 0.11b Pascal Dupuis (dup...@lei.ucl.ac.be): works as a module
+ under 2.1.xx. Debug messages are flagged as KERN_DEBUG to
+ avoid console flooding. Added locking at critical parts. Now
X the dawn thing is SMP safe.
X 0.11a Attempt to get 2.1.xx support up (RMC)
X 0.11 Brian Candler added support for multiple cards. Tested as
X a module, no idea if it works when compiled into kernel.
X
X 0.10e Rick Bressler notified me that ifconfig up;ifconfig down fails
- because the irq is lost somewhere. Fixed that by moving
+ because the irq is lost somewhere. Fixed that by moving
X request_irq and free_irq to eepro_open and eepro_close respectively.
X 0.10d Ugh! Now Wakeup works. Was seriously broken in my first attempt.
X I'll need to find a way to specify an ioport other than
@@ -50,8 +55,8 @@
X And, yes, this is not the only reason.
X 0.10c PnP Wakeup Test for 595FX. uncomment #define PnPWakeup;
X to use.
- 0.10b Should work now with (some) Pro/10+. At least for
- me (and my two cards) it does. _No_ guarantee for
+ 0.10b Should work now with (some) Pro/10+. At least for
+ me (and my two cards) it does. _No_ guarantee for
X function with non-Pro/10+ cards! (don't have any)
X (RMC, 9/11/96)
X
@@ -75,7 +80,7 @@
X 0.07a Fix a stat report which counts every packet as a
X heart-beat failure. (BCH, 6/3/95)
X
- 0.07 Modified to support all other 82595-based lan cards.
+ 0.07 Modified to support all other 82595-based lan cards.
X The IRQ vector of the EtherExpress Pro will be set
X according to the value saved in the EEPROM. For other
X cards, I will do autoirq_request() to grab the next
@@ -85,37 +90,37 @@
X print out format. (BCH, 3/9/95 and 3/14/95)
X
X 0.06 First stable release that I am comfortable with. (BCH,
- 3/2/95)
+ 3/2/95)
X
- 0.05 Complete testing of multicast. (BCH, 2/23/95)
+ 0.05 Complete testing of multicast. (BCH, 2/23/95)
X
- 0.04 Adding multicast support. (BCH, 2/14/95)
+ 0.04 Adding multicast support. (BCH, 2/14/95)
X
- 0.03 First widely alpha release for public testing.
- (BCH, 2/14/95)
+ 0.03 First widely alpha release for public testing.
+ (BCH, 2/14/95)
X
X */
X
X static const char version[] =
- "eepro.c: v0.12c 01/08/2000 ar...@conectiva.com.br\n";
+ "eepro.c: v0.13 11/08/2001 ar...@cathedrallabs.org\n";
X
X #include <linux/module.h>
X
X /*
X Sources:
X
- This driver wouldn't have been written without the availability
- of the Crynwr's Lan595 driver source code. It helps me to
- familiarize with the 82595 chipset while waiting for the Intel
- documentation. I also learned how to detect the 82595 using
+ This driver wouldn't have been written without the availability
+ of the Crynwr's Lan595 driver source code. It helps me to
+ familiarize with the 82595 chipset while waiting for the Intel
+ documentation. I also learned how to detect the 82595 using
X the packet driver's technique.
X
X This driver is written by cutting and pasting the skeleton.c driver
X provided by Donald Becker. I also borrowed the EEPROM routine from
X Donald Becker's 82586 driver.
X
- Datasheet for the Intel 82595 (including the TX and FX version). It
- provides just enough info that the casual reader might think that it
+ Datasheet for the Intel 82595 (including the TX and FX version). It
+ provides just enough info that the casual reader might think that it
X documents the i82595.
X
X The User Manual for the 82595. It provides a lot of the missing
@@ -157,7 +162,7 @@
X /* A zero-terminated list of I/O addresses to be probed. */
X static unsigned int eepro_portlist[] compat_init_data =
X { 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};
-/* note: 0x300 is default, the 595FX supports ALL IO Ports
+/* note: 0x300 is default, the 595FX supports ALL IO Ports
X from 0x000 to 0x3F0, some of which are reserved in PCs */
X
X /* To try the (not-really PnP Wakeup: */
@@ -189,12 +194,24 @@
X unsigned tx_end; /* end of the transmit chain (plus 1) */
X int eepro; /* 1 for the EtherExpress Pro/10,
X 2 for the EtherExpress Pro/10+,
+ 3 for the EtherExpress 10 (blue cards),
X 0 for other 82595-based lan cards. */
X int version; /* a flag to indicate if this is a TX or FX
X version of the 82595 chip. */
X int stepping;
X
- spinlock_t lock; /* Serializing lock */
+ spinlock_t lock; /* Serializing lock */
+
+ unsigned rcv_ram; /* pre-calculated space for rx */
+ unsigned xmt_ram; /* pre-calculated space for tx */
+ unsigned char xmt_bar;
+ unsigned char xmt_lower_limit_reg;
+ unsigned char xmt_upper_limit_reg;
+ short xmt_lower_limit;
+ short xmt_upper_limit;
+ short rcv_lower_limit;
+ short rcv_upper_limit;
+ unsigned char eeprom_reg;
X };
X
X /* The station (ethernet) address prefix, used for IDing the board. */
@@ -244,7 +261,7 @@
X /* Word 5: */
X #define ee_BNC_TPE 0 /* 0=TPE */
X #define ee_BootType 1 /* 00=None, 01=IPX, 10=ODI, 11=NDIS */
-#define ee_BootTypeMask 0x3
+#define ee_BootTypeMask 0x3
X #define ee_NumConn 3 /* Number of Connections 0= One or Two */
X #define ee_FlashSock 4 /* Presence of Flash Socket 0= Present */
X #define ee_PortTPE 5
@@ -299,7 +316,7 @@
X static void eepro_tx_timeout (struct net_device *dev);
X
X static int read_eeprom(int ioaddr, int location, struct net_device *dev);
-static void hardware_send_packet(struct net_device *dev, void *buf, short length);
+static int hardware_send_packet(struct net_device *dev, void *buf, short length);
X static int eepro_grab_irq(struct net_device *dev);
X
X /*
@@ -323,55 +340,42 @@
X network traffics, the ring linked list should improve performance by
X allowing up to 8K worth of packets to be queued.
X
-The sizes of the receive and transmit buffers can now be changed via lilo
+The sizes of the receive and transmit buffers can now be changed via lilo
X or insmod. Lilo uses the appended line "ether=io,irq,debug,rx-buffer,eth0"
X where rx-buffer is in KB unit. Modules uses the parameter mem which is
-also in KB unit, for example "insmod io=io-address irq=0 mem=rx-buffer."
+also in KB unit, for example "insmod io=io-address irq=0 mem=rx-buffer."
X The receive buffer has to be more than 3K or less than 29K. Otherwise,
X it is reset to the default of 24K, and, hence, 8K for the trasnmit
X buffer (transmit-buffer = 32K - receive-buffer).
X
X */
-/* now this section could be used by both boards: the oldies and the ee10:
- * ee10 uses tx buffer before of rx buffer and the oldies the inverse.
- * (aris)
- */
X #define RAM_SIZE 0x8000
X
X #define RCV_HEADER 8
X #define RCV_DEFAULT_RAM 0x6000
-#define RCV_RAM rcv_ram
-
-static unsigned rcv_ram = RCV_DEFAULT_RAM;
X
X #define XMT_HEADER 8
-#define XMT_RAM (RAM_SIZE - RCV_RAM)
-
-#define XMT_START ((rcv_start + RCV_RAM) % RAM_SIZE)
+#define XMT_DEFAULT_RAM (RAM_SIZE - RCV_DEFAULT_RAM)
X
-#define RCV_LOWER_LIMIT (rcv_start >> 8)
-#define RCV_UPPER_LIMIT (((rcv_start + RCV_RAM) - 2) >> 8)
-#define XMT_LOWER_LIMIT (XMT_START >> 8)
-#define XMT_UPPER_LIMIT (((XMT_START + XMT_RAM) - 2) >> 8)
-
-#define RCV_START_PRO 0x00
-#define RCV_START_10 XMT_RAM
- /* by default the old driver */
-static unsigned rcv_start = RCV_START_PRO;
+#define XMT_START_PRO RCV_DEFAULT_RAM
+#define XMT_START_10 0x0000
+#define RCV_START_PRO 0x0000
+#define RCV_START_10 XMT_DEFAULT_RAM
X
X #define RCV_DONE 0x0008
X #define RX_OK 0x2000
X #define RX_ERROR 0x0d81
X
X #define TX_DONE_BIT 0x0080
+#define TX_OK 0x2000
X #define CHAIN_BIT 0x8000
X #define XMT_STATUS 0x02
X #define XMT_CHAIN 0x04
X #define XMT_COUNT 0x06
X
-#define BANK0_SELECT 0x00
-#define BANK1_SELECT 0x40
-#define BANK2_SELECT 0x80
+#define BANK0_SELECT 0x00
+#define BANK1_SELECT 0x40
+#define BANK2_SELECT 0x80
X
X /* Bank 0 registers */
X #define COMMAND_REG 0x00 /* Register 0 */
@@ -406,7 +410,6 @@
X
X #define XMT_BAR_PRO 0x0a
X #define XMT_BAR_10 0x0b
-static unsigned xmt_bar = XMT_BAR_PRO;
X
X #define HOST_ADDRESS_REG 0x0c
X #define IO_PORT 0x0e
@@ -424,8 +427,6 @@
X #define XMT_UPPER_LIMIT_REG_PRO 0x0b
X #define XMT_LOWER_LIMIT_REG_10 0x0b
X #define XMT_UPPER_LIMIT_REG_10 0x0a
-static unsigned xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO;
-static unsigned xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO;
X
X /* Bank 2 registers */
X #define XMT_Chain_Int 0x20 /* Interrupt at the end of the transmit chain */
@@ -440,7 +441,7 @@
X #define REG13 0x0d
X #define FDX 0x00
X #define A_N_ENABLE 0x02
-
+
X #define I_ADD_REG0 0x04
X #define I_ADD_REG1 0x05
X #define I_ADD_REG2 0x06
@@ -450,7 +451,6 @@
X
X #define EEPROM_REG_PRO 0x0a
X #define EEPROM_REG_10 0x0b
-static unsigned eeprom_reg = EEPROM_REG_PRO;
X
X #define EESK 0x01
X #define EECS 0x02
@@ -502,11 +502,6 @@
X /* set diagnose flag */
X #define eepro_diag(ioaddr) outb(DIAGNOSE_CMD, ioaddr)
X
-#ifdef ANSWER_TX_AND_RX /* experimental way of handling interrupts */
-/* ack for rx/tx int */
-#define eepro_ack_rxtx(ioaddr) outb (RX_INT | TX_INT, ioaddr + STATUS_REG)
-#endif
-
X /* ack for rx int */
X #define eepro_ack_rx(ioaddr) outb (RX_INT, ioaddr + STATUS_REG)
X
@@ -514,16 +509,15 @@
X #define eepro_ack_tx(ioaddr) outb (TX_INT, ioaddr + STATUS_REG)
X
X /* a complete sel reset */
-#define eepro_complete_selreset(ioaddr) { eepro_dis_int(ioaddr);\
+#define eepro_complete_selreset(ioaddr) { \
X lp->stats.tx_errors++;\
X eepro_sel_reset(ioaddr);\
X lp->tx_end = \
- (XMT_LOWER_LIMIT << 8);\
+ lp->xmt_lower_limit;\
X lp->tx_start = lp->tx_end;\
X lp->tx_last = 0;\


X dev->trans_start = jiffies;\

X netif_wake_queue(dev);\
- eepro_en_int(ioaddr);\
X eepro_en_rx(ioaddr);\
X }
X
@@ -542,7 +536,7 @@
X
X #ifdef PnPWakeup
X /* XXXX for multiple cards should this only be run once? */
-
+
X /* Wakeup: */
X #define WakeupPort 0x279
X #define WakeupSeq {0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,\
@@ -568,7 +562,6 @@


X }
X #endif
X
-

X if (base_addr > 0x1ff) /* Check a single specified location. */
X return eepro_probe1(dev, base_addr);
X
@@ -595,13 +588,13 @@
X
X for (i=0, j=ee_Checksum; i<ee_SIZE; i++)
X j+=read_eeprom(ioaddr,i,dev);
- printk("Checksum: %#x\n",j&0xffff);
+ printk(KERN_DEBUG "Checksum: %#x\n",j&0xffff);
X
X Word=read_eeprom(ioaddr, 0, dev);
X printk(KERN_DEBUG "Word0:\n");
X printk(KERN_DEBUG " Plug 'n Pray: %d\n",GetBit(Word,ee_PnP));
X printk(KERN_DEBUG " Buswidth: %d\n",(GetBit(Word,ee_BusWidth)+1)*8 );
- printk(KERN_DEBUG " AutoNegotiation: %d\n",GetBit(Word,ee_AutoNeg));
+ printk(KERN_DEBUG " AutoNegotiation: %d\n",GetBit(Word,ee_AutoNeg));
X printk(KERN_DEBUG " IO Address: %#x\n", (Word>>ee_IO0)<<4);
X
X if (net_debug>4) {
@@ -621,10 +614,10 @@
X printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE));
X printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn));
X printk(KERN_DEBUG " Has ");
- if (GetBit(Word,ee_PortTPE)) printk("TPE ");
- if (GetBit(Word,ee_PortBNC)) printk("BNC ");
- if (GetBit(Word,ee_PortAUI)) printk("AUI ");
- printk("port(s) \n");
+ if (GetBit(Word,ee_PortTPE)) printk(KERN_DEBUG "TPE ");
+ if (GetBit(Word,ee_PortBNC)) printk(KERN_DEBUG "BNC ");
+ if (GetBit(Word,ee_PortAUI)) printk(KERN_DEBUG "AUI ");
+ printk(KERN_DEBUG "port(s) \n");
X
X Word=read_eeprom(ioaddr, 6, dev);
X printk(KERN_DEBUG "Word6:\n");
@@ -635,12 +628,85 @@
X printk(KERN_DEBUG "Word7:\n");
X printk(KERN_DEBUG " INT to IRQ:\n");
X
- printk(KERN_DEBUG);
-
X for (i=0, j=0; i<15; i++)
- if (GetBit(Word,i)) printk(" INT%d -> IRQ %d;",j++,i);
+ if (GetBit(Word,i)) printk(KERN_DEBUG " INT%d -> IRQ %d;",j++,i);
+
+ printk(KERN_DEBUG "\n");
+}
+
+/* function to recalculate the limits of buffer based on rcv_ram */
+static void eepro_recalc (struct net_device *dev)
+{
+ struct eepro_local * lp;
+
+ lp = dev->priv;
+ lp->xmt_ram = RAM_SIZE - lp->rcv_ram;
+
+ if (lp->eepro == LAN595FX_10ISA) {
+ lp->xmt_lower_limit = XMT_START_10;
+ lp->xmt_upper_limit = (lp->xmt_ram - 2);
+ lp->rcv_lower_limit = lp->xmt_ram;
+ lp->rcv_upper_limit = (RAM_SIZE - 2);
+ }
+ else {
+ lp->rcv_lower_limit = RCV_START_PRO;
+ lp->rcv_upper_limit = (lp->rcv_ram - 2);
+ lp->xmt_lower_limit = lp->rcv_ram;
+ lp->xmt_upper_limit = (RAM_SIZE - 2);
+ }
+}
+
+/* prints boot-time info */
+static void eepro_print_info (struct net_device *dev)
+{
+ struct eepro_local * lp = dev->priv;
+ int i;
+ const char * ifmap[] = {"AUI", "10Base2", "10BaseT"};
+
+ i = inb(dev->base_addr + ID_REG);
+ printk(KERN_DEBUG " id: %#x ",i);
+ printk(KERN_DEBUG " io: %#x ", (unsigned)dev->base_addr);
+
+ switch (lp->eepro) {
+ case LAN595FX_10ISA:
+ printk(KERN_INFO "%s: Intel EtherExpress 10 ISA\n at %#x,",
+ dev->name, (unsigned)dev->base_addr);
+ break;
+ case LAN595FX:
+ printk(KERN_INFO "%s: Intel EtherExpress Pro/10+ ISA\n at %#x,",
+ dev->name, (unsigned)dev->base_addr);
+ break;
+ case LAN595TX:
+ printk(KERN_INFO "%s: Intel EtherExpress Pro/10 ISA at %#x,",
+ dev->name, (unsigned)dev->base_addr);
+ break;
+ case LAN595:
+ printk(KERN_INFO "%s: Intel 82595-based lan card at %#x,",
+ dev->name, (unsigned)dev->base_addr);
+ }
+
+ for (i=0; i < 6; i++)
+ printk(KERN_INFO "%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
+
+ if (net_debug > 3)
+ printk(KERN_DEBUG ", %dK RCV buffer",
+ (int)(lp->rcv_ram)/1024);
+
+ if (dev->irq > 2)
+ printk(KERN_INFO ", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]);
+ else
+ printk(KERN_INFO ", %s.\n", ifmap[dev->if_port]);
X
- printk("\n");
+ if (net_debug > 3) {
+ i = read_eeprom(dev->base_addr, 5, dev);
+ if (i & 0x2000) /* bit 13 of EEPROM word 5 */
+ printk(KERN_DEBUG "%s: Concurrent Processing is "
+ "enabled but not used!\n", dev->name);
+ }
+
+ /* Check the station address for the manufacturer's code */
+ if (net_debug>3)
+ printEEPROMInfo(dev->base_addr, dev);
X }
X
X /* This is the real probe routine. Linux has a history of friendly device
@@ -650,42 +716,51 @@
X static int __init eepro_probe1(struct net_device *dev, short ioaddr)
X {
X unsigned short station_addr[6], id, counter;
- int i,j, irqMask;
- int eepro = 0;
+ int i, j, irqMask, retval = 0;
X struct eepro_local *lp;
- const char *ifmap[] = {"AUI", "10Base2", "10BaseT"};
X enum iftype { AUI=0, BNC=1, TPE=2 };
X
X /* Now, we are going to check for the signature of the
X ID_REG (register 2 of bank 0) */
X
X id=inb(ioaddr + ID_REG);
-
- if (((id) & ID_REG_MASK) == ID_REG_SIG) {
+
+ if (((id) & ID_REG_MASK) != ID_REG_SIG) {
+ retval = -ENODEV;
+ goto exit;
+ }
X
X /* We seem to have the 82595 signature, let's
X play with its counter (last 2 bits of
X register 2 of bank 0) to be sure. */
-
- counter = (id & R_ROBIN_BITS);
- if (((id=inb(ioaddr+ID_REG)) & R_ROBIN_BITS) ==
- (counter + 0x40)) {
-
- /* Yes, the 82595 has been found */
- printk(KERN_DEBUG " id: %#x ",id);
- printk(" io: %#x ",ioaddr);
+
+ counter = (id & R_ROBIN_BITS);
+
+ if (((id=inb(ioaddr+ID_REG)) & R_ROBIN_BITS)!=(counter + 0x40)) {
+ retval = -ENODEV;
+ goto exit;
+ }
X
X /* Initialize the device structure */
X dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL);
- if (dev->priv == NULL)
- return -ENOMEM;
+ if (!dev->priv) {


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

echo 'End of part 051'
echo 'File patch-2.4.15 is continued in part 052'
echo "052" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:32 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part056

#!/bin/sh -x
# this is part 056 of a 115 - part archive


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

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

+ spin_lock_init(&dev->lock);
+ dev->chanA.lock = &dev->lock;
+ dev->chanB.lock = &dev->lock;
+

+ spin_lock_irqsave(&dev->lock, flags);
+ ret = do_z8530_init(dev);
+ spin_unlock_irqrestore(&dev->lock, flags);


+
+ return ret;
+}
+

X
X EXPORT_SYMBOL(z8530_init);
X
@@ -1297,15 +1361,22 @@
X * We set the interrupt handlers to silence any interrupts. We then
X * reset the chip and wait 100uS to be sure the reset completed. Just
X * in case the caller then tries to do stuff.
+ *
+ * This is called without the lock held
X */
X
X int z8530_shutdown(struct z8530_dev *dev)


X {
+ unsigned long flags;

X /* Reset the chip */

+
+ spin_lock_irqsave(&dev->lock, flags);
X dev->chanA.irqs=&z8530_nop;
X dev->chanB.irqs=&z8530_nop;


X write_zsreg(&dev->chanA, R9, 0xC0);

+ /* We must lock the udelay, the chip is offlimits here */
X udelay(100);
+ spin_unlock_irqrestore(&dev->lock, flags);


X return 0;
X }
X

@@ -1324,6 +1395,10 @@
X
X int z8530_channel_load(struct z8530_channel *c, u8 *rtable)


X {
+ unsigned long flags;
+
+ spin_lock_irqsave(c->lock, flags);
+

X while(*rtable!=255)
X {
X int reg=*rtable++;
@@ -1344,6 +1419,8 @@
X c->status=read_zsreg(c, R0);
X c->sync=1;


X write_zsreg(c, R3, c->regs[R3]|RxENABLE);
+
+ spin_unlock_irqrestore(c->lock, flags);
X return 0;
X }
X

@@ -1360,6 +1437,8 @@
X *
X * Note: We are handling this code path in the interrupt path, keep it
X * fast or bad things will happen.
+ *
+ * Called with the lock held.
X */
X
X static void z8530_tx_begin(struct z8530_channel *c)
@@ -1430,8 +1509,7 @@
X }
X else
X {


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

X /* ABUNDER off */
X write_zsreg(c, R10, c->regs[10]);
X write_zsctrl(c, RES_Tx_CRC);
@@ -1442,7 +1520,7 @@
X write_zsreg(c, R8, *c->tx_ptr++);
X c->txcount--;
X }
- restore_flags(flags);
+
X }
X }
X }
@@ -1454,25 +1532,22 @@
X * This is called when we complete a packet send. We wake the queue,
X * start the next packet going and then free the buffer of the existing
X * packet. This code is fairly timing sensitive.
+ *
+ * Called with the register lock held.
X */
X
X static void z8530_tx_done(struct z8530_channel *c)


X {
- unsigned long flags;

X struct sk_buff *skb;
X

- spin_lock_irqsave(&z8530_buffer_lock, flags);
X netif_wake_queue(c->netdevice);
X /* Actually this can happen.*/
X if(c->tx_skb==NULL)
- {
- spin_unlock_irqrestore(&z8530_buffer_lock, flags);
X return;
- }
+
X skb=c->tx_skb;
X c->tx_skb=NULL;
X z8530_tx_begin(c);
- spin_unlock_irqrestore(&z8530_buffer_lock, flags);
X c->stats.tx_packets++;
X c->stats.tx_bytes+=skb->len;
X dev_kfree_skb_irq(skb);
@@ -1489,7 +1564,7 @@
X
X void z8530_null_rx(struct z8530_channel *c, struct sk_buff *skb)
X {
- kfree_skb(skb);
+ dev_kfree_skb_any(skb);
X }
X
X EXPORT_SYMBOL(z8530_null_rx);
@@ -1503,6 +1578,8 @@
X * ESCC mode, but on the older chips we have no choice. We flip to the
X * new buffer immediately in DMA mode so that the DMA of the next
X * frame can occur while we are copying the previous buffer to an sk_buff
+ *
+ * Called with the lock held
X */
X
X static void z8530_rx_done(struct z8530_channel *c)
@@ -1673,6 +1750,9 @@
X * hard to hit interrupt latencies for the Z85230 per packet
X * even in DMA mode we do the flip to DMA buffer if needed here
X * not in the IRQ.
+ *
+ * Called from the network code. The lock is not held at this
+ * point.
X */
X
X int z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb)
@@ -1711,9 +1791,9 @@
X c->tx_next_skb=skb;
X RT_UNLOCK;
X
- spin_lock_irqsave(&z8530_buffer_lock, flags);
+ spin_lock_irqsave(c->lock, flags);
X z8530_tx_begin(c);
- spin_unlock_irqrestore(&z8530_buffer_lock, flags);


+ spin_unlock_irqrestore(c->lock, flags);
X

X netif_wake_queue(c->netdevice);
X return 0;
@@ -1727,6 +1807,9 @@
X *
X * Get the statistics block. We keep the statistics in software as
X * the chip doesn't do it for us.
+ *
+ * Locking is ignored here - we could lock for a copy but its
+ * not likely to be that big an issue
X */
X
X struct net_device_stats *z8530_get_stats(struct z8530_channel *c)
diff -u --recursive --new-file v2.4.14/linux/drivers/net/wan/z85230.h linux/drivers/net/wan/z85230.h
--- v2.4.14/linux/drivers/net/wan/z85230.h Tue Feb 13 13:15:05 2001
+++ linux/drivers/net/wan/z85230.h Fri Nov 9 14:03:11 2001
@@ -368,6 +368,8 @@
X
X unsigned char tx_active; /* character is being xmitted */
X unsigned char tx_stopped; /* output is suspended */
+
+ spinlock_t *lock; /* Devicr lock */
X };
X
X /*
@@ -386,6 +388,7 @@
X int irq; /* Interrupt for the device */
X int active; /* Soft interrupt enable - the Mac doesn't
X always have a hard disable on its 8530s... */
+ spinlock_t lock;
X };
X
X
diff -u --recursive --new-file v2.4.14/linux/drivers/net/wireless/airo.c linux/drivers/net/wireless/airo.c
--- v2.4.14/linux/drivers/net/wireless/airo.c Tue Oct 23 22:48:51 2001
+++ linux/drivers/net/wireless/airo.c Fri Nov 9 13:41:42 2001
@@ -3214,17 +3214,19 @@
X static int __devinit airo_pci_probe(struct pci_dev *pdev,
X const struct pci_device_id *pent)
X {
- pdev->driver_data = init_airo_card(pdev->irq,
- pdev->resource[2].start, 0);
- if (!pdev->driver_data) {
+ struct net_device *dev;
+
+ dev = init_airo_card(pdev->irq, pdev->resource[2].start, 0);
+ if (!dev)
X return -ENODEV;
- }
+
+ pci_set_drvdata(pdev, dev);


X return 0;
X }
X

X static void __devexit airo_pci_remove(struct pci_dev *pdev)
X {
- stop_airo_card(pdev->driver_data, 1);
+ stop_airo_card(pci_get_drvdata(pdev), 1);
X }
X #endif
X
diff -u --recursive --new-file v2.4.14/linux/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog
--- v2.4.14/linux/drivers/parport/ChangeLog Mon Nov 5 15:55:31 2001
+++ linux/drivers/parport/ChangeLog Mon Nov 12 09:45:32 2001
@@ -1,3 +1,12 @@
+2001-11-12 Tim Waugh <twa...@redhat.com>
+
+ * parport_pc.c (init_module): Warn when parameters are ignored.
+
+2001-11-01 Damian Gruszka <damian....@VisionSystems.de>
+
+ * parport_serial.c (serial_register): Set base_baud before
+ calling register_serial.
+
X 2001-10-26 Tim Waugh <twa...@redhat.com>
X
X * parport_pc.c (parport_irq_probe): When ECR programmable IRQ
diff -u --recursive --new-file v2.4.14/linux/drivers/parport/Config.in linux/drivers/parport/Config.in
--- v2.4.14/linux/drivers/parport/Config.in Sun Sep 23 11:40:59 2001
+++ linux/drivers/parport/Config.in Sun Nov 11 10:09:33 2001
@@ -45,6 +45,12 @@
X else
X define_tristate CONFIG_PARPORT_ATARI n
X fi
+ if [ "$CONFIG_GSC_LASI" = "y" ]; then
+ dep_tristate ' LASI/ASP builtin parallel-port' CONFIG_PARPORT_GSC $CONFIG_PARPORT
+ else
+ define_tristate CONFIG_PARPORT_GSC n
+ fi
+
X if [ "$CONFIG_SBUS" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
X dep_tristate ' Sparc hardware (EXPERIMENTAL)' CONFIG_PARPORT_SUNBPP $CONFIG_PARPORT
X else
diff -u --recursive --new-file v2.4.14/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- v2.4.14/linux/drivers/parport/parport_pc.c Mon Nov 5 15:55:31 2001
+++ linux/drivers/parport/parport_pc.c Mon Nov 12 09:44:58 2001
@@ -3047,6 +3047,12 @@
X case PARPORT_IRQ_NONE:
X case PARPORT_IRQ_AUTO:
X irqval[0] = val;
+ break;
+ default:
+ printk (KERN_WARNING
+ "parport_pc: irq specified "
+ "without base address. Use 'io=' "
+ "to specify one\n");
X }
X
X if (dma[0] && !parport_parse_dmas (1, dma, &val))
@@ -3054,6 +3060,12 @@
X case PARPORT_DMA_NONE:
X case PARPORT_DMA_AUTO:
X dmaval[0] = val;
+ break;
+ default:
+ printk (KERN_WARNING
+ "parport_pc: dma specified "
+ "without base address. Use 'io=' "
+ "to specify one\n");
X }
X }
X
diff -u --recursive --new-file v2.4.14/linux/drivers/parport/parport_serial.c linux/drivers/parport/parport_serial.c
--- v2.4.14/linux/drivers/parport/parport_serial.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/parport/parport_serial.c Fri Nov 9 14:30:55 2001
@@ -217,6 +217,7 @@
X if (get_pci_port (dev, board, &serial_req, k))
X break;
X serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
+ serial_req.baud_base = base_baud;
X line = register_serial (&serial_req);
X if (line < 0) {
X printk (KERN_DEBUG
diff -u --recursive --new-file v2.4.14/linux/drivers/pci/names.c linux/drivers/pci/names.c
--- v2.4.14/linux/drivers/pci/names.c Sun Sep 23 11:40:59 2001
+++ linux/drivers/pci/names.c Fri Nov 9 14:03:11 2001
@@ -52,7 +52,7 @@
X
X #define VENDORS (sizeof(pci_vendor_list)/sizeof(struct pci_vendor_info))
X
-void __init pci_name_device(struct pci_dev *dev)
+void __devinit pci_name_device(struct pci_dev *dev)
X {
X const struct pci_vendor_info *vendor_p = pci_vendor_list;
X int i = VENDORS;
diff -u --recursive --new-file v2.4.14/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.4.14/linux/drivers/pci/pci.c Mon Nov 5 15:55:31 2001
+++ linux/drivers/pci/pci.c Tue Nov 20 21:53:29 2001
@@ -684,22 +684,17 @@
X }
X
X /**
- * pci_insert_device - insert a hotplug device
- * @dev: the device to insert
- * @bus: where to insert it
+ * pci_announce_device_to_drivers - tell the drivers a new device has appeared
+ * @dev: the device that has shown up
X *
- * Add a new device to the device lists and notify userspace (/sbin/hotplug).
+ * Notifys the drivers that a new device has appeared, and also notifys
+ * userspace through /sbin/hotplug.
X */
X void
-pci_insert_device(struct pci_dev *dev, struct pci_bus *bus)
+pci_announce_device_to_drivers(struct pci_dev *dev)
X {
X struct list_head *ln;
X
- list_add_tail(&dev->bus_list, &bus->devices);
- list_add_tail(&dev->global_list, &pci_devices);
-#ifdef CONFIG_PROC_FS
- pci_proc_attach_device(dev);
-#endif
X for(ln=pci_drivers.next; ln != &pci_drivers; ln=ln->next) {
X struct pci_driver *drv = list_entry(ln, struct pci_driver, node);
X if (drv->remove && pci_announce_device(drv, dev))
@@ -710,6 +705,24 @@
X run_sbin_hotplug(dev, TRUE);
X }
X
+/**
+ * pci_insert_device - insert a hotplug device
+ * @dev: the device to insert
+ * @bus: where to insert it
+ *
+ * Add a new device to the device lists and notify userspace (/sbin/hotplug).
+ */
+void
+pci_insert_device(struct pci_dev *dev, struct pci_bus *bus)
+{
+ list_add_tail(&dev->bus_list, &bus->devices);
+ list_add_tail(&dev->global_list, &pci_devices);
+#ifdef CONFIG_PROC_FS
+ pci_proc_attach_device(dev);
+#endif
+ pci_announce_device_to_drivers(dev);


+}
+
X static void

X pci_free_resources(struct pci_dev *dev)
X {
@@ -951,7 +964,7 @@
X }
X }
X
-void __init pci_read_bridge_bases(struct pci_bus *child)
+void __devinit pci_read_bridge_bases(struct pci_bus *child)
X {
X struct pci_dev *dev = child->self;
X u8 io_base_lo, io_limit_lo;
@@ -972,7 +985,7 @@
X base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
X limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
X
- if ((base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
+ if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
X u16 io_base_hi, io_limit_hi;
X pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
X pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
@@ -1042,7 +1055,7 @@
X }
X }
X
-static struct pci_bus * __init pci_alloc_bus(void)
+static struct pci_bus * __devinit pci_alloc_bus(void)
X {
X struct pci_bus *b;
X
@@ -1055,7 +1068,7 @@
X return b;
X }
X
-static struct pci_bus * __init pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
+struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
X {
X struct pci_bus *child;
X int i;
@@ -1087,7 +1100,7 @@
X return child;
X }
X
-static unsigned int __init pci_do_scan_bus(struct pci_bus *bus);
+unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus);
X
X /*
X * If it's a bridge, configure it and scan the bus behind it.
@@ -1099,7 +1112,7 @@
X * them, we proceed to assigning numbers to the remaining buses in
X * order to avoid overlaps between old and new bus numbers.
X */
-static int __init pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass)
+static int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass)
X {
X unsigned int buses;
X unsigned short cr;
@@ -1255,7 +1268,7 @@
X * Read the config data for a PCI device, sanity-check it
X * and fill in the dev structure...
X */
-static struct pci_dev * __init pci_scan_device(struct pci_dev *temp)
+struct pci_dev * __devinit pci_scan_device(struct pci_dev *temp)
X {
X struct pci_dev *dev;
X u32 l;
@@ -1285,7 +1298,7 @@
X return dev;
X }
X
-struct pci_dev * __init pci_scan_slot(struct pci_dev *temp)
+struct pci_dev * __devinit pci_scan_slot(struct pci_dev *temp)
X {
X struct pci_bus *bus = temp->bus;
X struct pci_dev *dev;
@@ -1323,7 +1336,7 @@
X return first_dev;
X }
X
-static unsigned int __init pci_do_scan_bus(struct pci_bus *bus)
+unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
X {
X unsigned int devfn, max, pass;
X struct list_head *ln;
@@ -1367,7 +1380,7 @@
X return max;
X }
X
-int __init pci_bus_exists(const struct list_head *list, int nr)
+int __devinit pci_bus_exists(const struct list_head *list, int nr)
X {
X const struct list_head *l;
X
@@ -1379,7 +1392,7 @@


X return 0;
X }
X

-struct pci_bus * __init pci_alloc_primary_bus(int bus)
+struct pci_bus * __devinit pci_alloc_primary_bus(int bus)
X {
X struct pci_bus *b;
X
@@ -1398,7 +1411,7 @@
X return b;
X }
X
-struct pci_bus * __init pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata)
+struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata)
X {
X struct pci_bus *b = pci_alloc_primary_bus(bus);
X if (b) {
@@ -1916,7 +1929,7 @@
X }
X
X
-void __init pci_init(void)
+void __devinit pci_init(void)
X {
X struct pci_dev *dev;
X
@@ -1931,7 +1944,7 @@
X #endif
X }
X
-static int __init pci_setup(char *str)
+static int __devinit pci_setup(char *str)
X {
X while (str) {
X char *k = strchr(str, ',');
@@ -1979,6 +1992,14 @@
X EXPORT_SYMBOL(pci_setup_device);
X EXPORT_SYMBOL(pci_insert_device);
X EXPORT_SYMBOL(pci_remove_device);
+EXPORT_SYMBOL(pci_announce_device_to_drivers);
+EXPORT_SYMBOL(pci_add_new_bus);
+EXPORT_SYMBOL(pci_do_scan_bus);
+EXPORT_SYMBOL(pci_scan_slot);
+EXPORT_SYMBOL(pci_proc_attach_device);
+EXPORT_SYMBOL(pci_proc_detach_device);
+EXPORT_SYMBOL(pci_proc_attach_bus);
+EXPORT_SYMBOL(pci_proc_detach_bus);
X #endif
X
X EXPORT_SYMBOL(pci_set_power_state);
diff -u --recursive --new-file v2.4.14/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids
--- v2.4.14/linux/drivers/pci/pci.ids Mon Nov 5 15:55:31 2001
+++ linux/drivers/pci/pci.ids Fri Nov 9 14:03:11 2001
@@ -540,6 +540,11 @@
X 7411 AMD-765 [Viper] IDE
X 7413 AMD-765 [Viper] ACPI
X 7414 AMD-765 [Viper] USB
+ 7440 AMD-768 [??] ISA
+ 7441 AMD-768 [??] IDE
+ 7443 AMD-768 [??] ACPI
+ 7448 AMD-768 [??] PCI
+ 7449 AMD-768 [??] USB
X 1023 Trident Microsystems
X 0194 82C194
X 2000 4DWave DX
@@ -1094,6 +1099,8 @@
X 4d33 20246
X 4d38 20262
X 4d68 20268
+ 6268 20268R
+ 4d69 20269
X 5300 DC5300
X 105b Foxconn International, Inc.
X 105c Wipro Infotech Limited
@@ -1370,6 +1377,7 @@
X 0650 PBC0650A
X 0670 USB0670
X 0673 USB0673
+ 0680 PCI0680
X 1096 Alacron
X 1097 Appian Technology
X 1098 Quantum Designs (H.K.) Ltd
@@ -4186,7 +4194,7 @@
X 14e4 0007 NetXtreme BCM5701 1000BaseSX
X 14e4 0008 NetXtreme BCM5701 1000BaseTX
X 14e4 8008 NetXtreme BCM5701 1000BaseTX
- 1647 NetXtreme BCM5701 Gigabit Ethernet
+ 1647 NetXtreme BCM5703 Gigabit Ethernet
X 5820 BCM5820 Crypto Accelerator
X 14e5 Pixelfusion Ltd
X 14e6 SHINING Technology Inc
diff -u --recursive --new-file v2.4.14/linux/drivers/pci/proc.c linux/drivers/pci/proc.c
--- v2.4.14/linux/drivers/pci/proc.c Mon Nov 5 15:55:31 2001
+++ linux/drivers/pci/proc.c Fri Nov 16 18:38:39 2001
@@ -11,6 +11,7 @@
X #include <linux/pci.h>
X #include <linux/proc_fs.h>
X #include <linux/init.h>
+#include <linux/seq_file.h>
X
X #include <asm/uaccess.h>
X #include <asm/byteorder.h>
@@ -302,53 +303,72 @@
X #define LONG_FORMAT "\t%16lx"
X #endif
X
-static int
-get_pci_dev_info(char *buf, char **start, off_t pos, int count)
+/* iterator */
+static void *pci_seq_start(struct seq_file *m, loff_t *pos)
X {
+ struct list_head *p = &pci_devices;
+ loff_t n = *pos;
+
+ /* XXX: surely we need some locking for traversing the list? */
+ while (n--) {
+ p = p->next;
+ if (p == &pci_devices)
+ return NULL;
+ }
+ return p;
+}
+static void *pci_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ struct list_head *p = v;
+ (*pos)++;
+ return p->next != &pci_devices ? p->next : NULL;
+}
+static void pci_seq_stop(struct seq_file *m, void *v)
+{
+ /* release whatever locks we need */
+}
+
+static int show_device(struct seq_file *m, void *v)
+{
+ struct list_head *p = v;
X const struct pci_dev *dev;
- off_t at = 0;
- int len, i, cnt;
+ const struct pci_driver *drv;
+ int i;
+
+ if (p == &pci_devices)
+ return 0;
X
- cnt = 0;
- pci_for_each_dev(dev) {
- const struct pci_driver *drv = pci_dev_driver(dev);
- len = sprintf(buf, "%02x%02x\t%04x%04x\t%x",
+ dev = pci_dev_g(p);
+ drv = pci_dev_driver(dev);
+ seq_printf(m, "%02x%02x\t%04x%04x\t%x",
X dev->bus->number,
X dev->devfn,
X dev->vendor,
X dev->device,
X dev->irq);
- /* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */
- for(i=0; i<7; i++)
- len += sprintf(buf+len, LONG_FORMAT,
- dev->resource[i].start | (dev->resource[i].flags & PCI_REGION_FLAG_MASK));
- for(i=0; i<7; i++)
- len += sprintf(buf+len, LONG_FORMAT, dev->resource[i].start < dev->resource[i].end ?
- dev->resource[i].end - dev->resource[i].start + 1 : 0);
- buf[len++] = '\t';
- if (drv)
- len += sprintf(buf+len, "%s", drv->name);
- buf[len++] = '\n';
- at += len;
- if (at >= pos) {
- if (!*start) {
- *start = buf + (pos - (at - len));
- cnt = at - pos;
- } else
- cnt += len;
- buf += len;
- if (cnt >= count)
- /*
- * proc_file_read() gives us 1KB of slack so it's OK if the
- * above printfs write a little beyond the buffer end (we
- * never write more than 1KB beyond the buffer end).
- */
- break;
- }
- }
- return (count > cnt) ? cnt : count;
+ /* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */
+ for(i=0; i<7; i++)
+ seq_printf(m, LONG_FORMAT,
+ dev->resource[i].start |
+ (dev->resource[i].flags & PCI_REGION_FLAG_MASK));
+ for(i=0; i<7; i++)
+ seq_printf(m, LONG_FORMAT,
+ dev->resource[i].start < dev->resource[i].end ?
+ dev->resource[i].end - dev->resource[i].start + 1 : 0);
+ seq_putc(m, '\t');
+ if (drv)
+ seq_printf(m, "%s", drv->name);
+ seq_putc(m, '\n');


+ return 0;
X }
X

+static struct seq_operations proc_bus_pci_devices_op = {
+ start: pci_seq_start,
+ next: pci_seq_next,
+ stop: pci_seq_stop,
+ show: show_device
+};
+
X static struct proc_dir_entry *proc_bus_pci_dir;
X
X int pci_proc_attach_device(struct pci_dev *dev)
@@ -386,6 +406,28 @@


X return 0;
X }
X

+int pci_proc_attach_bus(struct pci_bus* bus)
+{
+ struct proc_dir_entry *de = bus->procdir;
+
+ if (!de) {
+ char name[16];
+ sprintf(name, "%02x", bus->number);
+ de = bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
+ if (!de)
+ return -ENOMEM;


+ }
+ return 0;
+}
+

+int pci_proc_detach_bus(struct pci_bus* bus)
+{
+ struct proc_dir_entry *de = bus->procdir;
+ if (de)
+ remove_proc_entry(de->name, proc_bus_pci_dir);
+ return 0;
+}
+
X
X /*
X * Backward compatible /proc/pci interface.
@@ -397,54 +439,56 @@
X * The configuration string is stored starting at buf[len]. If the
X * string would exceed the size of the buffer (SIZE), 0 is returned.
X */
-static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
+static int show_dev_config(struct seq_file *m, void *v)
X {
+ struct list_head *p = v;
+ struct pci_dev *dev;
+ struct pci_driver *drv;
X u32 class_rev;
X unsigned char latency, min_gnt, max_lat, *class;
- int reg, len = 0;
+ int reg;
+
+ if (p == &pci_devices) {
+ seq_puts(m, "PCI devices found:\n");


+ return 0;
+ }
+

+ dev = pci_dev_g(p);
+ drv = pci_dev_driver(dev);
X
X pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
X pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
X pci_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
X pci_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
- if (len + 160 > size)
- return -1;
- len += sprintf(buf + len, " Bus %2d, device %3d, function %2d:\n",
- dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+ seq_printf(m, " Bus %2d, device %3d, function %2d:\n",
+ dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
X class = pci_class_name(class_rev >> 16);
X if (class)
- len += sprintf(buf+len, " %s", class);
+ seq_printf(m, " %s", class);
X else
- len += sprintf(buf+len, " Class %04x", class_rev >> 16);
- len += sprintf(buf+len, ": %s (rev %d).\n", dev->name, class_rev & 0xff);
+ seq_printf(m, " Class %04x", class_rev >> 16);
+ seq_printf(m, ": %s (rev %d).\n", dev->name, class_rev & 0xff);
X
- if (dev->irq) {
- if (len + 40 > size)
- return -1;
- len += sprintf(buf + len, " IRQ %d.\n", dev->irq);
- }
+ if (dev->irq)
+ seq_printf(m, " IRQ %d.\n", dev->irq);
X
X if (latency || min_gnt || max_lat) {
- if (len + 80 > size)
- return -1;
- len += sprintf(buf + len, " Master Capable. ");
+ seq_printf(m, " Master Capable. ");
X if (latency)
- len += sprintf(buf + len, "Latency=%d. ", latency);
+ seq_printf(m, "Latency=%d. ", latency);
X else
- len += sprintf(buf + len, "No bursts. ");
+ seq_puts(m, "No bursts. ");
X if (min_gnt)
- len += sprintf(buf + len, "Min Gnt=%d.", min_gnt);
+ seq_printf(m, "Min Gnt=%d.", min_gnt);
X if (max_lat)
- len += sprintf(buf + len, "Max Lat=%d.", max_lat);
- len += sprintf(buf + len, "\n");
+ seq_printf(m, "Max Lat=%d.", max_lat);
+ seq_putc(m, '\n');
X }
X
X for (reg = 0; reg < 6; reg++) {
X struct resource *res = dev->resource + reg;
X unsigned long base, end, flags;
X
- if (len + 40 > size)
- return -1;
X base = res->start;
X end = res->end;
X flags = res->flags;
@@ -452,9 +496,8 @@
X continue;
X
X if (flags & PCI_BASE_ADDRESS_SPACE_IO) {
- len += sprintf(buf + len,
- " I/O at 0x%lx [0x%lx].\n",
- base, end);
+ seq_printf(m, " I/O at 0x%lx [0x%lx].\n",
+ base, end);
X } else {
X const char *pref, *type = "unknown";
X
@@ -470,65 +513,58 @@
X case PCI_BASE_ADDRESS_MEM_TYPE_64:
X type = "64 bit"; break;
X }
- len += sprintf(buf + len,
- " %srefetchable %s memory at "
+ seq_printf(m, " %srefetchable %s memory at "
X "0x%lx [0x%lx].\n", pref, type,
X base,
X end);
X }
X }
-
- return len;


+ return 0;
X }
X

-/*
- * Return list of PCI devices as a character string for /proc/pci.
- * BUF is a buffer that is PAGE_SIZE bytes long.
- */
-static int pci_read_proc(char *buf, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int nprinted, len, begin = 0;
- struct pci_dev *dev;
-
- len = sprintf(buf, "PCI devices found:\n");
+static struct seq_operations proc_pci_op = {
+ start: pci_seq_start,
+ next: pci_seq_next,
+ stop: pci_seq_stop,
+ show: show_dev_config
+};
X
- *eof = 1;
- pci_for_each_dev(dev) {
- nprinted = sprint_dev_config(dev, buf + len, PAGE_SIZE - len);
- if (nprinted < 0) {
- *eof = 0;
- break;
- }
- len += nprinted;
- if (len+begin < off) {
- begin += len;
- len = 0;
- }
- if (len+begin >= off+count)
- break;
- }
- off -= begin;
- *start = buf + off;
- len -= off;
- if (len>count)
- len = count;
- if (len<0)
- len = 0;
- return len;
+static int proc_bus_pci_dev_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &proc_bus_pci_devices_op);
+}
+static struct file_operations proc_bus_pci_dev_operations = {
+ open: proc_bus_pci_dev_open,
+ read: seq_read,
+ llseek: seq_lseek,
+ release: seq_release,
+};
+static int proc_pci_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &proc_pci_op);
X }
+static struct file_operations proc_pci_operations = {
+ open: proc_pci_open,
+ read: seq_read,
+ llseek: seq_lseek,
+ release: seq_release,
+};
X
X static int __init pci_proc_init(void)
X {
X if (pci_present()) {
+ struct proc_dir_entry *entry;
X struct pci_dev *dev;
X proc_bus_pci_dir = proc_mkdir("pci", proc_bus);
- create_proc_info_entry("devices", 0, proc_bus_pci_dir,
- get_pci_dev_info);
+ entry = create_proc_entry("devices", 0, proc_bus_pci_dir);
+ if (entry)
+ entry->proc_fops = &proc_bus_pci_dev_operations;
X pci_for_each_dev(dev) {
X pci_proc_attach_device(dev);
X }
- create_proc_read_entry("pci", 0, NULL, pci_read_proc, NULL);
+ entry = create_proc_entry("pci", 0, NULL);
+ if (entry)
+ entry->proc_fops = &proc_pci_operations;


X }
X return 0;
X }

diff -u --recursive --new-file v2.4.14/linux/drivers/pci/quirks.c linux/drivers/pci/quirks.c
--- v2.4.14/linux/drivers/pci/quirks.c Mon Nov 5 15:55:31 2001
+++ linux/drivers/pci/quirks.c Sun Nov 11 10:09:33 2001
@@ -411,6 +411,48 @@
X pci_write_config_dword(dev, PCI_CB_LEGACY_MODE_BASE, 0);
X }
X
+/*
+ * The AMD io apic can hang the box when an apic irq is masked.
+ * We check all revs >= B0 (yet not in the pre production!) as the bug
+ * is currently marked NoFix
+ *
+ * We have multiple reports of hangs with this chipset that went away with
+ * noapic specified. For the moment we assume its the errata. We may be wrong
+ * of course. However the advice is demonstrably good even if so..
+ */
+
+static void __init quirk_amd_ioapic(struct pci_dev *dev)
+{
+ u8 rev;
+
+ pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+ if(rev >= 0x02)
+ {
+ printk(KERN_WARNING "I/O APIC: AMD Errata #22 may be present. In the event of instability try\n");
+ printk(KERN_WARNING " : booting with the \"noapic\" option.\n");
+ }
+}
+
+/*
+ * Following the PCI ordering rules is optional on the AMD762. I'm not
+ * sure what the designers were smoking but let's not inhale...
+ *
+ * To be fair to AMD, it follows the spec by default, its BIOS people
+ * who turn it off!
+ */
+
+static void __init quirk_amd_ordering(struct pci_dev *dev)
+{
+ u32 pcic;
+
+ pci_read_config_dword(dev, 0x42, &pcic);
+ if((pcic&2)==0)
+ {
+ pcic |= 2;
+ printk(KERN_WARNING "BIOS disabled PCI ordering compliance, so we enabled it again.\n");
+ pci_write_config_dword(dev, 0x42, pcic);
+ }
+}
X
X /*
X * The main table of quirks.
@@ -462,6 +504,9 @@
X { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irqpic },
X { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irqpic },
X { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_6, quirk_via_irqpic },
+
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic },
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering },
X
X { 0 }
X };
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/Config.in linux/drivers/pcmcia/Config.in
--- v2.4.14/linux/drivers/pcmcia/Config.in Mon Nov 5 15:55:31 2001
+++ linux/drivers/pcmcia/Config.in Fri Nov 9 14:03:11 2001
@@ -17,7 +17,7 @@
X if [ "$CONFIG_PCI" != "n" ]; then
X bool ' CardBus support' CONFIG_CARDBUS
X fi
- bool ' i82092 compatible bridge support' CONFIG_I82092
+ dep_bool ' i82092 compatible bridge support' CONFIG_I82092 $CONFIG_PCI
X bool ' i82365 compatible bridge support' CONFIG_I82365
X bool ' Databook TCIC host bridge support' CONFIG_TCIC
X if [ "$CONFIG_HD64465" = "y" ]; then
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/Makefile linux/drivers/pcmcia/Makefile
--- v2.4.14/linux/drivers/pcmcia/Makefile Mon Nov 5 15:55:31 2001
+++ linux/drivers/pcmcia/Makefile Mon Nov 12 09:39:01 2001


@@ -10,7 +10,7 @@
X

X O_TARGET := pcmcia.o
X
-export-objs := ds.o cs.o cb_enabler.o yenta.o pci_socket.o
+export-objs := ds.o cs.o yenta.o pci_socket.o
X
X list-multi := pcmcia_core.o yenta_socket.o
X
@@ -24,7 +24,7 @@
X ifeq ($(CONFIG_PCMCIA),y)
X obj-y := cistpl.o rsrc_mgr.o bulkmem.o ds.o cs.o
X ifeq ($(CONFIG_CARDBUS),y)
- obj-y += cardbus.o cb_enabler.o yenta.o pci_socket.o
+ obj-y += cardbus.o yenta.o pci_socket.o
X endif
X ifeq ($(CONFIG_I82365),y)
X obj-y += i82365.o
@@ -54,7 +54,7 @@
X obj-m += hd64465_ss.o
X endif
X ifeq ($(CONFIG_CARDBUS),y)
- obj-m += yenta_socket.o cb_enabler.o
+ obj-m += yenta_socket.o
X endif
X endif
X endif
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/cardbus.c linux/drivers/pcmcia/cardbus.c
--- v2.4.14/linux/drivers/pcmcia/cardbus.c Sat Mar 3 10:49:17 2001
+++ linux/drivers/pcmcia/cardbus.c Mon Nov 12 09:39:01 2001
@@ -66,7 +66,6 @@
X #include <pcmcia/bulkmem.h>
X #include <pcmcia/cistpl.h>
X #include "cs_internal.h"
-#include "rsrc_mgr.h"
X
X #ifdef PCMCIA_DEBUG
X static int pc_debug = PCMCIA_DEBUG;
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/cb_enabler.c linux/drivers/pcmcia/cb_enabler.c
--- v2.4.14/linux/drivers/pcmcia/cb_enabler.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/pcmcia/cb_enabler.c Wed Dec 31 16:00:00 1969
@@ -1,403 +0,0 @@
-/*======================================================================
-
- CardBus device enabler
-
- cb_enabler.c 1.31 2000/06/12 21:29:36
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dah...@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
-
- The general idea:
-
- A client driver registers using register_driver(). This module
- then creates a Card Services pseudo-client and registers it, and
- configures the socket if this is the first client. It then
- invokes the appropriate PCI client routines in response to Card
- Services events.
-
-======================================================================*/
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-
-#include <pcmcia/version.h>
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-


-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)

-static char *version =
-"cb_enabler.c 1.31 2000/06/12 21:29:36 (David Hinds)";
-#else
-#define DEBUG(n, args...) do { } while (0)
-#endif
-
-MODULE_AUTHOR("David Hinds <dah...@users.sourceforge.net>");
-MODULE_DESCRIPTION("CardBus stub enabler module");
-MODULE_LICENSE("Dual MPL/GPL");
-
-/*====================================================================*/
-


-/* Parameters that can be set with 'insmod' */

-
-/*====================================================================*/
-
-typedef struct driver_info_t {
- dev_link_t *(*attach)(void);
- dev_info_t dev_info;
- driver_operations *ops;
- dev_link_t *dev_list;
-} driver_info_t;
-
-static dev_link_t *cb_attach(int n);
-#define MK_ENTRY(fn, n) \
-static dev_link_t *fn(void) { return cb_attach(n); }
-
-#define MAX_DRIVER 4
-
-MK_ENTRY(attach_0, 0);
-MK_ENTRY(attach_1, 1);
-MK_ENTRY(attach_2, 2);
-MK_ENTRY(attach_3, 3);
-
-static driver_info_t driver[4] = {
- { attach_0 }, { attach_1 }, { attach_2 }, { attach_3 }
-};
-
-typedef struct bus_info_t {
- u_char bus;
- int flags, ncfg, nuse;
- dev_link_t *owner;
-} bus_info_t;
-
-#define DID_REQUEST 1
-#define DID_CONFIG 2
-
-static void cb_release(u_long arg);
-static int cb_event(event_t event, int priority,
- event_callback_args_t *args);
-
-static void cb_detach(dev_link_t *);
-
-static bus_info_t bus_table[MAX_DRIVER];
-
-/*====================================================================*/
-
-static void cs_error(client_handle_t handle, int func, int ret)
-{
- error_info_t err = { func, ret };
- pcmcia_report_error(handle, &err);
-}
-
-/*====================================================================*/
-
-struct dev_link_t *cb_attach(int n)
-{
- client_reg_t client_reg;
- dev_link_t *link;
- int ret;
-
- DEBUG(0, "cb_attach(%d)\n", n);
-
- link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link) return NULL;
-
- MOD_INC_USE_COUNT;
- memset(link, 0, sizeof(struct dev_link_t));
- link->conf.IntType = INT_CARDBUS;
- link->conf.Vcc = 33;
-
- /* Insert into instance chain for this driver */
- link->priv = &driver[n];
- link->next = driver[n].dev_list;
- driver[n].dev_list = link;
-
- /* Register with Card Services */
- client_reg.dev_info = &driver[n].dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
- client_reg.event_handler = &cb_event;
- client_reg.EventMask = CS_EVENT_RESET_PHYSICAL |
- CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
- CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
- CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
- client_reg.Version = 0x0210;
- client_reg.event_callback_args.client_data = link;
- ret = pcmcia_register_client(&link->handle, &client_reg);


- if (ret != 0) {

- cs_error(link->handle, RegisterClient, ret);
- cb_detach(link);
- return NULL;
- }
- return link;
-}
-
-/*====================================================================*/
-
-static void cb_detach(dev_link_t *link)
-{
- driver_info_t *dev = link->priv;
- dev_link_t **linkp;
- bus_info_t *b = (void *)link->win;
-
- DEBUG(0, "cb_detach(0x%p)\n", link);
-
- /* Locate device structure */
- for (linkp = &dev->dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
-
- if (link->state & DEV_CONFIG)
- cb_release((u_long)link);
-
- /* Don't drop Card Services connection if we are the bus owner */
- if (b && (b->flags != 0) && (link == b->owner)) {
- link->state |= DEV_STALE_LINK;
- return;
- }
-
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- *linkp = link->next;
- kfree(link);
- MOD_DEC_USE_COUNT;
-}
-
-/*====================================================================*/
-
-static void cb_config(dev_link_t *link)
-{
- client_handle_t handle = link->handle;
- driver_info_t *drv = link->priv;
- dev_locator_t loc;
- bus_info_t *b;
- config_info_t config;
- u_char bus, devfn;
- int i;
-
- DEBUG(0, "cb_config(0x%p)\n", link);
- link->state |= DEV_CONFIG;
-
- /* Get PCI bus info */
- pcmcia_get_configuration_info(handle, &config);
- bus = config.Option; devfn = config.Function;
-
- /* Is this a new bus? */
- for (i = 0; i < MAX_DRIVER; i++)
- if (bus == bus_table[i].bus) break;
- if (i == MAX_DRIVER) {
- for (i = 0; i < MAX_DRIVER; i++)
- if (bus_table[i].bus == 0) break;
- b = &bus_table[i]; link->win = (void *)b;
- b->bus = bus;
- b->flags = 0;
- b->ncfg = b->nuse = 1;
-
- /* Special hook: CS know what to do... */
- i = pcmcia_request_io(handle, NULL);
- if (i != CS_SUCCESS) {
- cs_error(handle, RequestIO, i);
- return;
- }
- b->flags |= DID_REQUEST;
- b->owner = link;
- i = pcmcia_request_configuration(handle, &link->conf);
- if (i != CS_SUCCESS) {
- cs_error(handle, RequestConfiguration, i);
- return;
- }
- b->flags |= DID_CONFIG;
- } else {
- b = &bus_table[i]; link->win = (void *)b;
- if (b->flags & DID_CONFIG) {
- b->ncfg++; b->nuse++;
- }
- }
- loc.bus = LOC_PCI;
- loc.b.pci.bus = bus;
- loc.b.pci.devfn = devfn;
- link->dev = drv->ops->attach(&loc);
-
- link->state &= ~DEV_CONFIG_PENDING;
-}
-
-/*====================================================================*/
-
-static void cb_release(u_long arg)
-{
- dev_link_t *link = (dev_link_t *)arg;
- driver_info_t *drv = link->priv;
- bus_info_t *b = (void *)link->win;
-
- DEBUG(0, "cb_release(0x%p)\n", link);
-
- if (link->dev != NULL) {
- drv->ops->detach(link->dev);
- link->dev = NULL;
- }
- if (link->state & DEV_CONFIG) {
- /* If we're suspended, config was already released */
- if (link->state & DEV_SUSPEND)
- b->flags &= ~DID_CONFIG;
- else if ((b->flags & DID_CONFIG) && (--b->ncfg == 0)) {
- pcmcia_release_configuration(b->owner->handle);
- b->flags &= ~DID_CONFIG;
- }
- if ((b->flags & DID_REQUEST) && (--b->nuse == 0)) {
- pcmcia_release_io(b->owner->handle, NULL);
- b->flags &= ~DID_REQUEST;
- }
- if (b->flags == 0) {
- if (b->owner && (b->owner->state & DEV_STALE_LINK))
- cb_detach(b->owner);
- b->bus = 0; b->owner = NULL;
- }
- }
- link->state &= ~DEV_CONFIG;
-}
-
-/*====================================================================*/
-
-static int cb_event(event_t event, int priority,
- event_callback_args_t *args)
-{
- dev_link_t *link = args->client_data;
- driver_info_t *drv = link->priv;
- bus_info_t *b = (void *)link->win;
-
- DEBUG(0, "cb_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- cb_release((u_long)link);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- cb_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG) {
- if (drv->ops->suspend != NULL)
- drv->ops->suspend(link->dev);
- b->ncfg--;
- if (b->ncfg == 0)
- pcmcia_release_configuration(link->handle);
- }
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (link->state & DEV_CONFIG) {
- b->ncfg++;
- if (b->ncfg == 1)
- pcmcia_request_configuration(link->handle,
- &link->conf);
- if (drv->ops->resume != NULL)
- drv->ops->resume(link->dev);
- }
- break;


- }
- return 0;
-}

-
-/*====================================================================*/
-
-int register_driver(struct driver_operations *ops)


-{
- int i;
-

- DEBUG(0, "register_driver('%s')\n", ops->name);
-
- for (i = 0; i < MAX_DRIVER; i++)
- if (driver[i].ops == NULL) break;
- if (i == MAX_DRIVER)
- return -1;
-
- MOD_INC_USE_COUNT;
- driver[i].ops = ops;
- strcpy(driver[i].dev_info, ops->name);
- register_pccard_driver(&driver[i].dev_info, driver[i].attach,
- &cb_detach);


- return 0;
-}
-

-void unregister_driver(struct driver_operations *ops)


-{
- int i;
-

- DEBUG(0, "unregister_driver('%s')\n", ops->name);
- for (i = 0; i < MAX_DRIVER; i++)
- if (driver[i].ops == ops) break;
- if (i < MAX_DRIVER) {
- unregister_pccard_driver(&driver[i].dev_info);
- driver[i].ops = NULL;
- MOD_DEC_USE_COUNT;
- }
-}
-
-/*====================================================================*/
-
-EXPORT_SYMBOL(register_driver);
-EXPORT_SYMBOL(unregister_driver);
-
-static int __init init_cb_enabler(void)
-{
- servinfo_t serv;
- DEBUG(0, "%s\n", version);
- pcmcia_get_card_services_info(&serv);
- if (serv.Revision != CS_RELEASE_CODE) {
- printk(KERN_NOTICE "cb_enabler: Card Services release "
- "does not match!\n");
- return -1;


- }
- return 0;
-}

-
-static void __exit exit_cb_enabler(void)
-{
- DEBUG(0, "cb_enabler: unloading\n");
-}
-
-module_init(init_cb_enabler);
-module_exit(exit_cb_enabler);
-
-/*====================================================================*/
-
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/cistpl.c linux/drivers/pcmcia/cistpl.c
--- v2.4.14/linux/drivers/pcmcia/cistpl.c Fri Feb 16 16:02:36 2001
+++ linux/drivers/pcmcia/cistpl.c Mon Nov 12 09:39:01 2001


@@ -2,7 +2,7 @@
X

X PCMCIA Card Information Structure parser
X
- cistpl.c 1.91 2000/09/16 03:48:28
+ cistpl.c 1.97 2001/10/04 03:33:49
X
X The contents of this file are subject to the Mozilla Public
X License Version 1.1 (the "License"); you may not use this file
@@ -19,8 +19,8 @@
X are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
X
X Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
+ terms of the GNU General Public License version 2 (the "GPL"), in
+ which case the provisions of the GPL are applicable instead of the
X above. If you wish to allow the use of your version of this file
X only under the terms of the GPL and not to allow others to use
X your version of this file under the MPL, indicate your decision
@@ -46,6 +46,7 @@
X #include <linux/pci.h>
X #include <linux/ioport.h>
X #include <asm/io.h>
+#include <asm/byteorder.h>
X
X #include <pcmcia/cs_types.h>
X #include <pcmcia/bus_ops.h>
@@ -55,7 +56,6 @@
X #include <pcmcia/cisreg.h>
X #include <pcmcia/cistpl.h>
X #include "cs_internal.h"
-#include "rsrc_mgr.h"
X
X static const u_char mantissa[] = {
X 10, 12, 13, 15, 20, 25, 30, 35,
@@ -644,8 +644,6 @@
X case 4: device->dev[i].speed = 100; break;
X case 7:
X if (++p == q) return CS_BAD_TUPLE;
- if (p == q)
- return CS_BAD_TUPLE;
X device->dev[i].speed = SPEED_CVT(*p);
X while (*p & 0x80)
X if (++p == q) return CS_BAD_TUPLE;
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- v2.4.14/linux/drivers/pcmcia/cs.c Tue Oct 23 22:48:51 2001
+++ linux/drivers/pcmcia/cs.c Mon Nov 12 09:48:43 2001
@@ -60,14 +60,6 @@
X #include <pcmcia/cisreg.h>
X #include <pcmcia/bus_ops.h>
X #include "cs_internal.h"
-#include "rsrc_mgr.h"
-
-#ifdef PCMCIA_DEBUG
-int pc_debug = PCMCIA_DEBUG;


-MODULE_PARM(pc_debug, "i");
-static const char *version =

-"cs.c 1.271 2000/10/02 20:27:49 (David Hinds)";
-#endif
X
X #ifdef CONFIG_PCI
X #define PCI_OPT " [pci]"
@@ -93,15 +85,15 @@
X static const char *release = "Linux Kernel Card Services " CS_RELEASE;
X static const char *options = "options: " OPTIONS;
X

+/*====================================================================*/
+
+/* Module parameters */
+

X MODULE_AUTHOR("David Hinds <dah...@users.sourceforge.net>");
X MODULE_DESCRIPTION("Linux Kernel Card Services " CS_RELEASE
X "\n options:" OPTIONS);
X MODULE_LICENSE("Dual MPL/GPL");
X
-/*====================================================================*/
-


-/* Parameters that can be set with 'insmod' */

-


X #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
X

X INT_MODULE_PARM(setup_delay, 10); /* centiseconds */
@@ -126,6 +118,12 @@
X INT_MODULE_PARM(do_apm, 0);
X #endif
X

+#ifdef PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+static const char *version =

+"cs.c 1.279 2001/10/13 00:08:28 (David Hinds)";
+#endif
+
X /*====================================================================*/
X
X socket_state_t dead_socket = {
@@ -472,6 +470,15 @@
X kfree(s->fake_cis);
X s->fake_cis = NULL;
X }
+ /* Should not the socket be forced quiet as well? e.g. turn off Vcc */
+ /* Without these changes, the socket is left hot, even though card-services */
+ /* realizes that no card is in place. */
+ s->socket.flags &= ~SS_OUTPUT_ENA;
+ s->socket.Vpp = 0;
+ s->socket.Vcc = 0;
+ s->socket.io_irq = 0;
+ set_socket(s, &s->socket);
+ /* */
X #ifdef CONFIG_CARDBUS
X cb_release_cis_mem(s);
X cb_free(s);
@@ -622,7 +629,7 @@
X
X The central event handler. Send_event() sends an event to all
X valid clients. Parse_events() interprets the event bits from
- a card status change report. Do_shotdown() handles the high
+ a card status change report. Do_shutdown() handles the high
X priority stuff associated with a card removal.
X
X ======================================================================*/
@@ -1508,7 +1515,7 @@
X if (!(handle->state & CLIENT_STALE)) {
X config_t *c = CONFIG(handle);
X if (--(s->lock_count) == 0) {
- s->socket.flags = SS_OUTPUT_ENA;
+ s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
X s->socket.Vpp = 0;
X s->socket.io_irq = 0;
X set_socket(s, &s->socket);
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- v2.4.14/linux/drivers/pcmcia/ds.c Mon Nov 5 15:55:31 2001
+++ linux/drivers/pcmcia/ds.c Mon Nov 12 09:39:01 2001


@@ -2,7 +2,7 @@
X

X PC Card Driver Services
X
- ds.c 1.108 2000/08/07 19:06:15
+ ds.c 1.112 2001/10/13 00:08:28
X
X The contents of this file are subject to the Mozilla Public
X License Version 1.1 (the "License"); you may not use this file
@@ -19,8 +19,8 @@
X are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
X
X Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
+ terms of the GNU General Public License version 2 (the "GPL"), in
+ which case the provisions of the GPL are applicable instead of the
X above. If you wish to allow the use of your version of this file
X only under the terms of the GPL and not to allow others to use
X your version of this file under the MPL, indicate your decision
@@ -56,20 +56,24 @@
X #include <pcmcia/cistpl.h>
X #include <pcmcia/ds.h>
X

+/*====================================================================*/
+
+/* Module parameters */

+
+MODULE_AUTHOR("David Hinds <dah...@users.sourceforge.net>");

+MODULE_DESCRIPTION("PCMCIA Driver Services " CS_RELEASE);
+MODULE_LICENSE("Dual MPL/GPL");


+
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")

+
X #ifdef PCMCIA_DEBUG
-int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);


X #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)

X static const char *version =
-"ds.c 1.108 2000/08/07 19:06:15 (David Hinds)";
+"ds.c 1.112 2001/10/13 00:08:28 (David Hinds)";


X #else
X #define DEBUG(n, args...)
X #endif

-
-MODULE_AUTHOR("David Hinds <dah...@users.sourceforge.net>");
-MODULE_DESCRIPTION("PCMCIA Driver Services " CS_RELEASE);
-MODULE_LICENSE("Dual MPL/GPL");
-
X
X /*====================================================================*/
X
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/i82092.c linux/drivers/pcmcia/i82092.c
--- v2.4.14/linux/drivers/pcmcia/i82092.c Mon Nov 5 15:55:31 2001
+++ linux/drivers/pcmcia/i82092.c Fri Nov 9 13:45:35 2001
@@ -795,7 +795,7 @@
X mem->card_start = ( (unsigned long)(i & 0x3fff)<12) + mem->sys_start;
X mem->card_start &= 0x3ffffff;
X
- printk("Card %i is from %x to %x \n",sock,mem->sys_start,mem->sys_stop);
+ printk("Card %i is from %lx to %lx \n",sock,mem->sys_start,mem->sys_stop);
X
X leave("i82092aa_get_mem_map");
X return 0;
@@ -819,7 +819,7 @@
X if ( (mem->card_start > 0x3ffffff) || (mem->sys_start > mem->sys_stop) ||
X (mem->speed > 1000) ) {
X leave("i82092aa_set_mem_map: invalid address / speed");
- printk("invalid mem map for socket %i : %x to %x with a start of %x \n",sock,mem->sys_start, mem->sys_stop, mem->card_start);
+ printk("invalid mem map for socket %i : %lx to %lx with a start of %x \n",sock,mem->sys_start, mem->sys_stop, mem->card_start);


X return -EINVAL;
X }
X

@@ -895,7 +895,6 @@
X
X static void i82092aa_module_exit(void)
X {
- int i;
X enter("i82092aa_module_exit");
X pci_unregister_driver(&i82092aa_pci_drv);
X unregister_ss_entry(&i82092aa_operations);
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/i82365.c linux/drivers/pcmcia/i82365.c
--- v2.4.14/linux/drivers/pcmcia/i82365.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/pcmcia/i82365.c Mon Nov 12 09:39:01 2001
@@ -66,11 +66,6 @@
X #include "ricoh.h"
X #include "o2micro.h"
X
-/* PCI-bus controllers */
-#include "old-yenta.h"
-#include "smc34c90.h"
-#include "topic.h"
-
X #ifdef PCMCIA_DEBUG
X static int pc_debug = PCMCIA_DEBUG;
X MODULE_PARM(pc_debug, "i");
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/old-yenta.h linux/drivers/pcmcia/old-yenta.h
--- v2.4.14/linux/drivers/pcmcia/old-yenta.h Fri Feb 16 16:02:36 2001
+++ linux/drivers/pcmcia/old-yenta.h Wed Dec 31 16:00:00 1969
@@ -1,153 +0,0 @@
-/*
- * yenta.h 1.16 1999/10/25 20:03:34
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
- *
- * The initial developer of the original code is David A. Hinds
- * <dhi...@pcmcia.sourceforge.org>. Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL. If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the MPL or the GPL.
- */
-
-#ifndef _LINUX_YENTA_H
-#define _LINUX_YENTA_H
-
-/* PCI Configuration Registers */
-
-#define PCI_STATUS_CAPLIST 0x10
-#define PCI_CB_CAPABILITY_POINTER 0x14 /* 8 bit */
-#define PCI_CAPABILITY_ID 0x00 /* 8 bit */
-#define PCI_CAPABILITY_PM 0x01
-#define PCI_NEXT_CAPABILITY 0x01 /* 8 bit */
-#define PCI_PM_CAPABILITIES 0x02 /* 16 bit */
-#define PCI_PMCAP_PME_D3COLD 0x8000
-#define PCI_PMCAP_PME_D3HOT 0x4000
-#define PCI_PMCAP_PME_D2 0x2000
-#define PCI_PMCAP_PME_D1 0x1000
-#define PCI_PMCAP_PME_D0 0x0800
-#define PCI_PMCAP_D2_CAP 0x0400
-#define PCI_PMCAP_D1_CAP 0x0200
-#define PCI_PMCAP_DYN_DATA 0x0100
-#define PCI_PMCAP_DSI 0x0020
-#define PCI_PMCAP_AUX_PWR 0x0010
-#define PCI_PMCAP_PMECLK 0x0008
-#define PCI_PMCAP_VERSION_MASK 0x0007
-#define PCI_PM_CONTROL_STATUS 0x04 /* 16 bit */
-#define PCI_PMCS_PME_STATUS 0x8000
-#define PCI_PMCS_DATASCALE_MASK 0x6000
-#define PCI_PMCS_DATASCALE_SHIFT 13
-#define PCI_PMCS_DATASEL_MASK 0x1e00
-#define PCI_PMCS_DATASEL_SHIFT 9
-#define PCI_PMCS_PME_ENABLE 0x0100
-#define PCI_PMCS_PWR_STATE_MASK 0x0003
-#define PCI_PMCS_PWR_STATE_D0 0x0000
-#define PCI_PMCS_PWR_STATE_D1 0x0001
-#define PCI_PMCS_PWR_STATE_D2 0x0002
-#define PCI_PMCS_PWR_STATE_D3 0x0003
-#define PCI_PM_BRIDGE_EXT 0x06 /* 8 bit */
-#define PCI_PM_DATA 0x07 /* 8 bit */
-
-#define CB_PRIMARY_BUS 0x18 /* 8 bit */
-#define CB_CARDBUS_BUS 0x19 /* 8 bit */
-#define CB_SUBORD_BUS 0x1a /* 8 bit */
-#define CB_LATENCY_TIMER 0x1b /* 8 bit */
-
-#define CB_MEM_BASE(m) (0x1c + 8*(m))
-#define CB_MEM_LIMIT(m) (0x20 + 8*(m))
-#define CB_IO_BASE(m) (0x2c + 8*(m))
-#define CB_IO_LIMIT(m) (0x30 + 8*(m))
-
-#define CB_BRIDGE_CONTROL 0x3e /* 16 bit */
-#define CB_BCR_PARITY_ENA 0x0001
-#define CB_BCR_SERR_ENA 0x0002
-#define CB_BCR_ISA_ENA 0x0004
-#define CB_BCR_VGA_ENA 0x0008
-#define CB_BCR_MABORT 0x0020
-#define CB_BCR_CB_RESET 0x0040
-#define CB_BCR_ISA_IRQ 0x0080
-#define CB_BCR_PREFETCH(m) (0x0100 << (m))
-#define CB_BCR_WRITE_POST 0x0400
-
-#define CB_LEGACY_MODE_BASE 0x44
-
-/* Memory mapped registers */
-
-#define CB_SOCKET_EVENT 0x0000
-#define CB_SE_CSTSCHG 0x00000001
-#define CB_SE_CCD1 0x00000002
-#define CB_SE_CCD2 0x00000004
-#define CB_SE_PWRCYCLE 0x00000008
-
-#define CB_SOCKET_MASK 0x0004
-#define CB_SM_CSTSCHG 0x00000001
-#define CB_SM_CCD 0x00000006
-#define CB_SM_PWRCYCLE 0x00000008
-
-#define CB_SOCKET_STATE 0x0008
-#define CB_SS_CSTSCHG 0x00000001
-#define CB_SS_CCD1 0x00000002
-#define CB_SS_CCD2 0x00000004
-#define CB_SS_PWRCYCLE 0x00000008
-#define CB_SS_16BIT 0x00000010
-#define CB_SS_32BIT 0x00000020
-#define CB_SS_CINT 0x00000040
-#define CB_SS_BADCARD 0x00000080
-#define CB_SS_DATALOST 0x00000100
-#define CB_SS_BADVCC 0x00000200
-#define CB_SS_5VCARD 0x00000400
-#define CB_SS_3VCARD 0x00000800
-#define CB_SS_XVCARD 0x00001000
-#define CB_SS_YVCARD 0x00002000
-#define CB_SS_5VSOCKET 0x10000000
-#define CB_SS_3VSOCKET 0x20000000
-#define CB_SS_XVSOCKET 0x40000000
-#define CB_SS_YVSOCKET 0x80000000
-
-#define CB_SOCKET_FORCE 0x000c
-#define CB_SF_CVSTEST 0x00004000
-
-#define CB_SOCKET_CONTROL 0x0010
-#define CB_SC_VPP_MASK 0x00000007
-#define CB_SC_VPP_OFF 0x00000000
-#define CB_SC_VPP_12V 0x00000001
-#define CB_SC_VPP_5V 0x00000002
-#define CB_SC_VPP_3V 0x00000003
-#define CB_SC_VPP_XV 0x00000004
-#define CB_SC_VPP_YV 0x00000005
-#define CB_SC_VCC_MASK 0x00000070
-#define CB_SC_VCC_OFF 0x00000000
-#define CB_SC_VCC_5V 0x00000020
-#define CB_SC_VCC_3V 0x00000030
-#define CB_SC_VCC_XV 0x00000040
-#define CB_SC_VCC_YV 0x00000050
-#define CB_SC_CCLK_STOP 0x00000080
-
-#define CB_SOCKET_POWER 0x0020
-#define CB_SP_CLK_CTRL 0x00000001
-#define CB_SP_CLK_CTRL_ENA 0x00010000
-#define CB_SP_CLK_MODE 0x01000000
-#define CB_SP_ACCESS 0x02000000
-
-/* Address bits 31..24 for memory windows for 16-bit cards,
- accessable only by memory mapping the 16-bit register set */
-#define CB_MEM_PAGE(map) (0x40 + (map))
-
-#endif /* _LINUX_YENTA_H */
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/pci_socket.c linux/drivers/pcmcia/pci_socket.c
--- v2.4.14/linux/drivers/pcmcia/pci_socket.c Tue Jul 3 17:08:20 2001
+++ linux/drivers/pcmcia/pci_socket.c Fri Nov 9 13:41:42 2001
@@ -177,13 +177,13 @@
X memset(socket, 0, sizeof(*socket));
X socket->dev = dev;
X socket->op = ops;
- dev->driver_data = socket;
+ pci_set_drvdata(dev, socket);
X spin_lock_init(&socket->event_lock);
X err = socket->op->open(socket);
X if(err)
X {
X socket->dev = NULL;
- dev->driver_data = NULL;
+ pci_set_drvdata(dev, NULL);


X }
X return err;
X }

@@ -210,24 +210,24 @@
X
X static void __devexit cardbus_remove (struct pci_dev *dev)
X {
- pci_socket_t *socket = (pci_socket_t *) dev->driver_data;
+ pci_socket_t *socket = pci_get_drvdata(dev);
X
X pcmcia_unregister_socket (socket->pcmcia_socket);
X if (socket->op && socket->op->close)
X socket->op->close(socket);
- dev->driver_data = 0;
+ pci_set_drvdata(dev, NULL);
X }
X
X static int cardbus_suspend (struct pci_dev *dev, u32 state)
X {
- pci_socket_t *socket = (pci_socket_t *) dev->driver_data;
+ pci_socket_t *socket = pci_get_drvdata(dev);
X pcmcia_suspend_socket (socket->pcmcia_socket);


X return 0;
X }
X

X static int cardbus_resume (struct pci_dev *dev)
X {
- pci_socket_t *socket = (pci_socket_t *) dev->driver_data;
+ pci_socket_t *socket = pci_get_drvdata(dev);
X pcmcia_resume_socket (socket->pcmcia_socket);
X return 0;
X }
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/rsrc_mgr.c linux/drivers/pcmcia/rsrc_mgr.c
--- v2.4.14/linux/drivers/pcmcia/rsrc_mgr.c Wed Jul 25 17:10:22 2001
+++ linux/drivers/pcmcia/rsrc_mgr.c Mon Nov 12 09:39:01 2001
@@ -53,7 +53,6 @@
X #include <pcmcia/bulkmem.h>
X #include <pcmcia/cistpl.h>
X #include "cs_internal.h"
-#include "rsrc_mgr.h"
X
X /*====================================================================*/
X
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/rsrc_mgr.h linux/drivers/pcmcia/rsrc_mgr.h
--- v2.4.14/linux/drivers/pcmcia/rsrc_mgr.h Fri Feb 16 16:02:36 2001
+++ linux/drivers/pcmcia/rsrc_mgr.h Wed Dec 31 16:00:00 1969
@@ -1,33 +0,0 @@
-/*
- * rsrc_mgr.h 1.20 2000/06/12 21:29:37
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
- *
- * The initial developer of the original code is David A. Hinds


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

echo 'End of part 056'
echo 'File patch-2.4.15 is continued in part 057'
echo "057" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:28 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part052

#!/bin/sh -x
# this is part 052 of a 115 - part archive


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

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

+ retval = -ENOMEM;


+ goto exit;
+ }
+

X memset(dev->priv, 0, sizeof(struct eepro_local));
X
X lp = (struct eepro_local *)dev->priv;
X
+ /* default values */
+ lp->eepro = 0;
+ lp->xmt_bar = XMT_BAR_PRO;
+ lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO;
+ lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO;
+ lp->eeprom_reg = EEPROM_REG_PRO;
+
X /* Now, get the ethernet hardware address from
X the EEPROM */
-
X station_addr[0] = read_eeprom(ioaddr, 2, dev);
X
X /* FIXME - find another way to know that we've found
@@ -693,81 +768,47 @@
X */
X if (station_addr[0] == 0x0000 ||
X station_addr[0] == 0xffff) {
- eepro = 3;
X lp->eepro = LAN595FX_10ISA;
- eeprom_reg = EEPROM_REG_10;
- rcv_start = RCV_START_10;
- xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10;
- xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10;
-
+ lp->eeprom_reg = EEPROM_REG_10;
+ lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10;
+ lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10;
+ lp->xmt_bar = XMT_BAR_10;
X station_addr[0] = read_eeprom(ioaddr, 2, dev);
X }
-
X station_addr[1] = read_eeprom(ioaddr, 3, dev);
X station_addr[2] = read_eeprom(ioaddr, 4, dev);
X
- if (eepro) {
- printk("%s: Intel EtherExpress 10 ISA\n at %#x,",
- dev->name, ioaddr);
- } else if (read_eeprom(ioaddr,7,dev)== ee_FX_INT2IRQ) {
- /* int to IRQ Mask */
- eepro = 2;
- printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,",
- dev->name, ioaddr);
- } else
- if (station_addr[2] == 0x00aa) {
- eepro = 1;
- printk("%s: Intel EtherExpress Pro/10 ISA at %#x,",
- dev->name, ioaddr);
- }
- else {
- eepro = 0;
- printk("%s: Intel 82595-based lan card at %#x,",
- dev->name, ioaddr);
+ if (!lp->eepro) {
+ if (read_eeprom(ioaddr,7,dev)== ee_FX_INT2IRQ)
+ lp->eepro = 2;
+ else if (station_addr[2] == SA_ADDR1)
+ lp->eepro = 1;
X }
X
X /* Fill in the 'dev' fields. */


X dev->base_addr = ioaddr;

-
- for (i=0; i < 6; i++) {


+
+ for (i=0; i < 6; i++)

X dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i];
- printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
- }
-
- dev->mem_start = (RCV_LOWER_LIMIT << 8);
-
- if ((dev->mem_end & 0x3f) < 3 || /* RX buffer must be more than 3K */
- (dev->mem_end & 0x3f) > 29) /* and less than 29K */
- dev->mem_end = (RCV_UPPER_LIMIT << 8);
- else {
- dev->mem_end = (dev->mem_end * 1024) +
- (RCV_LOWER_LIMIT << 8);
- rcv_ram = dev->mem_end - (RCV_LOWER_LIMIT << 8);
- }
X
- /* From now on, dev->mem_end - dev->mem_start contains
- * the actual size of rx buffer
- */
-
- if (net_debug > 3)
- printk(", %dK RCV buffer", (int)(dev->mem_end -
- dev->mem_start)/1024);
-
-
- /* ............... */
+ /* RX buffer must be more than 3K and less than 29K */
+ if (dev->mem_end < 3072 || dev->mem_end > 29696)
+ lp->rcv_ram = RCV_DEFAULT_RAM;
X
- if (GetBit( read_eeprom(ioaddr, 5, dev),ee_BNC_TPE))
- dev->if_port = BNC;
- else dev->if_port = TPE;
+ /* calculate {xmt,rcv}_{lower,upper}_limit */
+ eepro_recalc(dev);
X
- /* ............... */
X
+ if (GetBit( read_eeprom(ioaddr, 5, dev),ee_BNC_TPE))
+ dev->if_port = BNC;
+ else
+ dev->if_port = TPE;
X
- if ((dev->irq < 2) && (eepro!=0)) {
+ if ((dev->irq < 2) && (lp->eepro!=0)) {
X i = read_eeprom(ioaddr, 1, dev);
X irqMask = read_eeprom(ioaddr, 7, dev);
X i &= 0x07; /* Mask off INT number */
-
+
X for (j=0; ((j<16) && (i>=0)); j++) {
X if ((irqMask & (1<<j))!=0) {
X if (i==0) {
@@ -778,34 +819,14 @@
X }
X }
X if (dev->irq < 2) {
- printk(" Duh! illegal interrupt vector stored in EEPROM.\n");
+ printk(KERN_ERR " Duh! illegal interrupt vector stored in EEPROM.\n");
X kfree(dev->priv);
- return -ENODEV;
- } else
-
- if (dev->irq==2)
- dev->irq = 9;
- }
-
- if (dev->irq > 2) {
- printk(", IRQ %d, %s.\n", dev->irq,
- ifmap[dev->if_port]);
- }
- else printk(", %s.\n", ifmap[dev->if_port]);
-
- if ((dev->mem_start & 0xf) > 0) /* I don't know if this is */
- net_debug = dev->mem_start & 7; /* still useful or not */
-
- if (net_debug > 3) {
- i = read_eeprom(ioaddr, 5, dev);
- if (i & 0x2000) /* bit 13 of EEPROM word 5 */
- printk(KERN_DEBUG "%s: Concurrent Processing is enabled but not used!\n",
- dev->name);
+ retval = -ENODEV;
+ goto freeall;
+ } else
+ if (dev->irq==2) dev->irq = 9;
X }
X
- if (net_debug)
- printk(version);
-
X /* Grab the region so we can find another board if autoIRQ fails. */
X request_region(ioaddr, EEPRO_IO_EXTENT, dev->name);
X
@@ -821,23 +842,20 @@
X
X /* Fill in the fields of the device structure with
X ethernet generic values */
-
X ether_setup(dev);
X
- /* Check the station address for the manufacturer's code */
- if (net_debug>3)
- printEEPROMInfo(ioaddr, dev);
+ /* print boot time info */
+ eepro_print_info(dev);
X
- /* RESET the 82595 */
+ /* reset 82595 */
X eepro_reset(ioaddr);
X
- return 0;
- }
- else return -ENODEV;
- }
- else if (net_debug > 3)
- printk ("EtherExpress Pro probed failed!\n");
- return -ENODEV;
+exit:
+ return retval;
+freeall:
+ kfree(dev->priv);


+ goto exit;
+
X }
X

X /* Open/initialize the board. This is called (in the current kernel)
@@ -854,15 +872,15 @@
X {
X int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12, 0 };
X int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr;
-
+
X eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */
X
X /* Enable the interrupt line. */
X eepro_en_intline(ioaddr);
-
+
X /* be CAREFUL, BANK 0 now */
X eepro_sw2bank0(ioaddr);
-
+
X /* clear all interrupts */
X eepro_clear_int(ioaddr);
X
@@ -877,12 +895,12 @@
X
X eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
X
- if (request_irq (*irqp, NULL, 0, "bogus", dev) != EBUSY) {
+ if (request_irq (*irqp, NULL, SA_SHIRQ, "bogus", dev) != EBUSY) {
X /* Twinkle the interrupt, and check if it's seen */
X autoirq_setup(0);
X
X eepro_diag(ioaddr); /* RESET the 82595 */
-
+
X if (*irqp == autoirq_report(2)) /* It's a good IRQ line */
X break;
X
@@ -920,38 +938,38 @@
X irqMask = read_eeprom(ioaddr,7,dev);
X
X if (lp->eepro == LAN595FX_10ISA) {
- if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 3;\n");
+ if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 3;\n");
X }
X else if (irqMask == ee_FX_INT2IRQ) /* INT to IRQ Mask */
X {
X lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */
- if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n");
+ if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n");
X }
X
X else if ((dev->dev_addr[0] == SA_ADDR0 &&
X dev->dev_addr[1] == SA_ADDR1 &&
X dev->dev_addr[2] == SA_ADDR2))
- {
+ {
X lp->eepro = 1;
- if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 1;\n");
+ if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 1;\n");
X } /* Yes, an Intel EtherExpress Pro/10 */
X
X else lp->eepro = 0; /* No, it is a generic 82585 lan card */
X
- /* Get the interrupt vector for the 82595 */
+ /* Get the interrupt vector for the 82595 */
X if (dev->irq < 2 && eepro_grab_irq(dev) == 0) {
- printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
+ printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
X return -EAGAIN;
X }
-
+
X if (request_irq(dev->irq , &eepro_interrupt, 0, dev->name, dev)) {
- printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
+ printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
X return -EAGAIN;
X }
-
+
X #ifdef irq2dev_map
X if (((irq2dev_map[dev->irq] != 0)
- || (irq2dev_map[dev->irq] = dev) == 0) &&
+ || (irq2dev_map[dev->irq] = dev) == 0) &&
X (irq2dev_map[dev->irq]!=dev)) {
X /* printk("%s: IRQ map wrong\n", dev->name); */
X free_irq(dev->irq, dev);
@@ -962,21 +980,21 @@
X /* Initialize the 82595. */
X
X eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
- temp_reg = inb(ioaddr + eeprom_reg);
+ temp_reg = inb(ioaddr + lp->eeprom_reg);
X
X lp->stepping = temp_reg >> 5; /* Get the stepping number of the 595 */
-
+
X if (net_debug > 3)
X printk(KERN_DEBUG "The stepping of the 82595 is %d\n", lp->stepping);
X
X if (temp_reg & 0x10) /* Check the TurnOff Enable bit */
- outb(temp_reg & 0xef, ioaddr + eeprom_reg);
- for (i=0; i < 6; i++)
- outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i);
-
+ outb(temp_reg & 0xef, ioaddr + lp->eeprom_reg);


+ for (i=0; i < 6; i++)

+ outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i);
+
X temp_reg = inb(ioaddr + REG1); /* Setup Transmit Chaining */
X outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop /* and discard bad RCV frames */
- | RCV_Discard_BadFrame, ioaddr + REG1);
+ | RCV_Discard_BadFrame, ioaddr + REG1);
X
X temp_reg = inb(ioaddr + REG2); /* Match broadcast */
X outb(temp_reg | 0x14, ioaddr + REG2);
@@ -987,15 +1005,15 @@
X /* Set the receiving mode */
X eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */
X
- /* Set the interrupt vector */
+ /* Set the interrupt vector */
X temp_reg = inb(ioaddr + INT_NO_REG);
- if (lp->eepro == 2 || lp->eepro == LAN595FX_10ISA)
+ if (lp->eepro == LAN595FX || lp->eepro == LAN595FX_10ISA)
X outb((temp_reg & 0xf8) | irqrmap2[dev->irq], ioaddr + INT_NO_REG);
- else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
+ else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
X
X
X temp_reg = inb(ioaddr + INT_NO_REG);
- if (lp->eepro == 2 || lp->eepro == LAN595FX_10ISA)
+ if (lp->eepro == LAN595FX || lp->eepro == LAN595FX_10ISA)
X outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG);
X else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
X
@@ -1004,10 +1022,10 @@
X
X
X /* Initialize the RCV and XMT upper and lower limits */
- outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG);
- outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG);
- outb(XMT_LOWER_LIMIT, ioaddr + xmt_lower_limit_reg);
- outb(XMT_UPPER_LIMIT, ioaddr + xmt_upper_limit_reg);
+ outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG);
+ outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG);
+ outb(lp->xmt_lower_limit >> 8, ioaddr + lp->xmt_lower_limit_reg);
+ outb(lp->xmt_upper_limit >> 8, ioaddr + lp->xmt_upper_limit_reg);
X
X /* Enable the interrupt line. */
X eepro_en_intline(ioaddr);
@@ -1022,12 +1040,14 @@
X eepro_clear_int(ioaddr);
X
X /* Initialize RCV */
- outw(RCV_LOWER_LIMIT << 8, ioaddr + RCV_BAR);
- lp->rx_start = (RCV_LOWER_LIMIT << 8) ;
- outw((RCV_UPPER_LIMIT << 8) | 0xfe, ioaddr + RCV_STOP);
+ outw(lp->rcv_lower_limit, ioaddr + RCV_BAR);
+ lp->rx_start = lp->rcv_lower_limit;
+ outw(lp->rcv_upper_limit | 0xfe, ioaddr + RCV_STOP);
X
X /* Initialize XMT */
- outw(XMT_LOWER_LIMIT << 8, ioaddr + xmt_bar);
+ outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar);
+ lp->tx_start = lp->tx_end = lp->xmt_lower_limit;
+ lp->tx_last = 0;
X
X /* Check for the i82595TX and i82595FX */
X old8 = inb(ioaddr + 8);
@@ -1042,9 +1062,7 @@
X lp->version = LAN595TX;
X outb(old8, ioaddr + 8);
X old9 = inb(ioaddr + 9);
- /*outb(~old9, ioaddr + 9);
- if (((temp_reg = inb(ioaddr + 9)) == ( (~old9)&0xff) )) {*/
-
+
X if (irqMask==ee_FX_INT2IRQ) {


X enum iftype { AUI=0, BNC=1, TPE=2 };
X

@@ -1070,15 +1088,10 @@
X printk(KERN_DEBUG "i82595TX detected!\n");
X }
X }
-
- eepro_sel_reset(ioaddr);
- SLOW_DOWN;
- SLOW_DOWN;
X
- lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8;
- lp->tx_last = 0;
+ eepro_sel_reset(ioaddr);
X
- netif_start_queue(dev);
+ netif_start_queue(dev);
X
X if (net_debug > 3)
X printk(KERN_DEBUG "%s: exiting eepro_open routine.\n", dev->name);
@@ -1086,6 +1099,8 @@
X /* enabling rx */
X eepro_en_rx(ioaddr);
X
+ MOD_INC_USE_COUNT;


+
X return 0;
X }
X

@@ -1097,7 +1112,7 @@
X /* if (net_debug > 1) */
X printk (KERN_ERR "%s: transmit timed out, %s?\n", dev->name,
X "network cable problem");
- /* This is not a duplicate. One message for the console,
+ /* This is not a duplicate. One message for the console,
X one for the the log file */
X printk (KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
X "network cable problem");
@@ -1109,23 +1124,28 @@
X {
X struct eepro_local *lp = (struct eepro_local *)dev->priv;


X unsigned long flags;
-

+ int ioaddr = dev->base_addr;
+
X if (net_debug > 5)
X printk(KERN_DEBUG "%s: entering eepro_send_packet routine.\n", dev->name);
-
+
X netif_stop_queue (dev);
X
+ eepro_dis_int(ioaddr);
X spin_lock_irqsave(&lp->lock, flags);
X
X {
X short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
X unsigned char *buf = skb->data;
X
+ if (hardware_send_packet(dev, buf, length))
+ /* we won't wake queue here because we're out of space */
+ lp->stats.tx_dropped++;
+ else {
X lp->stats.tx_bytes+=skb->len;
-
- hardware_send_packet(dev, buf, length);
-


X dev->trans_start = jiffies;

+ netif_wake_queue(dev);
+ }
X
X }
X
@@ -1137,8 +1157,9 @@
X if (net_debug > 5)
X printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name);
X
+ eepro_en_int(ioaddr);
X spin_unlock_irqrestore(&lp->lock, flags);
-

+
X return 0;
X }
X

@@ -1151,7 +1172,7 @@
X {
X struct net_device *dev = (struct net_device *)dev_id;
X /* (struct net_device *)(irq2dev_map[irq]);*/
- struct eepro_local *lp = (struct eepro_local *)dev->priv;
+ struct eepro_local *lp;
X int ioaddr, status, boguscount = 20;
X

X if (dev == NULL) {

@@ -1159,44 +1180,41 @@
X return;
X }
X
+ lp = (struct eepro_local *)dev->priv;
+
X spin_lock(&lp->lock);
X
X if (net_debug > 5)
X printk(KERN_DEBUG "%s: entering eepro_interrupt routine.\n", dev->name);
-
+
X ioaddr = dev->base_addr;
X
- while (((status = inb(ioaddr + STATUS_REG)) & 0x06) && (boguscount--))
+ while (((status = inb(ioaddr + STATUS_REG)) & (RX_INT|TX_INT)) && (boguscount--))
X {
- switch (status & (RX_INT | TX_INT)) {
-#ifdef ANSWER_TX_AND_RX
- case (RX_INT | TX_INT):
- eepro_ack_rxtx(ioaddr);
- break;
-#endif
- case RX_INT:
- eepro_ack_rx(ioaddr);
- break;
- case TX_INT:
- eepro_ack_tx(ioaddr);
- break;
- }
X if (status & RX_INT) {
X if (net_debug > 4)
X printk(KERN_DEBUG "%s: packet received interrupt.\n", dev->name);
X
+ eepro_dis_int(ioaddr);
+
X /* Get the received packets */
+ eepro_ack_rx(ioaddr);
X eepro_rx(dev);
-#ifndef ANSWER_TX_AND_RX
- continue;
-#endif
+
+ eepro_en_int(ioaddr);
X }
X if (status & TX_INT) {
X if (net_debug > 4)
X printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name);
X
+
+ eepro_dis_int(ioaddr);
+
X /* Process the status of transmitted packets */
+ eepro_ack_tx(ioaddr);
X eepro_transmit_interrupt(dev);
+
+ eepro_en_int(ioaddr);
X }
X }
X
@@ -1219,13 +1237,13 @@
X
X /* Disable the physical interrupt line. */
X temp_reg = inb(ioaddr + REG1);
- outb(temp_reg & 0x7f, ioaddr + REG1);
+ outb(temp_reg & 0x7f, ioaddr + REG1);
X
X eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
X
X /* Flush the Tx and disable Rx. */
- outb(STOP_RCV_CMD, ioaddr);
- lp->tx_start = lp->tx_end = (XMT_LOWER_LIMIT << 8);
+ outb(STOP_RCV_CMD, ioaddr);
+ lp->tx_start = lp->tx_end = lp->xmt_lower_limit;


X lp->tx_last = 0;
X

X /* Mask all the interrupts. */
@@ -1246,6 +1264,8 @@
X
X /* Update the statistics here. What statistics? */
X
+ MOD_DEC_USE_COUNT;


+
X return 0;
X }
X

@@ -1269,7 +1289,7 @@
X unsigned short mode;
X struct dev_mc_list *dmi=dev->mc_list;
X
- if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || dev->mc_count > 63)
+ if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || dev->mc_count > 63)
X {
X /*
X * We must make the kernel realise we had to move
@@ -1277,18 +1297,18 @@
X * the cable. If it was a promisc request the
X * flag is already set. If not we assert it.
X */
- dev->flags|=IFF_PROMISC;
+ dev->flags|=IFF_PROMISC;
X
X eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
X mode = inb(ioaddr + REG2);
- outb(mode | PRMSC_Mode, ioaddr + REG2);
+ outb(mode | PRMSC_Mode, ioaddr + REG2);
X mode = inb(ioaddr + REG3);
X outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
X eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
- printk("%s: promiscuous mode enabled.\n", dev->name);
+ printk(KERN_INFO "%s: promiscuous mode enabled.\n", dev->name);
X }
-
- else if (dev->mc_count==0 )
+
+ else if (dev->mc_count==0 )
X {
X eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
X mode = inb(ioaddr + REG2);
@@ -1297,12 +1317,12 @@
X outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
X eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
X }
-
- else
+
+ else
X {
X unsigned short status, *eaddrs;
X int i, boguscount = 0;
-
+
X /* Disable RX and TX interrupts. Necessary to avoid
X corruption of the HOST_ADDRESS_REG by interrupt
X service routines. */
@@ -1310,7 +1330,7 @@
X
X eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
X mode = inb(ioaddr + REG2);
- outb(mode | Multi_IA, ioaddr + REG2);
+ outb(mode | Multi_IA, ioaddr + REG2);
X mode = inb(ioaddr + REG3);
X outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
X eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
@@ -1319,8 +1339,8 @@
X outw(0, ioaddr + IO_PORT);
X outw(0, ioaddr + IO_PORT);
X outw(6*(dev->mc_count + 1), ioaddr + IO_PORT);
-
- for (i = 0; i < dev->mc_count; i++)
+
+ for (i = 0; i < dev->mc_count; i++)
X {
X eaddrs=(unsigned short *)dmi->dmi_addr;
X dmi=dmi->next;
@@ -1328,20 +1348,20 @@
X outw(*eaddrs++, ioaddr + IO_PORT);
X outw(*eaddrs++, ioaddr + IO_PORT);
X }
-
+
X eaddrs = (unsigned short *) dev->dev_addr;
X outw(eaddrs[0], ioaddr + IO_PORT);
X outw(eaddrs[1], ioaddr + IO_PORT);
X outw(eaddrs[2], ioaddr + IO_PORT);
- outw(lp->tx_end, ioaddr + xmt_bar);
+ outw(lp->tx_end, ioaddr + lp->xmt_bar);
X outb(MC_SETUP, ioaddr);
X
X /* Update the transmit queue */
X i = lp->tx_end + XMT_HEADER + 6*(dev->mc_count + 1);
-
- if (lp->tx_start != lp->tx_end)
+
+ if (lp->tx_start != lp->tx_end)
X {
- /* update the next address and the chain bit in the
+ /* update the next address and the chain bit in the
X last packet */
X outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
X outw(i, ioaddr + IO_PORT);
@@ -1358,17 +1378,17 @@
X do { /* We should be doing this in the eepro_interrupt()! */
X SLOW_DOWN;
X SLOW_DOWN;
- if (inb(ioaddr + STATUS_REG) & 0x08)
+ if (inb(ioaddr + STATUS_REG) & 0x08)
X {
X i = inb(ioaddr);
X outb(0x08, ioaddr + STATUS_REG);
-
+
X if (i & 0x20) { /* command ABORTed */
- printk("%s: multicast setup failed.\n",
+ printk(KERN_NOTICE "%s: multicast setup failed.\n",
X dev->name);
X break;
X } else if ((i & 0x0f) == 0x03) { /* MC-Done */
- printk("%s: set Rx mode to %d address%s.\n",
+ printk(KERN_DEBUG "%s: set Rx mode to %d address%s.\n",
X dev->name, dev->mc_count,
X dev->mc_count > 1 ? "es":"");
X break;
@@ -1398,23 +1418,19 @@
X {
X int i;
X unsigned short retval = 0;
- short ee_addr = ioaddr + eeprom_reg;
- struct eepro_local *lp = (struct eepro_local *)dev->priv;
+ struct eepro_local *lp = dev->priv;
+ short ee_addr = ioaddr + lp->eeprom_reg;
X int read_cmd = location | EE_READ_CMD;
X short ctrl_val = EECS ;
X
- /* XXXX - this is not the final version. We must test this on other
- * boards other than eepro10. I think that it won't let other
- * boards to fail. (aris)
- */
- if (lp->eepro == LAN595FX_10ISA) {
+ /* XXXX - black magic */
X eepro_sw2bank1(ioaddr);
X outb(0x00, ioaddr + STATUS_REG);
- }
-
+ /* XXXX - black magic */
+
X eepro_sw2bank2(ioaddr);
X outb(ctrl_val, ee_addr);
-
+
X /* Shift the read command bits out. */
X for (i = 8; i >= 0; i--) {
X short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI
@@ -1426,7 +1442,7 @@
X eeprom_delay();
X }
X outb(ctrl_val, ee_addr);
-
+
X for (i = 16; i > 0; i--) {
X outb(ctrl_val | EESK, ee_addr); eeprom_delay();
X retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0);
@@ -1443,57 +1459,44 @@


X return retval;
X }
X

-static void
+static int
X hardware_send_packet(struct net_device *dev, void *buf, short length)
X {
X struct eepro_local *lp = (struct eepro_local *)dev->priv;
X short ioaddr = dev->base_addr;
- unsigned status, tx_available, last, end, boguscount = 100;
+ unsigned status, tx_available, last, end;
X
X if (net_debug > 5)
X printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name);
X
- while (boguscount-- > 0) {
-
- /* Disable RX and TX interrupts. Necessary to avoid
- corruption of the HOST_ADDRESS_REG by interrupt
- service routines. */
- eepro_dis_int(ioaddr);
-
X /* determine how much of the transmit buffer space is available */
X if (lp->tx_end > lp->tx_start)
- tx_available = XMT_RAM - (lp->tx_end - lp->tx_start);
+ tx_available = lp->xmt_ram - (lp->tx_end - lp->tx_start);
X else if (lp->tx_end < lp->tx_start)
X tx_available = lp->tx_start - lp->tx_end;
- else tx_available = XMT_RAM;
-
- if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER)
- >= tx_available) /* No space available ??? */
- {
- eepro_transmit_interrupt(dev); /* Clean up the transmiting queue */
+ else tx_available = lp->xmt_ram;
X
- /* Enable RX and TX interrupts */
- eepro_en_int(ioaddr);
- continue;
+ if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) >= tx_available) {
+ /* No space available ??? */


+ return 1;
X }
X

X last = lp->tx_end;
X end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
X
- if (end >= (XMT_UPPER_LIMIT << 8)) { /* the transmit buffer is wrapped around */
- if (((XMT_UPPER_LIMIT << 8) - last) <= XMT_HEADER) {
+ if (end >= lp->xmt_upper_limit + 2) { /* the transmit buffer is wrapped around */
+ if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) {
X /* Arrrr!!!, must keep the xmt header together,
X several days were lost to chase this one down. */
-
- last = (XMT_LOWER_LIMIT << 8);
+ last = lp->xmt_lower_limit;
X end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
X }
-
- else end = (XMT_LOWER_LIMIT << 8) + (end -
- (XMT_UPPER_LIMIT <<8));
+ else end = lp->xmt_lower_limit + (end -
+ lp->xmt_upper_limit + 2);
X }
+
X outw(last, ioaddr + HOST_ADDRESS_REG);
- outw(XMT_CMD, ioaddr + IO_PORT);
+ outw(XMT_CMD, ioaddr + IO_PORT);
X outw(0, ioaddr + IO_PORT);
X outw(end, ioaddr + IO_PORT);
X outw(length, ioaddr + IO_PORT);
@@ -1508,24 +1511,24 @@
X }
X
X /* A dummy read to flush the DRAM write pipeline */
- status = inw(ioaddr + IO_PORT);
+ status = inw(ioaddr + IO_PORT);
X
- if (lp->tx_start == lp->tx_end) {
- outw(last, ioaddr + xmt_bar);
+ if (lp->tx_start == lp->tx_end) {
+ outw(last, ioaddr + lp->xmt_bar);
X outb(XMT_CMD, ioaddr);
X lp->tx_start = last; /* I don't like to change tx_start here */
X }
X else {
- /* update the next address and the chain bit in the
+ /* update the next address and the chain bit in the
X last packet */
-
+
X if (lp->tx_end != last) {
X outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
- outw(last, ioaddr + IO_PORT);
+ outw(last, ioaddr + IO_PORT);
X }
-
+
X outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
- status = inw(ioaddr + IO_PORT);
+ status = inw(ioaddr + IO_PORT);
X outw(status | CHAIN_BIT, ioaddr + IO_PORT);
X
X /* Continue the transmit command */
@@ -1535,27 +1538,10 @@
X lp->tx_last = last;
X lp->tx_end = end;
X
- if (netif_queue_stopped(dev))
- netif_wake_queue(dev);
-
- /* now we are serializing tx. queue won't come back until
- * the tx interrupt
- */
- if (lp->eepro == LAN595FX_10ISA)
- netif_stop_queue(dev);
-
- /* Enable RX and TX interrupts */
- eepro_en_int(ioaddr);
-
X if (net_debug > 5)
X printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
- return;
- }
- if (lp->eepro == LAN595FX_10ISA)
- netif_stop_queue(dev);
X
- if (net_debug > 5)
- printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
+ return 0;


X }
X
X static void

@@ -1564,7 +1550,7 @@
X struct eepro_local *lp = (struct eepro_local *)dev->priv;
X short ioaddr = dev->base_addr;
X short boguscount = 20;
- unsigned rcv_car = lp->rx_start;
+ short rcv_car = lp->rx_start;
X unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size;
X
X if (net_debug > 5)
@@ -1572,17 +1558,17 @@
X
X /* Set the read pointer to the start of the RCV */
X outw(rcv_car, ioaddr + HOST_ADDRESS_REG);
-
+
X rcv_event = inw(ioaddr + IO_PORT);
X
X while (rcv_event == RCV_DONE) {
-
- rcv_status = inw(ioaddr + IO_PORT);
+
+ rcv_status = inw(ioaddr + IO_PORT);
X rcv_next_frame = inw(ioaddr + IO_PORT);
- rcv_size = inw(ioaddr + IO_PORT);
+ rcv_size = inw(ioaddr + IO_PORT);
X
X if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) {
-
+
X /* Malloc up new buffer. */


X struct sk_buff *skb;
X

@@ -1602,49 +1588,50 @@
X else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
X unsigned short temp = inb(ioaddr + INT_MASK_REG);
X outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
- insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size),
+ insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size),
X (rcv_size + 3) >> 2);
X outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
X }
-
- skb->protocol = eth_type_trans(skb,dev);
+
+ skb->protocol = eth_type_trans(skb,dev);
X netif_rx(skb);


X dev->last_rx = jiffies;

X lp->stats.rx_packets++;
X }
-
- else { /* Not sure will ever reach here,
+
+ else { /* Not sure will ever reach here,
X I set the 595 to discard bad received frames */
X lp->stats.rx_errors++;
-
+
X if (rcv_status & 0x0100)
X lp->stats.rx_over_errors++;
-
+
X else if (rcv_status & 0x0400)
X lp->stats.rx_frame_errors++;
-
+
X else if (rcv_status & 0x0800)
X lp->stats.rx_crc_errors++;
-
- printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
+
+ printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
X dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
X }
X
X if (rcv_status & 0x1000)
X lp->stats.rx_length_errors++;
X
+ rcv_car = lp->rx_start + RCV_HEADER + rcv_size;
+ lp->rx_start = rcv_next_frame;
+
X if (--boguscount == 0)
X break;
X
- rcv_car = lp->rx_start + RCV_HEADER + rcv_size;
- lp->rx_start = rcv_next_frame;
X outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);
X rcv_event = inw(ioaddr + IO_PORT);
X
- }
+ }
X if (rcv_car == 0)
- rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff;
-
+ rcv_car = lp->rcv_upper_limit | 0xff;
+
X outw(rcv_car - 1, ioaddr + RCV_STOP);
X
X if (net_debug > 5)
@@ -1656,54 +1643,24 @@
X {
X struct eepro_local *lp = (struct eepro_local *)dev->priv;
X short ioaddr = dev->base_addr;
- short boguscount = 20;
- unsigned xmt_status;
-
- /*
- if (dev->tbusy == 0) {
- printk("%s: transmit_interrupt called with tbusy = 0 ??\n",
- dev->name);
- printk(KERN_DEBUG "%s: transmit_interrupt called with tbusy = 0 ??\n",
- dev->name);
- }
- */
- while (lp->tx_start != lp->tx_end && boguscount) {
+ short boguscount = 25;
+ short xmt_status;
+
+ while ((lp->tx_start != lp->tx_end) && boguscount--) {
X
- outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
+ outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
X xmt_status = inw(ioaddr+IO_PORT);
-
- if ((xmt_status & TX_DONE_BIT) == 0) {
- if (lp->eepro == LAN595FX_10ISA) {
- udelay(40);
- boguscount--;
- continue;
- }
- else
+
+ if (!(xmt_status & TX_DONE_BIT))
X break;
- }
X
- xmt_status = inw(ioaddr+IO_PORT);
+ xmt_status = inw(ioaddr+IO_PORT);
X lp->tx_start = inw(ioaddr+IO_PORT);
X
- if (lp->eepro == LAN595FX_10ISA) {
- lp->tx_start = (XMT_LOWER_LIMIT << 8);
- lp->tx_end = lp->tx_start;
-
- /* yeah, black magic :( */
- eepro_sw2bank0(ioaddr);
- eepro_en_int(ioaddr);
-
- /* disabling rx */
- eepro_dis_rx(ioaddr);
-
- /* enabling rx */
- eepro_en_rx(ioaddr);
- }
-
X netif_wake_queue (dev);
X
- if (xmt_status & 0x2000)
- lp->stats.tx_packets++;
+ if (xmt_status & TX_OK)
+ lp->stats.tx_packets++;
X else {
X lp->stats.tx_errors++;
X if (xmt_status & 0x0400) {
@@ -1719,35 +1676,15 @@
X printk(KERN_DEBUG "%s: XMT status = %#x\n",
X dev->name, xmt_status);
X }
- if (lp->eepro == LAN595FX_10ISA) {
- /* Try to restart the adaptor. */
- /* We are supposed to wait for 2 us after a SEL_RESET */
- eepro_sel_reset(ioaddr);
-
- /* first enable interrupts */
- eepro_sw2bank0(ioaddr);
- outb(ALL_MASK & ~(RX_INT | TX_INT), ioaddr + STATUS_REG);
-
- /* enabling rx */
- eepro_en_rx(ioaddr);
- }
X }
X if (xmt_status & 0x000f) {
X lp->stats.collisions += (xmt_status & 0x000f);
X }
-
+
X if ((xmt_status & 0x0040) == 0x0) {
X lp->stats.tx_heartbeat_errors++;
X }
-
- boguscount--;
X }
- /* if it reached here then it's probable that the adapter won't
- * interrupt again for tx. in other words: tx timeout what will take
- * a lot of time to happen, so we'll do a complete selreset.
- */
- if (!boguscount && lp->eepro == LAN595FX_10ISA)
- eepro_complete_selreset(ioaddr);
X }
X
X #ifdef MODULE
@@ -1778,35 +1715,38 @@
X MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)");
X MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)");
X
-int
+int
X init_module(void)
X {
X int i;
X if (io[0] == 0 && autodetect == 0) {
- printk("eepro_init_module: Probe is very dangerous in ISA boards!\n");
- printk("eepro_init_module: Please add \"autodetect=1\" to force probe\n");
+ printk(KERN_WARNING "eepro_init_module: Probe is very dangerous in ISA boards!\n");
+ printk(KERN_WARNING "eepro_init_module: Please add \"autodetect=1\" to force probe\n");
X return 1;
X }
X else if (autodetect) {
X /* if autodetect is set then we must force detection */
X io[0] = 0;
-
- printk("eepro_init_module: Auto-detecting boards (May God protect us...)\n");
- }
+
+ printk(KERN_INFO "eepro_init_module: Auto-detecting boards (May God protect us...)\n");
+ }
X
X for (i = 0; i < MAX_EEPRO; i++) {
X struct net_device *d = &dev_eepro[n_eepro];
- d->mem_end = mem[n_eepro];
- d->base_addr = io[0];
- d->irq = irq[n_eepro];
+ d->mem_end = mem[i];
+ d->base_addr = io[i];
+ d->irq = irq[i];
X d->init = eepro_probe;
X
- if (register_netdev(d) == 0)
- n_eepro++;
- else
- break;
- }
-
+ if (register_netdev(d) == 0)
+ n_eepro++;
+ else
+ break;
+ }
+
+ if (n_eepro)
+ printk(KERN_INFO "%s", version);
+
X return n_eepro ? 0 : -ENODEV;
X }
X
@@ -1814,7 +1754,7 @@
X cleanup_module(void)
X {
X int i;
-
+
X for (i=0; i<n_eepro; i++) {
X struct net_device *d = &dev_eepro[i];
X unregister_netdev(d);
@@ -1824,7 +1764,7 @@
X
X /* If we don't do this, we can't re-insmod it later. */
X release_region(d->base_addr, EEPRO_IO_EXTENT);
-
+
X }
X }
X #endif /* MODULE */
diff -u --recursive --new-file v2.4.14/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- v2.4.14/linux/drivers/net/eepro100.c Tue Oct 9 17:06:51 2001
+++ linux/drivers/net/eepro100.c Mon Nov 12 09:47:18 2001
@@ -108,10 +108,12 @@
X

X #include <asm/bitops.h>
X #include <asm/io.h>

+#include <asm/uaccess.h>
X

X #include <linux/netdevice.h>
X #include <linux/etherdevice.h>

X #include <linux/skbuff.h>
+#include <linux/ethtool.h>
X #include <linux/delay.h>
X
X MODULE_AUTHOR("Maintainer: Andrey V. Savochkin <s...@saw.sw.com.sg>");
@@ -497,6 +499,9 @@
X unsigned short phy[2]; /* PHY media interfaces available. */
X unsigned short advertising; /* Current PHY advertised caps. */
X unsigned short partner; /* Link partner caps. */
+#ifdef CONFIG_PM
+ u32 pm_state[16];
+#endif
X };
X
X /* The parameters for a CmdConfigure operation.
@@ -1913,6 +1918,35 @@
X return &sp->stats;
X }
X
+static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
+{
+ u32 ethcmd;
+ struct speedo_private *sp = dev->priv;


+
+ if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
+ return -EFAULT;
+
+ switch (ethcmd) {
+ case ETHTOOL_GDRVINFO: {

+ struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};

+ strncpy(info.driver, "eepro100", sizeof(info.driver)-1);
+ strncpy(info.version, version, sizeof(info.version)-1);
+ if (sp && sp->pdev)
+ strcpy(info.bus_info, sp->pdev->slot_name);


+ if (copy_to_user(useraddr, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
+
+ }
+
+ return -EOPNOTSUPP;
+}
+
+

+
+
+
X static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
X {
X struct speedo_private *sp = (struct speedo_private *)dev->priv;
@@ -1952,6 +1986,8 @@
X add_timer(&sp->timer); /* may be set to the past --SAW */
X pci_set_power_state(sp->pdev, saved_acpi);
X return 0;
+ case SIOCETHTOOL:
+ return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
X default:
X return -EOPNOTSUPP;
X }
@@ -2160,8 +2196,11 @@
X static int eepro100_suspend(struct pci_dev *pdev, u32 state)
X {
X struct net_device *dev = pci_get_drvdata (pdev);
+ struct speedo_private *sp = (struct speedo_private *)dev->priv;


X long ioaddr = dev->base_addr;
X

+ pci_save_state(pdev, sp->pm_state);
+
X if (!netif_running(dev))
X return 0;
X
@@ -2177,6 +2216,8 @@
X struct net_device *dev = pci_get_drvdata (pdev);
X struct speedo_private *sp = (struct speedo_private *)dev->priv;


X long ioaddr = dev->base_addr;

+
+ pci_restore_state(pdev, sp->pm_state);
X
X if (!netif_running(dev))
X return 0;
diff -u --recursive --new-file v2.4.14/linux/drivers/net/fealnx.c linux/drivers/net/fealnx.c
--- v2.4.14/linux/drivers/net/fealnx.c Tue Oct 23 22:48:51 2001
+++ linux/drivers/net/fealnx.c Mon Nov 19 15:19:42 2001
@@ -431,7 +431,7 @@
X static struct net_device_stats *get_stats(struct net_device *dev);
X static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
X static int netdev_close(struct net_device *dev);
-
+static void reset_rx_descriptors(struct net_device *dev);
X
X void stop_nic_tx(long ioaddr, long crvalue)
X {
@@ -887,7 +887,8 @@
X 1 1 0 128
X 1 1 1 256
X Wait the specified 50 PCI cycles after a reset by initializing
- Tx and Rx queues and the address filter list. */
+ Tx and Rx queues and the address filter list.
+ FIXME (Ueimor): optimistic for alpha + posted writes ? */
X #if defined(__powerpc__) || defined(__sparc__)
X // 89/9/1 modify,
X // np->bcrvalue=0x04 | 0x0x38; /* big-endian, 256 burst length */
@@ -1164,12 +1165,12 @@
X {


X struct netdev_private *np = dev->priv;
X long ioaddr = dev->base_addr;

+ int i;
X
X printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
X " resetting...\n", dev->name, readl(ioaddr + ISR));
X

X {
- int i;
X

X printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring);
X for (i = 0; i < RX_RING_SIZE; i++)
@@ -1180,12 +1181,41 @@
X printk("\n");
X }
X
- /* Perhaps we should reinitialize the hardware here. Just trigger a
- Tx demand for now. */
+ + dev->if_port = np->default_port;
+ /* Reinit. Gross */
+
+ /* Reset the chip's Tx and Rx processes. */
+ stop_nic_tx(ioaddr, 0);
+ reset_rx_descriptors(dev);
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ writel(0x0000, ioaddr + IMR);
+
+ /* Reset the chip to erase previous misconfiguration. */
+ writel(0x00000001, ioaddr + BCR);
+
+ /* Ueimor: wait for 50 PCI cycles (and flush posted writes btw).
+ We surely wait too long (address+data phase). Who cares ? */
+ for (i = 0; i < 50; i++) {
+ readl(ioaddr + BCR);
+ rmb();
+ }
+
+ writel((np->cur_tx - np->tx_ring)*sizeof(struct fealnx_desc) +
+ np->tx_ring_dma, ioaddr + TXLBA);
+ writel((np->cur_rx - np->rx_ring)*sizeof(struct fealnx_desc) +
+ np->rx_ring_dma, ioaddr + RXLBA);
+
+ writel(np->bcrvalue, ioaddr + BCR);
+
+ writel(0, dev->base_addr + RXPDR);
+ set_rx_mode(dev);
+ /* Clear and Enable interrupts by setting the interrupt mask. */
+ writel(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR);
+ writel(np->imrvalue, ioaddr + IMR);
+
X writel(0, dev->base_addr + TXPDR);
- dev->if_port = 0;
X
- /* Stop and restart the chip's Tx processes . */


X dev->trans_start = jiffies;

X np->stats.tx_errors++;
X
@@ -1815,7 +1845,7 @@


X return 0;
X }
X

-static struct pci_device_id fealnx_pci_tbl[] = __devinitdata {
+static struct pci_device_id fealnx_pci_tbl[] __devinitdata = {
X {0x1516, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
X {0x1516, 0x0803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
X {0x1516, 0x0891, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
diff -u --recursive --new-file v2.4.14/linux/drivers/net/irda/irda-usb.c linux/drivers/net/irda/irda-usb.c
--- v2.4.14/linux/drivers/net/irda/irda-usb.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/irda/irda-usb.c Fri Nov 9 14:22:17 2001
@@ -279,7 +279,7 @@
X purb->timeout = MSECS_TO_JIFFIES(100);
X
X if ((ret = usb_submit_urb(purb))) {
- IRDA_DEBUG(0, __FUNCTION__ "(), failed Speed URB\n");
+ WARNING(__FUNCTION__ "(), failed Speed URB\n");
X }
X spin_unlock_irqrestore(&self->lock, flags);
X }
@@ -296,14 +296,14 @@
X
X /* We should always have a context */
X if (self == NULL) {
- IRDA_DEBUG(0, __FUNCTION__ "(), Bug : self == NULL\n");
+ WARNING(__FUNCTION__ "(), Bug : self == NULL\n");
X return;
X }
X
X /* Check for timeout and other USB nasties */
X if(purb->status != USB_ST_NOERROR) {
X /* I get a lot of -ECONNABORTED = -103 here - Jean II */
- WARNING(__FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", purb->status, purb->transfer_flags);
+ IRDA_DEBUG(0, __FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", purb->status, purb->transfer_flags);
X
X /* Don't do anything here, that might confuse the USB layer.
X * Instead, we will wait for irda_usb_net_timeout(), the
@@ -452,7 +452,7 @@
X
X /* Ask USB to send the packet */
X if ((res = usb_submit_urb(purb))) {
- IRDA_DEBUG(0, __FUNCTION__ "(), failed Tx URB\n");
+ WARNING(__FUNCTION__ "(), failed Tx URB\n");
X self->stats.tx_errors++;
X /* Let USB recover : We will catch that in the watchdog */
X /*netif_start_queue(netdev);*/
@@ -481,7 +481,7 @@
X
X /* We should always have a context */
X if (self == NULL) {
- IRDA_DEBUG(0, __FUNCTION__ "(), Bug : self == NULL\n");
+ WARNING(__FUNCTION__ "(), Bug : self == NULL\n");
X return;
X }
X
@@ -492,7 +492,7 @@
X /* Check for timeout and other USB nasties */
X if(purb->status != USB_ST_NOERROR) {
X /* I get a lot of -ECONNABORTED = -103 here - Jean II */
- WARNING(__FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", purb->status, purb->transfer_flags);
+ IRDA_DEBUG(0, __FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", purb->status, purb->transfer_flags);
X
X /* Don't do anything here, that might confuse the USB layer,
X * and we could go in recursion and blow the kernel stack...
@@ -514,7 +514,7 @@
X
X /* If we need to change the speed or xbofs, do it now */
X if ((self->new_speed != -1) || (self->new_xbofs != -1)) {
- IRDA_DEBUG(0, __FUNCTION__ "(), Changing speed now...\n");
+ IRDA_DEBUG(1, __FUNCTION__ "(), Changing speed now...\n");
X irda_usb_change_speed_xbofs(self);
X } else {
X /* Otherwise, allow the stack to send more packets */
@@ -548,7 +548,7 @@
X /* Check speed URB */
X purb = &(self->speed_urb);
X if (purb->status != USB_ST_NOERROR) {
- WARNING("%s: Speed change timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, purb->status, purb->transfer_flags);
+ IRDA_DEBUG(0, "%s: Speed change timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, purb->status, purb->transfer_flags);
X
X switch (purb->status) {
X case USB_ST_URB_PENDING: /* -EINPROGRESS == -115 */
@@ -575,7 +575,7 @@
X if (purb->status != USB_ST_NOERROR) {
X struct sk_buff *skb = purb->context;
X
- WARNING("%s: Tx timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, purb->status, purb->transfer_flags);
+ IRDA_DEBUG(0, "%s: Tx timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, purb->status, purb->transfer_flags);
X
X /* Increase error count */
X self->stats.tx_errors++;
@@ -694,7 +694,7 @@
X
X /* Check that we have an urb */
X if (!purb) {
- IRDA_DEBUG(0, __FUNCTION__ "(), Bug : purb == NULL\n");
+ WARNING(__FUNCTION__ "(), Bug : purb == NULL\n");
X return;
X }
X
@@ -704,7 +704,7 @@
X if (!skb) {
X /* If this ever happen, we are in deep s***.
X * Basically, the Rx path will stop... */
- IRDA_DEBUG(0, __FUNCTION__ "(), Failed to allocate Rx skb\n");
+ WARNING(__FUNCTION__ "(), Failed to allocate Rx skb\n");
X return;
X }
X } else {
@@ -734,7 +734,7 @@
X if (ret) {
X /* If this ever happen, we are in deep s***.
X * Basically, the Rx path will stop... */
- IRDA_DEBUG(0, __FUNCTION__ "(), Failed to submit Rx URB %d\n", ret);
+ WARNING(__FUNCTION__ "(), Failed to submit Rx URB %d\n", ret);
X }
X }
X
@@ -775,13 +775,13 @@
X self->stats.rx_crc_errors++;
X break;
X case -ECONNRESET: /* -104 */
- WARNING(__FUNCTION__ "(), Connection Reset (-104), transfer_flags 0x%04X \n", purb->transfer_flags);
+ IRDA_DEBUG(0, __FUNCTION__ "(), Connection Reset (-104), transfer_flags 0x%04X \n", purb->transfer_flags);
X /* uhci_cleanup_unlink() is going to kill the Rx
X * URB just after we return. No problem, at this
X * point the URB will be idle ;-) - Jean II */
X break;
X default:
- WARNING(__FUNCTION__ "(), RX status %d,transfer_flags 0x%04X \n", purb->status, purb->transfer_flags);
+ IRDA_DEBUG(0, __FUNCTION__ "(), RX status %d,transfer_flags 0x%04X \n", purb->status, purb->transfer_flags);
X break;
X }
X goto done;
@@ -893,7 +893,7 @@
X */
X static int irda_usb_net_init(struct net_device *dev)
X {
- IRDA_DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(1, __FUNCTION__ "()\n");
X
X /* Set up to be a normal IrDA network device driver */
X irda_device_setup(dev);
@@ -917,7 +917,7 @@
X char hwname[16];
X int i;
X
- IRDA_DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(1, __FUNCTION__ "()\n");
X
X ASSERT(netdev != NULL, return -1;);
X self = (struct irda_usb_cb *) netdev->priv;
@@ -977,7 +977,7 @@
X struct irda_usb_cb *self;
X int i;
X
- IRDA_DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(1, __FUNCTION__ "()\n");
X
X ASSERT(netdev != NULL, return -1;);
X self = (struct irda_usb_cb *) netdev->priv;
@@ -1142,7 +1142,7 @@
X struct net_device *netdev;
X int err;
X
- IRDA_DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(1, __FUNCTION__ "()\n");
X
X spin_lock_init(&self->lock);
X
@@ -1197,7 +1197,7 @@
X */
X static inline int irda_usb_close(struct irda_usb_cb *self)
X {
- IRDA_DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(1, __FUNCTION__ "()\n");
X
X ASSERT(self != NULL, return -1;);
X
@@ -1326,39 +1326,43 @@
X */
X static inline struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum)
X {
- struct usb_interface_descriptor *interface;
- struct irda_class_desc *desc, *ptr;
+ struct irda_class_desc *desc;
X int ret;
-
- desc = kmalloc(sizeof (struct irda_class_desc), GFP_KERNEL);
+
+ desc = kmalloc(sizeof (*desc), GFP_KERNEL);
X if (desc == NULL)
X return NULL;
- memset(desc, 0, sizeof(struct irda_class_desc));
-
- ret = usb_get_class_descriptor(dev, ifnum, USB_DT_IRDA, 0, (void *) desc, sizeof(struct irda_class_desc));
- IRDA_DEBUG(0, __FUNCTION__ "(), ret=%d\n", ret);
- if (ret) {
- WARNING("usb-irda: usb_get_class_descriptor failed (0x%x)\n", ret);
- }
+ memset(desc, 0, sizeof(*desc));
X
- /* Check if we found it? */
- if (desc->bDescriptorType == USB_DT_IRDA)
- return desc;
+ /* USB-IrDA class spec 1.0:
+ * 6.1.3: Standard "Get Descriptor" Device Request is not
+ * appropriate to retrieve class-specific descriptor
+ * 6.2.5: Class Specific "Get Class Descriptor" Interface Request
+ * is mandatory and returns the USB-IrDA class descriptor
+ */
X
- IRDA_DEBUG(0, __FUNCTION__ "(), parsing extra descriptors ...\n");
+ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
+ IU_REQ_GET_CLASS_DESC,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0, ifnum, desc, sizeof(*desc), MSECS_TO_JIFFIES(500));
X
- /* Check if the class descriptor is interleaved with standard descriptors */
- interface = &dev->actconfig->interface[ifnum].altsetting[0];
- ret = usb_get_extra_descriptor(interface, USB_DT_IRDA, &ptr);
- if (ret) {
- kfree(desc);
- return NULL;
+ IRDA_DEBUG(1, __FUNCTION__ "(), ret=%d\n", ret);
+ if (ret < sizeof(*desc)) {
+ WARNING("usb-irda: class_descriptor read %s (%d)\n",
+ (ret<0) ? "failed" : "too short", ret);
+ }
+ else if (desc->bDescriptorType != USB_DT_IRDA) {
+ WARNING("usb-irda: bad class_descriptor type\n");
X }
- *desc = *ptr;
+ else {
X #ifdef IU_DUMP_CLASS_DESC
- irda_usb_dump_class_desc(desc);
+ irda_usb_dump_class_desc(desc);
X #endif /* IU_DUMP_CLASS_DESC */
- return desc;


+
+ return desc;
+ }

+ kfree(desc);
+ return NULL;
X }
X
X /*********************** USB DEVICE CALLBACKS ***********************/
@@ -1389,9 +1393,9 @@
X * don't need to check if the dongle is really ours.
X * Jean II */
X
- IRDA_DEBUG(0, "Vendor: %x, Product: %x\n", dev->descriptor.idVendor, dev->descriptor.idProduct);
-
- MESSAGE("IRDA-USB found at address %d\n", dev->devnum);
+ MESSAGE("IRDA-USB found at address %d, Vendor: %x, Product: %x\n",
+ dev->devnum, dev->descriptor.idVendor,
+ dev->descriptor.idProduct);
X
X /* Try to cleanup all instance that have a pending disconnect
X * Instance will be in this state is the disconnect() occurs
@@ -1416,7 +1420,7 @@
X }
X }
X if(self == NULL) {
- IRDA_DEBUG(0, "Too many USB IrDA devices !!! (max = %d)\n",
+ WARNING("Too many USB IrDA devices !!! (max = %d)\n",
X NIRUSB);
X return NULL;
X }
@@ -1436,7 +1440,7 @@
X * specify an alternate, but very few driver do like this.
X * Jean II */
X ret = usb_set_interface(dev, ifnum, 0);
- IRDA_DEBUG(0, "usb-irda: set interface %d result %d\n", ifnum, ret);
+ IRDA_DEBUG(1, "usb-irda: set interface %d result %d\n", ifnum, ret);
X switch (ret) {
X case USB_ST_NOERROR: /* 0 */
X break;
@@ -1485,7 +1489,7 @@
X struct irda_usb_cb *self = (struct irda_usb_cb *) ptr;
X int i;
X
- IRDA_DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(1, __FUNCTION__ "()\n");
X
X /* Oups ! We are not there any more */
X self->present = 0;
diff -u --recursive --new-file v2.4.14/linux/drivers/net/irda/vlsi_ir.c linux/drivers/net/irda/vlsi_ir.c
--- v2.4.14/linux/drivers/net/irda/vlsi_ir.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/irda/vlsi_ir.c Fri Nov 9 13:41:42 2001
@@ -1238,7 +1238,7 @@
X }
X printk(KERN_INFO "%s: registered device %s\n", drivername, ndev->name);
X
- pdev->driver_data = ndev;
+ pci_set_drvdata(pdev, ndev);


X
X return 0;
X

@@ -1247,13 +1247,13 @@
X out_disable:
X pci_disable_device(pdev);
X out:


- pdev->driver_data = NULL;
+ pci_set_drvdata(pdev, NULL);

X return -ENODEV;
X }
X
X static void __devexit vlsi_irda_remove(struct pci_dev *pdev)
X {
- struct net_device *ndev = pdev->driver_data;
+ struct net_device *ndev = pci_get_drvdata(pdev);
X
X if (ndev) {
X printk(KERN_INFO "%s: unregister device %s\n",
@@ -1267,7 +1267,7 @@
X }
X else
X printk(KERN_CRIT "%s: lost netdevice?\n", drivername);


- pdev->driver_data = NULL;

+ pci_set_drvdata(pdev, NULL);
X
X pci_disable_device(pdev);
X printk(KERN_INFO "%s: %s disabled\n", drivername, pdev->name);
diff -u --recursive --new-file v2.4.14/linux/drivers/net/natsemi.c linux/drivers/net/natsemi.c
--- v2.4.14/linux/drivers/net/natsemi.c Mon Nov 5 15:55:30 2001
+++ linux/drivers/net/natsemi.c Mon Nov 19 15:19:42 2001
@@ -1,6 +1,7 @@
X /* natsemi.c: A Linux PCI Ethernet driver for the NatSemi DP8381x series. */
X /*
X Written/copyright 1999-2001 by Donald Becker.
+ Portions copyright (c) 2001 Sun Microsystems (tho...@sun.com)
X
X This software may be used and distributed according to the terms of
X the GNU General Public License (GPL), incorporated herein by reference.
@@ -95,6 +96,12 @@
X * MDIO Cleanup (Tim Hockin)
X * Reformat register offsets/bits (jgarzik)
X
+ version 1.0.12:
+ * ETHTOOL_* further support (Tim Hockin)
+
+ version 1.0.13:
+ * ETHTOOL_[GS]EEPROM support (Tim Hockin)
+
X TODO:
X * big endian support with CFG:BEM instead of cpu_to_le32
X * support for an external PHY
@@ -102,7 +109,7 @@
X */
X
X #define DRV_NAME "natsemi"
-#define DRV_VERSION "1.07+LK1.0.11"
+#define DRV_VERSION "1.07+LK1.0.13"
X #define DRV_RELDATE "Oct 19, 2001"
X
X /* Updated to recommendations in pci-skeleton v2.03. */
@@ -162,6 +169,14 @@
X
X #define NATSEMI_HW_TIMEOUT 400
X #define NATSEMI_TIMER_FREQ 3*HZ
+#define NATSEMI_PG0_NREGS 64
+#define NATSEMI_RFDR_NREGS 8
+#define NATSEMI_PG1_NREGS 4
+#define NATSEMI_NREGS (NATSEMI_PG0_NREGS + NATSEMI_RFDR_NREGS + \
+ NATSEMI_PG1_NREGS)
+#define NATSEMI_REGS_VER 1 /* v1 added RFDR registers */
+#define NATSEMI_REGS_SIZE (NATSEMI_NREGS * sizeof(u32))
+#define NATSEMI_EEPROM_SIZE 24 /* 12 16-bit values */
X
X #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */
X
@@ -647,6 +662,8 @@
X static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd);
X static void enable_wol_mode(struct net_device *dev, int enable_intr);
X static int netdev_close(struct net_device *dev);
+static int netdev_get_regs(struct net_device *dev, u8 *buf);
+static int netdev_get_eeprom(struct net_device *dev, u8 *buf);
X
X
X static int __devinit natsemi_probe1 (struct pci_dev *pdev,
@@ -789,7 +806,7 @@
X chip_config & CfgAnegFull ? "full" : "half");
X }
X printk(KERN_INFO "%s: Transceiver status 0x%4.4x advertising %4.4x.\n",
- dev->name, (int)mdio_read(dev, 1, MII_BMSR),
+ dev->name, mdio_read(dev, 1, MII_BMSR),
X np->advertising);
X
X /* save the silicon revision for later querying */
@@ -1647,8 +1664,12 @@
X printk(KERN_NOTICE "%s: Link wake-up event %8.8x\n",
X dev->name, wol_status);
X }
- if (intr_status & RxStatusFIFOOver && debug) {
- printk(KERN_NOTICE "%s: Rx status FIFO overrun\n", dev->name);
+ if (intr_status & RxStatusFIFOOver) {
+ if (debug >= 2) {
+ printk(KERN_NOTICE "%s: Rx status FIFO overrun\n",
+ dev->name);
+ }
+ np->stats.rx_fifo_errors++;
X }
X /* Hmmmmm, it's not clear how to recover from PCI faults. */
X if (intr_status & IntrPCIErr) {
@@ -1794,22 +1815,29 @@
X static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
X {


X struct netdev_private *np = dev->priv;

- struct ethtool_cmd ecmd;
-
- if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+ u32 cmd;
+
+ if (get_user(cmd, (u32 *)useraddr))
X return -EFAULT;
X
- switch (ecmd.cmd) {
+ switch (cmd) {
+ /* get driver info */
X case ETHTOOL_GDRVINFO: {
X struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
- strcpy(info.driver, DRV_NAME);
- strcpy(info.version, DRV_VERSION);
- strcpy(info.bus_info, np->pci_dev->slot_name);
+ strncpy(info.driver, DRV_NAME, ETHTOOL_BUSINFO_LEN);
+ strncpy(info.version, DRV_VERSION, ETHTOOL_BUSINFO_LEN);
+ info.fw_version[0] = '\0';
+ strncpy(info.bus_info, np->pci_dev->slot_name,
+ ETHTOOL_BUSINFO_LEN);
+ info.eedump_len = NATSEMI_EEPROM_SIZE;
+ info.regdump_len = NATSEMI_REGS_SIZE;
X if (copy_to_user(useraddr, &info, sizeof(info)))
X return -EFAULT;
X return 0;
X }
+ /* get settings */
X case ETHTOOL_GSET: {
+ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
X spin_lock_irq(&np->lock);
X netdev_get_ecmd(dev, &ecmd);
X spin_unlock_irq(&np->lock);
@@ -1817,7 +1845,9 @@
X return -EFAULT;
X return 0;
X }
+ /* set settings */
X case ETHTOOL_SSET: {
+ struct ethtool_cmd ecmd;
X int r;
X if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
X return -EFAULT;
@@ -1826,6 +1856,7 @@
X spin_unlock_irq(&np->lock);
X return r;
X }
+ /* get wake-on-lan */
X case ETHTOOL_GWOL: {
X struct ethtool_wolinfo wol = {ETHTOOL_GWOL};
X spin_lock_irq(&np->lock);
@@ -1836,6 +1867,7 @@
X return -EFAULT;
X return 0;
X }
+ /* set wake-on-lan */
X case ETHTOOL_SWOL: {
X struct ethtool_wolinfo wol;
X int r;
@@ -1847,6 +1879,99 @@
X spin_unlock_irq(&np->lock);
X return r;
X }
+ /* get registers */
+ case ETHTOOL_GREGS: {
+ struct ethtool_regs regs;
+ u8 regbuf[NATSEMI_REGS_SIZE];
+ int r;
+
+ if (copy_from_user(&regs, useraddr, sizeof(regs)))
+ return -EFAULT;
+
+ if (regs.len > NATSEMI_REGS_SIZE) {
+ regs.len = NATSEMI_REGS_SIZE;
+ }
+ regs.version = NATSEMI_REGS_VER;
+ if (copy_to_user(useraddr, &regs, sizeof(regs)))
+ return -EFAULT;
+
+ useraddr += offsetof(struct ethtool_regs, data);
+
+ spin_lock_irq(&np->lock);
+ r = netdev_get_regs(dev, regbuf);
+ spin_unlock_irq(&np->lock);
+
+ if (r)
+ return r;
+ if (copy_to_user(useraddr, regbuf, regs.len))


+ return -EFAULT;
+ return 0;
+ }

+ /* get message-level */
+ case ETHTOOL_GMSGLVL: {
+ struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+ edata.data = debug;
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))


+ return -EFAULT;
+ return 0;
+ }

+ /* set message-level */
+ case ETHTOOL_SMSGLVL: {
+ struct ethtool_value edata;
+ if (copy_from_user(&edata, useraddr, sizeof(edata)))
+ return -EFAULT;
+ debug = edata.data;
+ return 0;
+ }
+ /* restart autonegotiation */
+ case ETHTOOL_NWAY_RST: {
+ int tmp;
+ int r = -EINVAL;
+ /* if autoneg is off, it's an error */
+ tmp = mdio_read(dev, 1, MII_BMCR);
+ if (tmp & BMCR_ANENABLE) {
+ tmp |= (BMCR_ANRESTART);
+ mdio_write(dev, 1, MII_BMCR, tmp);
+ r = 0;
+ }
+ return r;
+ }
+ /* get link status */
+ case ETHTOOL_GLINK: {
+ struct ethtool_value edata = {ETHTOOL_GLINK};
+ edata.data = (mdio_read(dev, 1, MII_BMSR)&BMSR_LSTATUS) ? 1:0;
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))


+ return -EFAULT;
+ return 0;
+ }

+ /* get EEPROM */
+ case ETHTOOL_GEEPROM: {
+ struct ethtool_eeprom eeprom;
+ u8 eebuf[NATSEMI_EEPROM_SIZE];
+ int r;
+
+ if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
+ return -EFAULT;
+
+ if ((eeprom.offset+eeprom.len) > NATSEMI_EEPROM_SIZE) {
+ eeprom.len = NATSEMI_EEPROM_SIZE-eeprom.offset;
+ }
+ eeprom.magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16);
+ if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
+ return -EFAULT;
+
+ useraddr += offsetof(struct ethtool_eeprom, data);
+
+ spin_lock_irq(&np->lock);
+ r = netdev_get_eeprom(dev, eebuf);
+ spin_unlock_irq(&np->lock);
+
+ if (r)
+ return r;
+ if (copy_to_user(useraddr, eebuf+eeprom.offset, eeprom.len))


+ return -EFAULT;
+ return 0;
+ }

X
X }
X
@@ -2081,6 +2206,69 @@


X np->full_duplex = 0;

X }
X mdio_write(dev, 1, MII_BMCR, tmp);


+ }
+ return 0;
+}
+

+static int netdev_get_regs(struct net_device *dev, u8 *buf)
+{
+ int i;
+ int j;
+ u32 rfcr;
+ u32 *rbuf = (u32 *)buf;
+
+ /* read all of page 0 of registers */
+ for (i = 0; i < NATSEMI_PG0_NREGS; i++) {
+ rbuf[i] = readl(dev->base_addr + i*4);
+ }
+
+ /* read only the 'magic' registers from page 1 */
+ writew(1, dev->base_addr + PGSEL);
+ rbuf[i++] = readw(dev->base_addr + PMDCSR);
+ rbuf[i++] = readw(dev->base_addr + TSTDAT);
+ rbuf[i++] = readw(dev->base_addr + DSPCFG);
+ rbuf[i++] = readw(dev->base_addr + SDCFG);
+ writew(0, dev->base_addr + PGSEL);
+
+ /* read RFCR indexed registers */
+ rfcr = readl(dev->base_addr + RxFilterAddr);
+ for (j = 0; j < NATSEMI_RFDR_NREGS; j++) {
+ writel(j*2, dev->base_addr + RxFilterAddr);
+ rbuf[i++] = readw(dev->base_addr + RxFilterData);
+ }
+ writel(rfcr, dev->base_addr + RxFilterAddr);
+
+ /* the interrupt status is clear-on-read - see if we missed any */
+ if (rbuf[4] & rbuf[5]) {
+ printk(KERN_WARNING
+ "%s: shoot, we dropped an interrupt (0x%x)\n",
+ dev->name, rbuf[4] & rbuf[5]);
+ }


+
+ return 0;
+}
+

+#define SWAP_BITS(x) ( (((x) & 0x0001) << 15) | (((x) & 0x0002) << 13) \
+ | (((x) & 0x0004) << 11) | (((x) & 0x0008) << 9) \
+ | (((x) & 0x0010) << 7) | (((x) & 0x0020) << 5) \
+ | (((x) & 0x0040) << 3) | (((x) & 0x0080) << 1) \
+ | (((x) & 0x0100) >> 1) | (((x) & 0x0200) >> 3) \
+ | (((x) & 0x0400) >> 5) | (((x) & 0x0800) >> 7) \
+ | (((x) & 0x1000) >> 9) | (((x) & 0x2000) >> 11) \
+ | (((x) & 0x4000) >> 13) | (((x) & 0x8000) >> 15) )
+
+static int netdev_get_eeprom(struct net_device *dev, u8 *buf)
+{
+ int i;
+ u16 *ebuf = (u16 *)buf;
+
+ /* eeprom_read reads 16 bits, and indexes by 16 bits */
+ for (i = 0; i < NATSEMI_EEPROM_SIZE/2; i++) {
+ ebuf[i] = eeprom_read(dev->base_addr, i);
+ /* The EEPROM itself stores data bit-swapped, but eeprom_read
+ * reads it back "sanely". So we swap it back here in order to
+ * present it to userland as it is stored. */
+ ebuf[i] = SWAP_BITS(ebuf[i]);


X }
X return 0;
X }

diff -u --recursive --new-file v2.4.14/linux/drivers/net/ns83820.c linux/drivers/net/ns83820.c
--- v2.4.14/linux/drivers/net/ns83820.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/ns83820.c Fri Nov 9 13:45:35 2001
@@ -1465,7 +1465,7 @@
X
X static int __init ns83820_init(void)
X {
- printk(KERN_INFO "ns83820.c: National Semiconductor DP83820 10/100/100 driver.\n");
+ printk(KERN_INFO "ns83820.c: National Semiconductor DP83820 10/100/1000 driver.\n");
X return pci_module_init(&driver);
X }
X
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/3c574_cs.c linux/drivers/net/pcmcia/3c574_cs.c
--- v2.4.14/linux/drivers/net/pcmcia/3c574_cs.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/pcmcia/3c574_cs.c Tue Nov 13 09:02:30 2001
@@ -14,10 +14,6 @@
X
X */
X
-/* Driver author info must always be in the binary. Version too.. */
-static const char *tc574_version =
-"3c574_cs.c v1.08 9/24/98 Donald Becker/David Hinds, bec...@scyld.com.\n";


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

echo 'End of part 052'
echo 'File patch-2.4.15 is continued in part 053'
echo "053" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:37 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part061

#!/bin/sh -x
# this is part 061 of a 115 - part archive


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

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

+ * derived from this software without specific prior written permission.
+ *
+ * Where this Software is combined with software released under the terms of
+ * the GNU Public License ("GPL") and the terms of the GPL would require the
+ * combined work to also be released under the terms of the GPL, the terms
+ * and conditions of this License will apply in addition to those of the
+ * GPL with the exception of any terms or conditions of this License that
+ * conflict with, or are expressly prohibited by, the GPL.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+

+#ifndef SYM_FW_H
+#define SYM_FW_H
+/*
+ * Macro used to generate interfaces for script A.
+ */
+#define SYM_GEN_FW_A(s) \
+ SYM_GEN_A(s, start) SYM_GEN_A(s, getjob_begin) \
+ SYM_GEN_A(s, getjob_end) \
+ SYM_GEN_A(s, select) SYM_GEN_A(s, wf_sel_done) \
+ SYM_GEN_A(s, send_ident) \
+ SYM_GEN_A(s, dispatch) SYM_GEN_A(s, init) \
+ SYM_GEN_A(s, clrack) SYM_GEN_A(s, complete_error) \
+ SYM_GEN_A(s, done) SYM_GEN_A(s, done_end) \
+ SYM_GEN_A(s, idle) SYM_GEN_A(s, ungetjob) \
+ SYM_GEN_A(s, reselect) \
+ SYM_GEN_A(s, resel_tag) SYM_GEN_A(s, resel_dsa) \
+ SYM_GEN_A(s, resel_no_tag) \
+ SYM_GEN_A(s, data_in) SYM_GEN_A(s, data_in2) \
+ SYM_GEN_A(s, data_out) SYM_GEN_A(s, data_out2) \
+ SYM_GEN_A(s, pm0_data) SYM_GEN_A(s, pm1_data)
+
+/*
+ * Macro used to generate interfaces for script B.
+ */
+#define SYM_GEN_FW_B(s) \
+ SYM_GEN_B(s, no_data) \
+ SYM_GEN_B(s, sel_for_abort) SYM_GEN_B(s, sel_for_abort_1) \
+ SYM_GEN_B(s, msg_bad) SYM_GEN_B(s, msg_weird) \
+ SYM_GEN_B(s, wdtr_resp) SYM_GEN_B(s, send_wdtr) \
+ SYM_GEN_B(s, sdtr_resp) SYM_GEN_B(s, send_sdtr) \
+ SYM_GEN_B(s, ppr_resp) SYM_GEN_B(s, send_ppr) \
+ SYM_GEN_B(s, nego_bad_phase) \
+ SYM_GEN_B(s, ident_break) SYM_GEN_B(s, ident_break_atn) \
+ SYM_GEN_B(s, sdata_in) SYM_GEN_B(s, resel_bad_lun) \
+ SYM_GEN_B(s, bad_i_t_l) SYM_GEN_B(s, bad_i_t_l_q) \
+ SYM_GEN_B(s, wsr_ma_helper)
+
+/*
+ * Macro used to generate interfaces for script Z.
+ */
+#define SYM_GEN_FW_Z(s) \
+ SYM_GEN_Z(s, snooptest) SYM_GEN_Z(s, snoopend)
+
+/*
+ * Generates structure interface that contains
+ * offsets within script A, B and Z.
+ */
+#define SYM_GEN_A(s, label) s label;
+#define SYM_GEN_B(s, label) s label;
+#define SYM_GEN_Z(s, label) s label;
+struct sym_fwa_ofs {
+ SYM_GEN_FW_A(u_short)
+};
+struct sym_fwb_ofs {
+ SYM_GEN_FW_B(u_short)
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+ SYM_GEN_B(u_short, data_io)
+#endif
+ SYM_GEN_B(u_short, start64)
+ SYM_GEN_B(u_short, pm_handle)
+};
+struct sym_fwz_ofs {
+ SYM_GEN_FW_Z(u_short)
+#ifdef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ SYM_GEN_Z(u_short, start_ram)
+ SYM_GEN_Z(u_short, start_ram64)
+#endif
+};
+
+/*
+ * Generates structure interface that contains
+ * bus addresses within script A, B and Z.
+ */
+struct sym_fwa_ba {
+ SYM_GEN_FW_A(u32)
+};
+struct sym_fwb_ba {
+ SYM_GEN_FW_B(u32)
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+ SYM_GEN_B(u32, data_io)
+#endif
+ SYM_GEN_B(u32, start64);
+ SYM_GEN_B(u32, pm_handle);
+};
+struct sym_fwz_ba {
+ SYM_GEN_FW_Z(u32)
+#ifdef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ SYM_GEN_Z(u32, start_ram)
+ SYM_GEN_Z(u32, start_ram64)
+#endif


+};
+#undef SYM_GEN_A
+#undef SYM_GEN_B
+#undef SYM_GEN_Z
+

+/*
+ * Let cc know about the name of the controller data structure.
+ * We need this for function prototype declarations just below.
+ */
+struct sym_hcb;
+
+/*
+ * Generic structure that defines a firmware.
+ */
+struct sym_fw {
+ char *name; /* Name we want to print out */
+ u32 *a_base; /* Pointer to script A template */
+ int a_size; /* Size of script A */
+ struct sym_fwa_ofs
+ *a_ofs; /* Useful offsets in script A */
+ u32 *b_base; /* Pointer to script B template */
+ int b_size; /* Size of script B */
+ struct sym_fwb_ofs
+ *b_ofs; /* Useful offsets in script B */
+ u32 *z_base; /* Pointer to script Z template */
+ int z_size; /* Size of script Z */
+ struct sym_fwz_ofs
+ *z_ofs; /* Useful offsets in script Z */
+ /* Setup and patch methods for this firmware */
+ void (*setup)(struct sym_hcb *, struct sym_fw *);
+ void (*patch)(struct sym_hcb *);
+};
+
+/*
+ * Macro used to declare a firmware.
+ */
+#define SYM_FW_ENTRY(fw, name) \
+{ \
+ name, \
+ (u32 *) &fw##a_scr, sizeof(fw##a_scr), &fw##a_ofs, \
+ (u32 *) &fw##b_scr, sizeof(fw##b_scr), &fw##b_ofs, \
+ (u32 *) &fw##z_scr, sizeof(fw##z_scr), &fw##z_ofs, \
+ fw##_setup, fw##_patch \
+}
+
+/*
+ * Macros used from the C code to get useful
+ * SCRIPTS bus addresses.
+ */
+#define SCRIPTA_BA(np, label) (np->fwa_bas.label)
+#define SCRIPTB_BA(np, label) (np->fwb_bas.label)
+#define SCRIPTZ_BA(np, label) (np->fwz_bas.label)
+
+/*
+ * Macros used by scripts definitions.
+ *
+ * HADDR_1 generates a reference to a field of the controller data.
+ * HADDR_2 generates a reference to a field of the controller data
+ * with offset.
+ * RADDR_1 generates a reference to a script processor register.
+ * RADDR_2 generates a reference to a script processor register
+ * with offset.
+ * PADDR_A generates a reference to another part of script A.
+ * PADDR_B generates a reference to another part of script B.
+ *
+ * SYM_GEN_PADDR_A and SYM_GEN_PADDR_B are used to define respectively
+ * the PADDR_A and PADDR_B macros for each firmware by setting argument
+ * `s' to the name of the corresponding structure.
+ *
+ * SCR_DATA_ZERO is used to allocate a DWORD of data in scripts areas.
+ */
+
+#define RELOC_SOFTC 0x40000000
+#define RELOC_LABEL_A 0x50000000
+#define RELOC_REGISTER 0x60000000
+#define RELOC_LABEL_B 0x80000000
+#define RELOC_MASK 0xf0000000
+
+#define HADDR_1(label) (RELOC_SOFTC | offsetof(struct sym_hcb, label))
+#define HADDR_2(label,ofs) (RELOC_SOFTC | \
+ (offsetof(struct sym_hcb, label)+(ofs)))
+#define RADDR_1(label) (RELOC_REGISTER | REG(label))
+#define RADDR_2(label,ofs) (RELOC_REGISTER | ((REG(label))+(ofs)))
+
+#define SYM_GEN_PADDR_A(s, label) (RELOC_LABEL_A | offsetof(s, label))
+#define SYM_GEN_PADDR_B(s, label) (RELOC_LABEL_B | offsetof(s, label))
+
+#define SCR_DATA_ZERO 0xf00ff00f
+
+#endif /* SYM_FW_H */
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_fw1.h linux/drivers/scsi/sym53c8xx_2/sym_fw1.h
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_fw1.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym_fw1.h Fri Nov 9 15:22:54 2001
@@ -0,0 +1,1874 @@

+/*
+ * Scripts for SYMBIOS-Processor
+ *
+ * We have to know the offsets of all labels before we reach
+ * them (for forward jumps). Therefore we declare a struct
+ * here. If you make changes inside the script,
+ *
+ * DONT FORGET TO CHANGE THE LENGTHS HERE!
+ */
+
+/*
+ * Script fragments which are loaded into the on-chip RAM
+ * of 825A, 875, 876, 895, 895A, 896 and 1010 chips.
+ * Must not exceed 4K bytes.
+ */
+struct SYM_FWA_SCR {
+ u32 start [ 11];
+ u32 getjob_begin [ 4];
+ u32 _sms_a10 [ 5];
+ u32 getjob_end [ 4];
+ u32 _sms_a20 [ 4];
+#ifdef SYM_CONF_TARGET_ROLE_SUPPORT
+ u32 select [ 8];
+#else
+ u32 select [ 6];
+#endif
+ u32 _sms_a30 [ 5];
+ u32 wf_sel_done [ 2];
+ u32 send_ident [ 2];
+#ifdef SYM_CONF_IARB_SUPPORT
+ u32 select2 [ 8];
+#else
+ u32 select2 [ 2];
+#endif
+ u32 command [ 2];
+ u32 dispatch [ 28];
+ u32 sel_no_cmd [ 10];
+ u32 init [ 6];
+ u32 clrack [ 4];
+ u32 datai_done [ 11];
+ u32 datai_done_wsr [ 20];
+ u32 datao_done [ 11];
+ u32 datao_done_wss [ 6];
+ u32 datai_phase [ 5];
+ u32 datao_phase [ 5];
+ u32 msg_in [ 2];
+ u32 msg_in2 [ 10];
+#ifdef SYM_CONF_IARB_SUPPORT
+ u32 status [ 14];
+#else
+ u32 status [ 10];
+#endif
+ u32 complete [ 6];
+ u32 complete2 [ 8];
+ u32 _sms_a40 [ 12];
+ u32 done [ 5];
+ u32 _sms_a50 [ 5];
+ u32 _sms_a60 [ 2];
+ u32 done_end [ 4];
+ u32 complete_error [ 5];
+ u32 save_dp [ 11];
+ u32 restore_dp [ 7];
+ u32 disconnect [ 11];
+ u32 disconnect2 [ 5];
+ u32 _sms_a65 [ 3];
+#ifdef SYM_CONF_IARB_SUPPORT
+ u32 idle [ 4];
+#else
+ u32 idle [ 2];
+#endif
+#ifdef SYM_CONF_IARB_SUPPORT
+ u32 ungetjob [ 7];
+#else
+ u32 ungetjob [ 5];
+#endif
+#ifdef SYM_CONF_TARGET_ROLE_SUPPORT
+ u32 reselect [ 4];
+#else
+ u32 reselect [ 2];
+#endif
+ u32 reselected [ 19];
+ u32 _sms_a70 [ 6];
+ u32 _sms_a80 [ 4];
+ u32 reselected1 [ 25];
+ u32 _sms_a90 [ 4];
+ u32 resel_lun0 [ 7];
+ u32 _sms_a100 [ 4];
+ u32 resel_tag [ 8];
+#if SYM_CONF_MAX_TASK*4 > 512
+ u32 _sms_a110 [ 23];
+#elif SYM_CONF_MAX_TASK*4 > 256
+ u32 _sms_a110 [ 17];
+#else
+ u32 _sms_a110 [ 13];
+#endif
+ u32 _sms_a120 [ 2];
+ u32 resel_go [ 4];
+ u32 _sms_a130 [ 7];
+ u32 resel_dsa [ 2];
+ u32 resel_dsa1 [ 4];
+ u32 _sms_a140 [ 7];
+ u32 resel_no_tag [ 4];
+ u32 _sms_a145 [ 7];
+ u32 data_in [SYM_CONF_MAX_SG * 2];
+ u32 data_in2 [ 4];
+ u32 data_out [SYM_CONF_MAX_SG * 2];
+ u32 data_out2 [ 4];
+ u32 pm0_data [ 12];
+ u32 pm0_data_out [ 6];
+ u32 pm0_data_end [ 7];
+ u32 pm_data_end [ 4];
+ u32 _sms_a150 [ 4];
+ u32 pm1_data [ 12];
+ u32 pm1_data_out [ 6];
+ u32 pm1_data_end [ 9];
+};
+
+/*
+ * Script fragments which stay in main memory for all chips
+ * except for chips that support 8K on-chip RAM.
+ */
+struct SYM_FWB_SCR {
+ u32 no_data [ 2];
+#ifdef SYM_CONF_TARGET_ROLE_SUPPORT
+ u32 sel_for_abort [ 18];
+#else
+ u32 sel_for_abort [ 16];
+#endif
+ u32 sel_for_abort_1 [ 2];
+ u32 msg_in_etc [ 12];
+ u32 msg_received [ 5];
+ u32 msg_weird_seen [ 5];
+ u32 msg_extended [ 17];
+ u32 _sms_b10 [ 4];
+ u32 msg_bad [ 6];
+ u32 msg_weird [ 4];
+ u32 msg_weird1 [ 8];
+ u32 wdtr_resp [ 6];
+ u32 send_wdtr [ 4];
+ u32 sdtr_resp [ 6];
+ u32 send_sdtr [ 4];
+ u32 ppr_resp [ 6];
+ u32 send_ppr [ 4];
+ u32 nego_bad_phase [ 4];
+ u32 msg_out [ 4];
+ u32 msg_out_done [ 4];
+ u32 data_ovrun [ 3];
+ u32 data_ovrun1 [ 22];
+ u32 data_ovrun2 [ 8];
+ u32 abort_resel [ 16];
+ u32 resend_ident [ 4];
+ u32 ident_break [ 4];
+ u32 ident_break_atn [ 4];
+ u32 sdata_in [ 6];
+ u32 resel_bad_lun [ 4];
+ u32 bad_i_t_l [ 4];
+ u32 bad_i_t_l_q [ 4];
+ u32 bad_status [ 7];
+ u32 wsr_ma_helper [ 4];
+
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+ /* Unknown direction handling */
+ u32 data_io [ 2];
+ u32 data_io_com [ 8];
+ u32 data_io_out [ 7];
+#endif
+ /* Data area */
+ u32 zero [ 1];
+ u32 scratch [ 1];
+ u32 scratch1 [ 1];
+ u32 prev_done [ 1];
+ u32 done_pos [ 1];
+ u32 nextjob [ 1];
+ u32 startpos [ 1];
+ u32 targtbl [ 1];
+};
+
+/*
+ * Script fragments used at initialisations.
+ * Only runs out of main memory.
+ */
+struct SYM_FWZ_SCR {
+ u32 snooptest [ 9];
+ u32 snoopend [ 2];
+#ifdef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ u32 start_ram [ 1];
+ u32 scripta0_ba [ 4];
+#endif
+};
+
+static struct SYM_FWA_SCR SYM_FWA_SCR = {
+/*--------------------------< START >----------------------------*/ {
+ /*
+ * Switch the LED on.
+ * Will be patched with a NO_OP if LED
+ * not needed or not desired.
+ */
+ SCR_REG_REG (gpreg, SCR_AND, 0xfe),
+ 0,
+ /*
+ * Clear SIGP.
+ */
+ SCR_FROM_REG (ctest2),
+ 0,
+ /*
+ * Stop here if the C code wants to perform
+ * some error recovery procedure manually.
+ * (Indicate this by setting SEM in ISTAT)
+ */
+ SCR_FROM_REG (istat),
+ 0,
+ /*
+ * Report to the C code the next position in
+ * the start queue the SCRIPTS will schedule.
+ * The C code must not change SCRATCHA.
+ */
+ SCR_COPY (4),
+ PADDR_B (startpos),
+ RADDR_1 (scratcha),
+ SCR_INT ^ IFTRUE (MASK (SEM, SEM)),
+ SIR_SCRIPT_STOPPED,
+ /*
+ * Start the next job.
+ *
+ * @DSA = start point for this job.
+ * SCRATCHA = address of this job in the start queue.
+ *
+ * We will restore startpos with SCRATCHA if we fails the
+ * arbitration or if it is the idle job.
+ *
+ * The below GETJOB_BEGIN to GETJOB_END section of SCRIPTS
+ * is a critical path. If it is partially executed, it then
+ * may happen that the job address is not yet in the DSA
+ * and the the next queue position points to the next JOB.
+ */
+}/*-------------------------< GETJOB_BEGIN >---------------------*/,{
+ /*
+ * Copy to a fixed location both the next STARTPOS
+ * and the current JOB address, using self modifying
+ * SCRIPTS.
+ */
+ SCR_COPY (4),
+ RADDR_1 (scratcha),
+ PADDR_A (_sms_a10),
+ SCR_COPY (8),
+}/*-------------------------< _SMS_A10 >-------------------------*/,{
+ 0,
+ PADDR_B (nextjob),
+ /*
+ * Move the start address to TEMP using self-
+ * modifying SCRIPTS and jump indirectly to
+ * that address.
+ */
+ SCR_COPY (4),
+ PADDR_B (nextjob),
+ RADDR_1 (dsa),
+}/*-------------------------< GETJOB_END >-----------------------*/,{
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ PADDR_A (_sms_a20),
+ SCR_COPY (4),
+}/*-------------------------< _SMS_A20 >-------------------------*/,{
+ 0,
+ RADDR_1 (temp),
+ SCR_RETURN,
+ 0,
+}/*-------------------------< SELECT >---------------------------*/,{
+ /*
+ * DSA contains the address of a scheduled
+ * data structure.
+ *
+ * SCRATCHA contains the address of the start queue
+ * entry which points to the next job.
+ *
+ * Set Initiator mode.
+ *
+ * (Target mode is left as an exercise for the reader)
+ */
+#ifdef SYM_CONF_TARGET_ROLE_SUPPORT
+ SCR_CLR (SCR_TRG),
+ 0,
+#endif
+ /*
+ * And try to select this target.
+ */
+ SCR_SEL_TBL_ATN ^ offsetof (struct sym_dsb, select),
+ PADDR_A (ungetjob),
+ /*
+ * Now there are 4 possibilities:
+ *
+ * (1) The chip looses arbitration.
+ * This is ok, because it will try again,
+ * when the bus becomes idle.
+ * (But beware of the timeout function!)
+ *
+ * (2) The chip is reselected.
+ * Then the script processor takes the jump
+ * to the RESELECT label.
+ *
+ * (3) The chip wins arbitration.
+ * Then it will execute SCRIPTS instruction until
+ * the next instruction that checks SCSI phase.
+ * Then will stop and wait for selection to be
+ * complete or selection time-out to occur.
+ *
+ * After having won arbitration, the SCRIPTS
+ * processor is able to execute instructions while
+ * the SCSI core is performing SCSI selection.
+ */
+
+ /*
+ * Copy the CCB header to a fixed location
+ * in the HCB using self-modifying SCRIPTS.
+ */
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ PADDR_A (_sms_a30),
+ SCR_COPY (sizeof(struct sym_ccbh)),
+}/*-------------------------< _SMS_A30 >-------------------------*/,{
+ 0,
+ HADDR_1 (ccb_head),
+ /*
+ * Initialize the status register
+ */
+ SCR_COPY (4),
+ HADDR_1 (ccb_head.status),
+ RADDR_1 (scr0),
+}/*-------------------------< WF_SEL_DONE >----------------------*/,{
+ SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+ SIR_SEL_ATN_NO_MSG_OUT,
+}/*-------------------------< SEND_IDENT >-----------------------*/,{
+ /*
+ * Selection complete.
+ * Send the IDENTIFY and possibly the TAG message
+ * and negotiation message if present.
+ */
+ SCR_MOVE_TBL ^ SCR_MSG_OUT,
+ offsetof (struct sym_dsb, smsg),
+}/*-------------------------< SELECT2 >--------------------------*/,{
+#ifdef SYM_CONF_IARB_SUPPORT
+ /*
+ * Set IMMEDIATE ARBITRATION if we have been given
+ * a hint to do so. (Some job to do after this one).
+ */
+ SCR_FROM_REG (HF_REG),
+ 0,
+ SCR_JUMPR ^ IFFALSE (MASK (HF_HINT_IARB, HF_HINT_IARB)),
+ 8,
+ SCR_REG_REG (scntl1, SCR_OR, IARB),
+ 0,
+#endif
+ /*
+ * Anticipate the COMMAND phase.
+ * This is the PHASE we expect at this point.
+ */
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_COMMAND)),
+ PADDR_A (sel_no_cmd),
+}/*-------------------------< COMMAND >--------------------------*/,{
+ /*
+ * ... and send the command
+ */
+ SCR_MOVE_TBL ^ SCR_COMMAND,
+ offsetof (struct sym_dsb, cmd),
+}/*-------------------------< DISPATCH >-------------------------*/,{
+ /*
+ * MSG_IN is the only phase that shall be
+ * entered at least once for each (re)selection.
+ * So we test it first.
+ */
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
+ PADDR_A (msg_in),
+ SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT)),
+ PADDR_A (datao_phase),
+ SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN)),
+ PADDR_A (datai_phase),
+ SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)),
+ PADDR_A (status),
+ SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)),
+ PADDR_A (command),
+ SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)),
+ PADDR_B (msg_out),
+ /*
+ * Discard as many illegal phases as
+ * required and tell the C code about.
+ */
+ SCR_JUMPR ^ IFFALSE (WHEN (SCR_ILG_OUT)),
+ 16,
+ SCR_MOVE_ABS (1) ^ SCR_ILG_OUT,
+ HADDR_1 (scratch),
+ SCR_JUMPR ^ IFTRUE (WHEN (SCR_ILG_OUT)),
+ -16,
+ SCR_JUMPR ^ IFFALSE (WHEN (SCR_ILG_IN)),
+ 16,
+ SCR_MOVE_ABS (1) ^ SCR_ILG_IN,
+ HADDR_1 (scratch),
+ SCR_JUMPR ^ IFTRUE (WHEN (SCR_ILG_IN)),
+ -16,
+ SCR_INT,
+ SIR_BAD_PHASE,
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< SEL_NO_CMD >-----------------------*/,{
+ /*
+ * The target does not switch to command
+ * phase after IDENTIFY has been sent.
+ *
+ * If it stays in MSG OUT phase send it
+ * the IDENTIFY again.
+ */
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)),
+ PADDR_B (resend_ident),
+ /*
+ * If target does not switch to MSG IN phase
+ * and we sent a negotiation, assert the
+ * failure immediately.
+ */
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
+ PADDR_A (dispatch),
+ SCR_FROM_REG (HS_REG),
+ 0,
+ SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
+ SIR_NEGO_FAILED,
+ /*
+ * Jump to dispatcher.
+ */
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< INIT >-----------------------------*/,{
+ /*
+ * Wait for the SCSI RESET signal to be
+ * inactive before restarting operations,
+ * since the chip may hang on SEL_ATN
+ * if SCSI RESET is active.
+ */
+ SCR_FROM_REG (sstat0),
+ 0,
+ SCR_JUMPR ^ IFTRUE (MASK (IRST, IRST)),
+ -16,
+ SCR_JUMP,
+ PADDR_A (start),
+}/*-------------------------< CLRACK >---------------------------*/,{
+ /*
+ * Terminate possible pending message phase.
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< DATAI_DONE >-----------------------*/,{
+ /*
+ * Save current pointer to LASTP.
+ */
+ SCR_COPY (4),
+ RADDR_1 (temp),
+ HADDR_1 (ccb_head.lastp),
+ /*
+ * If the SWIDE is not full, jump to dispatcher.
+ * We anticipate a STATUS phase.
+ */
+ SCR_FROM_REG (scntl2),
+ 0,
+ SCR_JUMP ^ IFTRUE (MASK (WSR, WSR)),
+ PADDR_A (datai_done_wsr),
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)),
+ PADDR_A (status),
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< DATAI_DONE_WSR >-------------------*/,{
+ /*
+ * The SWIDE is full.
+ * Clear this condition.
+ */
+ SCR_REG_REG (scntl2, SCR_OR, WSR),
+ 0,
+ /*
+ * We are expecting an IGNORE RESIDUE message
+ * from the device, otherwise we are in data
+ * overrun condition. Check against MSG_IN phase.
+ */
+ SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)),
+ SIR_SWIDE_OVERRUN,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
+ PADDR_A (dispatch),
+ /*
+ * We are in MSG_IN phase,
+ * Read the first byte of the message.
+ * If it is not an IGNORE RESIDUE message,
+ * signal overrun and jump to message
+ * processing.
+ */
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ HADDR_1 (msgin[0]),
+ SCR_INT ^ IFFALSE (DATA (M_IGN_RESIDUE)),
+ SIR_SWIDE_OVERRUN,
+ SCR_JUMP ^ IFFALSE (DATA (M_IGN_RESIDUE)),
+ PADDR_A (msg_in2),
+ /*
+ * We got the message we expected.
+ * Read the 2nd byte, and jump to dispatcher.
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ HADDR_1 (msgin[1]),
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< DATAO_DONE >-----------------------*/,{
+ /*
+ * Save current pointer to LASTP.
+ */
+ SCR_COPY (4),
+ RADDR_1 (temp),
+ HADDR_1 (ccb_head.lastp),
+ /*
+ * If the SODL is not full jump to dispatcher.
+ * We anticipate a STATUS phase.
+ */
+ SCR_FROM_REG (scntl2),
+ 0,
+ SCR_JUMP ^ IFTRUE (MASK (WSS, WSS)),
+ PADDR_A (datao_done_wss),
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)),
+ PADDR_A (status),
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< DATAO_DONE_WSS >-------------------*/,{
+ /*
+ * The SODL is full, clear this condition.
+ */
+ SCR_REG_REG (scntl2, SCR_OR, WSS),
+ 0,
+ /*
+ * And signal a DATA UNDERRUN condition
+ * to the C code.
+ */
+ SCR_INT,
+ SIR_SODL_UNDERRUN,
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< DATAI_PHASE >----------------------*/,{
+ /*
+ * Jump to current pointer.
+ */
+ SCR_COPY (4),
+ HADDR_1 (ccb_head.lastp),
+ RADDR_1 (temp),
+ SCR_RETURN,
+ 0,
+}/*-------------------------< DATAO_PHASE >----------------------*/,{
+ /*
+ * Jump to current pointer.
+ */
+ SCR_COPY (4),
+ HADDR_1 (ccb_head.lastp),
+ RADDR_1 (temp),
+ SCR_RETURN,
+ 0,
+}/*-------------------------< MSG_IN >---------------------------*/,{
+ /*
+ * Get the first byte of the message.
+ *
+ * The script processor doesn't negate the
+ * ACK signal after this transfer.
+ */
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ HADDR_1 (msgin[0]),
+}/*-------------------------< MSG_IN2 >--------------------------*/,{
+ /*
+ * Check first against 1 byte messages
+ * that we handle from SCRIPTS.
+ */
+ SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)),
+ PADDR_A (complete),
+ SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)),
+ PADDR_A (disconnect),
+ SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)),
+ PADDR_A (save_dp),
+ SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)),
+ PADDR_A (restore_dp),
+ /*
+ * We handle all other messages from the
+ * C code, so no need to waste on-chip RAM
+ * for those ones.
+ */
+ SCR_JUMP,
+ PADDR_B (msg_in_etc),
+}/*-------------------------< STATUS >---------------------------*/,{
+ /*
+ * get the status
+ */
+ SCR_MOVE_ABS (1) ^ SCR_STATUS,
+ HADDR_1 (scratch),
+#ifdef SYM_CONF_IARB_SUPPORT
+ /*
+ * If STATUS is not GOOD, clear IMMEDIATE ARBITRATION,
+ * since we may have to tamper the start queue from
+ * the C code.
+ */
+ SCR_JUMPR ^ IFTRUE (DATA (S_GOOD)),
+ 8,
+ SCR_REG_REG (scntl1, SCR_AND, ~IARB),
+ 0,
+#endif
+ /*
+ * save status to scsi_status.
+ * mark as complete.
+ */
+ SCR_TO_REG (SS_REG),
+ 0,
+ SCR_LOAD_REG (HS_REG, HS_COMPLETE),
+ 0,
+ /*
+ * Anticipate the MESSAGE PHASE for
+ * the TASK COMPLETE message.
+ */
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
+ PADDR_A (msg_in),
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< COMPLETE >-------------------------*/,{
+ /*
+ * Complete message.
+ *
+ * When we terminate the cycle by clearing ACK,
+ * the target may disconnect immediately.
+ *
+ * We don't want to be told of an "unexpected disconnect",
+ * so we disable this feature.
+ */
+ SCR_REG_REG (scntl2, SCR_AND, 0x7f),
+ 0,
+ /*
+ * Terminate cycle ...
+ */
+ SCR_CLR (SCR_ACK|SCR_ATN),
+ 0,
+ /*
+ * ... and wait for the disconnect.
+ */
+ SCR_WAIT_DISC,
+ 0,
+}/*-------------------------< COMPLETE2 >------------------------*/,{
+ /*
+ * Save host status.
+ */
+ SCR_COPY (4),
+ RADDR_1 (scr0),
+ HADDR_1 (ccb_head.status),
+ /*
+ * Move back the CCB header using self-modifying
+ * SCRIPTS.
+ */
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ PADDR_A (_sms_a40),
+ SCR_COPY (sizeof(struct sym_ccbh)),
+ HADDR_1 (ccb_head),
+}/*-------------------------< _SMS_A40 >-------------------------*/,{
+ 0,
+ /*
+ * Some bridges may reorder DMA writes to memory.
+ * We donnot want the CPU to deal with completions
+ * without all the posted write having been flushed
+ * to memory. This DUMMY READ should flush posted
+ * buffers prior to the CPU having to deal with
+ * completions.
+ */
+ SCR_COPY (4), /* DUMMY READ */
+ HADDR_1 (ccb_head.status),
+ RADDR_1 (scr0),
+ /*
+ * If command resulted in not GOOD status,
+ * call the C code if needed.
+ */
+ SCR_FROM_REG (SS_REG),
+ 0,
+ SCR_CALL ^ IFFALSE (DATA (S_GOOD)),
+ PADDR_B (bad_status),
+ /*
+ * If we performed an auto-sense, call
+ * the C code to synchronyze task aborts
+ * with UNIT ATTENTION conditions.
+ */
+ SCR_FROM_REG (HF_REG),
+ 0,
+ SCR_JUMP ^ IFFALSE (MASK (0 ,(HF_SENSE|HF_EXT_ERR))),
+ PADDR_A (complete_error),
+}/*-------------------------< DONE >-----------------------------*/,{
+ /*
+ * Copy the DSA to the DONE QUEUE and
+ * signal completion to the host.
+ * If we are interrupted between DONE
+ * and DONE_END, we must reset, otherwise
+ * the completed CCB may be lost.
+ */
+ SCR_COPY (4),
+ PADDR_B (done_pos),
+ PADDR_A (_sms_a50),
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+}/*-------------------------< _SMS_A50 >-------------------------*/,{
+ 0,
+ SCR_COPY (4),
+ PADDR_B (done_pos),
+ PADDR_A (_sms_a60),
+ /*
+ * The instruction below reads the DONE QUEUE next
+ * free position from memory.
+ * In addition it ensures that all PCI posted writes
+ * are flushed and so the DSA value of the done
+ * CCB is visible by the CPU before INTFLY is raised.
+ */
+ SCR_COPY (8),
+}/*-------------------------< _SMS_A60 >-------------------------*/,{
+ 0,
+ PADDR_B (prev_done),
+}/*-------------------------< DONE_END >-------------------------*/,{
+ SCR_INT_FLY,
+ 0,
+ SCR_JUMP,
+ PADDR_A (start),
+}/*-------------------------< COMPLETE_ERROR >-------------------*/,{
+ SCR_COPY (4),
+ PADDR_B (startpos),
+ RADDR_1 (scratcha),
+ SCR_INT,
+ SIR_COMPLETE_ERROR,
+}/*-------------------------< SAVE_DP >--------------------------*/,{
+ /*
+ * Clear ACK immediately.
+ * No need to delay it.
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+ /*
+ * Keep track we received a SAVE DP, so
+ * we will switch to the other PM context
+ * on the next PM since the DP may point
+ * to the current PM context.
+ */
+ SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED),
+ 0,
+ /*
+ * SAVE_DP message:
+ * Copy LASTP to SAVEP.
+ */
+ SCR_COPY (4),
+ HADDR_1 (ccb_head.lastp),
+ HADDR_1 (ccb_head.savep),
+ /*
+ * Anticipate the MESSAGE PHASE for
+ * the DISCONNECT message.
+ */
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
+ PADDR_A (msg_in),
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< RESTORE_DP >-----------------------*/,{
+ /*
+ * Clear ACK immediately.
+ * No need to delay it.
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+ /*
+ * Copy SAVEP to LASTP.
+ */
+ SCR_COPY (4),
+ HADDR_1 (ccb_head.savep),
+ HADDR_1 (ccb_head.lastp),
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< DISCONNECT >-----------------------*/,{
+ /*
+ * DISCONNECTing ...
+ *
+ * disable the "unexpected disconnect" feature,
+ * and remove the ACK signal.
+ */
+ SCR_REG_REG (scntl2, SCR_AND, 0x7f),
+ 0,
+ SCR_CLR (SCR_ACK|SCR_ATN),
+ 0,
+ /*
+ * Wait for the disconnect.
+ */
+ SCR_WAIT_DISC,
+ 0,
+ /*
+ * Status is: DISCONNECTED.
+ */
+ SCR_LOAD_REG (HS_REG, HS_DISCONNECT),
+ 0,
+ /*
+ * Save host status.
+ */
+ SCR_COPY (4),
+ RADDR_1 (scr0),
+ HADDR_1 (ccb_head.status),
+}/*-------------------------< DISCONNECT2 >----------------------*/,{
+ /*
+ * Move back the CCB header using self-modifying
+ * SCRIPTS.
+ */
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ PADDR_A (_sms_a65),
+ SCR_COPY (sizeof(struct sym_ccbh)),
+ HADDR_1 (ccb_head),
+}/*-------------------------< _SMS_A65 >-------------------------*/,{
+ 0,
+ SCR_JUMP,
+ PADDR_A (start),
+}/*-------------------------< IDLE >-----------------------------*/,{
+ /*
+ * Nothing to do?
+ * Switch the LED off and wait for reselect.
+ * Will be patched with a NO_OP if LED
+ * not needed or not desired.
+ */
+ SCR_REG_REG (gpreg, SCR_OR, 0x01),
+ 0,
+#ifdef SYM_CONF_IARB_SUPPORT
+ SCR_JUMPR,
+ 8,
+#endif
+}/*-------------------------< UNGETJOB >-------------------------*/,{
+#ifdef SYM_CONF_IARB_SUPPORT
+ /*
+ * Set IMMEDIATE ARBITRATION, for the next time.
+ * This will give us better chance to win arbitration
+ * for the job we just wanted to do.
+ */
+ SCR_REG_REG (scntl1, SCR_OR, IARB),
+ 0,
+#endif
+ /*
+ * We are not able to restart the SCRIPTS if we are
+ * interrupted and these instruction haven't been
+ * all executed. BTW, this is very unlikely to
+ * happen, but we check that from the C code.
+ */
+ SCR_LOAD_REG (dsa, 0xff),
+ 0,
+ SCR_COPY (4),
+ RADDR_1 (scratcha),
+ PADDR_B (startpos),
+}/*-------------------------< RESELECT >-------------------------*/,{
+#ifdef SYM_CONF_TARGET_ROLE_SUPPORT
+ /*
+ * Make sure we are in initiator mode.
+ */
+ SCR_CLR (SCR_TRG),
+ 0,
+#endif
+ /*
+ * Sleep waiting for a reselection.
+ */
+ SCR_WAIT_RESEL,
+ PADDR_A(start),
+}/*-------------------------< RESELECTED >-----------------------*/,{
+ /*
+ * Switch the LED on.
+ * Will be patched with a NO_OP if LED
+ * not needed or not desired.
+ */
+ SCR_REG_REG (gpreg, SCR_AND, 0xfe),
+ 0,
+ /*
+ * load the target id into the sdid
+ */
+ SCR_REG_SFBR (ssid, SCR_AND, 0x8F),
+ 0,
+ SCR_TO_REG (sdid),
+ 0,
+ /*
+ * Load the target control block address
+ */
+ SCR_COPY (4),
+ PADDR_B (targtbl),
+ RADDR_1 (dsa),
+ SCR_SFBR_REG (dsa, SCR_SHL, 0),
+ 0,
+ SCR_REG_REG (dsa, SCR_SHL, 0),
+ 0,
+ SCR_REG_REG (dsa, SCR_AND, 0x3c),
+ 0,
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ PADDR_A (_sms_a70),
+ SCR_COPY (4),
+}/*-------------------------< _SMS_A70 >-------------------------*/,{
+ 0,
+ RADDR_1 (dsa),
+ /*
+ * Copy the TCB header to a fixed place in
+ * the HCB.
+ */
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ PADDR_A (_sms_a80),
+ SCR_COPY (sizeof(struct sym_tcbh)),
+}/*-------------------------< _SMS_A80 >-------------------------*/,{
+ 0,
+ HADDR_1 (tcb_head),
+ /*
+ * We expect MESSAGE IN phase.
+ * If not, get help from the C code.
+ */
+ SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)),
+ SIR_RESEL_NO_MSG_IN,
+}/*-------------------------< RESELECTED1 >----------------------*/,{
+ /*
+ * Load the synchronous transfer registers.
+ */
+ SCR_COPY (1),
+ HADDR_1 (tcb_head.wval),
+ RADDR_1 (scntl3),
+ SCR_COPY (1),
+ HADDR_1 (tcb_head.sval),
+ RADDR_1 (sxfer),
+ /*
+ * Get the IDENTIFY message.
+ */
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ HADDR_1 (msgin),
+ /*
+ * If IDENTIFY LUN #0, use a faster path
+ * to find the LCB structure.
+ */
+ SCR_JUMP ^ IFTRUE (MASK (0x80, 0xbf)),
+ PADDR_A (resel_lun0),
+ /*
+ * If message isn't an IDENTIFY,
+ * tell the C code about.
+ */
+ SCR_INT ^ IFFALSE (MASK (0x80, 0x80)),
+ SIR_RESEL_NO_IDENTIFY,
+ /*
+ * It is an IDENTIFY message,
+ * Load the LUN control block address.
+ */
+ SCR_COPY (4),
+ HADDR_1 (tcb_head.luntbl_sa),
+ RADDR_1 (dsa),
+ SCR_SFBR_REG (dsa, SCR_SHL, 0),
+ 0,
+ SCR_REG_REG (dsa, SCR_SHL, 0),
+ 0,
+ SCR_REG_REG (dsa, SCR_AND, 0xfc),
+ 0,
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ PADDR_A (_sms_a90),
+ SCR_COPY (4),
+}/*-------------------------< _SMS_A90 >-------------------------*/,{
+ 0,
+ RADDR_1 (dsa),
+ SCR_JUMPR,
+ 12,
+}/*-------------------------< RESEL_LUN0 >-----------------------*/,{
+ /*
+ * LUN 0 special case (but usual one :))
+ */
+ SCR_COPY (4),
+ HADDR_1 (tcb_head.lun0_sa),
+ RADDR_1 (dsa),
+ /*
+ * Jump indirectly to the reselect action for this LUN.
+ * (lcb.head.resel_sa assumed at offset zero of lcb).
+ */
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ PADDR_A (_sms_a100),
+ SCR_COPY (4),
+}/*-------------------------< _SMS_A100 >------------------------*/,{
+ 0,
+ RADDR_1 (temp),
+ SCR_RETURN,
+ 0,
+ /* In normal situations, we jump to RESEL_TAG or RESEL_NO_TAG */
+}/*-------------------------< RESEL_TAG >------------------------*/,{
+ /*
+ * ACK the IDENTIFY previously received.
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+ /*
+ * It shall be a tagged command.
+ * Read SIMPLE+TAG.
+ * The C code will deal with errors.
+ * Agressive optimization, is'nt it? :)
+ */
+ SCR_MOVE_ABS (2) ^ SCR_MSG_IN,
+ HADDR_1 (msgin),
+ /*
+ * Copy the LCB header to a fixed place in
+ * the HCB using self-modifying SCRIPTS.
+ */
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ PADDR_A (_sms_a110),
+ SCR_COPY (sizeof(struct sym_lcbh)),
+}/*-------------------------< _SMS_A110 >------------------------*/,{
+ 0,
+ HADDR_1 (lcb_head),
+ /*
+ * Load the pointer to the tagged task
+ * table for this LUN.
+ */
+ SCR_COPY (4),
+ HADDR_1 (lcb_head.itlq_tbl_sa),
+ RADDR_1 (dsa),
+ /*
+ * The SIDL still contains the TAG value.
+ * Agressive optimization, isn't it? :):)
+ */
+ SCR_REG_SFBR (sidl, SCR_SHL, 0),
+ 0,
+#if SYM_CONF_MAX_TASK*4 > 512
+ SCR_JUMPR ^ IFFALSE (CARRYSET),
+ 8,
+ SCR_REG_REG (dsa1, SCR_OR, 2),
+ 0,
+ SCR_REG_REG (sfbr, SCR_SHL, 0),
+ 0,
+ SCR_JUMPR ^ IFFALSE (CARRYSET),
+ 8,
+ SCR_REG_REG (dsa1, SCR_OR, 1),
+ 0,
+#elif SYM_CONF_MAX_TASK*4 > 256
+ SCR_JUMPR ^ IFFALSE (CARRYSET),
+ 8,
+ SCR_REG_REG (dsa1, SCR_OR, 1),
+ 0,
+#endif
+ /*
+ * Retrieve the DSA of this task.
+ * JUMP indirectly to the restart point of the CCB.
+ */
+ SCR_SFBR_REG (dsa, SCR_AND, 0xfc),
+ 0,
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ PADDR_A (_sms_a120),
+ SCR_COPY (4),
+}/*-------------------------< _SMS_A120 >------------------------*/,{
+ 0,
+ RADDR_1 (dsa),
+}/*-------------------------< RESEL_GO >-------------------------*/,{
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ PADDR_A (_sms_a130),
+ /*
+ * Move 'ccb.phys.head.go' action to
+ * scratch/scratch1. So scratch1 will
+ * contain the 'restart' field of the
+ * 'go' structure.
+ */
+ SCR_COPY (8),
+}/*-------------------------< _SMS_A130 >------------------------*/,{
+ 0,
+ PADDR_B (scratch),
+ SCR_COPY (4),
+ PADDR_B (scratch1), /* phys.head.go.restart */
+ RADDR_1 (temp),
+ SCR_RETURN,
+ 0,
+ /* In normal situations we branch to RESEL_DSA */
+}/*-------------------------< RESEL_DSA >------------------------*/,{
+ /*
+ * ACK the IDENTIFY or TAG previously received.
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+}/*-------------------------< RESEL_DSA1 >-----------------------*/,{
+ /*
+ * Copy the CCB header to a fixed location
+ * in the HCB using self-modifying SCRIPTS.
+ */
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ PADDR_A (_sms_a140),
+ SCR_COPY (sizeof(struct sym_ccbh)),
+}/*-------------------------< _SMS_A140 >------------------------*/,{
+ 0,
+ HADDR_1 (ccb_head),
+ /*
+ * Initialize the status register
+ */
+ SCR_COPY (4),
+ HADDR_1 (ccb_head.status),
+ RADDR_1 (scr0),
+ /*
+ * Jump to dispatcher.
+ */
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< RESEL_NO_TAG >---------------------*/,{
+ /*
+ * Copy the LCB header to a fixed place in
+ * the HCB using self-modifying SCRIPTS.
+ */
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ PADDR_A (_sms_a145),
+ SCR_COPY (sizeof(struct sym_lcbh)),
+}/*-------------------------< _SMS_A145 >------------------------*/,{
+ 0,
+ HADDR_1 (lcb_head),
+ /*
+ * Load the DSA with the unique ITL task.
+ */
+ SCR_COPY (4),
+ HADDR_1 (lcb_head.itl_task_sa),
+ RADDR_1 (dsa),
+ SCR_JUMP,
+ PADDR_A (resel_go),
+}/*-------------------------< DATA_IN >--------------------------*/,{
+/*
+ * Because the size depends on the
+ * #define SYM_CONF_MAX_SG parameter,
+ * it is filled in at runtime.
+ *
+ * ##===========< i=0; i<SYM_CONF_MAX_SG >=========
+ * || SCR_CHMOV_TBL ^ SCR_DATA_IN,
+ * || offsetof (struct sym_dsb, data[ i]),
+ * ##==========================================
+ */
+0
+}/*-------------------------< DATA_IN2 >-------------------------*/,{
+ SCR_CALL,
+ PADDR_A (datai_done),
+ SCR_JUMP,
+ PADDR_B (data_ovrun),
+}/*-------------------------< DATA_OUT >-------------------------*/,{
+/*
+ * Because the size depends on the
+ * #define SYM_CONF_MAX_SG parameter,
+ * it is filled in at runtime.
+ *
+ * ##===========< i=0; i<SYM_CONF_MAX_SG >=========
+ * || SCR_CHMOV_TBL ^ SCR_DATA_OUT,
+ * || offsetof (struct sym_dsb, data[ i]),
+ * ##==========================================
+ */
+0
+}/*-------------------------< DATA_OUT2 >------------------------*/,{
+ SCR_CALL,
+ PADDR_A (datao_done),
+ SCR_JUMP,
+ PADDR_B (data_ovrun),
+}/*-------------------------< PM0_DATA >-------------------------*/,{
+ /*
+ * Read our host flags to SFBR, so we will be able
+ * to check against the data direction we expect.
+ */
+ SCR_FROM_REG (HF_REG),
+ 0,
+ /*
+ * Check against actual DATA PHASE.
+ */
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)),
+ PADDR_A (pm0_data_out),
+ /*
+ * Actual phase is DATA IN.
+ * Check against expected direction.
+ */
+ SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)),
+ PADDR_B (data_ovrun),
+ /*
+ * Keep track we are moving data from the
+ * PM0 DATA mini-script.
+ */
+ SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0),
+ 0,
+ /*
+ * Move the data to memory.
+ */
+ SCR_CHMOV_TBL ^ SCR_DATA_IN,
+ offsetof (struct sym_ccb, phys.pm0.sg),
+ SCR_JUMP,
+ PADDR_A (pm0_data_end),
+}/*-------------------------< PM0_DATA_OUT >---------------------*/,{
+ /*
+ * Actual phase is DATA OUT.
+ * Check against expected direction.
+ */
+ SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)),
+ PADDR_B (data_ovrun),
+ /*
+ * Keep track we are moving data from the
+ * PM0 DATA mini-script.
+ */
+ SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0),
+ 0,
+ /*
+ * Move the data from memory.
+ */
+ SCR_CHMOV_TBL ^ SCR_DATA_OUT,
+ offsetof (struct sym_ccb, phys.pm0.sg),
+}/*-------------------------< PM0_DATA_END >---------------------*/,{
+ /*
+ * Clear the flag that told we were moving
+ * data from the PM0 DATA mini-script.
+ */
+ SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM0)),
+ 0,
+ /*
+ * Return to the previous DATA script which
+ * is guaranteed by design (if no bug) to be
+ * the main DATA script for this transfer.
+ */
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ RADDR_1 (scratcha),
+ SCR_REG_REG (scratcha, SCR_ADD, offsetof (struct sym_ccb,phys.pm0.ret)),
+ 0,
+}/*-------------------------< PM_DATA_END >----------------------*/,{
+ SCR_COPY (4),
+ RADDR_1 (scratcha),
+ PADDR_A (_sms_a150),
+ SCR_COPY (4),
+}/*-------------------------< _SMS_A150 >------------------------*/,{
+ 0,
+ RADDR_1 (temp),
+ SCR_RETURN,
+ 0,
+}/*-------------------------< PM1_DATA >-------------------------*/,{
+ /*
+ * Read our host flags to SFBR, so we will be able
+ * to check against the data direction we expect.
+ */
+ SCR_FROM_REG (HF_REG),
+ 0,
+ /*
+ * Check against actual DATA PHASE.
+ */
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)),
+ PADDR_A (pm1_data_out),
+ /*
+ * Actual phase is DATA IN.
+ * Check against expected direction.
+ */
+ SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)),
+ PADDR_B (data_ovrun),
+ /*
+ * Keep track we are moving data from the
+ * PM1 DATA mini-script.
+ */
+ SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1),
+ 0,
+ /*
+ * Move the data to memory.
+ */
+ SCR_CHMOV_TBL ^ SCR_DATA_IN,
+ offsetof (struct sym_ccb, phys.pm1.sg),
+ SCR_JUMP,
+ PADDR_A (pm1_data_end),
+}/*-------------------------< PM1_DATA_OUT >---------------------*/,{
+ /*
+ * Actual phase is DATA OUT.
+ * Check against expected direction.
+ */
+ SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)),
+ PADDR_B (data_ovrun),
+ /*
+ * Keep track we are moving data from the
+ * PM1 DATA mini-script.
+ */
+ SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1),
+ 0,
+ /*
+ * Move the data from memory.
+ */
+ SCR_CHMOV_TBL ^ SCR_DATA_OUT,
+ offsetof (struct sym_ccb, phys.pm1.sg),
+}/*-------------------------< PM1_DATA_END >---------------------*/,{
+ /*
+ * Clear the flag that told we were moving
+ * data from the PM1 DATA mini-script.
+ */
+ SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM1)),
+ 0,
+ /*
+ * Return to the previous DATA script which
+ * is guaranteed by design (if no bug) to be
+ * the main DATA script for this transfer.
+ */
+ SCR_COPY (4),
+ RADDR_1 (dsa),
+ RADDR_1 (scratcha),
+ SCR_REG_REG (scratcha, SCR_ADD, offsetof (struct sym_ccb,phys.pm1.ret)),
+ 0,
+ SCR_JUMP,
+ PADDR_A (pm_data_end),
+}/*--------------------------<>----------------------------------*/
+};
+
+static struct SYM_FWB_SCR SYM_FWB_SCR = {
+/*-------------------------< NO_DATA >--------------------------*/ {
+ SCR_JUMP,
+ PADDR_B (data_ovrun),
+}/*-------------------------< SEL_FOR_ABORT >--------------------*/,{
+ /*
+ * We are jumped here by the C code, if we have
+ * some target to reset or some disconnected
+ * job to abort. Since error recovery is a serious
+ * busyness, we will really reset the SCSI BUS, if
+ * case of a SCSI interrupt occuring in this path.
+ */
+
+#ifdef SYM_CONF_TARGET_ROLE_SUPPORT
+ /*
+ * Set initiator mode.
+ */
+ SCR_CLR (SCR_TRG),
+ 0,
+#endif
+ /*
+ * And try to select this target.
+ */
+ SCR_SEL_TBL_ATN ^ offsetof (struct sym_hcb, abrt_sel),
+ PADDR_A (reselect),
+ /*
+ * Wait for the selection to complete or
+ * the selection to time out.
+ */
+ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+ -8,
+ /*
+ * Call the C code.
+ */
+ SCR_INT,
+ SIR_TARGET_SELECTED,
+ /*
+ * The C code should let us continue here.
+ * Send the 'kiss of death' message.
+ * We expect an immediate disconnect once
+ * the target has eaten the message.
+ */
+ SCR_REG_REG (scntl2, SCR_AND, 0x7f),
+ 0,
+ SCR_MOVE_TBL ^ SCR_MSG_OUT,
+ offsetof (struct sym_hcb, abrt_tbl),
+ SCR_CLR (SCR_ACK|SCR_ATN),
+ 0,
+ SCR_WAIT_DISC,
+ 0,
+ /*
+ * Tell the C code that we are done.
+ */
+ SCR_INT,
+ SIR_ABORT_SENT,
+}/*-------------------------< SEL_FOR_ABORT_1 >------------------*/,{
+ /*
+ * Jump at scheduler.
+ */
+ SCR_JUMP,
+ PADDR_A (start),
+}/*-------------------------< MSG_IN_ETC >-----------------------*/,{
+ /*
+ * If it is an EXTENDED (variable size message)
+ * Handle it.
+ */
+ SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)),
+ PADDR_B (msg_extended),
+ /*
+ * Let the C code handle any other
+ * 1 byte message.
+ */
+ SCR_JUMP ^ IFTRUE (MASK (0x00, 0xf0)),
+ PADDR_B (msg_received),
+ SCR_JUMP ^ IFTRUE (MASK (0x10, 0xf0)),
+ PADDR_B (msg_received),
+ /*
+ * We donnot handle 2 bytes messages from SCRIPTS.
+ * So, let the C code deal with these ones too.
+ */
+ SCR_JUMP ^ IFFALSE (MASK (0x20, 0xf0)),
+ PADDR_B (msg_weird_seen),
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ HADDR_1 (msgin[1]),
+}/*-------------------------< MSG_RECEIVED >---------------------*/,{
+ SCR_COPY (4), /* DUMMY READ */
+ HADDR_1 (scratch),
+ RADDR_1 (scratcha),
+ SCR_INT,
+ SIR_MSG_RECEIVED,
+}/*-------------------------< MSG_WEIRD_SEEN >-------------------*/,{
+ SCR_COPY (4), /* DUMMY READ */
+ HADDR_1 (scratch),
+ RADDR_1 (scratcha),
+ SCR_INT,
+ SIR_MSG_WEIRD,
+}/*-------------------------< MSG_EXTENDED >---------------------*/,{
+ /*
+ * Clear ACK and get the next byte
+ * assumed to be the message length.
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ HADDR_1 (msgin[1]),
+ /*
+ * Try to catch some unlikely situations as 0 length
+ * or too large the length.
+ */
+ SCR_JUMP ^ IFTRUE (DATA (0)),
+ PADDR_B (msg_weird_seen),
+ SCR_TO_REG (scratcha),
+ 0,
+ SCR_REG_REG (sfbr, SCR_ADD, (256-8)),
+ 0,
+ SCR_JUMP ^ IFTRUE (CARRYSET),
+ PADDR_B (msg_weird_seen),
+ /*
+ * We donnot handle extended messages from SCRIPTS.
+ * Read the amount of data correponding to the
+ * message length and call the C code.
+ */
+ SCR_COPY (1),
+ RADDR_1 (scratcha),
+ PADDR_B (_sms_b10),
+ SCR_CLR (SCR_ACK),
+ 0,
+}/*-------------------------< _SMS_B10 >-------------------------*/,{
+ SCR_MOVE_ABS (0) ^ SCR_MSG_IN,
+ HADDR_1 (msgin[2]),
+ SCR_JUMP,
+ PADDR_B (msg_received),
+}/*-------------------------< MSG_BAD >--------------------------*/,{
+ /*
+ * unimplemented message - reject it.
+ */
+ SCR_INT,
+ SIR_REJECT_TO_SEND,
+ SCR_SET (SCR_ATN),
+ 0,
+ SCR_JUMP,
+ PADDR_A (clrack),
+}/*-------------------------< MSG_WEIRD >------------------------*/,{
+ /*
+ * weird message received
+ * ignore all MSG IN phases and reject it.
+ */
+ SCR_INT,
+ SIR_REJECT_TO_SEND,
+ SCR_SET (SCR_ATN),
+ 0,
+}/*-------------------------< MSG_WEIRD1 >-----------------------*/,{
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
+ PADDR_A (dispatch),
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ HADDR_1 (scratch),
+ SCR_JUMP,
+ PADDR_B (msg_weird1),
+}/*-------------------------< WDTR_RESP >------------------------*/,{
+ /*
+ * let the target fetch our answer.
+ */
+ SCR_SET (SCR_ATN),
+ 0,
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+ PADDR_B (nego_bad_phase),
+}/*-------------------------< SEND_WDTR >------------------------*/,{
+ /*
+ * Send the M_X_WIDE_REQ
+ */
+ SCR_MOVE_ABS (4) ^ SCR_MSG_OUT,
+ HADDR_1 (msgout),
+ SCR_JUMP,
+ PADDR_B (msg_out_done),
+}/*-------------------------< SDTR_RESP >------------------------*/,{
+ /*
+ * let the target fetch our answer.
+ */
+ SCR_SET (SCR_ATN),
+ 0,
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+ PADDR_B (nego_bad_phase),
+}/*-------------------------< SEND_SDTR >------------------------*/,{
+ /*
+ * Send the M_X_SYNC_REQ
+ */
+ SCR_MOVE_ABS (5) ^ SCR_MSG_OUT,
+ HADDR_1 (msgout),
+ SCR_JUMP,
+ PADDR_B (msg_out_done),
+}/*-------------------------< PPR_RESP >-------------------------*/,{
+ /*
+ * let the target fetch our answer.
+ */
+ SCR_SET (SCR_ATN),
+ 0,
+ SCR_CLR (SCR_ACK),
+ 0,
+ SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+ PADDR_B (nego_bad_phase),
+}/*-------------------------< SEND_PPR >-------------------------*/,{
+ /*
+ * Send the M_X_PPR_REQ
+ */
+ SCR_MOVE_ABS (8) ^ SCR_MSG_OUT,
+ HADDR_1 (msgout),
+ SCR_JUMP,
+ PADDR_B (msg_out_done),
+}/*-------------------------< NEGO_BAD_PHASE >-------------------*/,{
+ SCR_INT,
+ SIR_NEGO_PROTO,
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< MSG_OUT >--------------------------*/,{
+ /*
+ * The target requests a message.
+ * We donnot send messages that may
+ * require the device to go to bus free.
+ */
+ SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
+ HADDR_1 (msgout),
+ /*
+ * ... wait for the next phase
+ * if it's a message out, send it again, ...
+ */
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)),
+ PADDR_B (msg_out),
+}/*-------------------------< MSG_OUT_DONE >---------------------*/,{
+ /*
+ * Let the C code be aware of the
+ * sent message and clear the message.
+ */
+ SCR_INT,
+ SIR_MSG_OUT_DONE,
+ /*
+ * ... and process the next phase
+ */
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< DATA_OVRUN >-----------------------*/,{
+ /*
+ * Zero scratcha that will count the
+ * extras bytes.
+ */
+ SCR_COPY (4),
+ PADDR_B (zero),
+ RADDR_1 (scratcha),
+}/*-------------------------< DATA_OVRUN1 >----------------------*/,{
+ /*
+ * The target may want to transfer too much data.
+ *
+ * If phase is DATA OUT write 1 byte and count it.
+ */
+ SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)),
+ 16,
+ SCR_CHMOV_ABS (1) ^ SCR_DATA_OUT,
+ HADDR_1 (scratch),
+ SCR_JUMP,
+ PADDR_B (data_ovrun2),
+ /*
+ * If WSR is set, clear this condition, and
+ * count this byte.
+ */
+ SCR_FROM_REG (scntl2),
+ 0,
+ SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)),
+ 16,
+ SCR_REG_REG (scntl2, SCR_OR, WSR),
+ 0,
+ SCR_JUMP,
+ PADDR_B (data_ovrun2),
+ /*
+ * Finally check against DATA IN phase.
+ * Signal data overrun to the C code
+ * and jump to dispatcher if not so.
+ * Read 1 byte otherwise and count it.
+ */
+ SCR_JUMPR ^ IFTRUE (WHEN (SCR_DATA_IN)),
+ 16,
+ SCR_INT,
+ SIR_DATA_OVERRUN,
+ SCR_JUMP,
+ PADDR_A (dispatch),
+ SCR_CHMOV_ABS (1) ^ SCR_DATA_IN,
+ HADDR_1 (scratch),
+}/*-------------------------< DATA_OVRUN2 >----------------------*/,{
+ /*
+ * Count this byte.
+ * This will allow to return a negative
+ * residual to user.
+ */
+ SCR_REG_REG (scratcha, SCR_ADD, 0x01),
+ 0,
+ SCR_REG_REG (scratcha1, SCR_ADDC, 0),
+ 0,
+ SCR_REG_REG (scratcha2, SCR_ADDC, 0),
+ 0,
+ /*
+ * .. and repeat as required.
+ */
+ SCR_JUMP,
+ PADDR_B (data_ovrun1),
+}/*-------------------------< ABORT_RESEL >----------------------*/,{
+ SCR_SET (SCR_ATN),
+ 0,
+ SCR_CLR (SCR_ACK),
+ 0,
+ /*
+ * send the abort/abortag/reset message
+ * we expect an immediate disconnect
+ */
+ SCR_REG_REG (scntl2, SCR_AND, 0x7f),
+ 0,
+ SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
+ HADDR_1 (msgout),
+ SCR_CLR (SCR_ACK|SCR_ATN),
+ 0,
+ SCR_WAIT_DISC,
+ 0,
+ SCR_INT,
+ SIR_RESEL_ABORTED,
+ SCR_JUMP,
+ PADDR_A (start),
+}/*-------------------------< RESEND_IDENT >---------------------*/,{
+ /*
+ * The target stays in MSG OUT phase after having acked
+ * Identify [+ Tag [+ Extended message ]]. Targets shall
+ * behave this way on parity error.
+ * We must send it again all the messages.
+ */
+ SCR_SET (SCR_ATN), /* Shall be asserted 2 deskew delays before the */
+ 0, /* 1rst ACK = 90 ns. Hope the chip isn't too fast */
+ SCR_JUMP,
+ PADDR_A (send_ident),
+}/*-------------------------< IDENT_BREAK >----------------------*/,{
+ SCR_CLR (SCR_ATN),
+ 0,
+ SCR_JUMP,
+ PADDR_A (select2),
+}/*-------------------------< IDENT_BREAK_ATN >------------------*/,{
+ SCR_SET (SCR_ATN),
+ 0,
+ SCR_JUMP,
+ PADDR_A (select2),
+}/*-------------------------< SDATA_IN >-------------------------*/,{
+ SCR_CHMOV_TBL ^ SCR_DATA_IN,
+ offsetof (struct sym_dsb, sense),
+ SCR_CALL,
+ PADDR_A (datai_done),
+ SCR_JUMP,
+ PADDR_B (data_ovrun),
+}/*-------------------------< RESEL_BAD_LUN >--------------------*/,{
+ /*
+ * Message is an IDENTIFY, but lun is unknown.
+ * Signal problem to C code for logging the event.
+ * Send a M_ABORT to clear all pending tasks.
+ */
+ SCR_INT,
+ SIR_RESEL_BAD_LUN,
+ SCR_JUMP,
+ PADDR_B (abort_resel),
+}/*-------------------------< BAD_I_T_L >------------------------*/,{
+ /*
+ * We donnot have a task for that I_T_L.
+ * Signal problem to C code for logging the event.
+ * Send a M_ABORT message.
+ */
+ SCR_INT,
+ SIR_RESEL_BAD_I_T_L,
+ SCR_JUMP,
+ PADDR_B (abort_resel),
+}/*-------------------------< BAD_I_T_L_Q >----------------------*/,{
+ /*
+ * We donnot have a task that matches the tag.
+ * Signal problem to C code for logging the event.
+ * Send a M_ABORTTAG message.
+ */
+ SCR_INT,
+ SIR_RESEL_BAD_I_T_L_Q,
+ SCR_JUMP,
+ PADDR_B (abort_resel),
+}/*-------------------------< BAD_STATUS >-----------------------*/,{
+ /*
+ * Anything different from INTERMEDIATE
+ * CONDITION MET should be a bad SCSI status,
+ * given that GOOD status has already been tested.
+ * Call the C code.
+ */
+ SCR_COPY (4),
+ PADDR_B (startpos),
+ RADDR_1 (scratcha),
+ SCR_INT ^ IFFALSE (DATA (S_COND_MET)),
+ SIR_BAD_SCSI_STATUS,
+ SCR_RETURN,
+ 0,
+}/*-------------------------< WSR_MA_HELPER >--------------------*/,{
+ /*
+ * Helper for the C code when WSR bit is set.
+ * Perform the move of the residual byte.
+ */
+ SCR_CHMOV_TBL ^ SCR_DATA_IN,
+ offsetof (struct sym_ccb, phys.wresid),
+ SCR_JUMP,
+ PADDR_A (dispatch),
+
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+}/*-------------------------< DATA_IO >--------------------------*/,{
+ /*
+ * We jump here if the data direction was unknown at the
+ * time we had to queue the command to the scripts processor.
+ * Pointers had been set as follow in this situation:
+ * savep --> DATA_IO
+ * lastp --> start pointer when DATA_IN
+ * wlastp --> start pointer when DATA_OUT
+ * This script sets savep and lastp according to the
+ * direction chosen by the target.
+ */
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_OUT)),
+ PADDR_B (data_io_out),
+}/*-------------------------< DATA_IO_COM >----------------------*/,{
+ /*
+ * Direction is DATA IN.
+ */
+ SCR_COPY (4),
+ HADDR_1 (ccb_head.lastp),
+ HADDR_1 (ccb_head.savep),
+ /*
+ * Jump to the SCRIPTS according to actual direction.
+ */
+ SCR_COPY (4),
+ HADDR_1 (ccb_head.savep),
+ RADDR_1 (temp),
+ SCR_RETURN,
+ 0,
+}/*-------------------------< DATA_IO_OUT >----------------------*/,{
+ /*
+ * Direction is DATA OUT.
+ */
+ SCR_REG_REG (HF_REG, SCR_AND, (~HF_DATA_IN)),
+ 0,
+ SCR_COPY (4),
+ HADDR_1 (ccb_head.wlastp),
+ HADDR_1 (ccb_head.lastp),
+ SCR_JUMP,
+ PADDR_B(data_io_com),
+#endif /* SYM_OPT_HANDLE_DIR_UNKNOWN */
+
+}/*-------------------------< ZERO >-----------------------------*/,{
+ SCR_DATA_ZERO,
+}/*-------------------------< SCRATCH >--------------------------*/,{
+ SCR_DATA_ZERO, /* MUST BE BEFORE SCRATCH1 */
+}/*-------------------------< SCRATCH1 >-------------------------*/,{
+ SCR_DATA_ZERO,
+}/*-------------------------< PREV_DONE >------------------------*/,{
+ SCR_DATA_ZERO, /* MUST BE BEFORE DONE_POS ! */
+}/*-------------------------< DONE_POS >-------------------------*/,{
+ SCR_DATA_ZERO,
+}/*-------------------------< NEXTJOB >--------------------------*/,{
+ SCR_DATA_ZERO, /* MUST BE BEFORE STARTPOS ! */
+}/*-------------------------< STARTPOS >-------------------------*/,{
+ SCR_DATA_ZERO,
+}/*-------------------------< TARGTBL >--------------------------*/,{
+ SCR_DATA_ZERO,
+}/*--------------------------<>----------------------------------*/
+};
+
+static struct SYM_FWZ_SCR SYM_FWZ_SCR = {
+ /*-------------------------< SNOOPTEST >------------------------*/{
+ /*
+ * Read the variable.
+ */
+ SCR_COPY (4),
+ HADDR_1 (scratch),
+ RADDR_1 (scratcha),
+ /*
+ * Write the variable.
+ */
+ SCR_COPY (4),
+ RADDR_1 (temp),
+ HADDR_1 (scratch),
+ /*
+ * Read back the variable.
+ */
+ SCR_COPY (4),
+ HADDR_1 (scratch),
+ RADDR_1 (temp),
+}/*-------------------------< SNOOPEND >-------------------------*/,{
+ /*
+ * And stop.
+ */
+ SCR_INT,
+ 99,
+#ifdef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ /*
+ * We may use MEMORY MOVE instructions to load the on chip-RAM,
+ * if it happens that mapping PCI memory is not possible.
+ * But writing the RAM from the CPU is the preferred method,
+ * since PCI 2.2 seems to disallow PCI self-mastering.
+ */
+}/*-------------------------< START_RAM >------------------------*/,{
+ /*
+ * Load the script into on-chip RAM,
+ * and jump to start point.
+ */
+ SCR_COPY (sizeof(struct SYM_FWA_SCR)),
+}/*-------------------------< SCRIPTA0_BA >----------------------*/,{
+ 0,
+ PADDR_A (start),
+ SCR_JUMP,
+ PADDR_A (init),
+#endif /* SYM_OPT_NO_BUS_MEMORY_MAPPING */
+}/*--------------------------<>----------------------------------*/
+};
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_fw2.h linux/drivers/scsi/sym53c8xx_2/sym_fw2.h
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_fw2.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym_fw2.h Fri Nov 9 15:22:54 2001
@@ -0,0 +1,1994 @@


+/*
+ * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family
+ * of PCI-SCSI IO processors.
+ *
+ * Copyright (C) 1999-2001 Gerard Roudier <grou...@free.fr>
+ *
+ * This driver is derived from the Linux sym53c8xx driver.
+ * Copyright (C) 1998-2000 Gerard Roudier
+ *
+ * The sym53c8xx driver is derived from the ncr53c8xx driver that had been

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

echo 'End of part 061'
echo 'File patch-2.4.15 is continued in part 062'
echo "062" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:34 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part058

#!/bin/sh -x
# this is part 058 of a 115 - part archive


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

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

+ "Rebuild started: Unit #", // 0x00B
+ "Initialization started: Unit #", // 0x00C
+ "Logical unit deleted: Unit #", // 0x00D
+ NULL, // 0x00E unused
+ "SMART threshold exceeded: Port #", // 0x00F
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, // 0x010-0x020 unused
+ "ATA UDMA downgrade: Port #", // 0x021
+ "ATA UDMA upgrade: Port #", // 0x022
+ "Sector repair occurred: Port #", // 0x023
+ "SBUF integrity check failure", // 0x024
+ "Lost cached write: Port #", // 0x025
+ "Drive ECC error detected: Port #", // 0x026
+ "DCB checksum error: Port #", // 0x027
+ "DCB unsupported version: Port #", // 0x028
+ "Verify started: Unit #", // 0x029
+ "Verify failed: Port #", // 0x02A
+ "Verify complete: Unit #" // 0x02B
+};
+
+#define TW_AEN_STRING_MAX 0x02C
+
X /* Control register bit definitions */
X #define TW_CONTROL_CLEAR_HOST_INTERRUPT 0x00080000
X #define TW_CONTROL_CLEAR_ATTENTION_INTERRUPT 0x00040000
@@ -114,6 +152,7 @@
X #define TW_OP_SECTOR_INFO 0x1a
X #define TW_OP_AEN_LISTEN 0x1c
X #define TW_CMD_PACKET 0x1d
+#define TW_ATA_PASSTHRU 0x1e
X
X /* Asynchronous Event Notification (AEN) Codes */
X #define TW_AEN_QUEUE_EMPTY 0x0000
@@ -137,7 +176,10 @@
X #define TW_INIT_COMMAND_PACKET_SIZE 0x3
X #define TW_POLL_MAX_RETRIES 20000
X #define TW_MAX_SGL_LENGTH 62
-#define TW_Q_LENGTH 16
+#define TW_ATA_PASS_SGL_MAX 60
+#define TW_MAX_PASSTHRU_BYTES 4096
+#define TW_Q_LENGTH 256
+#define TW_MAX_BOUNCEBUF 16
X #define TW_Q_START 0
X #define TW_MAX_SLOT 32
X #define TW_MAX_PCI_BUSES 255
@@ -225,6 +267,7 @@
X unsigned short table_id;
X unsigned char parameter_id;
X unsigned char parameter_size_bytes;
+ unsigned char unit_index;
X unsigned char data[1];
X } TW_Ioctl;
X
@@ -261,14 +304,42 @@
X int position;
X } TW_Info;
X
-typedef enum TAG_TW_Cmd_State {
- TW_S_INITIAL, /* Initial state */
- TW_S_STARTED, /* Id in use */
- TW_S_POSTED, /* Posted to the controller */
- TW_S_PENDING, /* Waiting to be posted in isr */
- TW_S_COMPLETED, /* Completed by isr */
- TW_S_FINISHED, /* I/O completely done */
-} TW_Cmd_State;
+typedef int TW_Cmd_State;
+
+#define TW_S_INITIAL 0x1 /* Initial state */
+#define TW_S_STARTED 0x2 /* Id in use */
+#define TW_S_POSTED 0x4 /* Posted to the controller */
+#define TW_S_PENDING 0x8 /* Waiting to be posted in isr */
+#define TW_S_COMPLETED 0x10 /* Completed by isr */
+#define TW_S_FINISHED 0x20 /* I/O completely done */
+#define TW_START_MASK (TW_S_STARTED | TW_S_POSTED | TW_S_PENDING | TW_S_COMPLETED)
+
+/* Command header for ATA pass-thru */
+typedef struct TAG_TW_Passthru
+{
+ struct {
+ unsigned char opcode:5;
+ unsigned char sgloff:3;
+ } byte0;
+ unsigned char size;
+ unsigned char request_id;
+ struct {
+ unsigned char aport:4;
+ unsigned char host_id:4;
+ } byte3;
+ unsigned char status;
+ unsigned char flags;
+ unsigned short param;
+ unsigned short features;
+ unsigned short sector_count;
+ unsigned short sector_num;
+ unsigned short cylinder_lo;
+ unsigned short cylinder_hi;
+ unsigned char drive_head;
+ unsigned char command;
+ TW_SG_Entry sg_list[TW_ATA_PASS_SGL_MAX];
+ unsigned char padding[12];
+} TW_Passthru;
X
X typedef struct TAG_TW_Device_Extension {
X TW_Registers registers;
@@ -286,6 +357,7 @@
X unsigned char free_queue[TW_Q_LENGTH];
X unsigned char free_head;
X unsigned char free_tail;
+ unsigned char free_wrap;
X unsigned char pending_queue[TW_Q_LENGTH];
X unsigned char pending_head;
X unsigned char pending_tail;
@@ -304,7 +376,7 @@
X u32 aen_count;
X struct Scsi_Host *host;
X spinlock_t tw_lock;
- unsigned char ioctl_size[TW_Q_LENGTH];
+ int ioctl_size[TW_Q_LENGTH];
X unsigned short aen_queue[TW_Q_LENGTH];
X unsigned char aen_head;
X unsigned char aen_tail;
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- v2.4.14/linux/drivers/scsi/Config.in Tue Oct 23 22:48:52 2001
+++ linux/drivers/scsi/Config.in Fri Nov 9 15:22:54 2001
@@ -135,7 +135,16 @@
X bool ' allow FAST-SCSI [10MHz]' CONFIG_SCSI_NCR53C7xx_FAST
X bool ' allow DISCONNECT' CONFIG_SCSI_NCR53C7xx_DISCONNECT
X fi
-if [ "$CONFIG_PCI" = "y" -a "$CONFIG_SCSI_NCR53C7xx" != "y" ]; then
+if [ "$CONFIG_PCI" = "y" ]; then
+ dep_tristate 'SYM53C8XX Version 2 SCSI support' CONFIG_SCSI_SYM53C8XX_2 $CONFIG_SCSI
+ if [ "$CONFIG_SCSI_SYM53C8XX_2" != "n" ]; then
+ int ' DMA addressing mode' CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE 1
+ int ' default tagged command queue depth' CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS 16
+ int ' maximum number of queued commands' CONFIG_SCSI_SYM53C8XX_MAX_TAGS 64
+ bool ' use normal IO' CONFIG_SCSI_SYM53C8XX_IOMAPPED
+ fi
+fi
+if [ "$CONFIG_PCI" = "y" -a "$CONFIG_SCSI_SYM53C8XX_2" != "y" ]; then
X dep_tristate 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI
X dep_tristate 'SYM53C8XX SCSI support' CONFIG_SCSI_SYM53C8XX $CONFIG_SCSI
X if [ "$CONFIG_SCSI_NCR53C8XX" != "n" -o "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v2.4.14/linux/drivers/scsi/Makefile Tue Oct 9 17:06:52 2001
+++ linux/drivers/scsi/Makefile Wed Nov 21 09:59:11 2001
@@ -87,6 +87,10 @@
X obj-$(CONFIG_SCSI_DMX3191D) += dmx3191d.o
X obj-$(CONFIG_SCSI_DTC3280) += dtc.o
X obj-$(CONFIG_SCSI_NCR53C7xx) += 53c7,8xx.o
+subdir-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2
+ifeq ($(CONFIG_SCSI_SYM53C8XX_2),y)
+ obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/sym53c8xx.o
+endif
X obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
X obj-$(CONFIG_SCSI_NCR53C8XX) += ncr53c8xx.o
X obj-$(CONFIG_SCSI_EATA_DMA) += eata_dma.o
@@ -170,6 +174,8 @@
X rm fake8.c
X
X 53c8xx_u.h: 53c8xx_d.h
+
+53c7,8xx.o: 53c8xx_u.h
X
X 53c7xx_d.h: 53c7xx.scr script_asm.pl
X ln -sf 53c7xx.scr fake7.c
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/README.st linux/drivers/scsi/README.st
--- v2.4.14/linux/drivers/scsi/README.st Mon Aug 7 22:52:10 2000
+++ linux/drivers/scsi/README.st Fri Nov 9 13:52:21 2001
@@ -2,7 +2,7 @@
X The driver is currently maintained by Kai M{kisara (email
X Kai.Ma...@metla.fi)
X
-Last modified: Sat Aug 5 10:29:07 2000 by maki...@kai.makisara.local
+Last modified: Thu Nov 1 22:41:59 2001 by maki...@kai.makisara.local
X
X
X BASICS
@@ -312,6 +312,8 @@
X this flag unless there are tapes using the device
X dependent (from the old times) (global)
X MT_ST_SYSV sets the SYSV sematics (mode)
+ MT_ST_NOWAIT enables immediate mode (i.e., don't wait for
+ the command to finish) for some commands (e.g., rewind)
X MT_ST_DEBUGGING debugging (global; debugging must be
X compiled into the driver)
X MT_ST_SETBOOLEANS
@@ -341,6 +343,25 @@
X known to take a long time. The default is 14000 seconds
X (3.9 hours). For erase this value is further multiplied by
X eight.
+ MT_ST_SET_CLN
+ Set the cleaning request interpretation parameters using
+ the lowest 24 bits of the argument. The driver can set the
+ generic status bit GMT_CLN if a cleaning request bit pattern
+ is found from the extended sense data. Many drives set one or
+ more bits in the extended sense data when the drive needs
+ cleaning. The bits are device-dependent. The driver is
+ given the number of the sense data byte (the lowest eight
+ bits of the argument; must be >= 18 (values 1 - 17
+ reserved) and <= the maximum requested sense data sixe),
+ a mask to select the relevant bits (the bits 9-16), and the
+ bit pattern (bits 17-23). If the bit pattern is zero, one
+ or more bits under the mask indicate cleaning request. If
+ the pattern is non-zero, the pattern must match the masked
+ sense data byte.
+
+ (The cleaning bit is set if the additional sense code and
+ qualifier 00h 17h are seen regardless of the setting of
+ MT_ST_SET_CLN.)
X
X The following ioctl uses the structure mtpos:
X MTIOCPOS Reads the current position from the drive. Uses
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c
--- v2.4.14/linux/drivers/scsi/advansys.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/scsi/advansys.c Fri Nov 9 14:05:06 2001
@@ -18680,4 +18680,4 @@
X }
X }
X }
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- v2.4.14/linux/drivers/scsi/aha152x.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/scsi/aha152x.c Fri Nov 9 14:05:06 2001
@@ -2956,7 +2956,11 @@
X
X DO_LOCK(flags);
X if(HOSTDATA(shpnt)->in_intr!=0)
+ {
+ DO_UNLOCK(flags);
+ /* _error never returns.. */
X aha152x_error(shpnt, "bottom-half already running!?");
+ }
X HOSTDATA(shpnt)->in_intr++;
X DO_UNLOCK(flags);
X
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/aic7xxx/aic7xxx_linux.c linux/drivers/scsi/aic7xxx/aic7xxx_linux.c
--- v2.4.14/linux/drivers/scsi/aic7xxx/aic7xxx_linux.c Mon Nov 5 15:55:31 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_linux.c Wed Nov 21 14:05:29 2001
@@ -129,6 +129,7 @@
X #include "../sd.h" /* For geometry detection */
X
X #include <linux/mm.h> /* For fetching system memory size */
+#include <linux/blk.h>
X
X /*
X * To generate the correct addresses for the controller to issue
@@ -2742,7 +2743,7 @@


X struct buffer_head *bh;
X

X ahc = *((struct ahc_softc **)disk->device->host->hostdata);
- bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, 1024);
+ bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, block_size(dev));
X
X if (bh) {
X ret = scsi_partsize(bh, disk->capacity,
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/aic7xxx/aic7xxx_linux_pci.c linux/drivers/scsi/aic7xxx/aic7xxx_linux_pci.c
--- v2.4.14/linux/drivers/scsi/aic7xxx/aic7xxx_linux_pci.c Mon Nov 5 15:55:31 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_linux_pci.c Tue Nov 13 09:19:41 2001
@@ -51,9 +51,11 @@


X const struct pci_device_id *ent);

X static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc,
X u_long *base);
+#ifdef MMAPIO
X static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
X u_long *bus_addr,
X uint8_t **maddr);
+#endif /* MMAPIO */
X #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
X static void ahc_linux_pci_dev_remove(struct pci_dev *pdev);
X
@@ -89,7 +91,7 @@
X * the free directly, but check our
X * list for extra sanity.
X */
- ahc = (struct ahc_softc *)pdev->driver_data;
+ ahc = pci_get_drvdata(pdev);
X TAILQ_FOREACH(list_ahc, &ahc_tailq, links) {
X if (list_ahc == ahc) {
X ahc_free(ahc);
@@ -176,7 +178,7 @@
X return (-error);
X }
X #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- pdev->driver_data = ahc;
+ pci_set_drvdata(pdev, ahc);
X if (aic7xxx_detect_complete)
X ahc_linux_register_host(ahc, aic7xxx_driver_template);
X #endif
@@ -236,6 +238,7 @@
X return (0);
X }
X
+#ifdef MMAPIO
X static int
X ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
X u_long *bus_addr,
@@ -274,6 +277,7 @@
X error = ENOMEM;
X return (error);
X }
+#endif /* MMAPIO */
X
X int
X ahc_pci_map_registers(struct ahc_softc *ahc)
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/aic7xxx_old.c linux/drivers/scsi/aic7xxx_old.c
--- v2.4.14/linux/drivers/scsi/aic7xxx_old.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/scsi/aic7xxx_old.c Wed Nov 21 14:05:29 2001
@@ -238,6 +238,7 @@
X #include <linux/init.h>
X #include <linux/spinlock.h>
X #include <linux/smp.h>
+#include <linux/blk.h>
X #include "sd.h"
X #include "scsi.h"
X #include "hosts.h"
@@ -11739,7 +11740,7 @@


X struct buffer_head *bh;
X

X p = (struct aic7xxx_host *) disk->device->host->hostdata;
- bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, 1024);
+ bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, block_size(dev));
X
X if ( bh )
X {
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/dpt_i2o.c linux/drivers/scsi/dpt_i2o.c
--- v2.4.14/linux/drivers/scsi/dpt_i2o.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/scsi/dpt_i2o.c Fri Nov 9 14:05:06 2001
@@ -165,6 +165,13 @@
X *============================================================================
X */
X
+static struct pci_device_id dptids[] = {
+ { PCI_DPT_VENDOR_ID, PCI_DPT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+ { PCI_DPT_VENDOR_ID, PCI_DPT_RAPTOR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci,dptids);
+
X static int adpt_detect(Scsi_Host_Template* sht)
X {
X struct pci_dev *pDev = NULL;
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c
--- v2.4.14/linux/drivers/scsi/eata.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/scsi/eata.c Fri Nov 9 14:05:06 2001
@@ -2077,4 +2077,4 @@
X #ifndef MODULE
X __setup("eata=", option_setup);
X #endif /* end MODULE */
-MODULE_LICENSE("BSD");
+MODULE_LICENSE("Dual BSD/GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/gdth.c linux/drivers/scsi/gdth.c
--- v2.4.14/linux/drivers/scsi/gdth.c Mon Nov 5 15:55:32 2001
+++ linux/drivers/scsi/gdth.c Fri Nov 9 14:05:06 2001
@@ -799,6 +799,17 @@
X return cnt;
X }
X
+#if LINUX_VERSION_CODE >= 0x20363
+/* Vortex only makes RAID controllers.
+ * We do not really want to specify all 550 ids here, so wildcard match.
+ */
+static struct pci_device_id gdthtable[] = {
+ {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID },
+ {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID },
+ {0}
+};
+MODULE_DEVICE_TABLE(pci,gdthtable);
+#endif
X
X GDTH_INITFUNC(static void, gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
X ushort vendor, ushort device))
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/i60uscsi.c linux/drivers/scsi/i60uscsi.c
--- v2.4.14/linux/drivers/scsi/i60uscsi.c Fri Mar 2 18:38:38 2001
+++ linux/drivers/scsi/i60uscsi.c Fri Nov 9 14:05:06 2001
@@ -68,10 +68,6 @@
X * 08/08/99 bv - v1.02c Use waitForPause again.
X **************************************************************************/
X
-#ifndef CVT_LINUX_VERSION
-#define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S)
-#endif
-
X #include <linux/version.h>
X #include <linux/sched.h>
X #include <asm/io.h>
@@ -161,12 +157,8 @@
X static void waitForPause(unsigned amount)
X {
X ULONG the_time = jiffies + MS_TO_JIFFIES(amount);
-
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
- while (time_before_eq(jiffies, the_time));
-#else
- while (jiffies < the_time);
-#endif
+ while (time_before_eq(jiffies, the_time))
+ cpu_relax();
X }
X
X /***************************************************************************/
@@ -564,33 +556,16 @@
X { /* I need Host Control Block Information */
X ULONG flags;
X
-#if 0
- printk("inia100: enter inia100_reset\n");
-#endif
-
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- save_flags(flags);
- cli();
-#else
X spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
-#endif
X
X initAFlag(pHCB);
X /* reset scsi bus */
X ORC_WR(pHCB->HCS_Base + ORC_HCTRL, SCSIRST);
X if (waitSCSIRSTdone(pHCB) == FALSE) {
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- restore_flags(flags);
-#else
X spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-#endif
X return (SCSI_RESET_ERROR);
X } else {
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- restore_flags(flags);
-#else
X spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-#endif
X return (SCSI_RESET_SUCCESS);
X }
X }
@@ -611,16 +586,7 @@
X UCHAR i;
X ULONG flags;
X
-#if 0
- printk("inia100: enter inia100_reset\n");
-#endif
-
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- save_flags(flags);
- cli();
-#else
X spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
-#endif
X pScb = (ORC_SCB *) NULL;
X pVirEscb = (ESCB *) NULL;
X
@@ -638,19 +604,11 @@
X
X if (i == orc_num_scb) {
X printk("Unable to Reset - No SCB Found\n");
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- restore_flags(flags);
-#else
X spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-#endif
X return (SCSI_RESET_NOT_RUNNING);
X }
X if ((pScb = orc_alloc_scb(pHCB)) == NULL) {
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- restore_flags(flags);
-#else
X spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-#endif
X return (SCSI_RESET_NOT_RUNNING);
X }
X pScb->SCB_Opcode = ORC_BUSDEVRST;
@@ -669,17 +627,13 @@
X pVirEscb->SCB_Srb = (unsigned char *) SCpnt;
X }
X orc_exec_scb(pHCB, pScb); /* Start execute SCB */
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- restore_flags(flags);
-#else
X spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-#endif
X return SCSI_RESET_PENDING;
X }
X
X
X /***************************************************************************/
-ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp)
+ORC_SCB *__orc_alloc_scb(ORC_HCS * hcsp)
X {
X ORC_SCB *pTmpScb;
X UCHAR Ch;
@@ -688,12 +642,6 @@
X UCHAR i;
X ULONG flags;
X
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- save_flags(flags);
- cli();
-#else
- spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
-#endif
X Ch = hcsp->HCS_Index;
X for (i = 0; i < 8; i++) {
X for (index = 0; index < 32; index++) {
@@ -704,21 +652,22 @@
X }
X idx = index + 32 * i;
X pTmpScb = (PVOID) ((ULONG) hcsp->HCS_virScbArray + (idx * sizeof(ORC_SCB)));
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- restore_flags(flags);
-#else
- spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-#endif
X return (pTmpScb);
X }
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- restore_flags(flags);
-#else
- spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-#endif
X return (NULL);
X }
X
+ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp)
+{
+ ORC_SCB *pTmpScb;
+ ULONG flags;
+
+ spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
+ pTmpScb = __orc_alloc_scb(hcsp);
+ spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+ return (pTmpScb);
+}
+
X
X /***************************************************************************/
X void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
@@ -728,22 +677,13 @@
X UCHAR i;
X UCHAR Ch;
X
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- save_flags(flags);
- cli();
-#else
X spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
-#endif
X Ch = hcsp->HCS_Index;
X Index = scbp->SCB_ScbIdx;
X i = Index / 32;
X Index %= 32;
X hcsp->BitAllocFlag[Ch][i] |= (1 << Index);
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- restore_flags(flags);
-#else
X spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-#endif
X }
X
X
@@ -872,15 +812,7 @@
X UCHAR i;
X ULONG flags;
X
-#if 0
- printk("inia100: abort SRB \n");
-#endif
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- save_flags(flags);
- cli();
-#else
X spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
-#endif
X
X pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray;
X
@@ -888,37 +820,21 @@
X pVirEscb = pVirScb->SCB_EScb;
X if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == (unsigned char *) SCpnt)) {
X if (pVirScb->SCB_TagMsg == 0) {
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- restore_flags(flags);
-#else
X spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-#endif
X return (SCSI_ABORT_BUSY);
X } else {
X if (abort_SCB(hcsp, pVirScb)) {
X pVirEscb->SCB_Srb = NULL;
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- restore_flags(flags);
-#else
X spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-#endif
X return (SCSI_ABORT_SUCCESS);
X } else {
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- restore_flags(flags);
-#else
X spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-#endif
X return (SCSI_ABORT_NOT_RUNNING);
X }
X }
X }
X }
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
- restore_flags(flags);
-#else
X spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-#endif
X return (SCSI_ABORT_NOT_RUNNING);
X }
X
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/i60uscsi.h linux/drivers/scsi/i60uscsi.h
--- v2.4.14/linux/drivers/scsi/i60uscsi.h Tue Oct 23 22:48:52 2001
+++ linux/drivers/scsi/i60uscsi.h Fri Nov 9 14:05:06 2001
@@ -342,14 +342,10 @@
X UBYTE ActiveTags[16][16]; /* 50 */
X ORC_TCS HCS_Tcs[16]; /* 28 */
X U32 BitAllocFlag[MAX_CHANNELS][8]; /* Max STB is 256, So 256/32 */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
X spinlock_t BitAllocFlagLock;
-#endif
X ULONG pSRB_head;
X ULONG pSRB_tail;
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
X spinlock_t pSRB_lock;
-#endif
X } ORC_HCS;
X
X /* Bit Definition for HCS_Flags */
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/ips.c linux/drivers/scsi/ips.c
--- v2.4.14/linux/drivers/scsi/ips.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/scsi/ips.c Fri Nov 9 14:05:06 2001
@@ -7566,8 +7566,10 @@
X return (0);
X }
X
+#if defined (MODULE) || (LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0))
X static Scsi_Host_Template driver_template = IPS;
X #include "scsi_module.c"
+#endif
X
X /*
X * Overrides for Emacs so that we almost follow Linus's tabbing style.
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/osst.c linux/drivers/scsi/osst.c
--- v2.4.14/linux/drivers/scsi/osst.c Mon Nov 5 15:55:32 2001
+++ linux/drivers/scsi/osst.c Tue Nov 13 09:19:41 2001
@@ -1382,7 +1382,7 @@
X unsigned char cmd[MAX_COMMAND_SIZE];
X Scsi_Request * SRpnt;
X int dev = TAPE_NR(STp->devt);
- int expected __attribute__ ((__unused__));
+ int expected = 0;
X int attempts = 1000 / skip;
X int flag = 1;
X long startwait = jiffies;
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/pci2000.c linux/drivers/scsi/pci2000.c
--- v2.4.14/linux/drivers/scsi/pci2000.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/scsi/pci2000.c Fri Nov 9 14:05:06 2001
@@ -858,7 +858,7 @@
X }
X
X

-MODULE_LICENSE("BSD without advertisement clause");
+MODULE_LICENSE("Dual BSD/GPL");

X /* Eventually this will go into an include file, but this will be later */
X static Scsi_Host_Template driver_template = PCI2000;
X
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/pci2220i.c linux/drivers/scsi/pci2220i.c
--- v2.4.14/linux/drivers/scsi/pci2220i.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/scsi/pci2220i.c Fri Nov 9 14:05:06 2001
@@ -2924,7 +2924,7 @@


X return 0;
X }
X

-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
X
X /* Eventually this will go into an include file, but this will be later */
X static Scsi_Host_Template driver_template = PCI2220I;
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.4.14/linux/drivers/scsi/scsi.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/scsi/scsi.c Fri Nov 9 14:05:06 2001
@@ -96,17 +96,25 @@
X /* Do not call reset on error if we just did a reset within 15 sec. */
X #define MIN_RESET_PERIOD (15*HZ)
X
+/*
+ * Macro to determine the size of SCSI command. This macro takes vendor
+ * unique commands into account. SCSI commands in groups 6 and 7 are
+ * vendor unique and we will depend upon the command length being
+ * supplied correctly in cmd_len.
+ */
+#define CDB_SIZE(SCpnt) ((((SCpnt->cmnd[0] >> 5) & 7) < 6) ? \
+ COMMAND_SIZE(SCpnt->cmnd[0]) : SCpnt->cmd_len)
X
X /*
X * Data declarations.
X */
X unsigned long scsi_pid;
X Scsi_Cmnd *last_cmnd;
-/* Command groups 3 and 4 are reserved and should never be used. */
+/* Command group 3 is reserved and should never be used. */
X const unsigned char scsi_command_size[8] =
X {
X 6, 10, 10, 12,
- 12, 12, 10, 10
+ 16, 12, 10, 10
X };
X static unsigned long serial_number;
X static Scsi_Cmnd *scsi_bh_queue_head;
@@ -679,18 +687,44 @@
X * passes a meaningful return value.
X */
X if (host->hostt->use_new_eh_code) {
- spin_lock_irqsave(&io_request_lock, flags);
- rtn = host->hostt->queuecommand(SCpnt, scsi_done);
- spin_unlock_irqrestore(&io_request_lock, flags);
- if (rtn != 0) {
- scsi_delete_timer(SCpnt);
- scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_HOST_BUSY);
- SCSI_LOG_MLQUEUE(3, printk("queuecommand : request rejected\n"));
+ /*
+ * Before we queue this command, check if the command
+ * length exceeds what the host adapter can handle.
+ */
+ if (CDB_SIZE(SCpnt) <= SCpnt->host->max_cmd_len) {
+ spin_lock_irqsave(&io_request_lock, flags);
+ rtn = host->hostt->queuecommand(SCpnt, scsi_done);
+ spin_unlock_irqrestore(&io_request_lock, flags);
+ if (rtn != 0) {
+ scsi_delete_timer(SCpnt);
+ scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_HOST_BUSY);
+ SCSI_LOG_MLQUEUE(3, printk("queuecommand : request rejected\n"));
+ }
+ } else {
+ SCSI_LOG_MLQUEUE(3, printk("queuecommand : command too long.\n"));
+ SCpnt->result = (DID_ABORT << 16);
+ spin_lock_irqsave(&io_request_lock, flags);
+ scsi_done(SCpnt);
+ spin_unlock_irqrestore(&io_request_lock, flags);
+ rtn = 1;
X }
X } else {
- spin_lock_irqsave(&io_request_lock, flags);
- host->hostt->queuecommand(SCpnt, scsi_old_done);
- spin_unlock_irqrestore(&io_request_lock, flags);
+ /*
+ * Before we queue this command, check if the command
+ * length exceeds what the host adapter can handle.
+ */
+ if (CDB_SIZE(SCpnt) <= SCpnt->host->max_cmd_len) {
+ spin_lock_irqsave(&io_request_lock, flags);
+ host->hostt->queuecommand(SCpnt, scsi_old_done);
+ spin_unlock_irqrestore(&io_request_lock, flags);
+ } else {
+ SCSI_LOG_MLQUEUE(3, printk("queuecommand : command too long.\n"));
+ SCpnt->result = (DID_ABORT << 16);
+ spin_lock_irqsave(&io_request_lock, flags);
+ scsi_old_done(SCpnt);
+ spin_unlock_irqrestore(&io_request_lock, flags);
+ rtn = 1;
+ }
X }
X } else {
X int temp;
@@ -702,8 +736,10 @@
X #ifdef DEBUG_DELAY
X spin_unlock_irqrestore(&io_request_lock, flags);
X clock = jiffies + 4 * HZ;
- while (time_before(jiffies, clock))
+ while (time_before(jiffies, clock)) {


X barrier();
+ cpu_relax();
+ }

X printk("done(host = %d, result = %04x) : routine at %p\n",
X host->host_no, temp, host->hostt->command);
X spin_lock_irqsave(&io_request_lock, flags);
@@ -787,14 +823,15 @@
X {
X int i;
X int target = SDpnt->id;
+ int size = COMMAND_SIZE(((const unsigned char *)cmnd)[0]);
X printk("scsi_do_req (host = %d, channel = %d target = %d, "
X "buffer =%p, bufflen = %d, done = %p, timeout = %d, "
X "retries = %d)\n"
X "command : ", host->host_no, SDpnt->channel, target, buffer,
X bufflen, done, timeout, retries);
- for (i = 0; i < 10; ++i)
- printk("%02x ", ((unsigned char *) cmnd)[i]);
- printk("\n");
+ for (i = 0; i < size; ++i)
+ printk("%02x ", ((unsigned char *) cmnd)[i]);
+ printk("\n");
X });
X
X if (!host) {
@@ -976,14 +1013,15 @@
X {
X int i;
X int target = SCpnt->target;
+ int size = COMMAND_SIZE(((const unsigned char *)cmnd)[0]);
X printk("scsi_do_cmd (host = %d, channel = %d target = %d, "
X "buffer =%p, bufflen = %d, done = %p, timeout = %d, "
X "retries = %d)\n"
X "command : ", host->host_no, SCpnt->channel, target, buffer,
X bufflen, done, timeout, retries);
- for (i = 0; i < 10; ++i)
- printk("%02x ", ((unsigned char *) cmnd)[i]);
- printk("\n");
+ for (i = 0; i < size; ++i)
+ printk("%02x ", ((unsigned char *) cmnd)[i]);
+ printk("\n");
X });
X
X if (!host) {
@@ -1476,9 +1514,6 @@
X }
X spin_unlock_irqrestore(&device_request_lock, flags);
X }
-
-static int proc_scsi_gen_write(struct file * file, const char * buf,
- unsigned long length, void *data);
X
X void __init scsi_host_no_insert(char *str, int n)
X {
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v2.4.14/linux/drivers/scsi/scsi.h Tue Oct 23 22:48:52 2001
+++ linux/drivers/scsi/scsi.h Thu Nov 22 11:49:15 2001
@@ -61,7 +61,7 @@


X #endif
X #endif
X

-#if defined(CONFIG_SBUS) && !defined(CONFIG_SUN3)
+#if defined(CONFIG_SBUS) && !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
X #include <asm/sbus.h>
X #if ((SCSI_DATA_UNKNOWN == SBUS_DMA_BIDIRECTIONAL) && (SCSI_DATA_WRITE == SBUS_DMA_TODEVICE) && (SCSI_DATA_READ == SBUS_DMA_FROMDEVICE) && (SCSI_DATA_NONE == SBUS_DMA_NONE))
X #define scsi_to_sbus_dma_dir(scsi_dir) ((int)(scsi_dir))
@@ -351,7 +351,7 @@
X #define DRIVER_MASK 0x0f
X #define SUGGEST_MASK 0xf0
X
-#define MAX_COMMAND_SIZE 12
+#define MAX_COMMAND_SIZE 16
X #define SCSI_SENSE_BUFFERSIZE 64
X
X /*
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.4.14/linux/drivers/scsi/sd.c Mon Nov 5 15:55:32 2001
+++ linux/drivers/scsi/sd.c Fri Nov 9 14:05:06 2001
@@ -230,11 +230,8 @@


X return -EFAULT;
X return 0;
X }

- case BLKGETSIZE: /* Return device size */

- return put_user(sd[SD_PARTITION(inode->i_rdev)].nr_sects, (unsigned long *) arg);
+ case BLKGETSIZE:
X case BLKGETSIZE64:
- return put_user((u64)sd[SD_PARTITION(inode->i_rdev)].nr_sects << 9, (u64 *)arg);
-


X case BLKROSET:
X case BLKROGET:
X case BLKRASET:

@@ -459,8 +456,10 @@
X * is being re-read.
X */
X
- while (rscsi_disks[target].device->busy)
+ while (rscsi_disks[target].device->busy) {


X barrier();
+ cpu_relax();
+ }

X /*
X * The following code can sleep.
X * Module unloading must be prevented
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v2.4.14/linux/drivers/scsi/st.c Mon Nov 5 15:55:32 2001
+++ linux/drivers/scsi/st.c Fri Nov 9 13:52:21 2001
@@ -12,7 +12,7 @@
X Copyright 1992 - 2001 Kai Makisara
X email Kai.Ma...@metla.fi
X
- Last modified: Wed Oct 3 22:17:59 2001 by maki...@kai.makisara.local
+ Last modified: Sat Nov 3 19:30:55 2001 by maki...@kai.makisara.local
X Some small formal changes - aeb, 950809
X
X Last modified: 18-JAN-1998 Richard Gooch <rgo...@atnf.csiro.au> Devfs support
@@ -21,7 +21,7 @@
X error handling will be discarded.
X */
X
-static char *verstr = "20011003";
+static char *verstr = "20011103";


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

@@ -276,6 +276,17 @@
X driver_byte(result) & DRIVER_MASK, host_byte(result));
X }
X
+ if (STp->cln_mode >= EXTENDED_SENSE_START) {
+ if (STp->cln_sense_value)
+ STp->cleaning_req |= ((SRpnt->sr_sense_buffer[STp->cln_mode] &
+ STp->cln_sense_mask) == STp->cln_sense_value);
+ else
+ STp->cleaning_req |= ((SRpnt->sr_sense_buffer[STp->cln_mode] &
+ STp->cln_sense_mask) != 0);
+ }
+ if (sense[12] == 0 && sense[13] == 0x17) /* ASC and ASCQ => cleaning requested */
+ STp->cleaning_req = 1;
+
X if ((sense[0] & 0x70) == 0x70 &&
X scode == RECOVERED_ERROR
X #if ST_RECOVERED_WRITE_FATAL
@@ -414,15 +425,6 @@
X (STp->buffer)->syscall_result = st_chk_result(STp, (STp->buffer)->last_SRpnt);
X scsi_release_request((STp->buffer)->last_SRpnt);
X
- if (STbuffer->writing < STbuffer->buffer_bytes)
-#if 0
- memcpy(STbuffer->b_data,
- STbuffer->b_data + STbuffer->writing,
- STbuffer->buffer_bytes - STbuffer->writing);
-#else
- printk(KERN_WARNING
- "st: write_behind_check: something left in buffer!\n");
-#endif
X STbuffer->buffer_bytes -= STbuffer->writing;
X STps = &(STp->ps[STp->partition]);
X if (STps->drv_block >= 0) {
@@ -636,47 +638,27 @@


X return 0;
X }
X
-

-/* Open the device. Needs to be called with BKL only because of incrementing the SCSI host
- module count. */
-static int st_open(struct inode *inode, struct file *filp)
-{
- unsigned short st_flags;
- int i, need_dma_buffer, new_session = FALSE;
- int retval;
- unsigned char cmd[MAX_COMMAND_SIZE];
+/* See if the drive is ready and gather information about the tape. Return values:
+ < 0 negative error code from errno.h
+ 0 drive ready
+ 1 drive not ready (possibly no tape)
+*/
+#define CHKRES_READY 0
+#define CHKRES_NOT_READY 1
+
+static int check_tape(Scsi_Tape *STp, struct file *filp)
+{
+ int i, retval, new_session = FALSE;
+ unsigned char cmd[MAX_COMMAND_SIZE], saved_cleaning;
+ unsigned short st_flags = filp->f_flags;
X Scsi_Request *SRpnt;
- Scsi_Tape *STp;
X ST_mode *STm;
X ST_partstat *STps;
- int dev = TAPE_NR(inode->i_rdev);
+ int dev = TAPE_NR(STp->devt);
+ struct inode *inode = filp->f_dentry->d_inode;
X int mode = TAPE_MODE(inode->i_rdev);


- unsigned long flags;
-

- write_lock_irqsave(&st_dev_arr_lock, flags);
- STp = scsi_tapes[dev];
- if (dev >= st_template.dev_max || STp == NULL) {
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
- return (-ENXIO);
- }
-
- if (STp->in_use) {
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
- DEB( printk(ST_DEB_MSG "st%d: Device already in use.\n", dev); )
- return (-EBUSY);
- }
- STp->in_use = 1;
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
- STp->rew_at_close = STp->autorew_dev = (MINOR(inode->i_rdev) & 0x80) == 0;
-
- if (STp->device->host->hostt->module)
- __MOD_INC_USE_COUNT(STp->device->host->hostt->module);
- STp->device->access_count++;
X
- if (!scsi_block_when_processing_errors(STp->device)) {
- retval = (-ENXIO);
- goto err_out;
- }
+ STp->ready = ST_READY;
X
X if (mode != STp->current_mode) {
X DEBC(printk(ST_DEB_MSG "st%d: Mode change from %d to %d.\n",
@@ -686,54 +668,11 @@
X }
X STm = &(STp->modes[STp->current_mode]);
X
- /* Allocate a buffer for this user */
- need_dma_buffer = STp->restr_dma;
- write_lock_irqsave(&st_dev_arr_lock, flags);
- for (i = 0; i < st_nbr_buffers; i++)
- if (!st_buffers[i]->in_use &&
- (!need_dma_buffer || st_buffers[i]->dma)) {
- STp->buffer = st_buffers[i];
- (STp->buffer)->in_use = 1;
- break;
- }
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
- if (i >= st_nbr_buffers) {
- STp->buffer = new_tape_buffer(FALSE, need_dma_buffer, TRUE);
- if (STp->buffer == NULL) {
- printk(KERN_WARNING "st%d: Can't allocate tape buffer.\n", dev);
- retval = (-EBUSY);


- goto err_out;
- }
- }
-

- (STp->buffer)->writing = 0;
- (STp->buffer)->syscall_result = 0;
- (STp->buffer)->use_sg = STp->device->host->sg_tablesize;
-
- /* Compute the usable buffer size for this SCSI adapter */
- if (!(STp->buffer)->use_sg)
- (STp->buffer)->buffer_size = (STp->buffer)->sg[0].length;
- else {
- for (i = 0, (STp->buffer)->buffer_size = 0; i < (STp->buffer)->use_sg &&
- i < (STp->buffer)->sg_segs; i++)
- (STp->buffer)->buffer_size += (STp->buffer)->sg[i].length;
- }
-
- st_flags = filp->f_flags;
- STp->write_prot = ((st_flags & O_ACCMODE) == O_RDONLY);
-
- STp->dirty = 0;
- for (i = 0; i < ST_NBR_PARTITIONS; i++) {
- STps = &(STp->ps[i]);
- STps->rw = ST_IDLE;
- }
- STp->ready = ST_READY;
- STp->recover_count = 0;
- DEB( STp->nbr_waits = STp->nbr_finished = 0; )
-
X memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
X cmd[0] = TEST_UNIT_READY;
X
+ saved_cleaning = STp->cleaning_req;
+ STp->cleaning_req = 0;
X SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->long_timeout,
X MAX_READY_RETRIES, TRUE);
X if (!SRpnt) {
@@ -742,7 +681,7 @@
X }
X
X if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
- (SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
+ (SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
X
X /* Flush the queued UNIT ATTENTION sense data */
X for (i=0; i < 10; i++) {
@@ -771,6 +710,8 @@
X }
X new_session = TRUE;
X }
+ else
+ STp->cleaning_req |= saved_cleaning;
X
X if ((STp->buffer)->syscall_result != 0) {
X if ((STp->device)->scsi_level >= SCSI_2 &&
@@ -788,7 +729,7 @@
X STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
X STp->partition = STp->new_partition = 0;
X STp->door_locked = ST_UNLOCKED;
- return 0;
+ return CHKRES_NOT_READY;
X }
X
X if (STp->omit_blklims)
@@ -869,7 +810,8 @@
X
X DEBC(printk(ST_DEB_MSG "st%d: Write protected\n", dev));
X
- if ((st_flags & O_ACCMODE) == O_WRONLY || (st_flags & O_ACCMODE) == O_RDWR) {
+ if ((st_flags & O_ACCMODE) == O_WRONLY ||
+ (st_flags & O_ACCMODE) == O_RDWR) {
X retval = (-EROFS);
X goto err_out;
X }
@@ -904,6 +846,95 @@
X }
X }
X
+ return CHKRES_READY;
+
+ err_out:
+ return retval;
+}
+
+
+ /* Open the device. Needs to be called with BKL only because of incrementing the SCSI host
+ module count. */
+static int st_open(struct inode *inode, struct file *filp)
+{
+ int i, need_dma_buffer;
+ int retval = (-EIO);
+ Scsi_Tape *STp;
+ ST_partstat *STps;
+ int dev = TAPE_NR(inode->i_rdev);


+ unsigned long flags;
+

+ write_lock_irqsave(&st_dev_arr_lock, flags);
+ STp = scsi_tapes[dev];
+ if (dev >= st_template.dev_max || STp == NULL) {
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ return (-ENXIO);
+ }
+
+ if (STp->in_use) {
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ DEB( printk(ST_DEB_MSG "st%d: Device already in use.\n", dev); )
+ return (-EBUSY);
+ }
+ STp->in_use = 1;
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ STp->rew_at_close = STp->autorew_dev = (MINOR(inode->i_rdev) & 0x80) == 0;
+
+ if (STp->device->host->hostt->module)
+ __MOD_INC_USE_COUNT(STp->device->host->hostt->module);
+ STp->device->access_count++;
+
+ if (!scsi_block_when_processing_errors(STp->device)) {
+ retval = (-ENXIO);
+ goto err_out;
+ }
+
+ /* Allocate a buffer for this user */
+ need_dma_buffer = STp->restr_dma;
+ write_lock_irqsave(&st_dev_arr_lock, flags);
+ for (i = 0; i < st_nbr_buffers; i++)
+ if (!st_buffers[i]->in_use &&
+ (!need_dma_buffer || st_buffers[i]->dma)) {
+ STp->buffer = st_buffers[i];
+ (STp->buffer)->in_use = 1;
+ break;
+ }
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ if (i >= st_nbr_buffers) {
+ STp->buffer = new_tape_buffer(FALSE, need_dma_buffer, TRUE);
+ if (STp->buffer == NULL) {
+ printk(KERN_WARNING "st%d: Can't allocate tape buffer.\n", dev);
+ retval = (-EBUSY);
+ goto err_out;
+ }
+ }
+
+ (STp->buffer)->writing = 0;
+ (STp->buffer)->syscall_result = 0;
+ (STp->buffer)->use_sg = STp->device->host->sg_tablesize;
+
+ /* Compute the usable buffer size for this SCSI adapter */
+ if (!(STp->buffer)->use_sg)
+ (STp->buffer)->buffer_size = (STp->buffer)->sg[0].length;
+ else {
+ for (i = 0, (STp->buffer)->buffer_size = 0; i < (STp->buffer)->use_sg &&
+ i < (STp->buffer)->sg_segs; i++)
+ (STp->buffer)->buffer_size += (STp->buffer)->sg[i].length;
+ }
+
+ STp->write_prot = ((filp->f_flags & O_ACCMODE) == O_RDONLY);
+
+ STp->dirty = 0;
+ for (i = 0; i < ST_NBR_PARTITIONS; i++) {
+ STps = &(STp->ps[i]);
+ STps->rw = ST_IDLE;
+ }
+ STp->recover_count = 0;
+ DEB( STp->nbr_waits = STp->nbr_finished = 0; )
+
+ retval = check_tape(STp, filp);
+ if (retval < 0)
+ goto err_out;
X return 0;
X
X err_out:
@@ -1819,7 +1850,7 @@
X dev, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
X STp->scsi2_logical);
X printk(KERN_INFO
- "st%d: sysv: %d\n", dev, STm->sysv);
+ "st%d: sysv: %d nowait: %d\n", dev, STm->sysv, STp->immediate);
X DEB(printk(KERN_INFO
X "st%d: debugging: %d\n",
X dev, debugging);)
@@ -1856,6 +1887,7 @@
X if ((STp->device)->scsi_level >= SCSI_2)
X STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
X STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
+ STp->immediate = (options & MT_ST_NOWAIT) != 0;
X STm->sysv = (options & MT_ST_SYSV) != 0;
X DEB( debugging = (options & MT_ST_DEBUGGING) != 0; )
X st_log_options(STp, STm, dev);
@@ -1884,6 +1916,8 @@
X STp->can_partitions = value;
X if ((options & MT_ST_SCSI2LOGICAL) != 0)
X STp->scsi2_logical = value;
+ if ((options & MT_ST_NOWAIT) != 0)
+ STp->immediate = value;
X if ((options & MT_ST_SYSV) != 0)
X STm->sysv = value;
X DEB(
@@ -1922,6 +1956,17 @@
X printk(KERN_INFO "st%d: Normal timeout set to %d seconds.\n",
X dev, value);
X }
+ } else if (code == MT_ST_SET_CLN) {
+ value = (options & ~MT_ST_OPTIONS) & 0xff;
+ if (value != 0 &&
+ value < EXTENDED_SENSE_START && value >= SCSI_SENSE_BUFFERSIZE)
+ return (-EINVAL);
+ STp->cln_mode = value;
+ STp->cln_sense_mask = (options >> 8) & 0xff;
+ STp->cln_sense_value = (options >> 16) & 0xff;
+ printk(KERN_INFO
+ "st%d: Cleaning request mode %d, mask %02x, value %02x\n",
+ dev, value, STp->cln_sense_mask, STp->cln_sense_value);
X } else if (code == MT_ST_DEF_OPTIONS) {
X code = (options & ~MT_ST_CLEAR_DEFAULT);
X value = (options & MT_ST_CLEAR_DEFAULT);
@@ -2099,6 +2144,78 @@
X STp->compression_changed = TRUE;


X return 0;
X }
+

+
+/* Process the load and unload commands (does unload if the load code is zero) */
+static int do_load_unload(Scsi_Tape *STp, struct file *filp, int load_code)
+{
+ int retval = (-EIO), timeout;
+ DEB(int dev = TAPE_NR(STp->devt);)
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ ST_partstat *STps;
+ Scsi_Request *SRpnt;
+
+ if (STp->ready != ST_READY && !load_code) {
+ if (STp->ready == ST_NO_TAPE)
+ return (-ENOMEDIUM);
+ else
+ return (-EIO);
+ }
+
+ memset(cmd, 0, MAX_COMMAND_SIZE);
+ cmd[0] = START_STOP;
+ if (load_code)
+ cmd[4] |= 1;
+ /*
+ * If arg >= 1 && arg <= 6 Enhanced load/unload in HP C1553A
+ */
+ if (load_code >= 1 + MT_ST_HPLOADER_OFFSET
+ && load_code <= 6 + MT_ST_HPLOADER_OFFSET) {
+ DEBC(printk(ST_DEB_MSG "st%d: Enhanced %sload slot %2ld.\n",
+ dev, (cmd[4]) ? "" : "un",
+ load_code - MT_ST_HPLOADER_OFFSET));
+ cmd[3] = load_code - MT_ST_HPLOADER_OFFSET; /* MediaID field of C1553A */
+ }
+ if (STp->immediate) {
+ cmd[1] = 1; /* Don't wait for completion */
+ timeout = STp->timeout;
+ }
+ else
+ timeout = STp->long_timeout;
+
+ DEBC(
+ if (!load_code)
+ printk(ST_DEB_MSG "st%d: Unloading tape.\n", dev);
+ else
+ printk(ST_DEB_MSG "st%d: Loading tape.\n", dev);
+ );
+
+ SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE,
+ timeout, MAX_RETRIES, TRUE);
+ if (!SRpnt)
+ return (STp->buffer)->syscall_result;
+
+ retval = (STp->buffer)->syscall_result;
+ scsi_release_request(SRpnt);
+
+ if (!retval) { /* SCSI command successful */
+
+ if (!load_code)
+ STp->rew_at_close = 0;
+ else
+ STp->rew_at_close = STp->autorew_dev;
+
+ retval = check_tape(STp, filp);
+ if (retval > 0)
+ retval = 0;
+ }
+ else {
+ STps = &(STp->ps[STp->partition]);
+ STps->drv_file = STps->drv_block = (-1);


+ }
+
+ return retval;

+}
X
X
X /* Internal ioctl function */
@@ -2106,7 +2223,7 @@
X {
X int timeout;
X long ltmp;
- int i, ioctl_result;
+ int ioctl_result;
X int chg_eof = TRUE;
X unsigned char cmd[MAX_COMMAND_SIZE];
X Scsi_Request *SRpnt;
@@ -2115,7 +2232,7 @@
X int datalen = 0, direction = SCSI_DATA_NONE;
X int dev = TAPE_NR(STp->devt);
X
- if (STp->ready != ST_READY && cmd_in != MTLOAD) {
+ if (STp->ready != ST_READY) {
X if (STp->ready == ST_NO_TAPE)
X return (-ENOMEDIUM);
X else
@@ -2254,42 +2371,11 @@
X break;
X case MTREW:
X cmd[0] = REZERO_UNIT;
-#if ST_NOWAIT
- cmd[1] = 1; /* Don't wait for completion */
- timeout = STp->timeout;
-#endif
- DEBC(printk(ST_DEB_MSG "st%d: Rewinding tape.\n", dev));
- fileno = blkno = at_sm = 0;
- break;
- case MTOFFL:
- case MTLOAD:
- case MTUNLOAD:
- cmd[0] = START_STOP;
- if (cmd_in == MTLOAD)
- cmd[4] |= 1;
- /*
- * If arg >= 1 && arg <= 6 Enhanced load/unload in HP C1553A
- */
- if (cmd_in != MTOFFL &&
- arg >= 1 + MT_ST_HPLOADER_OFFSET
- && arg <= 6 + MT_ST_HPLOADER_OFFSET) {
- DEBC(printk(ST_DEB_MSG "st%d: Enhanced %sload slot %2ld.\n",
- dev, (cmd[4]) ? "" : "un",
- arg - MT_ST_HPLOADER_OFFSET));
- cmd[3] = arg - MT_ST_HPLOADER_OFFSET; /* MediaID field of C1553A */
+ if (STp->immediate) {
+ cmd[1] = 1; /* Don't wait for completion */
+ timeout = STp->timeout;
X }
-#if ST_NOWAIT
- cmd[1] = 1; /* Don't wait for completion */
- timeout = STp->timeout;
-#else
- timeout = STp->long_timeout;
-#endif
- DEBC(
- if (cmd_in != MTLOAD)
- printk(ST_DEB_MSG "st%d: Unloading tape.\n", dev);
- else
- printk(ST_DEB_MSG "st%d: Loading tape.\n", dev);
- )
+ DEBC(printk(ST_DEB_MSG "st%d: Rewinding tape.\n", dev));
X fileno = blkno = at_sm = 0;
X break;
X case MTNOP:
@@ -2298,10 +2384,10 @@
X break;
X case MTRETEN:
X cmd[0] = START_STOP;
-#if ST_NOWAIT
- cmd[1] = 1; /* Don't wait for completion */
- timeout = STp->timeout;
-#endif
+ if (STp->immediate) {
+ cmd[1] = 1; /* Don't wait for completion */
+ timeout = STp->timeout;
+ }
X cmd[4] = 3;
X DEBC(printk(ST_DEB_MSG "st%d: Retensioning tape.\n", dev));
X fileno = blkno = at_sm = 0;
@@ -2331,12 +2417,13 @@
X return (-EACCES);
X cmd[0] = ERASE;
X cmd[1] = 1; /* To the end of tape */
-#if ST_NOWAIT
- cmd[1] |= 2; /* Don't wait for completion */
- timeout = STp->timeout;
-#else
- timeout = STp->long_timeout * 8;
-#endif
+ if (STp->immediate) {
+ cmd[1] |= 2; /* Don't wait for completion */
+ timeout = STp->timeout;
+ }
+ else
+ timeout = STp->long_timeout * 8;
+
X DEBC(printk(ST_DEB_MSG "st%d: Erasing tape.\n", dev));
X fileno = blkno = at_sm = 0;
X break;
@@ -2462,17 +2549,6 @@
X else if (chg_eof)
X STps->eof = ST_NOEOF;
X
-
- if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
- STp->rew_at_close = 0;
- else if (cmd_in == MTLOAD) {
- STp->rew_at_close = STp->autorew_dev;
- for (i = 0; i < ST_NBR_PARTITIONS; i++) {
- STp->ps[i].rw = ST_IDLE;
- STp->ps[i].last_block_valid = FALSE;
- }
- STp->partition = 0;
- }
X } else { /* SCSI command was not completely successful. Don't return
X from this block without releasing the SCSI command block! */
X
@@ -2692,10 +2768,10 @@
X dev, STp->partition, partition));
X }
X }
-#if ST_NOWAIT
- scmd[1] |= 1; /* Don't wait for completion */
- timeout = STp->timeout;
-#endif
+ if (STp->immediate) {
+ scmd[1] |= 1; /* Don't wait for completion */
+ timeout = STp->timeout;
+ }
X
X SRpnt = st_do_scsi(NULL, STp, scmd, 0, SCSI_DATA_NONE,
X timeout, MAX_READY_RETRIES, TRUE);
@@ -3073,6 +3149,16 @@


X goto out;
X }
X

+ if (mtc.mt_op == MTUNLOAD || mtc.mt_op == MTOFFL) {
+ retval = do_load_unload(STp, file, 0);


+ goto out;
+ }
+

+ if (mtc.mt_op == MTLOAD) {
+ retval = do_load_unload(STp, file, max(1, mtc.mt_count));


+ goto out;
+ }
+

X if (STp->can_partitions && STp->ready == ST_READY &&
X (i = update_partition(STp)) < 0) {
X retval = i;
@@ -3155,6 +3241,8 @@
X (STm->do_buffer_writes && STp->block_size != 0) ||
X STp->drv_buffer != 0)
X mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
+ if (STp->cleaning_req)
+ mt_status.mt_gstat |= GMT_CLN(0xffffffff);
X
X i = copy_to_user((char *) arg, (char *) &(mt_status),
X sizeof(struct mtget));
@@ -3642,6 +3730,7 @@
X tpnt->two_fm = ST_TWO_FM;
X tpnt->fast_mteom = ST_FAST_MTEOM;
X tpnt->scsi2_logical = ST_SCSI2LOGICAL;
+ tpnt->immediate = ST_NOWAIT;
X tpnt->write_threshold = st_write_threshold;
X tpnt->default_drvbuffer = 0xff; /* No forced buffering */
X tpnt->partition = 0;
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/st.h linux/drivers/scsi/st.h
--- v2.4.14/linux/drivers/scsi/st.h Mon Aug 27 12:41:44 2001
+++ linux/drivers/scsi/st.h Fri Nov 9 13:52:21 2001
@@ -1,9 +1,6 @@
X
X #ifndef _ST_H
X #define _ST_H
-/*
- $Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/st.h,v 1.1 1992/04/24 18:01:50 root Exp root $
- */
X
X #ifndef _SCSI_H
X #include "scsi.h"
@@ -78,9 +75,13 @@
X unsigned char can_partitions;
X unsigned char two_fm;
X unsigned char fast_mteom;
+ unsigned char immediate;
X unsigned char restr_dma;
X unsigned char scsi2_logical;
X unsigned char default_drvbuffer; /* 0xff = don't touch, value 3 bits */
+ unsigned char cln_mode; /* 0 = none, otherwise sense byte nbr */
+ unsigned char cln_sense_value;
+ unsigned char cln_sense_mask;
X unsigned char use_pf; /* Set Page Format bit in all mode selects? */
X int tape_type;
X int write_threshold;
@@ -112,6 +113,7 @@
X unsigned char autorew_dev; /* auto-rewind device */
X unsigned char rew_at_close; /* rewind necessary at close */
X unsigned char inited;
+ unsigned char cleaning_req; /* cleaning requested? */
X int block_size;
X int min_block;
X int max_block;
@@ -167,5 +169,7 @@
X #define ST_DONT_TOUCH 0
X #define ST_NO 1
X #define ST_YES 2
+
+#define EXTENDED_SENSE_START 18
X
X #endif
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/ChangeLog.txt linux/drivers/scsi/sym53c8xx_2/ChangeLog.txt
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/ChangeLog.txt Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/ChangeLog.txt Fri Nov 9 15:22:54 2001
@@ -0,0 +1,130 @@
+Sat Dec 30 21:30 2000 Gerard Roudier
+ * version sym-2.1.0-20001230
+ - Initial release of SYM-2.
+
+Mon Jan 08 21:30 2001 Gerard Roudier
+ * version sym-2.1.1-20010108
+ - Change a couple of defines containing ncr or NCR by their
+ equivalent containing sym or SYM instead.
+
+Sun Jan 14 22:30 2001 Gerard Roudier
+ * version sym-2.1.2-20010114
+ - Fix a couple of printfs:
+ * Add the target number to the display of transfer parameters.
+ * Make the display of TCQ and queue depth clearer.
+
+Wed Jan 17 23:30 2001 Gerard Roudier
+ * version sym-2.1.3-20010117
+ - Wrong residual values were returned in some situations.
+ This broke cdrecord with linux-2.4.0, for example.
+
+Sat Jan 20 18:00 2001 Gerard Roudier
+ * version sym-2.1.4-20010120
+ - Add year 2001 to Copyright.
+ - A tiny bug in the dma memory freeing path has been fixed.
+ (Driver unload failed with a bad address reference).
+
+Wed Jan 24 21:00 2001 Gerard Roudier
+ * version sym-2.1.5-20010124
+ - Make the driver work under Linux-2.4.x when statically linked
+ with the kernel.
+ - Check against memory allocation failure for SCRIPTZ and add the
+ missing free of this memory on instance detach.
+ - Check against GPIO3 pulled low for HVD controllers (driver did
+ just the opposite).
+ Misdetection of BUS mode was triggerred on module reload only,
+ since BIOS settings were trusted instead on first load.
+
+Wed Feb 7 21:00 2001 Gerard Roudier
+ * version sym-2.1.6-20010207
+ - Call pci_enable_device() as wished by kernel maintainers.
+ - Change the sym_queue_scsiio() interface.
+ This is intended to simplify portability.
+ - Move the code intended to deal with the dowloading of SCRIPTS
+ from SCRIPTS :) in the patch method (was wrongly placed in
+ the SCRIPTS setup method).
+ - Add a missing cpu_to_scr() (np->abort_tbl.addr)
+ - Remove a wrong cpu_to_scr() (np->targtbl_ba)
+ - Cleanup a bit the PPR failure recovery code.
+
+Sat Mar 3 21:00 2001 Gerard Roudier
+ - Add option SYM_OPT_ANNOUNCE_TRANSFER_RATE and move the
+ corresponding code to file sym_misc.c.
+ Also move the code that sniffes INQUIRY to sym_misc.c.
+ This allows to share the corresponding code with NetBSD
+ without polluating the core driver source (sym_hipd.c).
+ - Add optionnal code that handles IO timeouts from the driver.
+ (not used under Linux, but required for NetBSD)
+ - Donnot assume any longer that PAGE_SHIFT and PAGE_SIZE are
+ defined at compile time, as at least NetBSD uses variables
+ in memory for that.
+ - Refine a work-around for the C1010-33 that consists in
+ disabling internal LOAD/STORE. Was applied up to revision 1.
+ Is now only applied to revision 0.
+ - Some code reorganisations due to code moves between files.
+
+Tues Apr 10 21:00 2001 Gerard Roudier
+ * version sym-2.1.9-20010412
+ - Reset 53C896 and 53C1010 chip according to the manual.
+ (i.e.: set the ABRT bit in ISTAT if SCRIPTS are running)
+ - Set #LUN in request sense only if scsi version <= 2 and
+ #LUN <= 7.
+ - Set busy_itl in LCB to 1 if the LCB is allocated and a
+ SCSI command is active. This is a simplification.
+ - In sym_hcb_free(), donnot scan the free_ccbq if no CCBs
+ has been allocated. This fixes a panic if attach failed.
+ - Add DT/ST (double/simple transition) in the transfer
+ negotiation announce.
+ - Forces the max number of tasks per LUN to at least 64.
+ - Use pci_set_dma_mask() for linux-2.4.3 and above.
+ - A couple of comments fixes.
+
+Wed May 22:00 2001 Gerard Roudier
+ * version sym-2.1.10-20010509
+ - Mask GPCNTL against 0x1c (was 0xfc) for the reading of the NVRAM.
+ This ensure LEDC bit will not be set on 896 and later chips.
+ Fix sent by Chip Salzenberg <ch...@perlsupport.com>.
+ - Define the number of PQS BUSes supported.
+ Fix sent by Stig Telfer <st...@api-networks.com>
+ - Miscellaneous common code rearrangements due to NetBSD accel
+ ioctl support, without impact on Linux (hopefully).
+
+Mon July 2 12:00 2001 Gerard Roudier
+ * version sym-2.1.11-20010702
+ - Add Tekram 390 U2B/U2W SCSI LED handling.
+ Submitted by Chip Salzenberg <ch...@valinux.com>
+ - Add call to scsi_set_pci_device() for kernels >= 2.4.4.
+ - Check pci dma mapping failures and complete the IO with some
+ error when such mapping fails.
+ - Fill in instance->max_cmd_len for kernels > 2.4.0.
+ - A couple of tiny fixes ...
+
+Sun Sep 9 18:00 2001 Gerard Roudier
+ * version sym-2.1.12-20010909
+ - Change my email address.
+ - Add infrastructure for the forthcoming 64 bit DMA adressing support.
+ (Based on PCI 64 bit patch from David S. Miller)
+ - Donnot use anymore vm_offset_t type.
+
+Sat Sep 15 20:00 2001 Gerard Roudier
+ * version sym-2.1.13-20010916
+ - Add support for 64 bit DMA addressing using segment registers.
+ 16 registers for up to 4 GB x 16 -> 64 GB.
+
+Sat Sep 22 12:00 2001 Gerard Roudier
+ * version sym-2.1.14-20010922
+ - Complete rewrite of the eh handling. The driver is now using a
+ semaphore in order to behave synchronously as required by the eh
+ threads. A timer is also used to prevent from waiting indefinitely.
+
+Sun Sep 30 17:00 2001 Gerard Roudier
+ * version sym-2.1.15-20010930
+ - Include <linux/module.h> unconditionnaly as expected by latest
+ kernels.
+ - Use del_timer_sync() for recent kernels to kill the driver timer
+ on module release.
+
+Sun Oct 28 15:00 2001 Gerard Roudier
+ * version sym-2.1.16-20011028
+ - Slightly simplify driver configuration.
+ - Prepare a new patch against linux-2.4.13.
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/Documentation.txt linux/drivers/scsi/sym53c8xx_2/Documentation.txt
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/Documentation.txt Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/Documentation.txt Fri Nov 9 15:22:54 2001
@@ -0,0 +1,1149 @@
+The Linux SYM-2 driver documentation file
+
+Written by Gerard Roudier <grou...@free.fr>
+21 Rue Carnot
+95170 DEUIL LA BARRE - FRANCE
+
+Decembre 28 2000
+===============================================================================
+
+1. Introduction


+2. Supported chips and SCSI features

+3. Advantages of this driver for newer chips.

+ 3.1 Optimized SCSI SCRIPTS
+ 3.2 New features appeared with the SYM53C896


+4. Memory mapped I/O versus normal I/O

+5. Tagged command queueing
+6. Parity checking
+7. Profiling information
+8. Control commands
+ 8.1 Set minimum synchronous period
+ 8.2 Set wide size
+ 8.3 Set maximum number of concurrent tagged commands
+ 8.4 Set debug mode
+ 8.5 Set flag (no_disc)
+ 8.6 Set verbose level
+ 8.7 Reset all logical units of a target
+ 8.8 Abort all tasks of all logical units of a target
+9. Configuration parameters
+10. Boot setup commands
+ 10.1 Syntax
+ 10.2 Available arguments
+ 10.2.1 Master parity checking
+ 10.2.2 Scsi parity checking
+ 10.2.3 Default number of tagged commands
+ 10.2.4 Default synchronous period factor
+ 10.2.5 Verbosity level
+ 10.2.6 Debug mode
+ 10.2.7 Burst max
+ 10.2.8 LED support
+ 10.2.9 Max wide
+ 10.2.10 Differential mode
+ 10.2.11 IRQ mode
+ 10.2.12 Reverse probe
+ 10.2.13 Fix up PCI configuration space
+ 10.2.14 Serial NVRAM
+ 10.2.15 Check SCSI BUS
+ 10.2.16 Exclude a host from being attached
+ 10.2.17 Suggest a default SCSI id for hosts
+ 10.3 PCI configuration fix-up boot option
+ 10.4 Serial NVRAM support boot option
+ 10.5 SCSI BUS checking boot option
+11. SCSI problem troubleshooting
+ 15.1 Problem tracking
+ 15.2 Understanding hardware error reports
+12. Serial NVRAM support (by Richard Waltham)
+ 17.1 Features
+ 17.2 Symbios NVRAM layout
+ 17.3 Tekram NVRAM layout
+
+===============================================================================
+
+1. Introduction
+
+This driver supports the whole SYM53C8XX family of PCI-SCSI controllers.
+It also support the subset of LSI53C10XX PCI-SCSI controllers that are based
+on the SYM53C8XX SCRIPTS language.
+
+It replaces the sym53c8xx+ncr53c8xx driver bundle and shares its core code
+with the FreeBSD SYM-2 driver. The `glue' that allows this driver to work

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

echo 'End of part 058'
echo 'File patch-2.4.15 is continued in part 059'
echo "059" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:42 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part066

#!/bin/sh -x
# this is part 066 of a 115 - part archive


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

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

+ if (i != j)
+ np->squeue[j] = np->squeue[i];
+ if ((j += 2) >= MAX_QUEUE*2) j = 0;
+ }
+ if ((i += 2) >= MAX_QUEUE*2) i = 0;
+ }
+ if (i != j) /* Copy back the idle task if needed */
+ np->squeue[j] = np->squeue[i];
+ np->squeueput = j; /* Update our current start queue pointer */
+
+ return (i - j) / 2;
+}
+
+/*
+ * Complete all CCBs queued to the COMP queue.
+ *
+ * These CCBs are assumed:
+ * - Not to be referenced either by devices or
+ * SCRIPTS-related queues and datas.
+ * - To have to be completed with an error condition
+ * or requeued.
+ *
+ * The device queue freeze count is incremented
+ * for each CCB that does not prevent this.
+ * This function is called when all CCBs involved
+ * in error handling/recovery have been reaped.
+ */
+void sym_flush_comp_queue(hcb_p np, int cam_status)
+{
+ SYM_QUEHEAD *qp;
+ ccb_p cp;
+
+ while ((qp = sym_remque_head(&np->comp_ccbq)) != 0) {
+ cam_ccb_p ccb;
+ cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
+ sym_insque_tail(&cp->link_ccbq, &np->busy_ccbq);
+ /* Leave quiet CCBs waiting for resources */
+ if (cp->host_status == HS_WAIT)
+ continue;
+ ccb = cp->cam_ccb;
+ if (cam_status)
+ sym_set_cam_status(ccb, cam_status);
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ if (sym_get_cam_status(ccb) == CAM_REQUEUE_REQ) {
+ tcb_p tp = &np->target[cp->target];
+ lcb_p lp = sym_lp(np, tp, cp->lun);
+ if (lp) {
+ sym_remque(&cp->link2_ccbq);
+ sym_insque_tail(&cp->link2_ccbq,
+ &lp->waiting_ccbq);
+ if (cp->started) {
+ if (cp->tag != NO_TAG)
+ --lp->started_tags;
+ else
+ --lp->started_no_tag;
+ }
+ }
+ cp->started = 0;
+ continue;
+ }
+#endif
+ sym_free_ccb(np, cp);
+ sym_freeze_cam_ccb(ccb);
+ sym_xpt_done(np, ccb);
+ }
+}
+
+/*
+ * chip handler for bad SCSI status condition
+ *
+ * In case of bad SCSI status, we unqueue all the tasks
+ * currently queued to the controller but not yet started
+ * and then restart the SCRIPTS processor immediately.
+ *
+ * QUEUE FULL and BUSY conditions are handled the same way.
+ * Basically all the not yet started tasks are requeued in
+ * device queue and the queue is frozen until a completion.
+ *
+ * For CHECK CONDITION and COMMAND TERMINATED status, we use
+ * the CCB of the failed command to prepare a REQUEST SENSE
+ * SCSI command and queue it to the controller queue.
+ *
+ * SCRATCHA is assumed to have been loaded with STARTPOS
+ * before the SCRIPTS called the C code.
+ */
+static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp)
+{
+ tcb_p tp = &np->target[cp->target];
+ u32 startp;
+ u_char s_status = cp->ssss_status;
+ u_char h_flags = cp->host_flags;
+ int msglen;
+ int nego;
+ int i;
+
+ /*
+ * Compute the index of the next job to start from SCRIPTS.
+ */
+ i = (INL (nc_scratcha) - np->squeue_ba) / 4;
+
+ /*
+ * The last CCB queued used for IARB hint may be
+ * no longer relevant. Forget it.
+ */
+#ifdef SYM_CONF_IARB_SUPPORT
+ if (np->last_cp)
+ np->last_cp = 0;
+#endif
+
+ /*
+ * Now deal with the SCSI status.
+ */
+ switch(s_status) {
+ case S_BUSY:
+ case S_QUEUE_FULL:
+ if (sym_verbose >= 2) {
+ PRINT_ADDR(cp);
+ printf ("%s\n",
+ s_status == S_BUSY ? "BUSY" : "QUEUE FULL\n");
+ }
+ default: /* S_INT, S_INT_COND_MET, S_CONFLICT */
+ sym_complete_error (np, cp);
+ break;
+ case S_TERMINATED:
+ case S_CHECK_COND:
+ /*
+ * If we get an SCSI error when requesting sense, give up.
+ */
+ if (h_flags & HF_SENSE) {
+ sym_complete_error (np, cp);
+ break;
+ }
+
+ /*
+ * Dequeue all queued CCBs for that device not yet started,
+ * and restart the SCRIPTS processor immediately.
+ */
+ (void) sym_dequeue_from_squeue(np, i, cp->target, cp->lun, -1);
+ OUTL_DSP (SCRIPTA_BA (np, start));
+
+ /*
+ * Save some info of the actual IO.
+ * Compute the data residual.
+ */
+ cp->sv_scsi_status = cp->ssss_status;
+ cp->sv_xerr_status = cp->xerr_status;
+ cp->sv_resid = sym_compute_residual(np, cp);
+
+ /*
+ * Prepare all needed data structures for
+ * requesting sense data.


+ */
+
+ /*

+ * identify message
+ */
+ cp->scsi_smsg2[0] = M_IDENTIFY | cp->lun;
+ msglen = 1;
+
+ /*
+ * If we are currently using anything different from
+ * async. 8 bit data transfers with that target,
+ * start a negotiation, since the device may want
+ * to report us a UNIT ATTENTION condition due to
+ * a cause we currently ignore, and we donnot want
+ * to be stuck with WIDE and/or SYNC data transfer.
+ *
+ * cp->nego_status is filled by sym_prepare_nego().
+ */
+ cp->nego_status = 0;
+ nego = 0;
+ if (tp->tinfo.curr.options & PPR_OPT_MASK)
+ nego = NS_PPR;
+ else if (tp->tinfo.curr.width != BUS_8_BIT)
+ nego = NS_WIDE;
+ else if (tp->tinfo.curr.offset != 0)
+ nego = NS_SYNC;
+ if (nego)
+ msglen +=
+ sym_prepare_nego (np,cp, nego, &cp->scsi_smsg2[msglen]);
+ /*
+ * Message table indirect structure.
+ */
+ cp->phys.smsg.addr = cpu_to_scr(CCB_BA (cp, scsi_smsg2));
+ cp->phys.smsg.size = cpu_to_scr(msglen);
+
+ /*
+ * sense command
+ */
+ cp->phys.cmd.addr = cpu_to_scr(CCB_BA (cp, sensecmd));
+ cp->phys.cmd.size = cpu_to_scr(6);
+
+ /*
+ * patch requested size into sense command
+ */
+ cp->sensecmd[0] = 0x03;
+ cp->sensecmd[1] = 0;
+ if (tp->tinfo.curr.scsi_version <= 2 && cp->lun <= 7)
+ cp->sensecmd[1] = cp->lun << 5;
+ cp->sensecmd[4] = SYM_SNS_BBUF_LEN;
+ cp->data_len = SYM_SNS_BBUF_LEN;
+
+ /*
+ * sense data
+ */
+ bzero(cp->sns_bbuf, SYM_SNS_BBUF_LEN);
+ cp->phys.sense.addr = cpu_to_scr(vtobus(cp->sns_bbuf));
+ cp->phys.sense.size = cpu_to_scr(SYM_SNS_BBUF_LEN);
+
+ /*
+ * requeue the command.
+ */
+ startp = SCRIPTB_BA (np, sdata_in);
+
+ cp->phys.head.savep = cpu_to_scr(startp);
+ cp->phys.head.lastp = cpu_to_scr(startp);
+ cp->startp = cpu_to_scr(startp);
+ cp->goalp = cpu_to_scr(startp + 16);
+
+ cp->host_xflags = 0;
+ cp->host_status = cp->nego_status ? HS_NEGOTIATE : HS_BUSY;
+ cp->ssss_status = S_ILLEGAL;
+ cp->host_flags = (HF_SENSE|HF_DATA_IN);
+ cp->xerr_status = 0;
+ cp->extra_bytes = 0;
+
+ cp->phys.head.go.start = cpu_to_scr(SCRIPTA_BA (np, select));
+
+ /*
+ * Requeue the command.
+ */
+ sym_put_start_queue(np, cp);
+
+ /*
+ * Give back to upper layer everything we have dequeued.
+ */
+ sym_flush_comp_queue(np, 0);
+ break;
+ }
+}
+
+/*
+ * After a device has accepted some management message
+ * as BUS DEVICE RESET, ABORT TASK, etc ..., or when
+ * a device signals a UNIT ATTENTION condition, some
+ * tasks are thrown away by the device. We are required
+ * to reflect that on our tasks list since the device
+ * will never complete these tasks.
+ *
+ * This function move from the BUSY queue to the COMP
+ * queue all disconnected CCBs for a given target that
+ * match the following criteria:
+ * - lun=-1 means any logical UNIT otherwise a given one.
+ * - task=-1 means any task, otherwise a given one.
+ */
+int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task)
+{
+ SYM_QUEHEAD qtmp, *qp;
+ int i = 0;
+ ccb_p cp;
+
+ /*
+ * Move the entire BUSY queue to our temporary queue.
+ */
+ sym_que_init(&qtmp);
+ sym_que_splice(&np->busy_ccbq, &qtmp);
+ sym_que_init(&np->busy_ccbq);
+
+ /*
+ * Put all CCBs that matches our criteria into
+ * the COMP queue and put back other ones into
+ * the BUSY queue.
+ */
+ while ((qp = sym_remque_head(&qtmp)) != 0) {
+ cam_ccb_p ccb;
+ cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
+ ccb = cp->cam_ccb;
+ if (cp->host_status != HS_DISCONNECT ||
+ cp->target != target ||
+ (lun != -1 && cp->lun != lun) ||
+ (task != -1 &&
+ (cp->tag != NO_TAG && cp->scsi_smsg[2] != task))) {
+ sym_insque_tail(&cp->link_ccbq, &np->busy_ccbq);
+ continue;
+ }
+ sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);
+
+ /* Preserve the software timeout condition */
+ if (sym_get_cam_status(ccb) != CAM_CMD_TIMEOUT)
+ sym_set_cam_status(ccb, cam_status);
+ ++i;
+#if 0
+printf("XXXX TASK @%p CLEARED\n", cp);
+#endif
+ }
+ return i;
+}
+
+/*
+ * chip handler for TASKS recovery
+ *
+ * We cannot safely abort a command, while the SCRIPTS
+ * processor is running, since we just would be in race
+ * with it.
+ *
+ * As long as we have tasks to abort, we keep the SEM
+ * bit set in the ISTAT. When this bit is set, the
+ * SCRIPTS processor interrupts (SIR_SCRIPT_STOPPED)
+ * each time it enters the scheduler.
+ *
+ * If we have to reset a target, clear tasks of a unit,
+ * or to perform the abort of a disconnected job, we
+ * restart the SCRIPTS for selecting the target. Once
+ * selected, the SCRIPTS interrupts (SIR_TARGET_SELECTED).
+ * If it loses arbitration, the SCRIPTS will interrupt again
+ * the next time it will enter its scheduler, and so on ...
+ *
+ * On SIR_TARGET_SELECTED, we scan for the more
+ * appropriate thing to do:
+ *
+ * - If nothing, we just sent a M_ABORT message to the
+ * target to get rid of the useless SCSI bus ownership.
+ * According to the specs, no tasks shall be affected.
+ * - If the target is to be reset, we send it a M_RESET
+ * message.
+ * - If a logical UNIT is to be cleared , we send the
+ * IDENTIFY(lun) + M_ABORT.
+ * - If an untagged task is to be aborted, we send the
+ * IDENTIFY(lun) + M_ABORT.
+ * - If a tagged task is to be aborted, we send the
+ * IDENTIFY(lun) + task attributes + M_ABORT_TAG.
+ *
+ * Once our 'kiss of death' :) message has been accepted
+ * by the target, the SCRIPTS interrupts again
+ * (SIR_ABORT_SENT). On this interrupt, we complete
+ * all the CCBs that should have been aborted by the
+ * target according to our message.
+ */
+static void sym_sir_task_recovery(hcb_p np, int num)
+{
+ SYM_QUEHEAD *qp;
+ ccb_p cp;
+ tcb_p tp;
+ int target=-1, lun=-1, task;
+ int i, k;
+
+ switch(num) {
+ /*
+ * The SCRIPTS processor stopped before starting
+ * the next command in order to allow us to perform
+ * some task recovery.
+ */
+ case SIR_SCRIPT_STOPPED:
+ /*
+ * Do we have any target to reset or unit to clear ?
+ */
+ for (i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {
+ tp = &np->target[i];
+ if (tp->to_reset ||
+ (tp->lun0p && tp->lun0p->to_clear)) {
+ target = i;
+ break;
+ }
+ if (!tp->lunmp)
+ continue;
+ for (k = 1 ; k < SYM_CONF_MAX_LUN ; k++) {
+ if (tp->lunmp[k] && tp->lunmp[k]->to_clear) {
+ target = i;
+ break;
+ }
+ }
+ if (target != -1)
+ break;
+ }
+
+ /*
+ * If not, walk the busy queue for any
+ * disconnected CCB to be aborted.
+ */
+ if (target == -1) {
+ FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
+ cp = sym_que_entry(qp,struct sym_ccb,link_ccbq);
+ if (cp->host_status != HS_DISCONNECT)
+ continue;
+ if (cp->to_abort) {
+ target = cp->target;
+ break;
+ }


+ }
+ }
+
+ /*

+ * If some target is to be selected,
+ * prepare and start the selection.
+ */
+ if (target != -1) {
+ tp = &np->target[target];
+ np->abrt_sel.sel_id = target;
+ np->abrt_sel.sel_scntl3 = tp->head.wval;
+ np->abrt_sel.sel_sxfer = tp->head.sval;
+ OUTL(nc_dsa, np->hcb_ba);
+ OUTL_DSP (SCRIPTB_BA (np, sel_for_abort));
+ return;
+ }
+
+ /*
+ * Now look for a CCB to abort that haven't started yet.
+ * Btw, the SCRIPTS processor is still stopped, so
+ * we are not in race.
+ */
+ i = 0;
+ cp = 0;
+ FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
+ cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
+ if (cp->host_status != HS_BUSY &&
+ cp->host_status != HS_NEGOTIATE)
+ continue;
+ if (!cp->to_abort)
+ continue;
+#ifdef SYM_CONF_IARB_SUPPORT
+ /*
+ * If we are using IMMEDIATE ARBITRATION, we donnot
+ * want to cancel the last queued CCB, since the
+ * SCRIPTS may have anticipated the selection.
+ */
+ if (cp == np->last_cp) {
+ cp->to_abort = 0;
+ continue;
+ }
+#endif
+ i = 1; /* Means we have found some */
+ break;
+ }
+ if (!i) {
+ /*
+ * We are done, so we donnot need
+ * to synchronize with the SCRIPTS anylonger.
+ * Remove the SEM flag from the ISTAT.
+ */
+ np->istat_sem = 0;
+ OUTB (nc_istat, SIGP);
+ break;
+ }
+ /*
+ * Compute index of next position in the start
+ * queue the SCRIPTS intends to start and dequeue
+ * all CCBs for that device that haven't been started.
+ */
+ i = (INL (nc_scratcha) - np->squeue_ba) / 4;
+ i = sym_dequeue_from_squeue(np, i, cp->target, cp->lun, -1);
+
+ /*
+ * Make sure at least our IO to abort has been dequeued.
+ */
+#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ assert(i && sym_get_cam_status(cp->cam_ccb) == CAM_REQUEUE_REQ);
+#else
+ sym_remque(&cp->link_ccbq);
+ sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);
+#endif
+ /*
+ * Keep track in cam status of the reason of the abort.
+ */
+ if (cp->to_abort == 2)
+ sym_set_cam_status(cp->cam_ccb, CAM_CMD_TIMEOUT);
+ else
+ sym_set_cam_status(cp->cam_ccb, CAM_REQ_ABORTED);
+
+ /*
+ * Complete with error everything that we have dequeued.
+ */
+ sym_flush_comp_queue(np, 0);
+ break;
+ /*
+ * The SCRIPTS processor has selected a target
+ * we may have some manual recovery to perform for.
+ */
+ case SIR_TARGET_SELECTED:
+ target = (INB (nc_sdid) & 0xf);
+ tp = &np->target[target];
+
+ np->abrt_tbl.addr = cpu_to_scr(vtobus(np->abrt_msg));
+
+ /*
+ * If the target is to be reset, prepare a
+ * M_RESET message and clear the to_reset flag
+ * since we donnot expect this operation to fail.
+ */
+ if (tp->to_reset) {
+ np->abrt_msg[0] = M_RESET;
+ np->abrt_tbl.size = 1;
+ tp->to_reset = 0;
+ break;
+ }
+
+ /*
+ * Otherwise, look for some logical unit to be cleared.
+ */
+ if (tp->lun0p && tp->lun0p->to_clear)
+ lun = 0;
+ else if (tp->lunmp) {
+ for (k = 1 ; k < SYM_CONF_MAX_LUN ; k++) {
+ if (tp->lunmp[k] && tp->lunmp[k]->to_clear) {
+ lun = k;
+ break;
+ }


+ }
+ }
+
+ /*

+ * If a logical unit is to be cleared, prepare
+ * an IDENTIFY(lun) + ABORT MESSAGE.
+ */
+ if (lun != -1) {
+ lcb_p lp = sym_lp(np, tp, lun);
+ lp->to_clear = 0; /* We donnot expect to fail here */
+ np->abrt_msg[0] = M_IDENTIFY | lun;
+ np->abrt_msg[1] = M_ABORT;
+ np->abrt_tbl.size = 2;
+ break;
+ }
+
+ /*
+ * Otherwise, look for some disconnected job to
+ * abort for this target.
+ */
+ i = 0;
+ cp = 0;
+ FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
+ cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
+ if (cp->host_status != HS_DISCONNECT)
+ continue;
+ if (cp->target != target)
+ continue;
+ if (!cp->to_abort)
+ continue;
+ i = 1; /* Means we have some */
+ break;
+ }
+
+ /*
+ * If we have none, probably since the device has
+ * completed the command before we won abitration,
+ * send a M_ABORT message without IDENTIFY.
+ * According to the specs, the device must just
+ * disconnect the BUS and not abort any task.
+ */
+ if (!i) {
+ np->abrt_msg[0] = M_ABORT;
+ np->abrt_tbl.size = 1;
+ break;
+ }
+
+ /*
+ * We have some task to abort.
+ * Set the IDENTIFY(lun)
+ */
+ np->abrt_msg[0] = M_IDENTIFY | cp->lun;
+
+ /*
+ * If we want to abort an untagged command, we
+ * will send a IDENTIFY + M_ABORT.
+ * Otherwise (tagged command), we will send
+ * a IDENTITFY + task attributes + ABORT TAG.
+ */
+ if (cp->tag == NO_TAG) {
+ np->abrt_msg[1] = M_ABORT;
+ np->abrt_tbl.size = 2;
+ }
+ else {
+ np->abrt_msg[1] = cp->scsi_smsg[1];
+ np->abrt_msg[2] = cp->scsi_smsg[2];
+ np->abrt_msg[3] = M_ABORT_TAG;
+ np->abrt_tbl.size = 4;
+ }
+ /*
+ * Keep track of software timeout condition, since the
+ * peripheral driver may not count retries on abort
+ * conditions not due to timeout.
+ */
+ if (cp->to_abort == 2)
+ sym_set_cam_status(cp->cam_ccb, CAM_CMD_TIMEOUT);
+ cp->to_abort = 0; /* We donnot expect to fail here */
+ break;
+
+ /*
+ * The target has accepted our message and switched
+ * to BUS FREE phase as we expected.
+ */
+ case SIR_ABORT_SENT:
+ target = (INB (nc_sdid) & 0xf);
+ tp = &np->target[target];
+
+ /*
+ ** If we didn't abort anything, leave here.
+ */
+ if (np->abrt_msg[0] == M_ABORT)
+ break;
+
+ /*
+ * If we sent a M_RESET, then a hardware reset has
+ * been performed by the target.
+ * - Reset everything to async 8 bit
+ * - Tell ourself to negotiate next time :-)
+ * - Prepare to clear all disconnected CCBs for
+ * this target from our task list (lun=task=-1)
+ */
+ lun = -1;
+ task = -1;
+ if (np->abrt_msg[0] == M_RESET) {
+ tp->head.sval = 0;
+ tp->head.wval = np->rv_scntl3;
+ tp->head.uval = 0;
+ tp->tinfo.curr.period = 0;
+ tp->tinfo.curr.offset = 0;
+ tp->tinfo.curr.width = BUS_8_BIT;
+ tp->tinfo.curr.options = 0;
+ }
+
+ /*
+ * Otherwise, check for the LUN and TASK(s)
+ * concerned by the cancelation.
+ * If it is not ABORT_TAG then it is CLEAR_QUEUE
+ * or an ABORT message :-)
+ */
+ else {
+ lun = np->abrt_msg[0] & 0x3f;
+ if (np->abrt_msg[1] == M_ABORT_TAG)
+ task = np->abrt_msg[2];
+ }
+
+ /*
+ * Complete all the CCBs the device should have
+ * aborted due to our 'kiss of death' message.
+ */
+ i = (INL (nc_scratcha) - np->squeue_ba) / 4;
+ (void) sym_dequeue_from_squeue(np, i, target, lun, -1);
+ (void) sym_clear_tasks(np, CAM_REQ_ABORTED, target, lun, task);
+ sym_flush_comp_queue(np, 0);
+
+ /*
+ * If we sent a BDR, make upper layer aware of that.
+ */
+ if (np->abrt_msg[0] == M_RESET)
+ sym_xpt_async_sent_bdr(np, target);
+ break;
+ }
+
+ /*
+ * Print to the log the message we intend to send.
+ */
+ if (num == SIR_TARGET_SELECTED) {
+ PRINT_TARGET(np, target);
+ sym_printl_hex("control msgout:", np->abrt_msg,
+ np->abrt_tbl.size);
+ np->abrt_tbl.size = cpu_to_scr(np->abrt_tbl.size);
+ }
+
+ /*
+ * Let the SCRIPTS processor continue.
+ */
+ OUTONB_STD ();
+}
+
+/*
+ * Gerard's alchemy:) that deals with with the data
+ * pointer for both MDP and the residual calculation.
+ *
+ * I didn't want to bloat the code by more than 200
+ * lignes for the handling of both MDP and the residual.
+ * This has been achieved by using a data pointer
+ * representation consisting in an index in the data
+ * array (dp_sg) and a negative offset (dp_ofs) that
+ * have the following meaning:
+ *
+ * - dp_sg = SYM_CONF_MAX_SG
+ * we are at the end of the data script.
+ * - dp_sg < SYM_CONF_MAX_SG
+ * dp_sg points to the next entry of the scatter array
+ * we want to transfer.
+ * - dp_ofs < 0
+ * dp_ofs represents the residual of bytes of the
+ * previous entry scatter entry we will send first.
+ * - dp_ofs = 0
+ * no residual to send first.
+ *
+ * The function sym_evaluate_dp() accepts an arbitray
+ * offset (basically from the MDP message) and returns
+ * the corresponding values of dp_sg and dp_ofs.
+ */
+
+static int sym_evaluate_dp(hcb_p np, ccb_p cp, u32 scr, int *ofs)
+{
+ u32 dp_scr;
+ int dp_ofs, dp_sg, dp_sgmin;
+ int tmp;
+ struct sym_pmc *pm;
+
+ /*
+ * Compute the resulted data pointer in term of a script
+ * address within some DATA script and a signed byte offset.
+ */
+ dp_scr = scr;
+ dp_ofs = *ofs;
+ if (dp_scr == SCRIPTA_BA (np, pm0_data))
+ pm = &cp->phys.pm0;
+ else if (dp_scr == SCRIPTA_BA (np, pm1_data))
+ pm = &cp->phys.pm1;
+ else
+ pm = 0;
+
+ if (pm) {
+ dp_scr = scr_to_cpu(pm->ret);
+ dp_ofs -= scr_to_cpu(pm->sg.size);
+ }
+
+ /*
+ * If we are auto-sensing, then we are done.
+ */
+ if (cp->host_flags & HF_SENSE) {
+ *ofs = dp_ofs;
+ return 0;
+ }
+
+ /*
+ * Deduce the index of the sg entry.
+ * Keep track of the index of the first valid entry.
+ * If result is dp_sg = SYM_CONF_MAX_SG, then we are at the
+ * end of the data.
+ */
+ tmp = scr_to_cpu(sym_goalp(cp));
+ dp_sg = SYM_CONF_MAX_SG;
+ if (dp_scr != tmp)
+ dp_sg -= (tmp - 8 - (int)dp_scr) / (2*4);
+ dp_sgmin = SYM_CONF_MAX_SG - cp->segments;
+
+ /*
+ * Move to the sg entry the data pointer belongs to.
+ *
+ * If we are inside the data area, we expect result to be:
+ *
+ * Either,
+ * dp_ofs = 0 and dp_sg is the index of the sg entry
+ * the data pointer belongs to (or the end of the data)
+ * Or,
+ * dp_ofs < 0 and dp_sg is the index of the sg entry
+ * the data pointer belongs to + 1.
+ */
+ if (dp_ofs < 0) {
+ int n;
+ while (dp_sg > dp_sgmin) {
+ --dp_sg;
+ tmp = scr_to_cpu(cp->phys.data[dp_sg].size);
+ n = dp_ofs + (tmp & 0xffffff);
+ if (n > 0) {
+ ++dp_sg;
+ break;
+ }
+ dp_ofs = n;
+ }
+ }
+ else if (dp_ofs > 0) {
+ while (dp_sg < SYM_CONF_MAX_SG) {
+ tmp = scr_to_cpu(cp->phys.data[dp_sg].size);
+ dp_ofs -= (tmp & 0xffffff);
+ ++dp_sg;
+ if (dp_ofs <= 0)
+ break;


+ }
+ }
+
+ /*

+ * Make sure the data pointer is inside the data area.
+ * If not, return some error.
+ */
+ if (dp_sg < dp_sgmin || (dp_sg == dp_sgmin && dp_ofs < 0))
+ goto out_err;
+ else if (dp_sg > SYM_CONF_MAX_SG ||
+ (dp_sg == SYM_CONF_MAX_SG && dp_ofs > 0))
+ goto out_err;
+
+ /*
+ * Save the extreme pointer if needed.
+ */
+ if (dp_sg > cp->ext_sg ||
+ (dp_sg == cp->ext_sg && dp_ofs > cp->ext_ofs)) {
+ cp->ext_sg = dp_sg;
+ cp->ext_ofs = dp_ofs;
+ }
+
+ /*
+ * Return data.
+ */
+ *ofs = dp_ofs;
+ return dp_sg;
+
+out_err:
+ return -1;
+}
+
+/*
+ * chip handler for MODIFY DATA POINTER MESSAGE
+ *
+ * We also call this function on IGNORE WIDE RESIDUE
+ * messages that do not match a SWIDE full condition.
+ * Btw, we assume in that situation that such a message
+ * is equivalent to a MODIFY DATA POINTER (offset=-1).
+ */
+
+static void sym_modify_dp(hcb_p np, tcb_p tp, ccb_p cp, int ofs)
+{
+ int dp_ofs = ofs;
+ u32 dp_scr = sym_get_script_dp (np, cp);
+ u32 dp_ret;
+ u32 tmp;
+ u_char hflags;
+ int dp_sg;
+ struct sym_pmc *pm;
+
+ /*
+ * Not supported for auto-sense.
+ */
+ if (cp->host_flags & HF_SENSE)
+ goto out_reject;
+
+ /*
+ * Apply our alchemy:) (see comments in sym_evaluate_dp()),
+ * to the resulted data pointer.
+ */
+ dp_sg = sym_evaluate_dp(np, cp, dp_scr, &dp_ofs);
+ if (dp_sg < 0)
+ goto out_reject;
+
+ /*
+ * And our alchemy:) allows to easily calculate the data
+ * script address we want to return for the next data phase.
+ */
+ dp_ret = cpu_to_scr(sym_goalp(cp));
+ dp_ret = dp_ret - 8 - (SYM_CONF_MAX_SG - dp_sg) * (2*4);
+
+ /*
+ * If offset / scatter entry is zero we donnot need
+ * a context for the new current data pointer.
+ */
+ if (dp_ofs == 0) {
+ dp_scr = dp_ret;
+ goto out_ok;
+ }
+
+ /*
+ * Get a context for the new current data pointer.
+ */
+ hflags = INB (HF_PRT);
+
+ if (hflags & HF_DP_SAVED)
+ hflags ^= HF_ACT_PM;
+
+ if (!(hflags & HF_ACT_PM)) {
+ pm = &cp->phys.pm0;
+ dp_scr = SCRIPTA_BA (np, pm0_data);
+ }
+ else {
+ pm = &cp->phys.pm1;
+ dp_scr = SCRIPTA_BA (np, pm1_data);
+ }
+
+ hflags &= ~(HF_DP_SAVED);
+
+ OUTB (HF_PRT, hflags);
+
+ /*
+ * Set up the new current data pointer.
+ * ofs < 0 there, and for the next data phase, we
+ * want to transfer part of the data of the sg entry
+ * corresponding to index dp_sg-1 prior to returning
+ * to the main data script.
+ */
+ pm->ret = cpu_to_scr(dp_ret);
+ tmp = scr_to_cpu(cp->phys.data[dp_sg-1].addr);
+ tmp += scr_to_cpu(cp->phys.data[dp_sg-1].size) + dp_ofs;
+ pm->sg.addr = cpu_to_scr(tmp);
+ pm->sg.size = cpu_to_scr(-dp_ofs);
+
+out_ok:
+ sym_set_script_dp (np, cp, dp_scr);
+ OUTL_DSP (SCRIPTA_BA (np, clrack));
+ return;
+
+out_reject:
+ OUTL_DSP (SCRIPTB_BA (np, msg_bad));
+}
+
+
+/*
+ * chip calculation of the data residual.
+ *
+ * As I used to say, the requirement of data residual
+ * in SCSI is broken, useless and cannot be achieved
+ * without huge complexity.
+ * But most OSes and even the official CAM require it.
+ * When stupidity happens to be so widely spread inside
+ * a community, it gets hard to convince.
+ *
+ * Anyway, I don't care, since I am not going to use
+ * any software that considers this data residual as
+ * a relevant information. :)
+ */
+
+int sym_compute_residual(hcb_p np, ccb_p cp)
+{
+ int dp_sg, dp_sgmin, resid = 0;
+ int dp_ofs = 0;
+
+ /*
+ * Check for some data lost or just thrown away.
+ * We are not required to be quite accurate in this
+ * situation. Btw, if we are odd for output and the
+ * device claims some more data, it may well happen
+ * than our residual be zero. :-)
+ */
+ if (cp->xerr_status & (XE_EXTRA_DATA|XE_SODL_UNRUN|XE_SWIDE_OVRUN)) {
+ if (cp->xerr_status & XE_EXTRA_DATA)
+ resid -= cp->extra_bytes;
+ if (cp->xerr_status & XE_SODL_UNRUN)
+ ++resid;
+ if (cp->xerr_status & XE_SWIDE_OVRUN)
+ --resid;
+ }
+
+ /*
+ * If all data has been transferred,
+ * there is no residual.
+ */
+ if (cp->phys.head.lastp == sym_goalp(cp))
+ return resid;
+
+ /*
+ * If no data transfer occurs, or if the data
+ * pointer is weird, return full residual.
+ */
+ if (cp->startp == cp->phys.head.lastp ||
+ sym_evaluate_dp(np, cp, scr_to_cpu(cp->phys.head.lastp),
+ &dp_ofs) < 0) {
+ return cp->data_len;
+ }
+
+ /*
+ * If we were auto-sensing, then we are done.
+ */
+ if (cp->host_flags & HF_SENSE) {
+ return -dp_ofs;
+ }
+
+ /*
+ * We are now full comfortable in the computation
+ * of the data residual (2's complement).
+ */
+ dp_sgmin = SYM_CONF_MAX_SG - cp->segments;
+ resid = -cp->ext_ofs;
+ for (dp_sg = cp->ext_sg; dp_sg < SYM_CONF_MAX_SG; ++dp_sg) {
+ u_int tmp = scr_to_cpu(cp->phys.data[dp_sg].size);
+ resid += (tmp & 0xffffff);
+ }
+
+ /*
+ * Hopefully, the result is not too wrong.
+ */
+ return resid;
+}
+
+/*
+ * Negotiation for WIDE and SYNCHRONOUS DATA TRANSFER.
+ *
+ * When we try to negotiate, we append the negotiation message
+ * to the identify and (maybe) simple tag message.
+ * The host status field is set to HS_NEGOTIATE to mark this
+ * situation.
+ *
+ * If the target doesn't answer this message immediately
+ * (as required by the standard), the SIR_NEGO_FAILED interrupt
+ * will be raised eventually.
+ * The handler removes the HS_NEGOTIATE status, and sets the
+ * negotiated value to the default (async / nowide).
+ *
+ * If we receive a matching answer immediately, we check it
+ * for validity, and set the values.
+ *
+ * If we receive a Reject message immediately, we assume the
+ * negotiation has failed, and fall back to standard values.
+ *
+ * If we receive a negotiation message while not in HS_NEGOTIATE
+ * state, it's a target initiated negotiation. We prepare a
+ * (hopefully) valid answer, set our parameters, and send back
+ * this answer to the target.
+ *
+ * If the target doesn't fetch the answer (no message out phase),
+ * we assume the negotiation has failed, and fall back to default
+ * settings (SIR_NEGO_PROTO interrupt).
+ *
+ * When we set the values, we adjust them in all ccbs belonging
+ * to this target, in the controller's register, and in the "phys"
+ * field of the controller's struct sym_hcb.
+ */
+
+/*
+ * chip handler for SYNCHRONOUS DATA TRANSFER REQUEST (SDTR) message.
+ */
+static int
+sym_sync_nego_check(hcb_p np, int req, int target)
+{
+ tcb_p tp = &np->target[target];
+ u_char chg, ofs, per, fak, div;
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ sym_print_nego_msg(np, target, "sync msgin", np->msgin);
+ };
+
+ /*
+ * Get requested values.
+ */
+ chg = 0;
+ per = np->msgin[3];
+ ofs = np->msgin[4];
+
+ /*
+ * Check values against our limits.
+ */
+ if (ofs) {
+ if (ofs > np->maxoffs)
+ {chg = 1; ofs = np->maxoffs;}
+ if (req) {
+ if (ofs > tp->tinfo.user.offset)
+ {chg = 1; ofs = tp->tinfo.user.offset;}
+ }
+ }
+
+ if (ofs) {
+ if (per < np->minsync)
+ {chg = 1; per = np->minsync;}
+ if (req) {
+ if (per < tp->tinfo.user.period)
+ {chg = 1; per = tp->tinfo.user.period;}


+ }
+ }
+
+ /*

+ * Get new chip synchronous parameters value.
+ */
+ div = fak = 0;
+ if (ofs && sym_getsync(np, 0, per, &div, &fak) < 0)
+ goto reject_it;
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_TARGET(np, target);
+ printf ("sdtr: ofs=%d per=%d div=%d fak=%d chg=%d.\n",
+ ofs, per, div, fak, chg);
+ }
+
+ /*
+ * If it was an answer we want to change,
+ * then it isn't acceptable. Reject it.
+ */
+ if (!req && chg)
+ goto reject_it;
+
+ /*
+ * Apply new values.
+ */
+ sym_setsync (np, target, ofs, per, div, fak);
+
+ /*
+ * It was an answer. We are done.
+ */
+ if (!req)
+ return 0;
+
+ /*
+ * It was a request. Prepare an answer message.
+ */
+ np->msgout[0] = M_EXTENDED;
+ np->msgout[1] = 3;
+ np->msgout[2] = M_X_SYNC_REQ;
+ np->msgout[3] = per;
+ np->msgout[4] = ofs;
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ sym_print_nego_msg(np, target, "sync msgout", np->msgout);
+ }
+
+ np->msgin [0] = M_NOOP;


+
+ return 0;
+

+reject_it:
+ sym_setsync (np, target, 0, 0, 0, 0);


+ return -1;
+}
+

+static void sym_sync_nego(hcb_p np, tcb_p tp, ccb_p cp)
+{
+ int req = 1;
+ int result;
+
+ /*
+ * Request or answer ?
+ */
+ if (INB (HS_PRT) == HS_NEGOTIATE) {
+ OUTB (HS_PRT, HS_BUSY);
+ if (cp->nego_status && cp->nego_status != NS_SYNC)
+ goto reject_it;
+ req = 0;
+ }
+
+ /*
+ * Check and apply new values.
+ */
+ result = sym_sync_nego_check(np, req, cp->target);
+ if (result) /* Not acceptable, reject it */
+ goto reject_it;
+ if (req) { /* Was a request, send response. */
+ cp->nego_status = NS_SYNC;
+ OUTL_DSP (SCRIPTB_BA (np, sdtr_resp));
+ }
+ else /* Was a response, we are done. */
+ OUTL_DSP (SCRIPTA_BA (np, clrack));
+ return;
+
+reject_it:
+ OUTL_DSP (SCRIPTB_BA (np, msg_bad));
+}
+
+/*
+ * chip handler for PARALLEL PROTOCOL REQUEST (PPR) message.
+ */
+static int
+sym_ppr_nego_check(hcb_p np, int req, int target)
+{
+ tcb_p tp = &np->target[target];
+ u_char chg, ofs, per, fak, dt, div, wide;
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ sym_print_nego_msg(np, target, "ppr msgin", np->msgin);
+ };
+
+ /*
+ * Get requested values.
+ */
+ chg = 0;
+ per = np->msgin[3];
+ ofs = np->msgin[5];
+ wide = np->msgin[6];
+ dt = np->msgin[7] & PPR_OPT_DT;
+
+ /*
+ * Check values against our limits.
+ */
+ if (wide > np->maxwide)
+ {chg = 1; wide = np->maxwide;}
+ if (!wide || !(np->features & FE_ULTRA3))
+ dt &= ~PPR_OPT_DT;
+ if (req) {
+ if (wide > tp->tinfo.user.width)
+ {chg = 1; wide = tp->tinfo.user.width;}
+ }
+
+ if (!(np->features & FE_U3EN)) /* Broken U3EN bit not supported */
+ dt &= ~PPR_OPT_DT;
+
+ if (dt != (np->msgin[7] & PPR_OPT_MASK)) chg = 1;
+
+ if (ofs) {
+ if (dt) {
+ if (ofs > np->maxoffs_dt)
+ {chg = 1; ofs = np->maxoffs_dt;}
+ }
+ else if (ofs > np->maxoffs)
+ {chg = 1; ofs = np->maxoffs;}
+ if (req) {
+ if (ofs > tp->tinfo.user.offset)
+ {chg = 1; ofs = tp->tinfo.user.offset;}
+ }
+ }
+
+ if (ofs) {
+ if (dt) {
+ if (per < np->minsync_dt)
+ {chg = 1; per = np->minsync_dt;}
+ }
+ else if (per < np->minsync)
+ {chg = 1; per = np->minsync;}
+ if (req) {
+ if (per < tp->tinfo.user.period)
+ {chg = 1; per = tp->tinfo.user.period;}


+ }
+ }
+
+ /*

+ * Get new chip synchronous parameters value.
+ */
+ div = fak = 0;
+ if (ofs && sym_getsync(np, dt, per, &div, &fak) < 0)
+ goto reject_it;
+
+ /*
+ * If it was an answer we want to change,
+ * then it isn't acceptable. Reject it.
+ */
+ if (!req && chg)
+ goto reject_it;
+
+ /*
+ * Apply new values.
+ */
+ sym_setpprot (np, target, dt, ofs, per, wide, div, fak);
+
+ /*
+ * It was an answer. We are done.
+ */
+ if (!req)
+ return 0;
+
+ /*
+ * It was a request. Prepare an answer message.
+ */
+ np->msgout[0] = M_EXTENDED;
+ np->msgout[1] = 6;
+ np->msgout[2] = M_X_PPR_REQ;
+ np->msgout[3] = per;
+ np->msgout[4] = 0;
+ np->msgout[5] = ofs;
+ np->msgout[6] = wide;
+ np->msgout[7] = dt;
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ sym_print_nego_msg(np, target, "ppr msgout", np->msgout);
+ }
+
+ np->msgin [0] = M_NOOP;


+
+ return 0;
+

+reject_it:
+ sym_setpprot (np, target, 0, 0, 0, 0, 0, 0);
+ /*
+ * If it is a device response that should result in
+ * ST, we may want to try a legacy negotiation later.
+ */
+ if (!req && !dt) {
+ tp->tinfo.goal.options = 0;
+ tp->tinfo.goal.width = wide;
+ tp->tinfo.goal.period = per;
+ tp->tinfo.goal.offset = ofs;
+ }


+ return -1;
+}
+

+static void sym_ppr_nego(hcb_p np, tcb_p tp, ccb_p cp)
+{
+ int req = 1;
+ int result;
+
+ /*
+ * Request or answer ?
+ */
+ if (INB (HS_PRT) == HS_NEGOTIATE) {
+ OUTB (HS_PRT, HS_BUSY);
+ if (cp->nego_status && cp->nego_status != NS_PPR)
+ goto reject_it;
+ req = 0;
+ }
+
+ /*
+ * Check and apply new values.
+ */
+ result = sym_ppr_nego_check(np, req, cp->target);
+ if (result) /* Not acceptable, reject it */
+ goto reject_it;
+ if (req) { /* Was a request, send response. */
+ cp->nego_status = NS_PPR;
+ OUTL_DSP (SCRIPTB_BA (np, ppr_resp));
+ }
+ else /* Was a response, we are done. */
+ OUTL_DSP (SCRIPTA_BA (np, clrack));
+ return;
+
+reject_it:
+ OUTL_DSP (SCRIPTB_BA (np, msg_bad));
+}
+
+/*
+ * chip handler for WIDE DATA TRANSFER REQUEST (WDTR) message.
+ */
+static int
+sym_wide_nego_check(hcb_p np, int req, int target)
+{
+ tcb_p tp = &np->target[target];
+ u_char chg, wide;
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ sym_print_nego_msg(np, target, "wide msgin", np->msgin);
+ };
+
+ /*
+ * Get requested values.
+ */
+ chg = 0;
+ wide = np->msgin[3];
+
+ /*
+ * Check values against our limits.
+ */
+ if (wide > np->maxwide)
+ {chg = 1; wide = np->maxwide;}
+ if (req) {
+ if (wide > tp->tinfo.user.width)
+ {chg = 1; wide = tp->tinfo.user.width;}
+ }
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ PRINT_TARGET(np, target);
+ printf ("wdtr: wide=%d chg=%d.\n", wide, chg);
+ }
+
+ /*
+ * If it was an answer we want to change,
+ * then it isn't acceptable. Reject it.
+ */
+ if (!req && chg)
+ goto reject_it;
+
+ /*
+ * Apply new values.
+ */
+ sym_setwide (np, target, wide);
+
+ /*
+ * It was an answer. We are done.
+ */
+ if (!req)
+ return 0;
+
+ /*
+ * It was a request. Prepare an answer message.
+ */
+ np->msgout[0] = M_EXTENDED;
+ np->msgout[1] = 2;
+ np->msgout[2] = M_X_WIDE_REQ;
+ np->msgout[3] = wide;
+
+ np->msgin [0] = M_NOOP;
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ sym_print_nego_msg(np, target, "wide msgout", np->msgout);


+ }
+
+ return 0;
+

+reject_it:


+ return -1;
+}
+

+static void sym_wide_nego(hcb_p np, tcb_p tp, ccb_p cp)
+{
+ int req = 1;
+ int result;
+
+ /*
+ * Request or answer ?
+ */
+ if (INB (HS_PRT) == HS_NEGOTIATE) {
+ OUTB (HS_PRT, HS_BUSY);
+ if (cp->nego_status && cp->nego_status != NS_WIDE)
+ goto reject_it;
+ req = 0;
+ }
+
+ /*
+ * Check and apply new values.
+ */
+ result = sym_wide_nego_check(np, req, cp->target);
+ if (result) /* Not acceptable, reject it */
+ goto reject_it;
+ if (req) { /* Was a request, send response. */
+ cp->nego_status = NS_WIDE;
+ OUTL_DSP (SCRIPTB_BA (np, wdtr_resp));
+ }
+ else { /* Was a response. */
+ /*
+ * Negotiate for SYNC immediately after WIDE response.
+ * This allows to negotiate for both WIDE and SYNC on
+ * a single SCSI command (Suggested by Justin Gibbs).
+ */
+ if (tp->tinfo.goal.offset) {
+ np->msgout[0] = M_EXTENDED;
+ np->msgout[1] = 3;
+ np->msgout[2] = M_X_SYNC_REQ;
+ np->msgout[3] = tp->tinfo.goal.period;
+ np->msgout[4] = tp->tinfo.goal.offset;
+
+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ sym_print_nego_msg(np, cp->target,
+ "sync msgout", np->msgout);
+ }
+
+ cp->nego_status = NS_SYNC;
+ OUTB (HS_PRT, HS_NEGOTIATE);
+ OUTL_DSP (SCRIPTB_BA (np, sdtr_resp));


+ return;
+ }
+ else

+ OUTL_DSP (SCRIPTA_BA (np, clrack));


+ };
+
+ return;
+

+reject_it:
+ OUTL_DSP (SCRIPTB_BA (np, msg_bad));
+}
+
+/*
+ * Reset DT, SYNC or WIDE to default settings.
+ *
+ * Called when a negotiation does not succeed either
+ * on rejection or on protocol error.
+ *
+ * A target that understands a PPR message should never
+ * reject it, and messing with it is very unlikely.
+ * So, if a PPR makes problems, we may just want to
+ * try a legacy negotiation later.
+ */
+static void sym_nego_default(hcb_p np, tcb_p tp, ccb_p cp)
+{
+ switch (cp->nego_status) {
+ case NS_PPR:
+#if 0
+ sym_setpprot (np, cp->target, 0, 0, 0, 0, 0, 0);
+#else
+ tp->tinfo.goal.options = 0;
+ if (tp->tinfo.goal.period < np->minsync)
+ tp->tinfo.goal.period = np->minsync;
+ if (tp->tinfo.goal.offset > np->maxoffs)
+ tp->tinfo.goal.offset = np->maxoffs;
+#endif
+ break;
+ case NS_SYNC:
+ sym_setsync (np, cp->target, 0, 0, 0, 0);
+ break;
+ case NS_WIDE:
+ sym_setwide (np, cp->target, 0);
+ break;
+ };
+ np->msgin [0] = M_NOOP;
+ np->msgout[0] = M_NOOP;
+ cp->nego_status = 0;
+}
+
+/*
+ * chip handler for MESSAGE REJECT received in response to
+ * PPR, WIDE or SYNCHRONOUS negotiation.
+ */
+static void sym_nego_rejected(hcb_p np, tcb_p tp, ccb_p cp)
+{
+ sym_nego_default(np, tp, cp);
+ OUTB (HS_PRT, HS_BUSY);
+}
+
+/*
+ * chip exception handler for programmed interrupts.
+ */
+static void sym_int_sir (hcb_p np)
+{
+ u_char num = INB (nc_dsps);
+ u32 dsa = INL (nc_dsa);
+ ccb_p cp = sym_ccb_from_dsa(np, dsa);
+ u_char target = INB (nc_sdid) & 0x0f;
+ tcb_p tp = &np->target[target];
+ int tmp;
+
+ if (DEBUG_FLAGS & DEBUG_TINY) printf ("I#%d", num);
+
+ switch (num) {


+#if SYM_CONF_DMA_ADDRESSING_MODE == 2
+ /*

+ * SCRIPTS tell us that we may have to update
+ * 64 bit DMA segment registers.
+ */
+ case SIR_DMAP_DIRTY:
+ sym_update_dmap_regs(np);
+ goto out;
+#endif
+ /*
+ * Command has been completed with error condition
+ * or has been auto-sensed.
+ */
+ case SIR_COMPLETE_ERROR:
+ sym_complete_error(np, cp);
+ return;
+ /*
+ * The C code is currently trying to recover from something.
+ * Typically, user want to abort some command.
+ */
+ case SIR_SCRIPT_STOPPED:
+ case SIR_TARGET_SELECTED:
+ case SIR_ABORT_SENT:
+ sym_sir_task_recovery(np, num);
+ return;
+ /*
+ * The device didn't go to MSG OUT phase after having
+ * been selected with ATN. We donnot want to handle
+ * that.
+ */
+ case SIR_SEL_ATN_NO_MSG_OUT:
+ printf ("%s:%d: No MSG OUT phase after selection with ATN.\n",
+ sym_name (np), target);
+ goto out_stuck;
+ /*
+ * The device didn't switch to MSG IN phase after
+ * having reseleted the initiator.
+ */
+ case SIR_RESEL_NO_MSG_IN:
+ printf ("%s:%d: No MSG IN phase after reselection.\n",
+ sym_name (np), target);
+ goto out_stuck;
+ /*
+ * After reselection, the device sent a message that wasn't
+ * an IDENTIFY.
+ */
+ case SIR_RESEL_NO_IDENTIFY:
+ printf ("%s:%d: No IDENTIFY after reselection.\n",
+ sym_name (np), target);
+ goto out_stuck;
+ /*
+ * The device reselected a LUN we donnot know about.
+ */
+ case SIR_RESEL_BAD_LUN:
+ np->msgout[0] = M_RESET;
+ goto out;
+ /*
+ * The device reselected for an untagged nexus and we
+ * haven't any.
+ */
+ case SIR_RESEL_BAD_I_T_L:
+ np->msgout[0] = M_ABORT;
+ goto out;
+ /*
+ * The device reselected for a tagged nexus that we donnot
+ * have.
+ */
+ case SIR_RESEL_BAD_I_T_L_Q:
+ np->msgout[0] = M_ABORT_TAG;
+ goto out;
+ /*
+ * The SCRIPTS let us know that the device has grabbed
+ * our message and will abort the job.
+ */
+ case SIR_RESEL_ABORTED:
+ np->lastmsg = np->msgout[0];
+ np->msgout[0] = M_NOOP;
+ printf ("%s:%d: message %x sent on bad reselection.\n",
+ sym_name (np), target, np->lastmsg);
+ goto out;
+ /*
+ * The SCRIPTS let us know that a message has been
+ * successfully sent to the device.
+ */
+ case SIR_MSG_OUT_DONE:
+ np->lastmsg = np->msgout[0];
+ np->msgout[0] = M_NOOP;
+ /* Should we really care of that */
+ if (np->lastmsg == M_PARITY || np->lastmsg == M_ID_ERROR) {
+ if (cp) {
+ cp->xerr_status &= ~XE_PARITY_ERR;
+ if (!cp->xerr_status)
+ OUTOFFB (HF_PRT, HF_EXT_ERR);
+ }
+ }
+ goto out;
+ /*
+ * The device didn't send a GOOD SCSI status.
+ * We may have some work to do prior to allow
+ * the SCRIPTS processor to continue.
+ */
+ case SIR_BAD_SCSI_STATUS:
+ if (!cp)
+ goto out;
+ sym_sir_bad_scsi_status(np, num, cp);
+ return;
+ /*
+ * We are asked by the SCRIPTS to prepare a
+ * REJECT message.
+ */
+ case SIR_REJECT_TO_SEND:
+ sym_print_msg(cp, "M_REJECT to send for ", np->msgin);
+ np->msgout[0] = M_REJECT;
+ goto out;
+ /*
+ * We have been ODD at the end of a DATA IN
+ * transfer and the device didn't send a
+ * IGNORE WIDE RESIDUE message.
+ * It is a data overrun condition.
+ */
+ case SIR_SWIDE_OVERRUN:
+ if (cp) {
+ OUTONB (HF_PRT, HF_EXT_ERR);
+ cp->xerr_status |= XE_SWIDE_OVRUN;
+ }
+ goto out;
+ /*
+ * We have been ODD at the end of a DATA OUT
+ * transfer.
+ * It is a data underrun condition.
+ */
+ case SIR_SODL_UNDERRUN:
+ if (cp) {
+ OUTONB (HF_PRT, HF_EXT_ERR);
+ cp->xerr_status |= XE_SODL_UNRUN;
+ }
+ goto out;
+ /*
+ * The device wants us to tranfer more data than
+ * expected or in the wrong direction.
+ * The number of extra bytes is in scratcha.
+ * It is a data overrun condition.
+ */
+ case SIR_DATA_OVERRUN:
+ if (cp) {
+ OUTONB (HF_PRT, HF_EXT_ERR);
+ cp->xerr_status |= XE_EXTRA_DATA;
+ cp->extra_bytes += INL (nc_scratcha);
+ }
+ goto out;
+ /*
+ * The device switched to an illegal phase (4/5).
+ */
+ case SIR_BAD_PHASE:
+ if (cp) {
+ OUTONB (HF_PRT, HF_EXT_ERR);
+ cp->xerr_status |= XE_BAD_PHASE;
+ }
+ goto out;
+ /*
+ * We received a message.
+ */
+ case SIR_MSG_RECEIVED:
+ if (!cp)
+ goto out_stuck;
+ switch (np->msgin [0]) {
+ /*
+ * We received an extended message.
+ * We handle MODIFY DATA POINTER, SDTR, WDTR
+ * and reject all other extended messages.
+ */
+ case M_EXTENDED:
+ switch (np->msgin [2]) {
+ case M_X_MODIFY_DP:
+ if (DEBUG_FLAGS & DEBUG_POINTER)
+ sym_print_msg(cp,"modify DP",np->msgin);
+ tmp = (np->msgin[3]<<24) + (np->msgin[4]<<16) +
+ (np->msgin[5]<<8) + (np->msgin[6]);
+ sym_modify_dp(np, tp, cp, tmp);
+ return;
+ case M_X_SYNC_REQ:
+ sym_sync_nego(np, tp, cp);
+ return;
+ case M_X_PPR_REQ:
+ sym_ppr_nego(np, tp, cp);
+ return;
+ case M_X_WIDE_REQ:
+ sym_wide_nego(np, tp, cp);
+ return;
+ default:
+ goto out_reject;
+ }
+ break;
+ /*
+ * We received a 1/2 byte message not handled from SCRIPTS.
+ * We are only expecting MESSAGE REJECT and IGNORE WIDE
+ * RESIDUE messages that haven't been anticipated by
+ * SCRIPTS on SWIDE full condition. Unanticipated IGNORE
+ * WIDE RESIDUE messages are aliased as MODIFY DP (-1).
+ */
+ case M_IGN_RESIDUE:
+ if (DEBUG_FLAGS & DEBUG_POINTER)
+ sym_print_msg(cp,"ign wide residue", np->msgin);
+ sym_modify_dp(np, tp, cp, -1);
+ return;
+ case M_REJECT:
+ if (INB (HS_PRT) == HS_NEGOTIATE)
+ sym_nego_rejected(np, tp, cp);
+ else {
+ PRINT_ADDR(cp);
+ printf ("M_REJECT received (%x:%x).\n",
+ scr_to_cpu(np->lastmsg), np->msgout[0]);
+ }
+ goto out_clrack;
+ break;
+ default:
+ goto out_reject;
+ }
+ break;
+ /*
+ * We received an unknown message.
+ * Ignore all MSG IN phases and reject it.
+ */
+ case SIR_MSG_WEIRD:
+ sym_print_msg(cp, "WEIRD message received", np->msgin);
+ OUTL_DSP (SCRIPTB_BA (np, msg_weird));
+ return;
+ /*
+ * Negotiation failed.
+ * Target does not send us the reply.
+ * Remove the HS_NEGOTIATE status.
+ */
+ case SIR_NEGO_FAILED:
+ OUTB (HS_PRT, HS_BUSY);
+ /*
+ * Negotiation failed.
+ * Target does not want answer message.
+ */
+ case SIR_NEGO_PROTO:
+ sym_nego_default(np, tp, cp);


+ goto out;
+ };
+

+out:
+ OUTONB_STD ();
+ return;
+out_reject:
+ OUTL_DSP (SCRIPTB_BA (np, msg_bad));
+ return;
+out_clrack:
+ OUTL_DSP (SCRIPTA_BA (np, clrack));
+ return;
+out_stuck:
+}
+
+/*
+ * Acquire a control block
+ */
+ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order)
+{
+ tcb_p tp = &np->target[tn];
+ lcb_p lp = sym_lp(np, tp, ln);
+ u_short tag = NO_TAG;
+ SYM_QUEHEAD *qp;
+ ccb_p cp = (ccb_p) 0;
+
+ /*
+ * Look for a free CCB
+ */
+ if (sym_que_empty(&np->free_ccbq))
+ (void) sym_alloc_ccb(np);
+ qp = sym_remque_head(&np->free_ccbq);
+ if (!qp)
+ goto out;
+ cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
+
+#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ /*
+ * If the LCB is not yet available and the LUN
+ * has been probed ok, try to allocate the LCB.
+ */
+ if (!lp && sym_is_bit(tp->lun_map, ln)) {
+ lp = sym_alloc_lcb(np, tn, ln);
+ if (!lp)
+ goto out_free;
+ }
+#endif
+
+ /*
+ * If the LCB is not available here, then the
+ * logical unit is not yet discovered. For those
+ * ones only accept 1 SCSI IO per logical unit,
+ * since we cannot allow disconnections.
+ */
+ if (!lp) {
+ if (!sym_is_bit(tp->busy0_map, ln))
+ sym_set_bit(tp->busy0_map, ln);
+ else
+ goto out_free;
+ } else {
+ /*
+ * If we have been asked for a tagged command.
+ */
+ if (tag_order) {
+ /*
+ * Debugging purpose.
+ */
+#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ assert(lp->busy_itl == 0);
+#endif
+ /*
+ * Allocate resources for tags if not yet.
+ */
+ if (!lp->cb_tags) {
+ sym_alloc_lcb_tags(np, tn, ln);
+ if (!lp->cb_tags)
+ goto out_free;
+ }
+ /*
+ * Get a tag for this SCSI IO and set up
+ * the CCB bus address for reselection,
+ * and count it for this LUN.
+ * Toggle reselect path to tagged.
+ */
+ if (lp->busy_itlq < SYM_CONF_MAX_TASK) {
+ tag = lp->cb_tags[lp->ia_tag];
+ if (++lp->ia_tag == SYM_CONF_MAX_TASK)
+ lp->ia_tag = 0;
+ ++lp->busy_itlq;
+#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ lp->itlq_tbl[tag] = cpu_to_scr(cp->ccb_ba);
+ lp->head.resel_sa =
+ cpu_to_scr(SCRIPTA_BA (np, resel_tag));
+#endif
+#ifdef SYM_OPT_LIMIT_COMMAND_REORDERING
+ cp->tags_si = lp->tags_si;
+ ++lp->tags_sum[cp->tags_si];
+ ++lp->tags_since;
+#endif
+ }
+ else
+ goto out_free;
+ }
+ /*
+ * This command will not be tagged.
+ * If we already have either a tagged or untagged
+ * one, refuse to overlap this untagged one.
+ */
+ else {
+ /*
+ * Debugging purpose.
+ */
+#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ assert(lp->busy_itl == 0 && lp->busy_itlq == 0);
+#endif
+ /*
+ * Count this nexus for this LUN.
+ * Set up the CCB bus address for reselection.
+ * Toggle reselect path to untagged.
+ */
+ ++lp->busy_itl;
+#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ if (lp->busy_itl == 1) {
+ lp->head.itl_task_sa = cpu_to_scr(cp->ccb_ba);
+ lp->head.resel_sa =
+ cpu_to_scr(SCRIPTA_BA (np, resel_no_tag));
+ }
+ else
+ goto out_free;
+#endif
+ }
+ }
+ /*
+ * Put the CCB into the busy queue.
+ */
+ sym_insque_tail(&cp->link_ccbq, &np->busy_ccbq);
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ if (lp) {
+ sym_remque(&cp->link2_ccbq);
+ sym_insque_tail(&cp->link2_ccbq, &lp->waiting_ccbq);
+ }
+
+#endif
+ /*
+ * Remember all informations needed to free this CCB.
+ */
+ cp->to_abort = 0;
+ cp->tag = tag;
+ cp->order = tag_order;
+ cp->target = tn;
+ cp->lun = ln;
+
+ if (DEBUG_FLAGS & DEBUG_TAGS) {
+ PRINT_LUN(np, tn, ln);
+ printf ("ccb @%p using tag %d.\n", cp, tag);
+ }
+
+out:
+ return cp;
+out_free:
+ sym_insque_head(&cp->link_ccbq, &np->free_ccbq);
+ return (ccb_p) 0;
+}
+
+/*
+ * Release one control block
+ */
+void sym_free_ccb (hcb_p np, ccb_p cp)
+{
+ tcb_p tp = &np->target[cp->target];
+ lcb_p lp = sym_lp(np, tp, cp->lun);
+
+ if (DEBUG_FLAGS & DEBUG_TAGS) {
+ PRINT_LUN(np, cp->target, cp->lun);
+ printf ("ccb @%p freeing tag %d.\n", cp, cp->tag);
+ }
+
+ /*
+ * If LCB available,
+ */
+ if (lp) {
+ /*
+ * If tagged, release the tag, set the relect path
+ */
+ if (cp->tag != NO_TAG) {
+#ifdef SYM_OPT_LIMIT_COMMAND_REORDERING
+ --lp->tags_sum[cp->tags_si];
+#endif
+ /*
+ * Free the tag value.
+ */
+ lp->cb_tags[lp->if_tag] = cp->tag;
+ if (++lp->if_tag == SYM_CONF_MAX_TASK)
+ lp->if_tag = 0;
+ /*
+ * Make the reselect path invalid,
+ * and uncount this CCB.
+ */
+ lp->itlq_tbl[cp->tag] = cpu_to_scr(np->bad_itlq_ba);
+ --lp->busy_itlq;
+ } else { /* Untagged */
+ /*
+ * Make the reselect path invalid,
+ * and uncount this CCB.
+ */
+ lp->head.itl_task_sa = cpu_to_scr(np->bad_itl_ba);
+ --lp->busy_itl;
+ }
+ /*
+ * If no JOB active, make the LUN reselect path invalid.
+ */
+ if (lp->busy_itlq == 0 && lp->busy_itl == 0)
+ lp->head.resel_sa =
+ cpu_to_scr(SCRIPTB_BA (np, resel_bad_lun));
+ }
+ /*
+ * Otherwise, we only accept 1 IO per LUN.
+ * Clear the bit that keeps track of this IO.
+ */
+ else
+ sym_clr_bit(tp->busy0_map, cp->lun);
+
+ /*
+ * We donnot queue more than 1 ccb per target
+ * with negotiation at any time. If this ccb was
+ * used for negotiation, clear this info in the tcb.
+ */
+ if (cp == tp->nego_cp)
+ tp->nego_cp = 0;
+
+#ifdef SYM_CONF_IARB_SUPPORT
+ /*
+ * If we just complete the last queued CCB,
+ * clear this info that is no longer relevant.
+ */
+ if (cp == np->last_cp)
+ np->last_cp = 0;
+#endif
+
+ /*
+ * Unmap user data from DMA map if needed.
+ */
+ sym_data_dmamap_unload(np, cp);
+
+ /*
+ * Make this CCB available.
+ */
+ cp->cam_ccb = 0;
+ cp->host_status = HS_IDLE;
+ sym_remque(&cp->link_ccbq);
+ sym_insque_head(&cp->link_ccbq, &np->free_ccbq);
+
+#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
+ /*
+ * Cancel any pending timeout condition.
+ */
+ sym_untimeout_ccb(np, cp);
+#endif
+
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ if (lp) {
+ sym_remque(&cp->link2_ccbq);
+ sym_insque_tail(&cp->link2_ccbq, &np->dummy_ccbq);
+ if (cp->started) {
+ if (cp->tag != NO_TAG)
+ --lp->started_tags;
+ else
+ --lp->started_no_tag;
+ }
+ }
+ cp->started = 0;
+#endif
+}
+
+/*
+ * Allocate a CCB from memory and initialize its fixed part.
+ */
+static ccb_p sym_alloc_ccb(hcb_p np)
+{
+ ccb_p cp = 0;
+ int hcode;
+
+ /*
+ * Prevent from allocating more CCBs than we can
+ * queue to the controller.
+ */
+ if (np->actccbs >= SYM_CONF_MAX_START)
+ return 0;
+
+ /*
+ * Allocate memory for this CCB.
+ */
+ cp = sym_calloc_dma(sizeof(struct sym_ccb), "CCB");
+ if (!cp)
+ goto out_free;
+
+ /*
+ * Allocate a bounce buffer for sense data.
+ */
+ cp->sns_bbuf = sym_calloc_dma(SYM_SNS_BBUF_LEN, "SNS_BBUF");
+ if (!cp->sns_bbuf)
+ goto out_free;
+
+ /*
+ * Allocate a map for the DMA of user data.
+ */
+ if (sym_data_dmamap_create(np, cp))
+ goto out_free;
+
+ /*
+ * Count it.
+ */
+ np->actccbs++;
+
+ /*
+ * Compute the bus address of this ccb.
+ */
+ cp->ccb_ba = vtobus(cp);
+
+ /*
+ * Insert this ccb into the hashed list.
+ */
+ hcode = CCB_HASH_CODE(cp->ccb_ba);
+ cp->link_ccbh = np->ccbh[hcode];
+ np->ccbh[hcode] = cp;
+
+ /*
+ * Initialyze the start and restart actions.
+ */
+ cp->phys.head.go.start = cpu_to_scr(SCRIPTA_BA (np, idle));
+ cp->phys.head.go.restart = cpu_to_scr(SCRIPTB_BA (np, bad_i_t_l));
+
+ /*
+ * Initilialyze some other fields.
+ */
+ cp->phys.smsg_ext.addr = cpu_to_scr(HCB_BA(np, msgin[2]));
+
+ /*
+ * Chain into free ccb queue.
+ */
+ sym_insque_head(&cp->link_ccbq, &np->free_ccbq);
+
+ /*
+ * Chain into optionnal lists.
+ */
+#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
+ sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
+#endif
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ sym_insque_head(&cp->link2_ccbq, &np->dummy_ccbq);
+#endif
+ return cp;
+out_free:
+ if (cp) {
+ if (cp->sns_bbuf)
+ sym_mfree_dma(cp->sns_bbuf,SYM_SNS_BBUF_LEN,"SNS_BBUF");
+ sym_mfree_dma(cp, sizeof(*cp), "CCB");
+ }
+ return 0;
+}
+
+/*
+ * Look up a CCB from a DSA value.
+ */
+static ccb_p sym_ccb_from_dsa(hcb_p np, u32 dsa)
+{
+ int hcode;
+ ccb_p cp;
+
+ hcode = CCB_HASH_CODE(dsa);
+ cp = np->ccbh[hcode];
+ while (cp) {
+ if (cp->ccb_ba == dsa)
+ break;
+ cp = cp->link_ccbh;
+ }
+
+ return cp;
+}
+
+/*
+ * Target control block initialisation.
+ * Nothing important to do at the moment.
+ */
+static void sym_init_tcb (hcb_p np, u_char tn)
+{
+#if 0 /* Hmmm... this checking looks paranoid. */
+ /*
+ * Check some alignments required by the chip.
+ */
+ assert (((offsetof(struct sym_reg, nc_sxfer) ^
+ offsetof(struct sym_tcb, head.sval)) &3) == 0);
+ assert (((offsetof(struct sym_reg, nc_scntl3) ^
+ offsetof(struct sym_tcb, head.wval)) &3) == 0);
+#endif
+}
+
+/*
+ * Lun control block allocation and initialization.
+ */
+lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln)
+{
+ tcb_p tp = &np->target[tn];
+ lcb_p lp = sym_lp(np, tp, ln);
+
+ /*
+ * Already done, just return.
+ */
+ if (lp)
+ return lp;
+
+ /*
+ * Donnot allow LUN control block
+ * allocation for not probed LUNs.
+ */
+ if (!sym_is_bit(tp->lun_map, ln))
+ return 0;
+
+ /*
+ * Initialize the target control block if not yet.
+ */
+ sym_init_tcb (np, tn);
+
+ /*
+ * Allocate the LCB bus address array.
+ * Compute the bus address of this table.
+ */
+ if (ln && !tp->luntbl) {
+ int i;
+
+ tp->luntbl = sym_calloc_dma(256, "LUNTBL");
+ if (!tp->luntbl)
+ goto fail;
+ for (i = 0 ; i < 64 ; i++)
+ tp->luntbl[i] = cpu_to_scr(vtobus(&np->badlun_sa));
+ tp->head.luntbl_sa = cpu_to_scr(vtobus(tp->luntbl));
+ }
+
+ /*
+ * Allocate the table of pointers for LUN(s) > 0, if needed.
+ */
+ if (ln && !tp->lunmp) {
+ tp->lunmp = sym_calloc(SYM_CONF_MAX_LUN * sizeof(lcb_p),
+ "LUNMP");
+ if (!tp->lunmp)
+ goto fail;
+ }
+
+ /*
+ * Allocate the lcb.
+ * Make it available to the chip.
+ */
+ lp = sym_calloc_dma(sizeof(struct sym_lcb), "LCB");
+ if (!lp)
+ goto fail;
+ if (ln) {
+ tp->lunmp[ln] = lp;
+ tp->luntbl[ln] = cpu_to_scr(vtobus(lp));
+ }
+ else {
+ tp->lun0p = lp;
+ tp->head.lun0_sa = cpu_to_scr(vtobus(lp));
+ }
+
+ /*
+ * Let the itl task point to error handling.
+ */
+ lp->head.itl_task_sa = cpu_to_scr(np->bad_itl_ba);
+
+ /*
+ * Set the reselect pattern to our default. :)
+ */
+ lp->head.resel_sa = cpu_to_scr(SCRIPTB_BA (np, resel_bad_lun));
+
+ /*
+ * Set user capabilities.
+ */
+ lp->user_flags = tp->usrflags & (SYM_DISC_ENABLED | SYM_TAGS_ENABLED);
+
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ /*
+ * Initialize device queueing.
+ */
+ sym_que_init(&lp->waiting_ccbq);
+ sym_que_init(&lp->started_ccbq);
+ lp->started_max = SYM_CONF_MAX_TASK;
+ lp->started_limit = SYM_CONF_MAX_TASK;
+#endif
+ /*
+ * If we are busy, count the IO.
+ */
+ if (sym_is_bit(tp->busy0_map, ln)) {
+ lp->busy_itl = 1;
+ sym_clr_bit(tp->busy0_map, ln);
+ }
+fail:
+ return lp;
+}
+
+/*
+ * Allocate LCB resources for tagged command queuing.
+ */
+static void sym_alloc_lcb_tags (hcb_p np, u_char tn, u_char ln)
+{
+ tcb_p tp = &np->target[tn];
+ lcb_p lp = sym_lp(np, tp, ln);
+ int i;
+
+ /*
+ * If LCB not available, try to allocate it.
+ */
+ if (!lp && !(lp = sym_alloc_lcb(np, tn, ln)))
+ goto fail;
+
+ /*
+ * Allocate the task table and and the tag allocation
+ * circular buffer. We want both or none.
+ */
+ lp->itlq_tbl = sym_calloc_dma(SYM_CONF_MAX_TASK*4, "ITLQ_TBL");
+ if (!lp->itlq_tbl)
+ goto fail;
+ lp->cb_tags = sym_calloc(SYM_CONF_MAX_TASK, "CB_TAGS");
+ if (!lp->cb_tags) {
+ sym_mfree_dma(lp->itlq_tbl, SYM_CONF_MAX_TASK*4, "ITLQ_TBL");
+ lp->itlq_tbl = 0;
+ goto fail;
+ }
+
+ /*
+ * Initialize the task table with invalid entries.
+ */
+ for (i = 0 ; i < SYM_CONF_MAX_TASK ; i++)
+ lp->itlq_tbl[i] = cpu_to_scr(np->notask_ba);
+
+ /*
+ * Fill up the tag buffer with tag numbers.
+ */
+ for (i = 0 ; i < SYM_CONF_MAX_TASK ; i++)
+ lp->cb_tags[i] = i;
+
+ /*
+ * Make the task table available to SCRIPTS,
+ * And accept tagged commands now.
+ */
+ lp->head.itlq_tbl_sa = cpu_to_scr(vtobus(lp->itlq_tbl));
+
+ return;
+fail:
+}
+
+/*
+ * Queue a SCSI IO to the controller.
+ */
+int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp)
+{
+ tcb_p tp;
+ lcb_p lp;
+ u_char idmsg, *msgptr;
+ u_int msglen;
+
+ /*
+ * Keep track of the IO in our CCB.
+ */
+ cp->cam_ccb = (cam_ccb_p) csio;
+
+ /*
+ * Retreive the target descriptor.
+ */
+ tp = &np->target[cp->target];
+
+ /*
+ * Retreive the lun descriptor.
+ */
+ lp = sym_lp(np, tp, cp->lun);
+
+ /*
+ * Build the IDENTIFY message.
+ */
+ idmsg = M_IDENTIFY | cp->lun;
+ if (cp->tag != NO_TAG || (lp && (lp->curr_flags & SYM_DISC_ENABLED)))
+ idmsg |= 0x40;
+
+ msgptr = cp->scsi_smsg;
+ msglen = 0;
+ msgptr[msglen++] = idmsg;
+
+ /*
+ * Build the tag message if present.
+ */
+ if (cp->tag != NO_TAG) {
+ u_char order = cp->order;
+
+ switch(order) {
+ case M_ORDERED_TAG:
+ break;
+ case M_HEAD_TAG:
+ break;
+ default:
+ order = M_SIMPLE_TAG;
+ }
+#ifdef SYM_OPT_LIMIT_COMMAND_REORDERING
+ /*
+ * Avoid too much reordering of SCSI commands.
+ * The algorithm tries to prevent completion of any
+ * tagged command from being delayed against more
+ * than 3 times the max number of queued commands.
+ */
+ if (lp && lp->tags_since > 3*SYM_CONF_MAX_TAG) {
+ lp->tags_si = !(lp->tags_si);
+ if (lp->tags_sum[lp->tags_si]) {
+ order = M_ORDERED_TAG;
+ if ((DEBUG_FLAGS & DEBUG_TAGS)||sym_verbose>1) {
+ PRINT_ADDR(cp);
+ printf("ordered tag forced.\n");
+ }
+ }
+ lp->tags_since = 0;
+ }
+#endif
+ msgptr[msglen++] = order;
+
+ /*
+ * For less than 128 tags, actual tags are numbered
+ * 1,3,5,..2*MAXTAGS+1,since we may have to deal
+ * with devices that have problems with #TAG 0 or too
+ * great #TAG numbers. For more tags (up to 256),
+ * we use directly our tag number.
+ */
+#if SYM_CONF_MAX_TASK > (512/4)
+ msgptr[msglen++] = cp->tag;
+#else
+ msgptr[msglen++] = (cp->tag << 1) + 1;
+#endif
+ }
+
+ /*
+ * Build a negotiation message if needed.
+ * (nego_status is filled by sym_prepare_nego())
+ */
+ cp->nego_status = 0;
+ if (tp->tinfo.curr.width != tp->tinfo.goal.width ||


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

echo 'End of part 066'
echo 'File patch-2.4.15 is continued in part 067'
echo "067" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:39 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part063

#!/bin/sh -x
# this is part 063 of a 115 - part archive


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

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

+#include "sym_glue.h"
+
+#define NAME53C "sym53c"
+#define NAME53C8XX "sym53c8xx"
+
+/*
+ * Simple Wrapper to kernel PCI bus interface.
+ */
+
+typedef struct pci_dev *pcidev_t;
+#define PCIDEV_NULL (0)
+#define PciBusNumber(d) (d)->bus->number
+#define PciDeviceFn(d) (d)->devfn
+#define PciVendorId(d) (d)->vendor
+#define PciDeviceId(d) (d)->device
+#define PciIrqLine(d) (d)->irq
+
+static u_long __init
+pci_get_base_cookie(struct pci_dev *pdev, int index)
+{
+ u_long base;
+
+#if LINUX_VERSION_CODE > LinuxVersionCode(2,3,12)
+ base = pdev->resource[index].start;
+#else
+ base = pdev->base_address[index];
+#if BITS_PER_LONG > 32
+ if ((base & 0x7) == 0x4)
+ base |= (((u_long)pdev->base_address[++index]) << 32);
+#endif
+#endif
+ return (base & ~0x7ul);


+}
+
+static int __init

+pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
+{
+ u32 tmp;
+#define PCI_BAR_OFFSET(index) (PCI_BASE_ADDRESS_0 + (index<<2))
+
+ pci_read_config_dword(pdev, PCI_BAR_OFFSET(index), &tmp);
+ *base = tmp;
+ ++index;
+ if ((tmp & 0x7) == 0x4) {
+#if BITS_PER_LONG > 32
+ pci_read_config_dword(pdev, PCI_BAR_OFFSET(index), &tmp);
+ *base |= (((u_long)tmp) << 32);
+#endif
+ ++index;
+ }
+ return index;
+#undef PCI_BAR_OFFSET
+}
+
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0)
+#define pci_enable_device(pdev) (0)
+#endif
+
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,4)
+#define scsi_set_pci_device(inst, pdev) do { ;} while (0)
+#endif
+
+/*
+ * Insert a delay in micro-seconds and milli-seconds.
+ */
+void sym_udelay(int us) { udelay(us); }
+void sym_mdelay(int ms) { mdelay(ms); }
+
+/*
+ * SMP threading.
+ *
+ * The whole SCSI sub-system under Linux is basically single-threaded.
+ * Everything, including low-level driver interrupt routine, happens
+ * whith the `io_request_lock' held.
+ * The sym53c8xx-1.x drivers series ran their interrupt code using a
+ * spin mutex per controller. This added complexity without improving
+ * scalability significantly. the sym-2 driver still use a spinlock
+ * per controller for safety, but basically runs with the damned
+ * io_request_lock held.
+ */
+
+spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
+
+#define SYM_LOCK_DRIVER(flags) spin_lock_irqsave(&sym53c8xx_lock, flags)
+#define SYM_UNLOCK_DRIVER(flags) spin_unlock_irqrestore(&sym53c8xx_lock,flags)
+
+#define SYM_INIT_LOCK_HCB(np) spin_lock_init(&np->s.smp_lock);
+#define SYM_LOCK_HCB(np, flags) spin_lock_irqsave(&np->s.smp_lock, flags)
+#define SYM_UNLOCK_HCB(np, flags) spin_unlock_irqrestore(&np->s.smp_lock, flags)
+
+#define SYM_LOCK_SCSI(np, flags) \
+ spin_lock_irqsave(&io_request_lock, flags)
+#define SYM_UNLOCK_SCSI(np, flags) \
+ spin_unlock_irqrestore(&io_request_lock, flags)
+
+/* Ugly, but will make things easier if this locking will ever disappear */
+#define SYM_LOCK_SCSI_NOSAVE(np) spin_lock_irq(&io_request_lock)
+#define SYM_UNLOCK_SCSI_NORESTORE(np) spin_unlock_irq(&io_request_lock)
+
+/*
+ * These simple macros limit expression involving
+ * kernel time values (jiffies) to some that have
+ * chance not to be too much incorrect. :-)
+ */
+#define ktime_get(o) (jiffies + (u_long) o)
+#define ktime_exp(b) ((long)(jiffies) - (long)(b) >= 0)
+#define ktime_dif(a, b) ((long)(a) - (long)(b))
+#define ktime_add(a, o) ((a) + (u_long)(o))
+#define ktime_sub(a, o) ((a) - (u_long)(o))
+
+/*
+ * Wrappers to the generic memory allocator.
+ */
+void *sym_calloc(int size, char *name)
+{
+ u_long flags;
+ void *m;
+ SYM_LOCK_DRIVER(flags);
+ m = sym_calloc_unlocked(size, name);
+ SYM_UNLOCK_DRIVER(flags);
+ return m;
+}
+
+void sym_mfree(void *m, int size, char *name)
+{
+ u_long flags;
+ SYM_LOCK_DRIVER(flags);
+ sym_mfree_unlocked(m, size, name);
+ SYM_UNLOCK_DRIVER(flags);
+}
+
+#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING
+
+void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name)
+{
+ u_long flags;
+ void *m;
+ SYM_LOCK_DRIVER(flags);
+ m = __sym_calloc_dma_unlocked(dev_dmat, size, name);
+ SYM_UNLOCK_DRIVER(flags);
+ return m;
+}
+
+void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name)
+{
+ u_long flags;
+ SYM_LOCK_DRIVER(flags);
+ __sym_mfree_dma_unlocked(dev_dmat, m, size, name);
+ SYM_UNLOCK_DRIVER(flags);
+}
+
+m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m)
+{
+ u_long flags;
+ m_addr_t b;
+ SYM_LOCK_DRIVER(flags);
+ b = __vtobus_unlocked(dev_dmat, m);
+ SYM_UNLOCK_DRIVER(flags);
+ return b;
+}
+
+#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */
+
+
+/*
+ * Map/unmap a PCI memory window.
+ */
+#ifndef SYM_OPT_NO_BUS_MEMORY_MAPPING
+static u_long __init pci_map_mem(u_long base, u_long size)
+{
+ u_long page_base = ((u_long) base) & PAGE_MASK;
+ u_long page_offs = ((u_long) base) - page_base;
+ u_long page_remapped = (u_long) ioremap(page_base, page_offs+size);
+
+ return page_remapped? (page_remapped + page_offs) : 0UL;
+}
+
+static void __init pci_unmap_mem(u_long vaddr, u_long size)
+{
+ if (vaddr)
+ iounmap((void *) (vaddr & PAGE_MASK));
+}
+#endif
+
+/*
+ * Used to retrieve the host structure when the
+ * driver is called from the proc FS.
+ */
+static struct Scsi_Host *first_host = NULL;
+
+/*
+ * /proc directory entry and proc_info.
+ */
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
+static struct proc_dir_entry proc_scsi_sym53c8xx = {
+ PROC_SCSI_SYM53C8XX, 9, NAME53C8XX,
+ S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+#endif
+
+/*
+ * Transfer direction
+ *
+ * Until some linux kernel version near 2.3.40, low-level scsi
+ * drivers were not told about data transfer direction.
+ */
+#if LINUX_VERSION_CODE > LinuxVersionCode(2, 3, 40)
+
+#define scsi_data_direction(cmd) (cmd->sc_data_direction)
+
+#else
+
+static __inline__ int scsi_data_direction(Scsi_Cmnd *cmd)
+{
+ int direction;
+
+ switch((int) cmd->cmnd[0]) {
+ case 0x08: /* READ(6) 08 */
+ case 0x28: /* READ(10) 28 */
+ case 0xA8: /* READ(12) A8 */
+ direction = SCSI_DATA_READ;
+ break;
+ case 0x0A: /* WRITE(6) 0A */
+ case 0x2A: /* WRITE(10) 2A */
+ case 0xAA: /* WRITE(12) AA */
+ direction = SCSI_DATA_WRITE;
+ break;
+ default:
+ direction = SCSI_DATA_UNKNOWN;
+ break;
+ }
+
+ return direction;
+}
+
+#endif
+
+/*
+ * Driver host data structure.
+ */
+struct host_data {
+ hcb_p ncb;
+};
+
+/*
+ * Some type that fit DMA addresses as seen from BUS.
+ */
+#ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING
+typedef u_long bus_addr_t;
+#else
+#if SYM_CONF_DMA_ADDRESSING_MODE > 0
+typedef dma64_addr_t bus_addr_t;
+#else
+typedef dma_addr_t bus_addr_t;
+#endif
+#endif
+
+/*
+ * Used by the eh thread to wait for command completion.
+ * It is allocated on the eh thread stack.
+ */
+struct sym_eh_wait {
+ struct semaphore sem;
+ struct timer_list timer;
+ void (*old_done)(Scsi_Cmnd *);
+ int to_do;
+ int timed_out;
+};
+
+/*
+ * Driver private area in the SCSI command structure.
+ */
+struct sym_ucmd { /* Override the SCSI pointer structure */
+ SYM_QUEHEAD link_cmdq; /* Must stay at offset ZERO */
+#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING
+ bus_addr_t data_mapping;
+ u_char data_mapped;
+#endif
+ struct sym_eh_wait *eh_wait;
+};
+
+typedef struct sym_ucmd *ucmd_p;
+
+#define SYM_UCMD_PTR(cmd) ((ucmd_p)(&(cmd)->SCp))
+#define SYM_SCMD_PTR(ucmd) sym_que_entry(ucmd, Scsi_Cmnd, SCp)
+#define SYM_SOFTC_PTR(cmd) (((struct host_data *)cmd->host->hostdata)->ncb)
+
+/*
+ * Deal with DMA mapping/unmapping.
+ */
+
+#ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING
+
+/* Linux versions prior to pci bus iommu kernel interface */
+
+#define __unmap_scsi_data(pdev, cmd) do {; } while (0)
+#define __map_scsi_single_data(pdev, cmd) (__vtobus(pdev,(cmd)->request_buffer))
+#define __map_scsi_sg_data(pdev, cmd) ((cmd)->use_sg)
+#define __sync_scsi_data(pdev, cmd) do {; } while (0)
+
+#define bus_sg_dma_address(sc) vtobus((sc)->address)
+#define bus_sg_dma_len(sc) ((sc)->length)
+
+#else /* Linux version with pci bus iommu kernel interface */
+
+#define bus_unmap_sg(pdev, sgptr, sgcnt, dir) \
+ pci_unmap_sg(pdev, sgptr, sgcnt, dir)
+
+#define bus_unmap_single(pdev, mapping, bufptr, dir) \
+ pci_unmap_single(pdev, mapping, bufptr, dir)
+
+#define bus_map_single(pdev, bufptr, bufsiz, dir) \
+ pci_map_single(pdev, bufptr, bufsiz, dir)
+
+#define bus_map_sg(pdev, sgptr, sgcnt, dir) \
+ pci_map_sg(pdev, sgptr, sgcnt, dir)
+
+#define bus_dma_sync_sg(pdev, sgptr, sgcnt, dir) \
+ pci_dma_sync_sg(pdev, sgptr, sgcnt, dir)
+
+#define bus_dma_sync_single(pdev, mapping, bufsiz, dir) \
+ pci_dma_sync_single(pdev, mapping, bufsiz, dir)
+
+#define bus_sg_dma_address(sc) sg_dma_address(sc)
+#define bus_sg_dma_len(sc) sg_dma_len(sc)
+
+static void __unmap_scsi_data(pcidev_t pdev, Scsi_Cmnd *cmd)
+{
+ int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
+
+ switch(SYM_UCMD_PTR(cmd)->data_mapped) {
+ case 2:
+ bus_unmap_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir);


+ break;
+ case 1:

+ bus_unmap_single(pdev, SYM_UCMD_PTR(cmd)->data_mapping,
+ cmd->request_bufflen, dma_dir);
+ break;
+ }
+ SYM_UCMD_PTR(cmd)->data_mapped = 0;
+}
+
+static bus_addr_t __map_scsi_single_data(pcidev_t pdev, Scsi_Cmnd *cmd)
+{
+ bus_addr_t mapping;
+ int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
+
+ mapping = bus_map_single(pdev, cmd->request_buffer,
+ cmd->request_bufflen, dma_dir);
+ if (mapping) {
+ SYM_UCMD_PTR(cmd)->data_mapped = 1;
+ SYM_UCMD_PTR(cmd)->data_mapping = mapping;
+ }
+
+ return mapping;
+}
+
+static int __map_scsi_sg_data(pcidev_t pdev, Scsi_Cmnd *cmd)
+{
+ int use_sg;
+ int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
+
+ use_sg = bus_map_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir);
+ if (use_sg > 0) {
+ SYM_UCMD_PTR(cmd)->data_mapped = 2;
+ SYM_UCMD_PTR(cmd)->data_mapping = use_sg;
+ }
+
+ return use_sg;
+}
+
+static void __sync_scsi_data(pcidev_t pdev, Scsi_Cmnd *cmd)
+{
+ int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
+
+ switch(SYM_UCMD_PTR(cmd)->data_mapped) {
+ case 2:
+ bus_dma_sync_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir);


+ break;
+ case 1:

+ bus_dma_sync_single(pdev, SYM_UCMD_PTR(cmd)->data_mapping,
+ cmd->request_bufflen, dma_dir);


+ break;
+ }
+}
+

+#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */
+
+#define unmap_scsi_data(np, cmd) \
+ __unmap_scsi_data(np->s.device, cmd)
+#define map_scsi_single_data(np, cmd) \
+ __map_scsi_single_data(np->s.device, cmd)
+#define map_scsi_sg_data(np, cmd) \
+ __map_scsi_sg_data(np->s.device, cmd)
+#define sync_scsi_data(np, cmd) \
+ __sync_scsi_data(np->s.device, cmd)
+
+/*
+ * Complete a pending CAM CCB.
+ */
+void sym_xpt_done(hcb_p np, Scsi_Cmnd *ccb)
+{
+ sym_remque(&SYM_UCMD_PTR(ccb)->link_cmdq);
+ unmap_scsi_data(np, ccb);
+ ccb->scsi_done(ccb);
+}
+
+void sym_xpt_done2(hcb_p np, Scsi_Cmnd *ccb, int cam_status)
+{
+ sym_set_cam_status(ccb, cam_status);


+ sym_xpt_done(np, ccb);
+}
+
+
+/*

+ * Print something that identifies the IO.
+ */
+void sym_print_addr (ccb_p cp)
+{
+ Scsi_Cmnd *cmd = cp->cam_ccb;
+ if (cmd)
+ printf("%s:%d:%d:", sym_name(SYM_SOFTC_PTR(cmd)),
+ cmd->target,cmd->lun);
+}
+
+/*
+ * Tell the SCSI layer about a BUS RESET.
+ */
+void sym_xpt_async_bus_reset(hcb_p np)
+{
+ printf_notice("%s: SCSI BUS has been reset.\n", sym_name(np));
+ np->s.settle_time = ktime_get(sym_driver_setup.settle_delay * HZ);
+ np->s.settle_time_valid = 1;


+ if (sym_verbose >= 2)

+ printf_info("%s: command processing suspended for %d seconds\n",
+ sym_name(np), sym_driver_setup.settle_delay);
+}
+
+/*
+ * Tell the SCSI layer about a BUS DEVICE RESET message sent.
+ */
+void sym_xpt_async_sent_bdr(hcb_p np, int target)
+{
+ printf_notice("%s: TARGET %d has been reset.\n", sym_name(np), target);
+}
+
+/*
+ * Tell the SCSI layer about the new transfer parameters.
+ */
+void sym_xpt_async_nego_wide(hcb_p np, int target)
+{
+ if (sym_verbose < 3)
+ return;
+ sym_announce_transfer_rate(np, target);
+}
+
+/*
+ * Choose the more appropriate CAM status if
+ * the IO encountered an extended error.
+ */
+static int sym_xerr_cam_status(int cam_status, int x_status)
+{
+ if (x_status) {
+ if (x_status & XE_PARITY_ERR)
+ cam_status = DID_PARITY;
+ else if (x_status &(XE_EXTRA_DATA|XE_SODL_UNRUN|XE_SWIDE_OVRUN))
+ cam_status = DID_ERROR;
+ else if (x_status & XE_BAD_PHASE)
+ cam_status = DID_ERROR;
+ else
+ cam_status = DID_ERROR;
+ }
+ return cam_status;
+}
+
+/*
+ * Build CAM result for a failed or auto-sensed IO.
+ */
+void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid)
+{
+ Scsi_Cmnd *csio = cp->cam_ccb;
+ u_int cam_status, scsi_status, drv_status;
+
+ drv_status = 0;
+ cam_status = DID_OK;
+ scsi_status = cp->ssss_status;
+


+ if (cp->host_flags & HF_SENSE) {

+ scsi_status = cp->sv_scsi_status;
+ resid = cp->sv_resid;
+ if (sym_verbose && cp->sv_xerr_status)
+ sym_print_xerr(cp, cp->sv_xerr_status);
+ if (cp->host_status == HS_COMPLETE &&
+ cp->ssss_status == S_GOOD &&
+ cp->xerr_status == 0) {
+ cam_status = sym_xerr_cam_status(DID_OK,
+ cp->sv_xerr_status);
+ drv_status = DRIVER_SENSE;
+ /*
+ * Bounce back the sense data to user.
+ */
+ bzero(&csio->sense_buffer, sizeof(csio->sense_buffer));
+ bcopy(cp->sns_bbuf, csio->sense_buffer,
+ MIN(sizeof(csio->sense_buffer),SYM_SNS_BBUF_LEN));
+#if 0
+ /*
+ * If the device reports a UNIT ATTENTION condition
+ * due to a RESET condition, we should consider all
+ * disconnect CCBs for this unit as aborted.
+ */
+ if (1) {
+ u_char *p;
+ p = (u_char *) csio->sense_data;
+ if (p[0]==0x70 && p[2]==0x6 && p[12]==0x29)
+ sym_clear_tasks(np, DID_ABORT,
+ cp->target,cp->lun, -1);
+ }
+#endif
+ }
+ else
+ cam_status = DID_ERROR;
+ }
+ else if (cp->host_status == HS_COMPLETE) /* Bad SCSI status */
+ cam_status = DID_OK;
+ else if (cp->host_status == HS_SEL_TIMEOUT) /* Selection timeout */
+ cam_status = DID_NO_CONNECT;
+ else if (cp->host_status == HS_UNEXPECTED) /* Unexpected BUS FREE*/
+ cam_status = DID_ERROR;
+ else { /* Extended error */
+ if (sym_verbose) {
+ PRINT_ADDR(cp);
+ printf ("COMMAND FAILED (%x %x %x).\n",
+ cp->host_status, cp->ssss_status,
+ cp->xerr_status);
+ }
+ /*
+ * Set the most appropriate value for CAM status.
+ */
+ cam_status = sym_xerr_cam_status(DID_ERROR, cp->xerr_status);
+ }
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,99)
+ csio->resid = resid;
+#endif
+ csio->result = (drv_status << 24) + (cam_status << 16) + scsi_status;
+}
+
+
+/*
+ * Called on successfull INQUIRY response.
+ */
+void sym_sniff_inquiry(hcb_p np, Scsi_Cmnd *cmd, int resid)
+{
+ int retv;
+
+ if (!cmd || cmd->use_sg)
+ return;
+
+ sync_scsi_data(np, cmd);
+ retv = __sym_sniff_inquiry(np, cmd->target, cmd->lun,
+ (u_char *) cmd->request_buffer,
+ cmd->request_bufflen - resid);
+ if (retv < 0)
+ return;
+ else if (retv)
+ sym_update_trans_settings(np, &np->target[cmd->target]);
+}
+
+/*
+ * Build the scatter/gather array for an I/O.
+ */
+
+static int sym_scatter_no_sglist(hcb_p np, ccb_p cp, Scsi_Cmnd *cmd)
+{
+ struct sym_tblmove *data = &cp->phys.data[SYM_CONF_MAX_SG-1];
+ int segment;
+
+ cp->data_len = cmd->request_bufflen;
+
+ if (cmd->request_bufflen) {
+ bus_addr_t baddr = map_scsi_single_data(np, cmd);
+ if (baddr) {
+ sym_build_sge(np, data, baddr, cmd->request_bufflen);
+ segment = 1;
+ }
+ else
+ segment = -2;
+ }
+ else
+ segment = 0;
+
+ return segment;
+}
+
+static int sym_scatter(hcb_p np, ccb_p cp, Scsi_Cmnd *cmd)
+{
+ int segment;
+ int use_sg = (int) cmd->use_sg;
+
+ cp->data_len = 0;
+
+ if (!use_sg)
+ segment = sym_scatter_no_sglist(np, cp, cmd);
+ else if (use_sg > SYM_CONF_MAX_SG)
+ segment = -1;
+ else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) {
+ struct scatterlist *scatter = (struct scatterlist *)cmd->buffer;
+ struct sym_tblmove *data;
+
+ data = &cp->phys.data[SYM_CONF_MAX_SG - use_sg];
+
+ for (segment = 0; segment < use_sg; segment++) {
+ bus_addr_t baddr = bus_sg_dma_address(&scatter[segment]);
+ unsigned int len = bus_sg_dma_len(&scatter[segment]);
+
+ sym_build_sge(np, &data[segment], baddr, len);
+ cp->data_len += len;
+ }
+ }
+ else
+ segment = -2;
+
+ return segment;
+}
+
+/*
+ * Queue a SCSI command.
+ */
+static int sym_queue_command(hcb_p np, Scsi_Cmnd *ccb)
+{
+/* Scsi_Device *device = ccb->device; */


+ tcb_p tp;
+ lcb_p lp;

+ ccb_p cp;
+ int order;
+
+ /*
+ * Minimal checkings, so that we will not
+ * go outside our tables.
+ */
+ if (ccb->target == np->myaddr ||
+ ccb->target >= SYM_CONF_MAX_TARGET ||
+ ccb->lun >= SYM_CONF_MAX_LUN) {
+ sym_xpt_done2(np, ccb, CAM_DEV_NOT_THERE);


+ return 0;
+ }
+
+ /*

+ * Retreive the target descriptor.
+ */

+ tp = &np->target[ccb->target];
+
+ /*
+ * Complete the 1st INQUIRY command with error
+ * condition if the device is flagged NOSCAN
+ * at BOOT in the NVRAM. This may speed up
+ * the boot and maintain coherency with BIOS
+ * device numbering. Clearing the flag allows
+ * user to rescan skipped devices later.
+ * We also return error for devices not flagged
+ * for SCAN LUNS in the NVRAM since some mono-lun
+ * devices behave badly when asked for some non
+ * zero LUN. Btw, this is an absolute hack.:-)
+ */
+ if (ccb->cmnd[0] == 0x12 || ccb->cmnd[0] == 0x0) {
+ if ((tp->usrflags & SYM_SCAN_BOOT_DISABLED) ||
+ ((tp->usrflags & SYM_SCAN_LUNS_DISABLED) &&
+ ccb->lun != 0)) {
+ tp->usrflags &= ~SYM_SCAN_BOOT_DISABLED;
+ sym_xpt_done2(np, ccb, CAM_DEV_NOT_THERE);


+ return 0;
+ }
+ }
+

+ /*
+ * Select tagged/untagged.
+ */
+ lp = sym_lp(np, tp, ccb->lun);
+ order = (lp && lp->s.reqtags) ? M_SIMPLE_TAG : 0;
+
+ /*
+ * Queue the SCSI IO.
+ */
+ cp = sym_get_ccb(np, ccb->target, ccb->lun, order);
+ if (!cp)
+ return 1; /* Means resource shortage */
+ (void) sym_queue_scsiio(np, ccb, cp);


+ return 0;
+}
+
+/*

+ * Setup buffers and pointers that address the CDB.
+ */
+static int __inline sym_setup_cdb(hcb_p np, Scsi_Cmnd *ccb, ccb_p cp)
+{
+ u32 cmd_ba;
+ int cmd_len;
+
+ /*
+ * CDB is 16 bytes max.
+ */
+ if (ccb->cmd_len > sizeof(cp->cdb_buf)) {
+ sym_set_cam_status(cp->cam_ccb, CAM_REQ_INVALID);


+ return -1;
+ }
+

+ bcopy(ccb->cmnd, cp->cdb_buf, ccb->cmd_len);
+ cmd_ba = CCB_BA (cp, cdb_buf[0]);
+ cmd_len = ccb->cmd_len;
+
+ cp->phys.cmd.addr = cpu_to_scr(cmd_ba);
+ cp->phys.cmd.size = cpu_to_scr(cmd_len);


+
+ return 0;
+}
+
+/*

+ * Setup pointers that address the data and start the I/O.
+ */
+int sym_setup_data_and_start(hcb_p np, Scsi_Cmnd *csio, ccb_p cp)
+{
+ int dir;


+ tcb_p tp = &np->target[cp->target];
+ lcb_p lp = sym_lp(np, tp, cp->lun);
+

+ /*
+ * Build the CDB.
+ */
+ if (sym_setup_cdb(np, csio, cp))
+ goto out_abort;
+
+ /*
+ * No direction means no data.
+ */
+ dir = scsi_data_direction(csio);
+ if (dir != SCSI_DATA_NONE) {
+ cp->segments = sym_scatter (np, cp, csio);
+ if (cp->segments < 0) {
+ if (cp->segments == -2)
+ sym_set_cam_status(csio, CAM_RESRC_UNAVAIL);
+ else
+ sym_set_cam_status(csio, CAM_REQ_TOO_BIG);
+ goto out_abort;
+ }
+ }
+ else {
+ cp->data_len = 0;
+ cp->segments = 0;
+ }
+
+ /*
+ * Set data pointers.
+ */
+ sym_setup_data_pointers(np, cp, dir);
+
+ /*
+ * When `#ifed 1', the code below makes the driver
+ * panic on the first attempt to write to a SCSI device.
+ * It is the first test we want to do after a driver
+ * change that does not seem obviously safe. :)
+ */
+#if 0
+ switch (cp->cdb_buf[0]) {
+ case 0x0A: case 0x2A: case 0xAA:
+ panic("XXXXXXXXXXXXX WRITE NOT YET ALLOWED XXXXXXXXXXXXXX\n");
+ MDELAY(10000);
+ break;
+ default:
+ break;


+ }
+#endif
+
+ /*

+ * activate this job.


+ */
+ if (lp)

+ sym_start_next_ccbs(np, lp, 2);
+ else
+ sym_put_start_queue(np, cp);
+ return 0;
+
+out_abort:
+ sym_free_ccb(np, cp);
+ sym_xpt_done(np, csio);


+ return 0;
+}
+
+

+/*
+ * timer daemon.
+ *
+ * Misused to keep the driver running when
+ * interrupts are not configured correctly.
+ */
+static void sym_timer (hcb_p np)
+{
+ u_long thistime = ktime_get(0);
+
+#if LINUX_VERSION_CODE < LinuxVersionCode(2, 4, 0)
+ /*
+ * If release process in progress, let's go
+ * Set the release stage from 1 to 2 to synchronize
+ * with the release process.
+ */
+
+ if (np->s.release_stage) {
+ if (np->s.release_stage == 1)
+ np->s.release_stage = 2;
+ return;


+ }
+#endif
+
+ /*

+ * Restart the timer.
+ */
+#ifdef SYM_CONF_PCIQ_BROKEN_INTR
+ np->s.timer.expires = ktime_get((HZ+99)/100);
+#else
+ np->s.timer.expires = ktime_get(SYM_CONF_TIMER_INTERVAL);
+#endif
+ add_timer(&np->s.timer);
+
+ /*
+ * If we are resetting the ncr, wait for settle_time before
+ * clearing it. Then command processing will be resumed.
+ */
+ if (np->s.settle_time_valid) {
+ if (ktime_dif(np->s.settle_time, thistime) <= 0){
+ if (sym_verbose >= 2 )
+ printk("%s: command processing resumed\n",
+ sym_name(np));
+ np->s.settle_time_valid = 0;
+ }


+ return;
+ }
+
+ /*

+ * Nothing to do for now, but that may come.
+ */
+ if (np->s.lasttime + 4*HZ < thistime) {
+ np->s.lasttime = thistime;
+ }
+
+#ifdef SYM_CONF_PCIQ_MAY_MISS_COMPLETIONS
+ /*
+ * Some way-broken PCI bridges may lead to
+ * completions being lost when the clearing
+ * of the INTFLY flag by the CPU occurs
+ * concurrently with the chip raising this flag.
+ * If this ever happen, lost completions will
+ * be reaped here.
+ */
+ sym_wakeup_done(np);
+#endif
+
+#ifdef SYM_CONF_PCIQ_BROKEN_INTR
+ if (INB(nc_istat) & (INTF|SIP|DIP)) {
+
+ /*
+ ** Process pending interrupts.
+ */
+ if (DEBUG_FLAGS & DEBUG_TINY) printk ("{");
+ sym_interrupt(np);
+ if (DEBUG_FLAGS & DEBUG_TINY) printk ("}");
+ }
+#endif /* SYM_CONF_PCIQ_BROKEN_INTR */
+}
+
+
+/*
+ * PCI BUS error handler.
+ */
+void sym_log_bus_error(hcb_p np)
+{
+ u_short pci_sts;
+ pci_read_config_word(np->s.device, PCI_STATUS, &pci_sts);
+ if (pci_sts & 0xf900) {
+ pci_write_config_word(np->s.device, PCI_STATUS,
+ pci_sts);
+ printf("%s: PCI STATUS = 0x%04x\n",
+ sym_name(np), pci_sts & 0xf900);
+ }
+}
+
+
+/*
+ * Requeue awaiting commands.
+ */
+static void sym_requeue_awaiting_cmds(hcb_p np)
+{
+ Scsi_Cmnd *cmd;
+ ucmd_p ucp = SYM_UCMD_PTR(cmd);
+ SYM_QUEHEAD tmp_cmdq;
+ int sts;
+
+ sym_que_move(&np->s.wait_cmdq, &tmp_cmdq);
+
+ while ((ucp = (ucmd_p) sym_remque_head(&tmp_cmdq)) != 0) {
+ sym_insque_tail(&ucp->link_cmdq, &np->s.busy_cmdq);
+ cmd = SYM_SCMD_PTR(ucp);
+ sts = sym_queue_command(np, cmd);
+ if (sts) {
+ sym_remque(&ucp->link_cmdq);
+ sym_insque_head(&ucp->link_cmdq, &np->s.wait_cmdq);
+ }
+ }
+}
+
+/*
+ * Linux entry point of the queuecommand() function
+ */
+int sym53c8xx_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+{
+ hcb_p np = SYM_SOFTC_PTR(cmd);
+ ucmd_p ucp = SYM_UCMD_PTR(cmd);
+ u_long flags;
+ int sts = 0;
+
+ cmd->scsi_done = done;
+ cmd->host_scribble = NULL;
+ memset(ucp, 0, sizeof(*ucp));
+
+ SYM_LOCK_HCB(np, flags);
+
+ /*
+ * Shorten our settle_time if needed for
+ * this command not to time out.
+ */
+ if (np->s.settle_time_valid && cmd->timeout_per_command) {
+ u_long tlimit = ktime_get(cmd->timeout_per_command);
+ tlimit = ktime_sub(tlimit, SYM_CONF_TIMER_INTERVAL*2);
+ if (ktime_dif(np->s.settle_time, tlimit) > 0) {
+ np->s.settle_time = tlimit;
+ }
+ }
+
+ if (np->s.settle_time_valid || !sym_que_empty(&np->s.wait_cmdq)) {
+ sym_insque_tail(&ucp->link_cmdq, &np->s.wait_cmdq);


+ goto out;
+ }
+

+ sym_insque_tail(&ucp->link_cmdq, &np->s.busy_cmdq);
+ sts = sym_queue_command(np, cmd);
+ if (sts) {
+ sym_remque(&ucp->link_cmdq);
+ sym_insque_tail(&ucp->link_cmdq, &np->s.wait_cmdq);
+ }
+out:
+ SYM_UNLOCK_HCB(np, flags);


+
+ return 0;
+}
+
+/*

+ * Linux entry point of the interrupt handler.
+ */
+static void sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs)
+{
+ unsigned long flags;
+ unsigned long flags1;
+ hcb_p np = (hcb_p) dev_id;
+
+ if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("[");
+
+ SYM_LOCK_SCSI(np, flags1);
+ SYM_LOCK_HCB(np, flags);
+
+ sym_interrupt(np);
+
+ if (!sym_que_empty(&np->s.wait_cmdq) && !np->s.settle_time_valid)
+ sym_requeue_awaiting_cmds(np);
+
+ SYM_UNLOCK_HCB(np, flags);
+ SYM_UNLOCK_SCSI(np, flags1);
+
+ if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("]\n");
+}
+
+/*
+ * Linux entry point of the timer handler
+ */
+static void sym53c8xx_timer(unsigned long npref)
+{
+ hcb_p np = (hcb_p) npref;
+ unsigned long flags;
+ unsigned long flags1;
+
+ SYM_LOCK_SCSI(np, flags1);
+ SYM_LOCK_HCB(np, flags);
+
+ sym_timer(np);
+
+ if (!sym_que_empty(&np->s.wait_cmdq) && !np->s.settle_time_valid)
+ sym_requeue_awaiting_cmds(np);
+
+ SYM_UNLOCK_HCB(np, flags);
+ SYM_UNLOCK_SCSI(np, flags1);
+}
+
+
+/*
+ * What the eh thread wants us to perform.
+ */
+#define SYM_EH_ABORT 0
+#define SYM_EH_DEVICE_RESET 1
+#define SYM_EH_BUS_RESET 2
+#define SYM_EH_HOST_RESET 3
+
+/*
+ * What we will do regarding the involved SCSI command.
+ */
+#define SYM_EH_DO_IGNORE 0
+#define SYM_EH_DO_COMPLETE 1
+#define SYM_EH_DO_WAIT 2
+
+/*
+ * Our general completion handler.
+ */
+static void __sym_eh_done(Scsi_Cmnd *cmd, int timed_out)
+{
+ struct sym_eh_wait *ep = SYM_UCMD_PTR(cmd)->eh_wait;
+ if (!ep)
+ return;
+
+ /* Try to avoid a race here (not 100% safe) */
+ if (!timed_out) {
+ ep->timed_out = 0;
+ if (ep->to_do == SYM_EH_DO_WAIT && !del_timer(&ep->timer))
+ return;
+ }
+
+ /* Revert everything */
+ SYM_UCMD_PTR(cmd)->eh_wait = 0;
+ cmd->scsi_done = ep->old_done;
+
+ /* Wake up the eh thread if it wants to sleep */
+ if (ep->to_do == SYM_EH_DO_WAIT)
+ up(&ep->sem);
+}
+
+/*
+ * scsi_done() alias when error recovery is in progress.
+ */
+static void sym_eh_done(Scsi_Cmnd *cmd) { __sym_eh_done(cmd, 0); }
+
+/*
+ * Some timeout handler to avoid waiting too long.
+ */
+static void sym_eh_timeout(u_long p) { __sym_eh_done((Scsi_Cmnd *)p, 1); }
+
+/*
+ * Generic method for our eh processing.
+ * The 'op' argument tells what we have to do.
+ */
+static int sym_eh_handler(int op, char *opname, Scsi_Cmnd *cmd)
+{
+ hcb_p np = SYM_SOFTC_PTR(cmd);
+ unsigned long flags;
+ SYM_QUEHEAD *qp;
+ int to_do = SYM_EH_DO_IGNORE;
+ int sts = -1;
+ struct sym_eh_wait eh, *ep = &eh;
+ char devname[20];
+
+ sprintf(devname, "%s:%d:%d", sym_name(np), cmd->target, cmd->lun);
+
+ printf_warning("%s: %s operation started.\n", devname, opname);
+
+ SYM_LOCK_HCB(np, flags);
+
+#if 0
+ /* This one should be the result of some race, thus to ignore */
+ if (cmd->serial_number != cmd->serial_number_at_timeout)
+ goto prepare;
+#endif
+
+ /* This one is not queued to the core driver -> to complete here */
+ FOR_EACH_QUEUED_ELEMENT(&np->s.wait_cmdq, qp) {
+ if (SYM_SCMD_PTR(qp) == cmd) {
+ to_do = SYM_EH_DO_COMPLETE;
+ goto prepare;
+ }
+ }
+
+ /* This one is queued in some place -> to wait for completion */
+ FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
+ ccb_p cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
+ if (cp->cam_ccb == cmd) {
+ to_do = SYM_EH_DO_WAIT;
+ goto prepare;
+ }
+ }
+
+prepare:
+ /* Prepare stuff to either ignore, complete or wait for completion */
+ switch(to_do) {
+ default:
+ case SYM_EH_DO_IGNORE:
+ goto finish;
+ break;
+ case SYM_EH_DO_WAIT:
+#if LINUX_VERSION_CODE > LinuxVersionCode(2,3,0)
+ init_MUTEX_LOCKED(&ep->sem);
+#else
+ ep->sem = MUTEX_LOCKED;
+#endif


+ /* fall through */

+ case SYM_EH_DO_COMPLETE:
+ ep->old_done = cmd->scsi_done;
+ cmd->scsi_done = sym_eh_done;
+ SYM_UCMD_PTR(cmd)->eh_wait = ep;
+ }
+
+ /* Try to proceed the operation we have been asked for */
+ sts = -1;
+ switch(op) {
+ case SYM_EH_ABORT:
+ sts = sym_abort_scsiio(np, cmd, 1);
+ break;
+ case SYM_EH_DEVICE_RESET:
+ sts = sym_reset_scsi_target(np, cmd->target);
+ break;
+ case SYM_EH_BUS_RESET:
+ sym_reset_scsi_bus(np, 1);
+ sts = 0;
+ break;
+ case SYM_EH_HOST_RESET:
+ sym_reset_scsi_bus(np, 0);
+ sym_start_up (np, 1);
+ sts = 0;
+ break;
+ default:
+ break;
+ }
+
+ /* On error, restore everything and cross fingers :) */
+ if (sts) {
+ SYM_UCMD_PTR(cmd)->eh_wait = 0;
+ cmd->scsi_done = ep->old_done;
+ to_do = SYM_EH_DO_IGNORE;
+ }
+
+finish:
+ ep->to_do = to_do;
+ /* Complete the command with locks held as required by the driver */
+ if (to_do == SYM_EH_DO_COMPLETE)
+ sym_xpt_done2(np, cmd, CAM_REQ_ABORTED);
+
+ SYM_UNLOCK_HCB(np, flags);
+
+ /* Wait for completion with locks released, as required by kernel */
+ if (to_do == SYM_EH_DO_WAIT) {
+ init_timer(&ep->timer);
+ ep->timer.expires = jiffies + (5*HZ);
+ ep->timer.function = sym_eh_timeout;
+ ep->timer.data = (u_long)cmd;
+ ep->timed_out = 1; /* Be pessimistic for once :) */
+ add_timer(&ep->timer);
+ SYM_UNLOCK_SCSI_NORESTORE(np);
+ down(&ep->sem);
+ SYM_LOCK_SCSI_NOSAVE(np);
+ if (ep->timed_out)
+ sts = -2;
+ }
+ printf_warning("%s: %s operation %s.\n", devname, opname,
+ sts==0?"complete":sts==-2?"timed-out":"failed");
+ return sts? SCSI_FAILED : SCSI_SUCCESS;
+}
+
+
+/*
+ * Error handlers called from the eh thread (one thread per HBA).
+ */
+int sym53c8xx_eh_abort_handler(Scsi_Cmnd *cmd)
+{
+ return sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd);
+}
+
+int sym53c8xx_eh_device_reset_handler(Scsi_Cmnd *cmd)
+{
+ return sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd);
+}
+
+int sym53c8xx_eh_bus_reset_handler(Scsi_Cmnd *cmd)
+{
+ return sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", cmd);
+}
+
+int sym53c8xx_eh_host_reset_handler(Scsi_Cmnd *cmd)
+{
+ return sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", cmd);
+}
+
+/*
+ * Tune device queuing depth, according to various limits.
+ */
+static void
+sym_tune_dev_queuing(hcb_p np, int target, int lun, u_short reqtags)


+{
+ tcb_p tp = &np->target[target];

+ lcb_p lp = sym_lp(np, tp, lun);

+ u_short oldtags;
+
+ if (!lp)
+ return;
+
+ oldtags = lp->s.reqtags;
+
+ if (reqtags > lp->s.scdev_depth)
+ reqtags = lp->s.scdev_depth;
+
+ lp->started_limit = reqtags ? reqtags : 2;
+ lp->started_max = 1;
+ lp->s.reqtags = reqtags;
+
+ if (reqtags != oldtags) {
+ printf_info("%s:%d:%d: "
+ "tagged command queuing %s, command queue depth %d.\n",
+ sym_name(np), target, lun,
+ lp->s.reqtags ? "enabled" : "disabled",
+ lp->started_limit);
+ }
+}
+
+#ifdef SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT
+/*
+ * Linux select queue depths function
+ */
+#define DEF_DEPTH (sym_driver_setup.max_tag)
+#define ALL_TARGETS -2
+#define NO_TARGET -1
+#define ALL_LUNS -2
+#define NO_LUN -1
+
+static int device_queue_depth(hcb_p np, int target, int lun)
+{
+ int c, h, t, u, v;
+ char *p = sym_driver_setup.tag_ctrl;
+ char *ep;
+
+ h = -1;
+ t = NO_TARGET;
+ u = NO_LUN;
+ while ((c = *p++) != 0) {
+ v = simple_strtoul(p, &ep, 0);
+ switch(c) {
+ case '/':
+ ++h;
+ t = ALL_TARGETS;
+ u = ALL_LUNS;
+ break;
+ case 't':
+ if (t != target)
+ t = (target == v) ? v : NO_TARGET;
+ u = ALL_LUNS;
+ break;
+ case 'u':
+ if (u != lun)
+ u = (lun == v) ? v : NO_LUN;
+ break;
+ case 'q':
+ if (h == np->s.unit &&
+ (t == ALL_TARGETS || t == target) &&
+ (u == ALL_LUNS || u == lun))
+ return v;
+ break;
+ case '-':
+ t = ALL_TARGETS;
+ u = ALL_LUNS;
+ break;
+ default:
+ break;
+ }
+ p = ep;
+ }
+ return DEF_DEPTH;
+}
+#else
+#define device_queue_depth(np, t, l) (sym_driver_setup.max_tag)
+#endif /* SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT */
+
+/*
+ * Linux entry point for device queue sizing.
+ */
+static void
+sym53c8xx_select_queue_depths(struct Scsi_Host *host,
+ struct scsi_device *devlist)
+{
+ struct scsi_device *device;
+
+ for (device = devlist; device; device = device->next) {
+ hcb_p np;


+ tcb_p tp;
+ lcb_p lp;

+ int reqtags;
+
+ if (device->host != host)
+ continue;
+
+ np = ((struct host_data *) host->hostdata)->ncb;
+ tp = &np->target[device->id];
+
+ /*
+ * Get user settings for transfer parameters.
+ */
+ tp->inq_byte7_valid = (INQ7_SYNC|INQ7_WIDE16);
+ sym_update_trans_settings(np, tp);
+
+ /*
+ * Allocate the LCB if not yet.
+ * If it fail, we may well be in the sh*t. :)
+ */
+ lp = sym_alloc_lcb(np, device->id, device->lun);
+ if (!lp) {
+ device->queue_depth = 1;
+ continue;
+ }
+
+ /*
+ * Get user flags.
+ */
+ lp->curr_flags = lp->user_flags;
+
+ /*
+ * Select queue depth from driver setup.
+ * Donnot use more than configured by user.
+ * Use at least 2.
+ * Donnot use more than our maximum.
+ */
+ reqtags = device_queue_depth(np, device->id, device->lun);
+ if (reqtags > tp->usrtags)
+ reqtags = tp->usrtags;
+ if (!device->tagged_supported)
+ reqtags = 0;
+#if 1 /* Avoid to locally queue commands for no good reasons */
+ if (reqtags > SYM_CONF_MAX_TAG)
+ reqtags = SYM_CONF_MAX_TAG;
+ device->queue_depth = reqtags ? reqtags : 2;
+#else
+ device->queue_depth = reqtags ? SYM_CONF_MAX_TAG : 2;
+#endif
+ lp->s.scdev_depth = device->queue_depth;
+ sym_tune_dev_queuing(np, device->id, device->lun, reqtags);
+ }
+}
+
+/*
+ * Linux entry point for info() function
+ */
+const char *sym53c8xx_info (struct Scsi_Host *host)
+{
+ return sym_driver_name();
+}
+
+
+#ifdef SYM_LINUX_PROC_INFO_SUPPORT
+/*
+ * Proc file system stuff
+ *
+ * A read operation returns adapter information.
+ * A write operation is a control command.
+ * The string is parsed in the driver code and the command is passed
+ * to the sym_usercmd() function.
+ */
+
+#ifdef SYM_LINUX_USER_COMMAND_SUPPORT
+
+struct sym_usrcmd {
+ u_long target;
+ u_long lun;
+ u_long data;
+ u_long cmd;
+};
+
+#define UC_SETSYNC 10
+#define UC_SETTAGS 11
+#define UC_SETDEBUG 12
+#define UC_SETWIDE 14
+#define UC_SETFLAG 15
+#define UC_SETVERBOSE 17
+#define UC_RESETDEV 18
+#define UC_CLEARDEV 19
+
+static void sym_exec_user_command (hcb_p np, struct sym_usrcmd *uc)
+{
+ tcb_p tp;
+ int t, l;
+
+ switch (uc->cmd) {
+ case 0: return;
+
+#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
+ case UC_SETDEBUG:
+ sym_debug_flags = uc->data;
+ break;
+#endif
+ case UC_SETVERBOSE:
+ np->verbose = uc->data;
+ break;
+ default:
+ /*
+ * We assume that other commands apply to targets.
+ * This should always be the case and avoid the below
+ * 4 lines to be repeated 6 times.
+ */
+ for (t = 0; t < SYM_CONF_MAX_TARGET; t++) {
+ if (!((uc->target >> t) & 1))
+ continue;
+ tp = &np->target[t];
+
+ switch (uc->cmd) {
+
+ case UC_SETSYNC:
+ if (!uc->data || uc->data >= 255) {


+ tp->tinfo.goal.options = 0;

+ tp->tinfo.goal.offset = 0;
+ break;
+ }
+ if (uc->data <= 9 && np->minsync_dt) {
+ if (uc->data < np->minsync_dt)
+ uc->data = np->minsync_dt;
+ tp->tinfo.goal.options = PPR_OPT_DT;
+ tp->tinfo.goal.width = 1;
+ tp->tinfo.goal.period = uc->data;
+ tp->tinfo.goal.offset = np->maxoffs_dt;
+ }
+ else {
+ if (uc->data < np->minsync)
+ uc->data = np->minsync;


+ tp->tinfo.goal.options = 0;

+ tp->tinfo.goal.period = uc->data;


+ tp->tinfo.goal.offset = np->maxoffs;

+ }
+ break;
+ case UC_SETWIDE:
+ tp->tinfo.goal.width = uc->data ? 1 : 0;
+ break;
+ case UC_SETTAGS:
+ for (l = 0; l < SYM_CONF_MAX_LUN; l++)
+ sym_tune_dev_queuing(np, t,l, uc->data);
+ break;
+ case UC_RESETDEV:
+ tp->to_reset = 1;
+ np->istat_sem = SEM;
+ OUTB (nc_istat, SIGP|SEM);
+ break;
+ case UC_CLEARDEV:
+ for (l = 0; l < SYM_CONF_MAX_LUN; l++) {
+ lcb_p lp = sym_lp(np, tp, l);
+ if (lp) lp->to_clear = 1;
+ }
+ np->istat_sem = SEM;
+ OUTB (nc_istat, SIGP|SEM);
+ break;
+ case UC_SETFLAG:
+ tp->usrflags = uc->data;
+ break;
+ }
+ }
+ break;
+ }
+}
+
+#define is_digit(c) ((c) >= '0' && (c) <= '9')
+#define digit_to_bin(c) ((c) - '0')
+#define is_space(c) ((c) == ' ' || (c) == '\t')
+
+static int skip_spaces(char *ptr, int len)
+{
+ int cnt, c;
+
+ for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt--);
+
+ return (len - cnt);
+}
+
+static int get_int_arg(char *ptr, int len, u_long *pv)
+{
+ int cnt, c;
+ u_long v;
+
+ for (v = 0, cnt = len; cnt > 0 && (c = *ptr++) && is_digit(c); cnt--) {
+ v = (v * 10) + digit_to_bin(c);
+ }
+
+ if (pv)
+ *pv = v;
+
+ return (len - cnt);
+}
+
+static int is_keyword(char *ptr, int len, char *verb)
+{
+ int verb_len = strlen(verb);
+
+ if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len))
+ return verb_len;
+ else


+ return 0;
+
+}
+

+#define SKIP_SPACES(min_spaces) \
+ if ((arg_len = skip_spaces(ptr, len)) < (min_spaces)) \
+ return -EINVAL; \
+ ptr += arg_len; len -= arg_len;
+
+#define GET_INT_ARG(v) \
+ if (!(arg_len = get_int_arg(ptr, len, &(v)))) \
+ return -EINVAL; \
+ ptr += arg_len; len -= arg_len;
+
+
+/*
+ * Parse a control command
+ */
+
+static int sym_user_command(hcb_p np, char *buffer, int length)
+{
+ char *ptr = buffer;
+ int len = length;
+ struct sym_usrcmd cmd, *uc = &cmd;
+ int arg_len;
+ u_long target;
+
+ bzero(uc, sizeof(*uc));
+
+ if (len > 0 && ptr[len-1] == '\n')
+ --len;
+
+ if ((arg_len = is_keyword(ptr, len, "setsync")) != 0)
+ uc->cmd = UC_SETSYNC;
+ else if ((arg_len = is_keyword(ptr, len, "settags")) != 0)
+ uc->cmd = UC_SETTAGS;
+ else if ((arg_len = is_keyword(ptr, len, "setverbose")) != 0)
+ uc->cmd = UC_SETVERBOSE;
+ else if ((arg_len = is_keyword(ptr, len, "setwide")) != 0)
+ uc->cmd = UC_SETWIDE;
+#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
+ else if ((arg_len = is_keyword(ptr, len, "setdebug")) != 0)
+ uc->cmd = UC_SETDEBUG;
+#endif
+ else if ((arg_len = is_keyword(ptr, len, "setflag")) != 0)
+ uc->cmd = UC_SETFLAG;
+ else if ((arg_len = is_keyword(ptr, len, "resetdev")) != 0)
+ uc->cmd = UC_RESETDEV;
+ else if ((arg_len = is_keyword(ptr, len, "cleardev")) != 0)
+ uc->cmd = UC_CLEARDEV;
+ else
+ arg_len = 0;
+
+#ifdef DEBUG_PROC_INFO
+printk("sym_user_command: arg_len=%d, cmd=%ld\n", arg_len, uc->cmd);
+#endif
+
+ if (!arg_len)
+ return -EINVAL;
+ ptr += arg_len; len -= arg_len;
+
+ switch(uc->cmd) {
+ case UC_SETSYNC:
+ case UC_SETTAGS:
+ case UC_SETWIDE:
+ case UC_SETFLAG:
+ case UC_RESETDEV:
+ case UC_CLEARDEV:
+ SKIP_SPACES(1);
+ if ((arg_len = is_keyword(ptr, len, "all")) != 0) {
+ ptr += arg_len; len -= arg_len;
+ uc->target = ~0;
+ } else {
+ GET_INT_ARG(target);
+ uc->target = (1<<target);
+#ifdef DEBUG_PROC_INFO
+printk("sym_user_command: target=%ld\n", target);
+#endif
+ }
+ break;
+ }
+
+ switch(uc->cmd) {
+ case UC_SETVERBOSE:
+ case UC_SETSYNC:
+ case UC_SETTAGS:
+ case UC_SETWIDE:
+ SKIP_SPACES(1);
+ GET_INT_ARG(uc->data);
+#ifdef DEBUG_PROC_INFO
+printk("sym_user_command: data=%ld\n", uc->data);
+#endif
+ break;
+#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
+ case UC_SETDEBUG:
+ while (len > 0) {
+ SKIP_SPACES(1);
+ if ((arg_len = is_keyword(ptr, len, "alloc")))
+ uc->data |= DEBUG_ALLOC;
+ else if ((arg_len = is_keyword(ptr, len, "phase")))
+ uc->data |= DEBUG_PHASE;
+ else if ((arg_len = is_keyword(ptr, len, "queue")))
+ uc->data |= DEBUG_QUEUE;
+ else if ((arg_len = is_keyword(ptr, len, "result")))
+ uc->data |= DEBUG_RESULT;
+ else if ((arg_len = is_keyword(ptr, len, "scatter")))
+ uc->data |= DEBUG_SCATTER;
+ else if ((arg_len = is_keyword(ptr, len, "script")))
+ uc->data |= DEBUG_SCRIPT;
+ else if ((arg_len = is_keyword(ptr, len, "tiny")))
+ uc->data |= DEBUG_TINY;
+ else if ((arg_len = is_keyword(ptr, len, "timing")))
+ uc->data |= DEBUG_TIMING;
+ else if ((arg_len = is_keyword(ptr, len, "nego")))
+ uc->data |= DEBUG_NEGO;
+ else if ((arg_len = is_keyword(ptr, len, "tags")))
+ uc->data |= DEBUG_TAGS;
+ else if ((arg_len = is_keyword(ptr, len, "pointer")))
+ uc->data |= DEBUG_POINTER;
+ else
+ return -EINVAL;
+ ptr += arg_len; len -= arg_len;
+ }
+#ifdef DEBUG_PROC_INFO
+printk("sym_user_command: data=%ld\n", uc->data);
+#endif
+ break;
+#endif /* SYM_LINUX_DEBUG_CONTROL_SUPPORT */
+ case UC_SETFLAG:
+ while (len > 0) {
+ SKIP_SPACES(1);
+ if ((arg_len = is_keyword(ptr, len, "no_disc")))
+ uc->data &= ~SYM_DISC_ENABLED;
+ else
+ return -EINVAL;
+ ptr += arg_len; len -= arg_len;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (len)
+ return -EINVAL;
+ else {
+ long flags;
+
+ SYM_LOCK_HCB(np, flags);
+ sym_exec_user_command (np, uc);
+ SYM_UNLOCK_HCB(np, flags);
+ }
+ return length;
+}
+
+#endif /* SYM_LINUX_USER_COMMAND_SUPPORT */
+
+
+#ifdef SYM_LINUX_USER_INFO_SUPPORT
+/*
+ * Informations through the proc file system.
+ */
+struct info_str {
+ char *buffer;
+ int length;
+ int offset;
+ int pos;
+};
+
+static void copy_mem_info(struct info_str *info, char *data, int len)
+{
+ if (info->pos + len > info->length)
+ len = info->length - info->pos;
+
+ if (info->pos + len < info->offset) {
+ info->pos += len;
+ return;
+ }
+ if (info->pos < info->offset) {
+ data += (info->offset - info->pos);
+ len -= (info->offset - info->pos);
+ }


+
+ if (len > 0) {

+ memcpy(info->buffer + info->pos, data, len);
+ info->pos += len;
+ }
+}
+
+static int copy_info(struct info_str *info, char *fmt, ...)
+{
+ va_list args;
+ char buf[81];
+ int len;
+
+ va_start(args, fmt);
+ len = vsprintf(buf, fmt, args);
+ va_end(args);
+
+ copy_mem_info(info, buf, len);
+ return len;
+}
+
+/*
+ * Copy formatted information into the input buffer.
+ */
+static int sym_host_info(hcb_p np, char *ptr, off_t offset, int len)
+{
+ struct info_str info;
+
+ info.buffer = ptr;
+ info.length = len;
+ info.offset = offset;
+ info.pos = 0;
+
+ copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "
+ "revision id 0x%x\n",
+ np->s.chip_name, np->device_id, np->revision_id);
+ copy_info(&info, "On PCI bus %d, device %d, function %d, "
+#ifdef __sparc__
+ "IRQ %s\n",
+#else
+ "IRQ %d\n",
+#endif
+ np->s.bus, (np->s.device_fn & 0xf8) >> 3, np->s.device_fn & 7,
+#ifdef __sparc__
+ __irq_itoa(np->s.irq));
+#else
+ (int) np->s.irq);
+#endif
+ copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n",
+ (int) (np->minsync_dt ? np->minsync_dt : np->minsync),
+ np->maxwide ? "Wide" : "Narrow",
+ np->minsync_dt ? ", DT capable" : "");
+
+ copy_info(&info, "Max. started commands %d, "
+ "max. commands per LUN %d\n",
+ SYM_CONF_MAX_START, SYM_CONF_MAX_TAG);
+
+ return info.pos > info.offset? info.pos - info.offset : 0;
+}
+#endif /* SYM_LINUX_USER_INFO_SUPPORT */
+
+/*
+ * Entry point of the scsi proc fs of the driver.
+ * - func = 0 means read (returns adapter infos)
+ * - func = 1 means write (not yet merget from sym53c8xx)
+ */
+static int sym53c8xx_proc_info(char *buffer, char **start, off_t offset,
+ int length, int hostno, int func)
+{
+ struct Scsi_Host *host;
+ struct host_data *host_data;
+ hcb_p np = 0;
+ int retv;
+
+ for (host = first_host; host; host = host->next) {
+ if (host->hostt != first_host->hostt)
+ continue;
+ if (host->host_no == hostno) {
+ host_data = (struct host_data *) host->hostdata;
+ np = host_data->ncb;


+ break;
+ }
+ }
+

+ if (!np)
+ return -EINVAL;
+
+ if (func) {
+#ifdef SYM_LINUX_USER_COMMAND_SUPPORT
+ retv = sym_user_command(np, buffer, length);
+#else
+ retv = -EINVAL;
+#endif
+ }
+ else {
+ if (start)
+ *start = buffer;
+#ifdef SYM_LINUX_USER_INFO_SUPPORT
+ retv = sym_host_info(np, buffer, offset, length);
+#else
+ retv = -EINVAL;
+#endif
+ }
+
+ return retv;
+}
+#endif /* SYM_LINUX_PROC_INFO_SUPPORT */
+
+/*
+ * Free controller resources.
+ */
+static void sym_free_resources(hcb_p np)
+{
+ /*
+ * Free O/S specific resources.
+ */
+ if (np->s.irq)
+ free_irq(np->s.irq, np);
+ if (np->s.io_port)
+ release_region(np->s.io_port, np->s.io_ws);
+#ifndef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ if (np->s.mmio_va)
+ pci_unmap_mem(np->s.mmio_va, np->s.io_ws);
+ if (np->s.ram_va)
+ pci_unmap_mem(np->s.ram_va, np->ram_ws);
+#endif
+ /*
+ * Free O/S independant resources.
+ */
+ sym_hcb_free(np);
+
+ sym_mfree_dma(np, sizeof(*np), "HCB");
+}
+
+/*
+ * Ask/tell the system about DMA addressing.
+ */
+#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING
+static int sym_setup_bus_dma_mask(hcb_p np)
+{
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,3)
+ if (!pci_dma_supported(np->s.device, 0xffffffffUL))
+ goto out_err32;
+#else
+#if SYM_CONF_DMA_ADDRESSING_MODE == 0
+ if (pci_set_dma_mask(np->s.device, 0xffffffffUL))
+ goto out_err32;
+#else
+#if SYM_CONF_DMA_ADDRESSING_MODE == 1
+#define PciDmaMask 0xffffffffff
+#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
+#define PciDmaMask 0xffffffffffffffff
+#endif
+ if (np->features & FE_DAC) {
+ if (!pci_set_dma_mask(np->s.device, PciDmaMask)) {
+ np->use_dac = 1;
+ printf_info("%s: using 64 bit DMA addressing\n",
+ sym_name(np));
+ }
+ else {
+ if (!pci_set_dma_mask(np->s.device, 0xffffffffUL))
+ goto out_err32;
+ }
+ }
+#undef PciDmaMask
+#endif


+#endif
+ return 0;
+

+out_err32:
+ printf_warning("%s: 32 BIT DMA ADDRESSING NOT SUPPORTED\n",
+ sym_name(np));
+ return -1;
+}
+#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */
+
+/*
+ * Host attach and initialisations.
+ *
+ * Allocate host data and ncb structure.
+ * Request IO region and remap MMIO region.
+ * Do chip initialization.
+ * If all is OK, install interrupt handling and
+ * start the timer daemon.
+ */
+static int __init
+sym_attach (Scsi_Host_Template *tpnt, int unit, sym_device *dev)
+{
+ struct host_data *host_data;
+ hcb_p np = 0;
+ struct Scsi_Host *instance = 0;
+ u_long flags = 0;
+ sym_nvram *nvram = dev->nvram;
+ struct sym_fw *fw;
+
+ printk(KERN_INFO
+ "sym%d: <%s> rev 0x%x on pci bus %d device %d function %d "
+#ifdef __sparc__
+ "irq %s\n",
+#else
+ "irq %d\n",
+#endif
+ unit, dev->chip.name, dev->chip.revision_id,
+ dev->s.bus, (dev->s.device_fn & 0xf8) >> 3,
+ dev->s.device_fn & 7,
+#ifdef __sparc__
+ __irq_itoa(dev->s.irq));
+#else
+ dev->s.irq);
+#endif
+
+ /*
+ * Get the firmware for this chip.
+ */
+ fw = sym_find_firmware(&dev->chip);
+ if (!fw)
+ goto attach_failed;
+
+ /*
+ * Allocate host_data structure
+ */
+ if (!(instance = scsi_register(tpnt, sizeof(*host_data))))
+ goto attach_failed;
+ host_data = (struct host_data *) instance->hostdata;
+
+ /*
+ * Allocate immediately the host control block,
+ * since we are only expecting to succeed. :)
+ * We keep track in the HCB of all the resources that
+ * are to be released on error.
+ */
+#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING
+ np = __sym_calloc_dma(dev->pdev, sizeof(*np), "HCB");
+ if (np) {
+ np->s.device = dev->pdev;
+ np->bus_dmat = dev->pdev; /* Result in 1 DMA pool per HBA */
+ }
+ else
+ goto attach_failed;
+#else
+ np = sym_calloc_dma(sizeof(*np), "HCB");
+ if (!np)
+ goto attach_failed;
+#endif
+ host_data->ncb = np;
+
+ SYM_INIT_LOCK_HCB(np);
+
+ /*
+ * Copy some useful infos to the HCB.
+ */
+ np->hcb_ba = vtobus(np);
+ np->verbose = sym_driver_setup.verbose;
+ np->s.device = dev->pdev;
+ np->s.unit = unit;
+ np->device_id = dev->chip.device_id;
+ np->revision_id = dev->chip.revision_id;
+ np->s.bus = dev->s.bus;
+ np->s.device_fn = dev->s.device_fn;
+ np->features = dev->chip.features;
+ np->clock_divn = dev->chip.nr_divisor;
+ np->maxoffs = dev->chip.offset_max;
+ np->maxburst = dev->chip.burst_max;
+ np->myaddr = dev->host_id;
+
+ /*
+ * Edit its name.
+ */
+ strncpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name)-1);
+ sprintf(np->s.inst_name, "sym%d", np->s.unit);
+
+ /*
+ * Ask/tell the system about DMA addressing.
+ */
+#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING
+ if (sym_setup_bus_dma_mask(np))
+ goto attach_failed;
+#endif
+
+ /*
+ * Try to map the controller chip to
+ * virtual and physical memory.
+ */
+ np->mmio_ba = (u32)dev->s.base;
+ np->s.io_ws = (np->features & FE_IO256)? 256 : 128;
+
+#ifndef SYM_CONF_IOMAPPED
+ np->s.mmio_va = pci_map_mem(dev->s.base_c, np->s.io_ws);
+ if (!np->s.mmio_va) {
+ printf_err("%s: can't map PCI MMIO region\n", sym_name(np));
+ goto attach_failed;
+ }
+ else if (sym_verbose > 1)
+ printf_info("%s: using memory mapped IO\n", sym_name(np));
+#endif /* !defined SYM_CONF_IOMAPPED */
+
+ /*
+ * Try to map the controller chip into iospace.
+ */
+ if (dev->s.io_port) {
+ request_region(dev->s.io_port, np->s.io_ws, NAME53C8XX);
+ np->s.io_port = dev->s.io_port;
+ }
+
+ /*
+ * Map on-chip RAM if present and supported.
+ */
+ if (!(np->features & FE_RAM))
+ dev->s.base_2 = 0;
+ if (dev->s.base_2) {
+ np->ram_ba = (u32)dev->s.base_2;
+ if (np->features & FE_RAM8K)
+ np->ram_ws = 8192;
+ else
+ np->ram_ws = 4096;
+#ifndef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ np->s.ram_va = pci_map_mem(dev->s.base_2_c, np->ram_ws);
+ if (!np->s.ram_va) {
+ printf_err("%s: can't map PCI MEMORY region\n",
+ sym_name(np));
+ goto attach_failed;
+ }


+#endif
+ }
+
+ /*

+ * Perform O/S independant stuff.
+ */
+ if (sym_hcb_attach(np, fw, nvram))
+ goto attach_failed;
+
+
+ /*
+ * Install the interrupt handler.
+ * If we synchonize the C code with SCRIPTS on interrupt,
+ * we donnot want to share the INTR line at all.
+ */
+ if (request_irq(dev->s.irq, sym53c8xx_intr, SA_SHIRQ,
+ NAME53C8XX, np)) {
+ printf_err("%s: request irq %d failure\n",
+ sym_name(np), dev->s.irq);
+ goto attach_failed;
+ }
+ np->s.irq = dev->s.irq;
+
+ /*
+ * After SCSI devices have been opened, we cannot
+ * reset the bus safely, so we do it here.
+ */
+ SYM_LOCK_HCB(np, flags);
+ if (sym_reset_scsi_bus(np, 0)) {
+ printf_err("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, "
+ "TERMINATION, DEVICE POWER etc.!\n", sym_name(np));
+ SYM_UNLOCK_HCB(np, flags);
+ goto attach_failed;
+ }
+
+ /*
+ * Initialize some queue headers.
+ */
+ sym_que_init(&np->s.wait_cmdq);
+ sym_que_init(&np->s.busy_cmdq);
+
+ /*
+ * Start the SCRIPTS.
+ */
+ sym_start_up (np, 1);
+
+ /*
+ * Start the timer daemon
+ */
+ init_timer(&np->s.timer);
+ np->s.timer.data = (unsigned long) np;
+ np->s.timer.function = sym53c8xx_timer;
+ np->s.lasttime=0;
+ sym_timer (np);
+
+ /*
+ * Done.
+ */
+ if (!first_host)
+ first_host = instance;
+
+ /*
+ * Fill Linux host instance structure
+ * and return success.
+ */
+ instance->max_channel = 0;
+ instance->this_id = np->myaddr;
+ instance->max_id = np->maxwide ? 16 : 8;
+ instance->max_lun = SYM_CONF_MAX_LUN;
+#ifndef SYM_CONF_IOMAPPED
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,29)
+ instance->base = (unsigned long) np->s.mmio_va;
+#else
+ instance->base = (char *) np->s.mmio_va;
+#endif
+#endif
+ instance->irq = np->s.irq;
+ instance->unique_id = np->s.io_port;
+ instance->io_port = np->s.io_port;
+ instance->n_io_port = np->s.io_ws;
+ instance->dma_channel = 0;
+ instance->cmd_per_lun = SYM_CONF_MAX_TAG;
+ instance->can_queue = (SYM_CONF_MAX_START-2);
+ instance->sg_tablesize = SYM_CONF_MAX_SG;
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
+ instance->max_cmd_len = 16;
+#endif
+ instance->select_queue_depths = sym53c8xx_select_queue_depths;
+
+ SYM_UNLOCK_HCB(np, flags);
+
+ scsi_set_pci_device(instance, dev->pdev);
+
+ /*
+ * Now let the generic SCSI driver
+ * look for the SCSI devices on the bus ..
+ */
+ return 0;
+
+attach_failed:
+ if (!instance) return -1;
+ printf_info("%s: giving up ...\n", sym_name(np));
+ if (np)
+ sym_free_resources(np);
+ scsi_unregister(instance);


+
+ return -1;
+ }
+
+

+/*
+ * Detect and try to read SYMBIOS and TEKRAM NVRAM.
+ */
+#if SYM_CONF_NVRAM_SUPPORT
+static void __init sym_get_nvram(sym_device *devp, sym_nvram *nvp)
+{
+ if (!nvp)
+ return;
+
+ devp->nvram = nvp;
+ devp->device_id = devp->chip.device_id;
+ nvp->type = 0;
+
+ /*
+ * Get access to chip IO registers
+ */
+#ifdef SYM_CONF_IOMAPPED
+ request_region(devp->s.io_port, 128, NAME53C8XX);
+#else
+ devp->s.mmio_va = pci_map_mem(devp->s.base_c, 128);
+ if (!devp->s.mmio_va)
+ return;
+#endif
+
+ /*
+ * Try to read SYMBIOS|TEKRAM nvram.
+ */
+ (void) sym_read_nvram(devp, nvp);
+
+ /*
+ * Release access to chip IO registers
+ */
+#ifdef SYM_CONF_IOMAPPED
+ release_region(devp->s.io_port, 128);
+#else
+ pci_unmap_mem((u_long) devp->s.mmio_va, 128ul);
+#endif
+}
+#endif /* SYM_CONF_NVRAM_SUPPORT */
+
+/*
+ * Driver setup from the boot command line
+ */
+#ifdef SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT
+
+static struct sym_driver_setup
+ sym_driver_safe_setup __initdata = SYM_LINUX_DRIVER_SAFE_SETUP;
+#ifdef MODULE
+char *sym53c8xx = 0; /* command line passed by insmod */
+MODULE_PARM(sym53c8xx, "s");
+#endif
+
+static void __init sym53c8xx_print_driver_setup(void)
+{
+ printf_info (NAME53C8XX ": setup="
+ "mpar:%d,spar:%d,tags:%d,sync:%d,burst:%d,"
+ "led:%d,wide:%d,diff:%d,irqm:%d, buschk:%d\n",
+ sym_driver_setup.pci_parity,
+ sym_driver_setup.scsi_parity,
+ sym_driver_setup.max_tag,
+ sym_driver_setup.min_sync,
+ sym_driver_setup.burst_order,
+ sym_driver_setup.scsi_led,
+ sym_driver_setup.max_wide,
+ sym_driver_setup.scsi_diff,
+ sym_driver_setup.irq_mode,
+ sym_driver_setup.scsi_bus_check);
+ printf_info (NAME53C8XX ": setup="
+ "hostid:%d,offs:%d,luns:%d,pcifix:%d,revprob:%d,"
+ "verb:%d,debug:0x%x,setlle_delay:%d\n",
+ sym_driver_setup.host_id,
+ sym_driver_setup.max_offs,
+ sym_driver_setup.max_lun,
+ sym_driver_setup.pci_fix_up,
+ sym_driver_setup.reverse_probe,
+ sym_driver_setup.verbose,
+ sym_driver_setup.debug,
+ sym_driver_setup.settle_delay);
+#ifdef DEBUG_2_0_X
+MDELAY(5000);
+#endif
+};
+
+#define OPT_PCI_PARITY 1
+#define OPT_SCSI_PARITY 2
+#define OPT_MAX_TAG 3
+#define OPT_MIN_SYNC 4
+#define OPT_BURST_ORDER 5
+#define OPT_SCSI_LED 6
+#define OPT_MAX_WIDE 7
+#define OPT_SCSI_DIFF 8
+#define OPT_IRQ_MODE 9
+#define OPT_SCSI_BUS_CHECK 10
+#define OPT_HOST_ID 11
+#define OPT_MAX_OFFS 12
+#define OPT_MAX_LUN 13
+#define OPT_PCI_FIX_UP 14
+
+#define OPT_REVERSE_PROBE 15
+#define OPT_VERBOSE 16
+#define OPT_DEBUG 17
+#define OPT_SETTLE_DELAY 18
+#define OPT_USE_NVRAM 19
+#define OPT_EXCLUDE 20
+#define OPT_SAFE_SETUP 21
+
+static char setup_token[] __initdata =
+ "mpar:" "spar:"
+ "tags:" "sync:"
+ "burst:" "led:"
+ "wide:" "diff:"
+ "irqm:" "buschk:"
+ "hostid:" "offset:"
+ "luns:" "pcifix:"
+ "revprob:" "verb:"
+ "debug:" "settle:"
+ "nvram:" "excl:"
+ "safe:"
+ ;
+
+#ifdef MODULE
+#define ARG_SEP ' '
+#else
+#define ARG_SEP ','
+#endif
+
+static int __init get_setup_token(char *p)
+{
+ char *cur = setup_token;
+ char *pc;


+ int i = 0;
+

+ while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
+ ++pc;
+ ++i;
+ if (!strncmp(p, cur, pc - cur))
+ return i;
+ cur = pc;


+ }
+ return 0;
+}

+#endif /* SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT */
+
+int __init sym53c8xx_setup(char *str)
+{
+#ifdef SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT
+ char *cur = str;
+ char *pc, *pv;
+ unsigned long val;
+ int i, c;
+ int xi = 0;
+
+ while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
+ char *pe;
+
+ val = 0;
+ pv = pc;
+ c = *++pv;
+
+ if (c == 'n')
+ val = 0;
+ else if (c == 'y')
+ val = 1;
+ else
+ val = (int) simple_strtoul(pv, &pe, 0);
+
+ switch (get_setup_token(cur)) {
+ case OPT_MAX_TAG:
+ sym_driver_setup.max_tag = val;
+ if (!(pe && *pe == '/'))
+ break;
+ i = 0;
+ while (*pe && *pe != ARG_SEP &&
+ i < sizeof(sym_driver_setup.tag_ctrl)-1) {
+ sym_driver_setup.tag_ctrl[i++] = *pe++;
+ }
+ sym_driver_setup.tag_ctrl[i] = '\0';
+ break;
+ case OPT_SAFE_SETUP:
+ memcpy(&sym_driver_setup, &sym_driver_safe_setup,
+ sizeof(sym_driver_setup));
+ break;
+ case OPT_EXCLUDE:
+ if (xi < 8)
+ sym_driver_setup.excludes[xi++] = val;
+ break;
+
+#define __SIMPLE_OPTION(NAME, name) \
+ case OPT_ ## NAME : \
+ sym_driver_setup.name = val;\
+ break;
+
+ __SIMPLE_OPTION(PCI_PARITY, pci_parity)
+ __SIMPLE_OPTION(SCSI_PARITY, scsi_parity)
+ __SIMPLE_OPTION(MIN_SYNC, min_sync)
+ __SIMPLE_OPTION(BURST_ORDER, burst_order)
+ __SIMPLE_OPTION(SCSI_LED, scsi_led)
+ __SIMPLE_OPTION(MAX_WIDE, max_wide)
+ __SIMPLE_OPTION(SCSI_DIFF, scsi_diff)
+ __SIMPLE_OPTION(IRQ_MODE, irq_mode)
+ __SIMPLE_OPTION(SCSI_BUS_CHECK, scsi_bus_check)
+ __SIMPLE_OPTION(HOST_ID, host_id)
+ __SIMPLE_OPTION(MAX_OFFS, max_offs)
+ __SIMPLE_OPTION(MAX_LUN, max_lun)
+ __SIMPLE_OPTION(PCI_FIX_UP, pci_fix_up)
+ __SIMPLE_OPTION(REVERSE_PROBE, reverse_probe)
+ __SIMPLE_OPTION(VERBOSE, verbose)
+ __SIMPLE_OPTION(DEBUG, debug)
+ __SIMPLE_OPTION(SETTLE_DELAY, settle_delay)
+ __SIMPLE_OPTION(USE_NVRAM, use_nvram)
+
+#undef __SIMPLE_OPTION
+
+ default:
+ printk("sym53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
+ break;
+ }
+
+ if ((cur = strchr(cur, ARG_SEP)) != NULL)
+ ++cur;
+ }
+#endif /* SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT */


+ return 1;
+}
+

+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,13)
+#ifndef MODULE
+__setup("sym53c8xx=", sym53c8xx_setup);
+#endif
+#endif
+
+#ifdef SYM_CONF_PQS_PDS_SUPPORT
+/*
+ * Detect all NCR PQS/PDS boards and keep track of their bus nr.
+ *
+ * The NCR PQS or PDS card is constructed as a DEC bridge
+ * behind which sit a proprietary NCR memory controller and
+ * four or two 53c875s as separate devices. In its usual mode
+ * of operation, the 875s are slaved to the memory controller
+ * for all transfers. We can tell if an 875 is part of a
+ * PQS/PDS or not since if it is, it will be on the same bus
+ * as the memory controller. To operate with the Linux
+ * driver, the memory controller is disabled and the 875s
+ * freed to function independently. The only wrinkle is that
+ * the preset SCSI ID (which may be zero) must be read in from
+ * a special configuration space register of the 875
+ */
+#ifndef SYM_CONF_MAX_PQS_BUS
+#define SYM_CONF_MAX_PQS_BUS 16
+#endif
+static int pqs_bus[SYM_CONF_MAX_PQS_BUS] __initdata = { 0 };
+
+static void __init sym_detect_pqs_pds(void)
+{
+ short index;
+ pcidev_t dev = PCIDEV_NULL;
+
+ for(index=0; index < SYM_CONF_MAX_PQS_BUS; index++) {
+ u_char tmp;
+
+ dev = pci_find_device(0x101a, 0x0009, dev);
+ if (dev == PCIDEV_NULL) {
+ pqs_bus[index] = -1;
+ break;
+ }
+ printf_info(NAME53C8XX ": NCR PQS/PDS memory controller detected on bus %d\n", PciBusNumber(dev));


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

echo 'End of part 063'
echo 'File patch-2.4.15 is continued in part 064'
echo "064" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:29 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part053

#!/bin/sh -x
# this is part 053 of a 115 - part archive


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

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

-
X /*
X Theory of Operation
X
@@ -63,7 +59,7 @@
X
X V. References
X
-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+http://www.scyld.com/expert/NWay.html
X http://www.national.com/pf/DP/DP83840.html
X
X Thanks to Terry Murphy of 3Com for providing development information for
@@ -100,24 +96,43 @@
X #include <pcmcia/ds.h>
X #include <pcmcia/mem_op.h>
X
-/* A few values that may be tweaked. */


-MODULE_PARM(irq_mask, "i");
-MODULE_PARM(irq_list, "1-4i");

-MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(full_duplex, "i");


+/*====================================================================*/
+
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dah...@users.sourceforge.net>");

+MODULE_DESCRIPTION("3Com 3c574 series PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");


+
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")

X
X /* Now-standard PC card module parameters. */
-static u_int irq_mask = 0xdeb8; /* IRQ3,4,5,7,9,10,11,12,14,15 */


+INT_MODULE_PARM(irq_mask, 0xdeb8);
X static int irq_list[4] = { -1 };
-

-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT ((800*HZ)/1000)
+MODULE_PARM(irq_list, "1-4i");
X
X /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 32;
+INT_MODULE_PARM(max_interrupt_work, 32);
X
X /* Force full duplex modes? */
-static int full_duplex;
+INT_MODULE_PARM(full_duplex, 0);
+
+/* Autodetect link polarity reversal? */
+INT_MODULE_PARM(auto_polarity, 1);


+
+#ifdef PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);

+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version =
+"3c574_cs.c 1.65 2001/10/13 00:08:50 Donald Becker/David Hinds, bec...@scyld.com.\n";


+#else
+#define DEBUG(n, args...)
+#endif
+
+/*====================================================================*/

+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT ((800*HZ)/1000)
X
X /* To minimize the size of the driver source and make the driver more
X readable not all constants are symbolically defined.
@@ -197,7 +212,7 @@
X dev_node_t node;
X struct net_device_stats stats;
X u16 advertising, partner; /* NWay media advertisement */
- unsigned char phys[2]; /* MII device addresses. */
+ unsigned char phys; /* MII device address */
X unsigned int
X autoselect:1, default_media:3; /* Read from the EEPROM/Wn3_Config. */
X /* for transceiver monitoring */
@@ -210,17 +225,7 @@
X /* Set iff a MII transceiver on any interface requires mdio preamble.
X This only set with the original DP83840 on older 3c905 boards, so the extra
X code size of a per-interface flag is not worthwhile. */
-static char mii_preamble_required;


-
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version =

-"3c574_cs.c 1.000 1998/1/8 Donald Becker, bec...@scyld.com.\n";


-#else
-#define DEBUG(n, args...)
-#endif

+static char mii_preamble_required = 0;
X
X /* Index of functions. */
X
@@ -509,7 +514,7 @@
X }
X
X {
- int phy, phy_idx = 0;
+ int phy;
X
X /* Roadrunner only: Turn on the MII transceiver */
X outw(0x8040, ioaddr + Wn3_Options);
@@ -521,29 +526,30 @@
X outw(0x8040, ioaddr + Wn3_Options);
X
X EL3WINDOW(4);
- for (phy = 1; phy <= 32 && phy_idx < sizeof(lp->phys); phy++) {
+ for (phy = 1; phy <= 32; phy++) {
X int mii_status;
X mdio_sync(ioaddr, 32);
X mii_status = mdio_read(ioaddr, phy & 0x1f, 1);
X if (mii_status != 0xffff) {
- lp->phys[phy_idx++] = phy & 0x1f;
+ lp->phys = phy & 0x1f;
X DEBUG(0, " MII transceiver at index %d, status %x.\n",
X phy, mii_status);
X if ((mii_status & 0x0040) == 0)
X mii_preamble_required = 1;
+ break;
X }
X }
- if (phy_idx == 0) {
+ if (phy > 32) {
X printk(KERN_NOTICE " No MII transceivers found!\n");
X goto failed;
X }
- i = mdio_read(ioaddr, lp->phys[0], 16) | 0x40;
- mdio_write(ioaddr, lp->phys[0], 16, i);
- lp->advertising = mdio_read(ioaddr, lp->phys[0], 4);
+ i = mdio_read(ioaddr, lp->phys, 16) | 0x40;
+ mdio_write(ioaddr, lp->phys, 16, i);
+ lp->advertising = mdio_read(ioaddr, lp->phys, 4);
X if (full_duplex) {
X /* Only advertise the FD media types. */
X lp->advertising &= ~0x02a0;
- mdio_write(ioaddr, lp->phys[0], 4, lp->advertising);
+ mdio_write(ioaddr, lp->phys, 4, lp->advertising);
X }
X }
X
@@ -807,7 +813,12 @@
X outw(0x0040, ioaddr + Wn4_NetDiag);
X /* .. re-sync MII and re-fill what NWay is advertising. */
X mdio_sync(ioaddr, 32);
- mdio_write(ioaddr, lp->phys[0], 4, lp->advertising);
+ mdio_write(ioaddr, lp->phys, 4, lp->advertising);
+ if (!auto_polarity) {
+ /* works for TDK 78Q2120 series MII's */
+ int i = mdio_read(ioaddr, lp->phys, 16) | 0x20;
+ mdio_write(ioaddr, lp->phys, 16, i);
+ }
X
X /* Switch to register set 1 for normal use, just for TxFree. */
X EL3WINDOW(1);
@@ -1032,8 +1043,8 @@
X save_flags(flags);
X cli();
X EL3WINDOW(4);
- media = mdio_read(ioaddr, lp->phys[0], 1);
- partner = mdio_read(ioaddr, lp->phys[0], 5);
+ media = mdio_read(ioaddr, lp->phys, 1);
+ partner = mdio_read(ioaddr, lp->phys, 5);
X EL3WINDOW(1);
X restore_flags(flags);
X
@@ -1122,7 +1133,6 @@
X /* BadSSD */ inb(ioaddr + 12);
X up = inb(ioaddr + 13);
X
- lp->stats.rx_bytes += rx + ((up & 0x0f) << 16);
X lp->stats.tx_bytes += tx + ((up & 0xf0) << 12);
X
X EL3WINDOW(1);
@@ -1160,10 +1170,8 @@
X if (skb != NULL) {


X skb->dev = dev;
X skb_reserve(skb, 2);

-
X insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len),
X ((pkt_len+3)>>2));
-


X skb->protocol = eth_type_trans(skb, dev);

X netif_rx(skb);
X dev->last_rx = jiffies;

@@ -1187,7 +1195,7 @@
X struct el3_private *lp = (struct el3_private *)dev->priv;
X ioaddr_t ioaddr = dev->base_addr;


X u16 *data = (u16 *)&rq->ifr_data;

- int phy = lp->phys[0] & 0x1f;
+ int phy = lp->phys & 0x1f;
X
X DEBUG(2, "%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n",
X dev->name, rq->ifr_ifrn.ifrn_name, cmd,
@@ -1289,8 +1297,6 @@
X {
X servinfo_t serv;
X
- /* Always emit the version, before any failure. */
- printk(KERN_INFO"%s", tc574_version);
X DEBUG(0, "%s\n", version);
X CardServices(GetCardServicesInfo, &serv);
X if (serv.Revision != CS_RELEASE_CODE) {
@@ -1312,7 +1318,6 @@
X
X module_init(init_3c574_cs);
X module_exit(exit_3c574_cs);
-MODULE_LICENSE("GPL");
X
X /*
X * Local variables:
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/3c589_cs.c linux/drivers/net/pcmcia/3c589_cs.c
--- v2.4.14/linux/drivers/net/pcmcia/3c589_cs.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/net/pcmcia/3c589_cs.c Tue Nov 13 09:02:30 2001
@@ -4,7 +4,7 @@


X
X Copyright (C) 1999 David A. Hinds -- dah...@users.sourceforge.net
X

- 3c589_cs.c 1.156 2001/02/07 00:19:41
+ 3c589_cs.c 1.162 2001/10/13 00:08:50
X
X The network driver code is based on Donald Becker's 3c589 code:
X
@@ -112,31 +112,33 @@
X
X static char *if_names[] = { "auto", "10baseT", "10base2", "AUI" };
X

-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version =

-"3c589_cs.c 1.156 2001/02/07 00:19:41 (David Hinds)";
-#else
-#define DEBUG(n, args...)
-#endif
-
X /*====================================================================*/
X

-/* Parameters that can be set with 'insmod' */

+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dah...@users.sourceforge.net>");

+MODULE_DESCRIPTION("3Com 3c589 series PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");


+
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")

X
X /* Special hook for setting if_port when module is loaded */


-static int if_port;
+INT_MODULE_PARM(if_port, 0);
X

X /* Bit map of interrupts to choose from */


-static u_int irq_mask = 0xdeb8;

+INT_MODULE_PARM(irq_mask, 0xdeb8);
X static int irq_list[4] = { -1 };
-
-MODULE_PARM(if_port, "i");
-MODULE_PARM(irq_mask, "i");
X MODULE_PARM(irq_list, "1-4i");

X
+#ifdef PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);

+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version =
+"3c589_cs.c 1.162 2001/10/13 00:08:50 (David Hinds)";
+#else
+#define DEBUG(n, args...)


+#endif
+
X /*====================================================================*/
X

X static void tc589_config(dev_link_t *link);
@@ -986,12 +988,10 @@
X pkt_len, rx_status);
X if (skb != NULL) {


X skb->dev = dev;

-
X skb_reserve(skb, 2);
X insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len),
X (pkt_len+3)>>2);


X skb->protocol = eth_type_trans(skb, dev);

-

X netif_rx(skb);
X dev->last_rx = jiffies;
X lp->stats.rx_packets++;

@@ -1097,4 +1097,3 @@
X
X module_init(init_3c589_cs);
X module_exit(exit_3c589_cs);
-MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/Config.in linux/drivers/net/pcmcia/Config.in
--- v2.4.14/linux/drivers/net/pcmcia/Config.in Sun Sep 23 11:40:58 2001
+++ linux/drivers/net/pcmcia/Config.in Mon Nov 12 09:35:43 2001
@@ -14,6 +14,7 @@
X dep_tristate ' New Media PCMCIA support' CONFIG_PCMCIA_NMCLAN $CONFIG_PCMCIA
X dep_tristate ' SMC 91Cxx PCMCIA support' CONFIG_PCMCIA_SMC91C92 $CONFIG_PCMCIA
X dep_tristate ' Xircom 16-bit PCMCIA support' CONFIG_PCMCIA_XIRC2PS $CONFIG_PCMCIA
+ dep_tristate ' broken NS8390-cards support' CONFIG_PCMCIA_AXNET $CONFIG_PCMCIA
X dep_tristate ' COM20020 ARCnet PCMCIA support' CONFIG_ARCNET_COM20020_CS $CONFIG_ARCNET_COM20020 $CONFIG_ARCNET $CONFIG_PCMCIA
X if [ "$CONFIG_IBMTR" != "y" ]; then
X dep_tristate ' IBM PCMCIA tokenring adapter support' CONFIG_PCMCIA_IBMTR $CONFIG_TR $CONFIG_PCMCIA
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/Makefile linux/drivers/net/pcmcia/Makefile
--- v2.4.14/linux/drivers/net/pcmcia/Makefile Sun Sep 23 11:40:58 2001
+++ linux/drivers/net/pcmcia/Makefile Mon Nov 12 09:35:43 2001
@@ -23,6 +23,7 @@
X obj-$(CONFIG_PCMCIA_SMC91C92) += smc91c92_cs.o
X obj-$(CONFIG_PCMCIA_XIRC2PS) += xirc2ps_cs.o
X obj-$(CONFIG_ARCNET_COM20020_CS)+= com20020_cs.o
+obj-$(CONFIG_PCMCIA_AXNET) += axnet_cs.o
X
X # 16-bit wireless client drivers
X obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/ax8390.h linux/drivers/net/pcmcia/ax8390.h
--- v2.4.14/linux/drivers/net/pcmcia/ax8390.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/pcmcia/ax8390.h Mon Nov 12 09:35:43 2001
@@ -0,0 +1,193 @@
+/* Generic NS8390 register definitions. */
+/* This file is part of Donald Becker's 8390 drivers, and is distributed
+ under the same license. Auto-loading of 8390.o only in v2.2 - Paul G.
+ Some of these names and comments originated from the Crynwr
+ packet drivers, which are distributed under the GPL. */
+
+#ifndef _8390_h
+#define _8390_h
+
+#include <linux/config.h>
+#include <linux/if_ether.h>
+#include <linux/ioport.h>
+#include <linux/skbuff.h>
+
+#define TX_2X_PAGES 12
+#define TX_1X_PAGES 6
+
+/* Should always use two Tx slots to get back-to-back transmits. */
+#define EI_PINGPONG
+
+#ifdef EI_PINGPONG
+#define TX_PAGES TX_2X_PAGES
+#else
+#define TX_PAGES TX_1X_PAGES
+#endif
+
+#define ETHER_ADDR_LEN 6
+
+/* The 8390 specific per-packet-header format. */
+struct e8390_pkt_hdr {
+ unsigned char status; /* status */
+ unsigned char next; /* pointer to next packet. */
+ unsigned short count; /* header + packet length in bytes */
+};
+
+#ifdef notdef
+extern int ei_debug;
+#else
+#define ei_debug 1
+#endif
+
+#ifndef HAVE_AUTOIRQ
+/* From auto_irq.c */
+extern void autoirq_setup(int waittime);
+extern unsigned long autoirq_report(int waittime);
+#endif
+
+static int ethdev_init(struct net_device *dev);
+static void NS8390_init(struct net_device *dev, int startp);
+static int ei_open(struct net_device *dev);
+static int ei_close(struct net_device *dev);
+static void ei_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+/* Most of these entries should be in 'struct net_device' (or most of the
+ things in there should be here!) */
+/* You have one of these per-board */
+struct ei_device {
+ const char *name;
+ void (*reset_8390)(struct net_device *);
+ void (*get_8390_hdr)(struct net_device *, struct e8390_pkt_hdr *, int);
+ void (*block_output)(struct net_device *, int, const unsigned char *, int);
+ void (*block_input)(struct net_device *, int, struct sk_buff *, int);
+ unsigned char mcfilter[8];
+ unsigned open:1;
+ unsigned word16:1; /* We have the 16-bit (vs 8-bit) version of the card. */
+ unsigned txing:1; /* Transmit Active */
+ unsigned irqlock:1; /* 8390's intrs disabled when '1'. */
+ unsigned dmaing:1; /* Remote DMA Active */
+ unsigned char tx_start_page, rx_start_page, stop_page;
+ unsigned char current_page; /* Read pointer in buffer */
+ unsigned char interface_num; /* Net port (AUI, 10bT.) to use. */
+ unsigned char txqueue; /* Tx Packet buffer queue length. */
+ short tx1, tx2; /* Packet lengths for ping-pong tx. */
+ short lasttx; /* Alpha version consistency check. */
+ unsigned char reg0; /* Register '0' in a WD8013 */
+ unsigned char reg5; /* Register '5' in a WD8013 */
+ unsigned char saved_irq; /* Original dev->irq value. */
+ struct net_device_stats stat; /* The new statistics table. */
+ u32 *reg_offset; /* Register mapping table */
+ spinlock_t page_lock; /* Page register locks */
+ unsigned long priv; /* Private field to store bus IDs etc. */
+};
+
+/* The maximum number of 8390 interrupt service routines called per IRQ. */
+#define MAX_SERVICE 12
+
+/* The maximum time waited (in jiffies) before assuming a Tx failed. (20ms) */
+#define TX_TIMEOUT (20*HZ/100)
+
+#define ei_status (*(struct ei_device *)(dev->priv))
+
+/* Some generic ethernet register configurations. */
+#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */
+#define E8390_RX_IRQ_MASK 0x5
+#define E8390_RXCONFIG 0x44 /* EN0_RXCR: broadcasts, no multicast,errors */
+#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */
+#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */
+#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */
+
+/* Register accessed at EN_CMD, the 8390 base addr. */
+#define E8390_STOP 0x01 /* Stop and reset the chip */
+#define E8390_START 0x02 /* Start the chip, clear reset */
+#define E8390_TRANS 0x04 /* Transmit a frame */
+#define E8390_RREAD 0x08 /* Remote read */
+#define E8390_RWRITE 0x10 /* Remote write */
+#define E8390_NODMA 0x20 /* Remote DMA */
+#define E8390_PAGE0 0x00 /* Select page chip registers */
+#define E8390_PAGE1 0x40 /* using the two high-order bits */
+#define E8390_PAGE2 0x80 /* Page 3 is invalid. */
+
+/*
+ * Only generate indirect loads given a machine that needs them.
+ */
+
+#if defined(CONFIG_MAC) || defined(CONFIG_AMIGA_PCMCIA) || \
+ defined(CONFIG_ARIADNE2) || defined(CONFIG_ARIADNE2_MODULE) || \
+ defined(CONFIG_HYDRA) || defined(CONFIG_HYDRA_MODULE)
+#define EI_SHIFT(x) (ei_local->reg_offset[x])
+#else
+#define EI_SHIFT(x) (x)
+#endif
+
+#define E8390_CMD EI_SHIFT(0x00) /* The command register (for all pages) */
+/* Page 0 register offsets. */
+#define EN0_CLDALO EI_SHIFT(0x01) /* Low byte of current local dma addr RD */
+#define EN0_STARTPG EI_SHIFT(0x01) /* Starting page of ring bfr WR */
+#define EN0_CLDAHI EI_SHIFT(0x02) /* High byte of current local dma addr RD */
+#define EN0_STOPPG EI_SHIFT(0x02) /* Ending page +1 of ring bfr WR */
+#define EN0_BOUNDARY EI_SHIFT(0x03) /* Boundary page of ring bfr RD WR */
+#define EN0_TSR EI_SHIFT(0x04) /* Transmit status reg RD */
+#define EN0_TPSR EI_SHIFT(0x04) /* Transmit starting page WR */
+#define EN0_NCR EI_SHIFT(0x05) /* Number of collision reg RD */
+#define EN0_TCNTLO EI_SHIFT(0x05) /* Low byte of tx byte count WR */
+#define EN0_FIFO EI_SHIFT(0x06) /* FIFO RD */
+#define EN0_TCNTHI EI_SHIFT(0x06) /* High byte of tx byte count WR */
+#define EN0_ISR EI_SHIFT(0x07) /* Interrupt status reg RD WR */
+#define EN0_CRDALO EI_SHIFT(0x08) /* low byte of current remote dma address RD */
+#define EN0_RSARLO EI_SHIFT(0x08) /* Remote start address reg 0 */
+#define EN0_CRDAHI EI_SHIFT(0x09) /* high byte, current remote dma address RD */
+#define EN0_RSARHI EI_SHIFT(0x09) /* Remote start address reg 1 */
+#define EN0_RCNTLO EI_SHIFT(0x0a) /* Remote byte count reg WR */
+#define EN0_RCNTHI EI_SHIFT(0x0b) /* Remote byte count reg WR */
+#define EN0_RSR EI_SHIFT(0x0c) /* rx status reg RD */
+#define EN0_RXCR EI_SHIFT(0x0c) /* RX configuration reg WR */
+#define EN0_TXCR EI_SHIFT(0x0d) /* TX configuration reg WR */
+#define EN0_COUNTER0 EI_SHIFT(0x0d) /* Rcv alignment error counter RD */
+#define EN0_DCFG EI_SHIFT(0x0e) /* Data configuration reg WR */
+#define EN0_COUNTER1 EI_SHIFT(0x0e) /* Rcv CRC error counter RD */
+#define EN0_IMR EI_SHIFT(0x0f) /* Interrupt mask reg WR */
+#define EN0_COUNTER2 EI_SHIFT(0x0f) /* Rcv missed frame error counter RD */
+
+/* Bits in EN0_ISR - Interrupt status register */
+#define ENISR_RX 0x01 /* Receiver, no error */
+#define ENISR_TX 0x02 /* Transmitter, no error */
+#define ENISR_RX_ERR 0x04 /* Receiver, with error */
+#define ENISR_TX_ERR 0x08 /* Transmitter, with error */
+#define ENISR_OVER 0x10 /* Receiver overwrote the ring */
+#define ENISR_COUNTERS 0x20 /* Counters need emptying */
+#define ENISR_RDC 0x40 /* remote dma complete */
+#define ENISR_RESET 0x80 /* Reset completed */
+#define ENISR_ALL 0x3f /* Interrupts we will enable */
+
+/* Bits in EN0_DCFG - Data config register */
+#define ENDCFG_WTS 0x01 /* word transfer mode selection */
+
+/* Page 1 register offsets. */
+#define EN1_PHYS EI_SHIFT(0x01) /* This board's physical enet addr RD WR */
+#define EN1_PHYS_SHIFT(i) EI_SHIFT(i+1) /* Get and set mac address */
+#define EN1_CURPAG EI_SHIFT(0x07) /* Current memory page RD WR */
+#define EN1_MULT EI_SHIFT(0x08) /* Multicast filter mask array (8 bytes) RD WR */
+#define EN1_MULT_SHIFT(i) EI_SHIFT(8+i) /* Get and set multicast filter */
+
+/* Bits in received packet status byte and EN0_RSR*/
+#define ENRSR_RXOK 0x01 /* Received a good packet */
+#define ENRSR_CRC 0x02 /* CRC error */
+#define ENRSR_FAE 0x04 /* frame alignment error */
+#define ENRSR_FO 0x08 /* FIFO overrun */
+#define ENRSR_MPA 0x10 /* missed pkt */
+#define ENRSR_PHY 0x20 /* physical/multicast address */
+#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */
+#define ENRSR_DEF 0x80 /* deferring */
+
+/* Transmitted packet status, EN0_TSR. */
+#define ENTSR_PTX 0x01 /* Packet transmitted without error */
+#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */
+#define ENTSR_COL 0x04 /* The transmit collided at least once. */
+#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */
+#define ENTSR_CRS 0x10 /* The carrier sense was lost. */
+#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */
+#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */
+#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */
+
+#endif /* _8390_h */
diff -u --recursive --new-file v2.4.14/linux/drivers/net/pcmcia/axnet_cs.c linux/drivers/net/pcmcia/axnet_cs.c
--- v2.4.14/linux/drivers/net/pcmcia/axnet_cs.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/pcmcia/axnet_cs.c Mon Nov 12 09:35:43 2001
@@ -0,0 +1,1958 @@
+/*======================================================================
+
+ A PCMCIA ethernet driver for Asix AX88190-based cards
+
+ The Asix AX88190 is a NS8390-derived chipset with a few nasty
+ idiosyncracies that make it very inconvenient to support with a
+ standard 8390 driver. This driver is based on pcnet_cs, with the
+ tweaked 8390 code grafted on the end. Much of what I did was to
+ clean up and update a similar driver supplied by Asix, which was
+ adapted by William Lee, wil...@asix.com.tw.
+
+ Copyright (C) 2001 David A. Hinds -- dah...@users.sourceforge.net
+
+ axnet_cs.c 1.11 2001/06/12 12:42:40
+
+ The network driver code is based on Donald Becker's NE2000 code:
+
+ Written 1992,1993 by Donald Becker.
+ Copyright 1993 United States Government as represented by the
+ Director, National Security Agency. This software may be used and
+ distributed according to the terms of the GNU General Public License,
+ incorporated herein by reference.
+ Donald Becker may be reached at bec...@cesdis1.gsfc.nasa.gov
+
+======================================================================*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+
+#include <linux/netdevice.h>
+#include "ax8390.h"
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ciscode.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+
+#define AXNET_CMD 0x00
+#define AXNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */
+#define AXNET_RESET 0x1f /* Issue a read to reset, a write to clear. */
+#define AXNET_MISC 0x18 /* For IBM CCAE and Socket EA cards */
+#define AXNET_MII_EEP 0x14 /* Offset of MII access port */
+
+#define AXNET_START_PG 0x40 /* First page of TX buffer */
+#define AXNET_STOP_PG 0x80 /* Last page +1 of RX ring */
+
+#define AXNET_RDC_TIMEOUT 0x02 /* Max wait in jiffies for Tx RDC */
+
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+MODULE_PARM(pc_debug, "i");
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version =
+"axnet_cs.c 1.11 2001/06/12 12:42:40 (David Hinds)";


+#else
+#define DEBUG(n, args...)
+#endif
+

+#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb);
+#define skb_tx_check(dev, skb)
+#define add_rx_bytes(stats, n) (stats)->rx_bytes += n;
+#define add_tx_bytes(stats, n) (stats)->tx_bytes += n;
+#define netif_mark_up(dev) do { } while (0)
+#define netif_mark_down(dev) do { } while (0)
+
+/*====================================================================*/
+
+/* Parameters that can be set with 'insmod' */


+
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
+

+/* Bit map of interrupts to choose from */
+INT_MODULE_PARM(irq_mask, 0xdeb8);

+static int irq_list[4] = { -1 };

+MODULE_PARM(irq_list, "1-4i");
+
+/* Ugh! Let the user hardwire the hardware address for queer cards */
+static int hw_addr[6] = { 0, /* ... */ };
+MODULE_PARM(hw_addr, "6i");
+
+/*====================================================================*/
+
+static void axnet_config(dev_link_t *link);
+static void axnet_release(u_long arg);
+static int axnet_event(event_t event, int priority,
+ event_callback_args_t *args);
+static int axnet_open(struct net_device *dev);
+static int axnet_close(struct net_device *dev);
+static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static void ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs);
+static void ei_watchdog(u_long arg);
+static void axnet_reset_8390(struct net_device *dev);
+
+static int mdio_read(ioaddr_t addr, int phy_id, int loc);


+static void mdio_write(ioaddr_t addr, int phy_id, int loc, int value);
+

+static void get_8390_hdr(struct net_device *,
+ struct e8390_pkt_hdr *, int);
+static void block_input(struct net_device *dev, int count,
+ struct sk_buff *skb, int ring_offset);
+static void block_output(struct net_device *dev, int count,
+ const u_char *buf, const int start_page);
+
+static dev_link_t *axnet_attach(void);
+static void axnet_detach(dev_link_t *);
+
+static dev_info_t dev_info = "axnet_cs";
+static dev_link_t *dev_list;
+
+/*====================================================================*/
+
+typedef struct axnet_dev_t {
+ struct net_device dev; /* so &dev == &axnet_dev_t */
+ dev_link_t link;
+ dev_node_t node;
+ caddr_t base;
+ struct timer_list watchdog;
+ int stale, fast_poll;
+ u_short link_status;
+ u_char duplex_flag;
+ int phy_id;
+} axnet_dev_t;
+
+/*======================================================================
+
+ This bit of code is used to avoid unregistering network devices
+ at inappropriate times. 2.2 and later kernels are fairly picky
+ about when this can happen.
+
+======================================================================*/
+
+static void flush_stale_links(void)
+{
+ dev_link_t *link, *next;
+ for (link = dev_list; link; link = next) {
+ next = link->next;
+ if (link->state & DEV_STALE_LINK)
+ axnet_detach(link);
+ }
+}
+
+/*====================================================================*/
+
+static void cs_error(client_handle_t handle, int func, int ret)
+{
+ error_info_t err = { func, ret };
+ CardServices(ReportError, handle, &err);
+}
+
+/*======================================================================
+
+ We never need to do anything when a axnet device is "initialized"
+ by the net software, because we only register already-found cards.
+
+======================================================================*/
+
+static int axnet_init(struct net_device *dev)


+{
+ return 0;
+}
+

+/*======================================================================
+
+ axnet_attach() creates an "instance" of the driver, allocating
+ local data structures for one device. The device is registered
+ with Card Services.
+
+======================================================================*/
+
+static dev_link_t *axnet_attach(void)
+{
+ axnet_dev_t *info;
+ dev_link_t *link;
+ struct net_device *dev;
+ client_reg_t client_reg;
+ int i, ret;
+
+ DEBUG(0, "axnet_attach()\n");
+ flush_stale_links();
+
+ /* Create new ethernet device */
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) return NULL;
+ memset(info, 0, sizeof(*info));
+ link = &info->link; dev = &info->dev;
+ link->priv = info;
+
+ link->release.function = &axnet_release;
+ link->release.data = (u_long)link;
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
+ if (irq_list[0] == -1)
+ link->irq.IRQInfo2 = irq_mask;
+ else
+ for (i = 0; i < 4; i++)
+ link->irq.IRQInfo2 |= 1 << irq_list[i];
+ link->conf.Attributes = CONF_ENABLE_IRQ;
+ link->conf.IntType = INT_MEMORY_AND_IO;
+
+ ethdev_init(dev);
+ dev->init = &axnet_init;
+ dev->open = &axnet_open;
+ dev->stop = &axnet_close;
+ dev->do_ioctl = &axnet_ioctl;
+
+ /* Register with Card Services */
+ link->next = dev_list;
+ dev_list = link;
+ client_reg.dev_info = &dev_info;
+ client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
+ client_reg.EventMask =
+ CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+ CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+ CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+ client_reg.event_handler = &axnet_event;
+ client_reg.Version = 0x0210;
+ client_reg.event_callback_args.client_data = link;
+ ret = CardServices(RegisterClient, &link->handle, &client_reg);
+ if (ret != CS_SUCCESS) {
+ cs_error(link->handle, RegisterClient, ret);
+ axnet_detach(link);


+ return NULL;
+ }
+

+ return link;
+} /* axnet_attach */
+
+/*======================================================================
+
+ This deletes a driver "instance". The device is de-registered
+ with Card Services. If it has been released, all local data
+ structures are freed. Otherwise, the structures will be freed
+ when the device is released.
+
+======================================================================*/
+
+static void axnet_detach(dev_link_t *link)
+{
+ axnet_dev_t *info = link->priv;
+ dev_link_t **linkp;
+
+ DEBUG(0, "axnet_detach(0x%p)\n", link);
+
+ /* Locate device structure */
+ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+ if (*linkp == link) break;
+ if (*linkp == NULL)
+ return;
+
+ del_timer(&link->release);
+ if (link->state & DEV_CONFIG) {
+ axnet_release((u_long)link);
+ if (link->state & DEV_STALE_CONFIG) {
+ link->state |= DEV_STALE_LINK;


+ return;
+ }
+ }
+

+ if (link->handle)
+ CardServices(DeregisterClient, link->handle);
+
+ /* Unlink device structure, free bits */
+ *linkp = link->next;
+ if (link->dev)
+ unregister_netdev(&info->dev);
+ kfree(info);
+
+} /* axnet_detach */
+
+/*======================================================================
+
+ This probes for a card's hardware address by reading the PROM.
+
+======================================================================*/
+
+static int get_prom(dev_link_t *link)
+{
+ struct net_device *dev = link->priv;
+ ioaddr_t ioaddr = dev->base_addr;
+ int i, j;
+
+ /* This is based on drivers/net/ne.c */
+ struct {
+ u_char value, offset;
+ } program_seq[] = {
+ {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+ {0x01, EN0_DCFG}, /* Set word-wide access. */
+ {0x00, EN0_RCNTLO}, /* Clear the count regs. */
+ {0x00, EN0_RCNTHI},
+ {0x00, EN0_IMR}, /* Mask completion irq. */
+ {0xFF, EN0_ISR},
+ {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
+ {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
+ {0x10, EN0_RCNTLO},
+ {0x00, EN0_RCNTHI},
+ {0x00, EN0_RSARLO}, /* DMA starting at 0x0400. */
+ {0x04, EN0_RSARHI},
+ {E8390_RREAD+E8390_START, E8390_CMD},
+ };
+
+ /* Not much of a test, but the alternatives are messy */
+ if (link->conf.ConfigBase != 0x03c0)
+ return 0;
+
+ axnet_reset_8390(dev);
+ mdelay(10);
+
+ for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
+ outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
+
+ for (i = 0; i < 6; i += 2) {
+ j = inw(ioaddr + AXNET_DATAPORT);
+ dev->dev_addr[i] = j & 0xff;
+ dev->dev_addr[i+1] = j >> 8;
+ }
+ return 1;
+} /* get_prom */
+
+/*======================================================================
+
+ This should be totally unnecessary... but when we can't figure
+ out the hardware address any other way, we'll let the user hard
+ wire it when the module is initialized.
+
+======================================================================*/
+
+static int get_hwired(dev_link_t *link)
+{
+ struct net_device *dev = link->priv;
+ int i;
+
+ for (i = 0; i < 6; i++)
+ if (hw_addr[i] != 0) break;
+ if (i == 6)
+ return 0;
+
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = hw_addr[i];
+
+ return 1;
+} /* get_hwired */
+
+/*======================================================================
+
+ axnet_config() is scheduled to run after a CARD_INSERTION event
+ is received, to configure the PCMCIA socket, and to make the
+ ethernet device available to the system.
+
+======================================================================*/
+
+#define CS_CHECK(fn, args...) \
+while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
+
+#define CFG_CHECK(fn, args...) \
+if (CardServices(fn, args) != 0) goto next_entry
+
+static int try_io_port(dev_link_t *link)
+{
+ int j, ret;
+ if (link->io.NumPorts1 == 32) {
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ if (link->io.NumPorts2 > 0) {
+ /* for master/slave multifunction cards */
+ link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
+ link->irq.Attributes =
+ IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
+ }
+ } else {
+ /* This should be two 16-port windows */
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
+ }
+ if (link->io.BasePort1 == 0) {
+ link->io.IOAddrLines = 16;
+ for (j = 0; j < 0x400; j += 0x20) {
+ link->io.BasePort1 = j ^ 0x300;
+ link->io.BasePort2 = (j ^ 0x300) + 0x10;
+ ret = CardServices(RequestIO, link->handle, &link->io);
+ if (ret == CS_SUCCESS) return ret;
+ }
+ return ret;
+ } else {
+ return CardServices(RequestIO, link->handle, &link->io);
+ }
+}
+
+static void axnet_config(dev_link_t *link)
+{
+ client_handle_t handle = link->handle;
+ axnet_dev_t *info = link->priv;
+ struct net_device *dev = &info->dev;
+ tuple_t tuple;
+ cisparse_t parse;
+ int i, j, last_ret, last_fn;
+ u_short buf[64];
+ config_info_t conf;
+
+ DEBUG(0, "axnet_config(0x%p)\n", link);
+
+ tuple.Attributes = 0;
+ tuple.TupleData = (cisdata_t *)buf;
+ tuple.TupleDataMax = sizeof(buf);
+ tuple.TupleOffset = 0;
+ tuple.DesiredTuple = CISTPL_CONFIG;
+ CS_CHECK(GetFirstTuple, handle, &tuple);
+ CS_CHECK(GetTupleData, handle, &tuple);
+ CS_CHECK(ParseTuple, handle, &tuple, &parse);
+ link->conf.ConfigBase = parse.config.base;
+ link->conf.Present = parse.config.rmask[0];
+
+ /* Configure card */
+ link->state |= DEV_CONFIG;
+
+ /* Look up current Vcc */
+ CS_CHECK(GetConfigurationInfo, handle, &conf);
+ link->conf.Vcc = conf.Vcc;
+
+ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+ tuple.Attributes = 0;
+ CS_CHECK(GetFirstTuple, handle, &tuple);
+ while (last_ret == CS_SUCCESS) {
+ cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+ cistpl_io_t *io = &(parse.cftable_entry.io);
+
+ CFG_CHECK(GetTupleData, handle, &tuple);
+ CFG_CHECK(ParseTuple, handle, &tuple, &parse);
+ if ((cfg->index == 0) || (cfg->io.nwin == 0))
+ goto next_entry;
+
+ link->conf.ConfigIndex = cfg->index;
+ /* For multifunction cards, by convention, we configure the
+ network function with window 0, and serial with window 1 */
+ if (io->nwin > 1) {
+ i = (io->win[1].len > io->win[0].len);
+ link->io.BasePort2 = io->win[1-i].base;
+ link->io.NumPorts2 = io->win[1-i].len;
+ } else {
+ i = link->io.NumPorts2 = 0;
+ }
+ link->io.BasePort1 = io->win[i].base;
+ link->io.NumPorts1 = io->win[i].len;
+ link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) {
+ last_ret = try_io_port(link);
+ if (last_ret == CS_SUCCESS) break;
+ }
+ next_entry:
+ last_ret = CardServices(GetNextTuple, handle, &tuple);
+ }
+ if (last_ret != CS_SUCCESS) {
+ cs_error(handle, RequestIO, last_ret);
+ goto failed;
+ }
+
+ CS_CHECK(RequestIRQ, handle, &link->irq);
+
+ if (link->io.NumPorts2 == 8) {
+ link->conf.Attributes |= CONF_ENABLE_SPKR;
+ link->conf.Status = CCSR_AUDIO_ENA;
+ }
+
+ CS_CHECK(RequestConfiguration, handle, &link->conf);
+ dev->irq = link->irq.AssignedIRQ;
+ dev->base_addr = link->io.BasePort1;
+ if (register_netdev(dev) != 0) {
+ printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n");
+ goto failed;
+ }
+
+ if (!get_prom(link) && !get_hwired(link)) {
+ printk(KERN_NOTICE "axnet_cs: unable to read hardware net"
+ " address for io base %#3lx\n", dev->base_addr);
+ unregister_netdev(dev);
+ goto failed;
+ }
+
+ ei_status.name = "AX88190";
+ ei_status.word16 = 1;
+ ei_status.tx_start_page = AXNET_START_PG;
+ ei_status.rx_start_page = AXNET_START_PG + TX_PAGES;
+ ei_status.stop_page = AXNET_STOP_PG;
+ ei_status.reset_8390 = &axnet_reset_8390;
+ ei_status.get_8390_hdr = &get_8390_hdr;
+ ei_status.block_input = &block_input;
+ ei_status.block_output = &block_output;
+
+ strcpy(info->node.dev_name, dev->name);
+ link->dev = &info->node;
+ link->state &= ~DEV_CONFIG_PENDING;
+
+ printk(KERN_INFO "%s: Asix AX88190: io %#3lx, irq %d, hw_addr ",
+ dev->name, dev->base_addr, dev->irq);
+ for (i = 0; i < 6; i++)
+ printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
+


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

+ j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);


+ if ((j != 0) && (j != 0xffff)) break;
+ }

+ info->phy_id = (i < 32) ? i : -1;


+ if (i < 32) {
+ DEBUG(0, " MII transceiver at index %d, status %x.\n", i, j);
+ } else {

+ printk(KERN_NOTICE " No MII transceivers found!\n");
+ }
+
+ return;
+
+cs_failed:
+ cs_error(link->handle, last_fn, last_ret);
+failed:
+ axnet_release((u_long)link);
+ return;
+} /* axnet_config */
+
+/*======================================================================
+
+ After a card is removed, axnet_release() will unregister the net
+ device, and release the PCMCIA configuration. If the device is
+ still open, this will be postponed until it is closed.
+
+======================================================================*/
+
+static void axnet_release(u_long arg)
+{
+ dev_link_t *link = (dev_link_t *)arg;
+
+ DEBUG(0, "axnet_release(0x%p)\n", link);
+
+ if (link->open) {
+ DEBUG(1, "axnet_cs: release postponed, '%s' still open\n",
+ info->node.dev_name);
+ link->state |= DEV_STALE_CONFIG;
+ return;
+ }
+
+ CardServices(ReleaseConfiguration, link->handle);
+ CardServices(ReleaseIO, link->handle, &link->io);
+ CardServices(ReleaseIRQ, link->handle, &link->irq);
+
+ link->state &= ~DEV_CONFIG;
+
+} /* axnet_release */
+
+/*======================================================================
+
+ The card status event handler. Mostly, this schedules other
+ stuff to run after an event is received. A CARD_REMOVAL event
+ also sets some flags to discourage the net drivers from trying
+ to talk to the card any more.
+
+======================================================================*/
+
+static int axnet_event(event_t event, int priority,
+ event_callback_args_t *args)
+{
+ dev_link_t *link = args->client_data;
+ axnet_dev_t *info = link->priv;
+
+ DEBUG(2, "axnet_event(0x%06x)\n", event);
+
+ switch (event) {
+ case CS_EVENT_CARD_REMOVAL:
+ link->state &= ~DEV_PRESENT;
+ if (link->state & DEV_CONFIG) {
+ netif_device_detach(&info->dev);
+ mod_timer(&link->release, jiffies + HZ/20);
+ }
+ break;
+ case CS_EVENT_CARD_INSERTION:
+ link->state |= DEV_PRESENT;
+ axnet_config(link);
+ break;
+ case CS_EVENT_PM_SUSPEND:
+ link->state |= DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_RESET_PHYSICAL:
+ if (link->state & DEV_CONFIG) {
+ if (link->open)
+ netif_device_detach(&info->dev);
+ CardServices(ReleaseConfiguration, link->handle);
+ }
+ break;
+ case CS_EVENT_PM_RESUME:
+ link->state &= ~DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_CARD_RESET:
+ if (link->state & DEV_CONFIG) {
+ CardServices(RequestConfiguration, link->handle, &link->conf);
+ if (link->open) {
+ axnet_reset_8390(&info->dev);
+ NS8390_init(&info->dev, 1);
+ netif_device_attach(&info->dev);
+ }
+ }
+ break;
+ }
+ return 0;
+} /* axnet_event */
+
+/*======================================================================


+
+ MII interface support

+
+======================================================================*/
+
+#define MDIO_SHIFT_CLK 0x01
+#define MDIO_DATA_WRITE0 0x00
+#define MDIO_DATA_WRITE1 0x08
+#define MDIO_DATA_READ 0x04
+#define MDIO_MASK 0x0f
+#define MDIO_ENB_IN 0x02


+
+static void mdio_sync(ioaddr_t addr)
+{
+ int bits;
+ for (bits = 0; bits < 32; bits++) {

+ outb_p(MDIO_DATA_WRITE1, addr);
+ outb_p(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
+ }
+}
+


+static int mdio_read(ioaddr_t addr, int phy_id, int loc)
+{

+ u_int cmd = (0xf6<<10)|(phy_id<<5)|loc;
+ int i, retval = 0;
+
+ mdio_sync(addr);
+ for (i = 14; i >= 0; i--) {


+ int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;

+ outb_p(dat, addr);
+ outb_p(dat | MDIO_SHIFT_CLK, addr);
+ }


+ for (i = 19; i > 0; i--) {

+ outb_p(MDIO_ENB_IN, addr);
+ retval = (retval << 1) | ((inb_p(addr) & MDIO_DATA_READ) != 0);
+ outb_p(MDIO_ENB_IN | MDIO_SHIFT_CLK, addr);


+ }
+ return (retval>>1) & 0xffff;
+}
+
+static void mdio_write(ioaddr_t addr, int phy_id, int loc, int value)
+{
+ u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;

+ int i;
+


+ mdio_sync(addr);
+ for (i = 31; i >= 0; i--) {
+ int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;

+ outb_p(dat, addr);
+ outb_p(dat | MDIO_SHIFT_CLK, addr);
+ }


+ for (i = 1; i >= 0; i--) {

+ outb_p(MDIO_ENB_IN, addr);
+ outb_p(MDIO_ENB_IN | MDIO_SHIFT_CLK, addr);
+ }
+}
+
+/*====================================================================*/
+
+static int axnet_open(struct net_device *dev)


+{
+ axnet_dev_t *info = (axnet_dev_t *)dev;

+ dev_link_t *link = &info->link;
+
+ DEBUG(2, "axnet_open('%s')\n", dev->name);
+
+ if (!DEV_OK(link))
+ return -ENODEV;
+
+ link->open++;
+ MOD_INC_USE_COUNT;
+
+ request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev);
+
+ info->link_status = 0x00;
+ info->watchdog.function = &ei_watchdog;
+ info->watchdog.data = (u_long)info;
+ info->watchdog.expires = jiffies + HZ;
+ add_timer(&info->watchdog);
+
+ return ei_open(dev);
+} /* axnet_open */
+
+/*====================================================================*/
+
+static int axnet_close(struct net_device *dev)


+{
+ axnet_dev_t *info = (axnet_dev_t *)dev;

+ dev_link_t *link = &info->link;
+
+ DEBUG(2, "axnet_close('%s')\n", dev->name);
+
+ free_irq(dev->irq, dev);
+
+ link->open--;
+ netif_stop_queue(dev);
+ netif_mark_down(dev);
+ del_timer(&info->watchdog);
+ if (link->state & DEV_STALE_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
+
+ MOD_DEC_USE_COUNT;
+
+ return 0;
+} /* axnet_close */
+
+/*======================================================================
+
+ Hard reset the card. This used to pause for the same period that
+ a 8390 reset command required, but that shouldn't be necessary.
+
+======================================================================*/
+
+static void axnet_reset_8390(struct net_device *dev)
+{
+ ioaddr_t nic_base = dev->base_addr;
+ int i;
+
+ ei_status.txing = ei_status.dmaing = 0;
+
+ outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, nic_base + E8390_CMD);
+
+ outb(inb(nic_base + AXNET_RESET), nic_base + AXNET_RESET);
+
+ for (i = 0; i < 100; i++) {
+ if ((inb_p(nic_base+EN0_ISR) & ENISR_RESET) != 0)
+ break;
+ udelay(100);
+ }
+ outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
+
+ if (i == 100)
+ printk(KERN_ERR "%s: axnet_reset_8390() did not complete.\n",
+ dev->name);
+
+} /* axnet_reset_8390 */
+
+/*====================================================================*/
+
+static void ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs)
+{
+ axnet_dev_t *info = dev_id;
+ info->stale = 0;
+ ei_interrupt(irq, dev_id, regs);
+}
+
+static void ei_watchdog(u_long arg)
+{
+ axnet_dev_t *info = (axnet_dev_t *)(arg);
+ struct net_device *dev = &info->dev;
+ ioaddr_t nic_base = dev->base_addr;
+ ioaddr_t mii_addr = nic_base + AXNET_MII_EEP;
+ u_short link;
+
+ if (!netif_device_present(dev)) goto reschedule;
+
+ /* Check for pending interrupt with expired latency timer: with
+ this, we can limp along even if the interrupt is blocked */
+ if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
+ if (!info->fast_poll)
+ printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
+ ei_irq_wrapper(dev->irq, dev, NULL);
+ info->fast_poll = HZ;
+ }
+ if (info->fast_poll) {
+ info->fast_poll--;
+ info->watchdog.expires = jiffies + 1;
+ add_timer(&info->watchdog);
+ return;
+ }
+
+ if (info->phy_id < 0)
+ goto reschedule;


+ link = mdio_read(mii_addr, info->phy_id, 1);

+ if (!link || (link == 0xffff)) {

+ printk(KERN_INFO "%s: MII is missing!\n", dev->name);
+ info->phy_id = -1;


+ goto reschedule;
+ }
+
+ link &= 0x0004;

+ if (link != info->link_status) {
+ u_short p = mdio_read(mii_addr, info->phy_id, 5);


+ printk(KERN_INFO "%s: %s link beat\n", dev->name,
+ (link) ? "found" : "lost");
+ if (link) {

+ info->duplex_flag = (p & 0x0140) ? 0x80 : 0x00;


+ if (p)
+ printk(KERN_INFO "%s: autonegotiation complete: "
+ "%sbaseT-%cD selected\n", dev->name,
+ ((p & 0x0180) ? "100" : "10"),
+ ((p & 0x0140) ? 'F' : 'H'));
+ else

+ printk(KERN_INFO "%s: link partner did not autonegotiate\n",
+ dev->name);
+ NS8390_init(dev, 1);
+ }
+ info->link_status = link;
+ }
+
+reschedule:
+ info->watchdog.expires = jiffies + HZ;
+ add_timer(&info->watchdog);
+}
+
+/*====================================================================*/
+
+static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)


+{
+ axnet_dev_t *info = (axnet_dev_t *)dev;

+ u16 *data = (u16 *)&rq->ifr_data;
+ ioaddr_t mii_addr = dev->base_addr + AXNET_MII_EEP;
+ switch (cmd) {
+ case SIOCDEVPRIVATE:


+ data[0] = info->phy_id;

+ case SIOCDEVPRIVATE+1:


+ data[3] = mdio_read(mii_addr, data[0], data[1] & 0x1f);

+ return 0;
+ case SIOCDEVPRIVATE+2:


+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;

+ mdio_write(mii_addr, data[0], data[1] & 0x1f, data[2]);

+ return 0;
+ }
+ return -EOPNOTSUPP;
+}
+
+/*====================================================================*/
+
+static void get_8390_hdr(struct net_device *dev,
+ struct e8390_pkt_hdr *hdr,
+ int ring_page)
+{
+ ioaddr_t nic_base = dev->base_addr;
+
+ outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */
+ outb_p(ring_page, nic_base + EN0_RSARHI);
+ outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD);
+
+ insw(nic_base + AXNET_DATAPORT, hdr,
+ sizeof(struct e8390_pkt_hdr)>>1);
+ /* Fix for big endian systems */
+ hdr->count = le16_to_cpu(hdr->count);
+
+}
+
+/*====================================================================*/
+
+static void block_input(struct net_device *dev, int count,
+ struct sk_buff *skb, int ring_offset)
+{
+ ioaddr_t nic_base = dev->base_addr;
+ int xfer_count = count;
+ char *buf = skb->data;
+
+#ifdef PCMCIA_DEBUG
+ if ((ei_debug > 4) && (count != 4))
+ printk(KERN_DEBUG "%s: [bi=%d]\n", dev->name, count+4);
+#endif
+ outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+ outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+ outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD);
+
+ insw(nic_base + AXNET_DATAPORT,buf,count>>1);
+ if (count & 0x01)
+ buf[count-1] = inb(nic_base + AXNET_DATAPORT), xfer_count++;
+
+}
+
+/*====================================================================*/
+
+static void block_output(struct net_device *dev, int count,
+ const u_char *buf, const int start_page)
+{
+ ioaddr_t nic_base = dev->base_addr;
+
+#ifdef PCMCIA_DEBUG
+ if (ei_debug > 4)
+ printk(KERN_DEBUG "%s: [bo=%d]\n", dev->name, count);
+#endif
+
+ /* Round the count up for word writes. Do we need to do this?
+ What effect will an odd byte count have on the 8390?
+ I should check someday. */
+ if (count & 0x01)
+ count++;
+
+ outb_p(0x00, nic_base + EN0_RSARLO);
+ outb_p(start_page, nic_base + EN0_RSARHI);
+ outb_p(E8390_RWRITE+E8390_START, nic_base + AXNET_CMD);
+ outsw(nic_base + AXNET_DATAPORT, buf, count>>1);
+}
+
+/*====================================================================*/
+
+static int __init init_axnet_cs(void)
+{
+ servinfo_t serv;
+ DEBUG(0, "%s\n", version);
+ CardServices(GetCardServicesInfo, &serv);
+ if (serv.Revision != CS_RELEASE_CODE) {
+ printk(KERN_NOTICE "axnet_cs: Card Services release "
+ "does not match!\n");
+ return -1;
+ }
+ register_pccard_driver(&dev_info, &axnet_attach, &axnet_detach);


+ return 0;
+}
+

+static void __exit exit_axnet_cs(void)
+{
+ DEBUG(0, "axnet_cs: unloading\n");
+ unregister_pccard_driver(&dev_info);
+ while (dev_list != NULL)
+ axnet_detach(dev_list);
+}
+
+module_init(init_axnet_cs);
+module_exit(exit_axnet_cs);
+
+/*====================================================================*/
+
+/* 8390.c: A general NS8390 ethernet driver core for linux. */
+/*
+ Written 1992-94 by Donald Becker.
+
+ Copyright 1993 United States Government as represented by the
+ Director, National Security Agency.


+
+ This software may be used and distributed according to the terms
+ of the GNU General Public License, incorporated herein by reference.
+

+ The author may be reached as bec...@CESDIS.gsfc.nasa.gov, or C/O
+ Center of Excellence in Space Data and Information Sciences
+ Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+
+ This is the chip-specific code for many 8390-based ethernet adaptors.
+ This is not a complete driver, it must be combined with board-specific
+ code such as ne.c, wd.c, 3c503.c, etc.
+
+ Seeing how at least eight drivers use this code, (not counting the
+ PCMCIA ones either) it is easy to break some card by what seems like
+ a simple innocent change. Please contact me or Donald if you think
+ you have found something that needs changing. -- PG
+
+
+ Changelog:
+
+ Paul Gortmaker : remove set_bit lock, other cleanups.
+ Paul Gortmaker : add ei_get_8390_hdr() so we can pass skb's to
+ ei_block_input() for eth_io_copy_and_sum().
+ Paul Gortmaker : exchange static int ei_pingpong for a #define,
+ also add better Tx error handling.
+ Paul Gortmaker : rewrite Rx overrun handling as per NS specs.
+ Alexey Kuznetsov : use the 8390's six bit hash multicast filter.
+ Paul Gortmaker : tweak ANK's above multicast changes a bit.
+ Paul Gortmaker : update packet statistics for v2.1.x
+ Alan Cox : support arbitary stupid port mappings on the
+ 68K Macintosh. Support >16bit I/O spaces
+ Paul Gortmaker : add kmod support for auto-loading of the 8390
+ module by all drivers that require it.
+ Alan Cox : Spinlocking work, added 'BUG_83C690'
+ Paul Gortmaker : Separate out Tx timeout code from Tx path.
+
+ Sources:
+ The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
+
+ */
+


+static const char *version =

+ "8390.c:v1.10cvs 9/23/94 Donald Becker (bec...@cesdis.gsfc.nasa.gov)\n";
+
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <asm/irq.h>
+#include <linux/fcntl.h>
+#include <linux/in.h>
+#include <linux/interrupt.h>
+
+#include <linux/etherdevice.h>
+
+#define BUG_83C690
+
+/* These are the operational function interfaces to board-specific
+ routines.
+ void reset_8390(struct net_device *dev)
+ Resets the board associated with DEV, including a hardware reset of
+ the 8390. This is only called when there is a transmit timeout, and
+ it is always followed by 8390_init().
+ void block_output(struct net_device *dev, int count, const unsigned char *buf,
+ int start_page)
+ Write the COUNT bytes of BUF to the packet buffer at START_PAGE. The
+ "page" value uses the 8390's 256-byte pages.
+ void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page)
+ Read the 4 byte, page aligned 8390 header. *If* there is a
+ subsequent read, it will be of the rest of the packet.
+ void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+ Read COUNT bytes from the packet buffer into the skb data area. Start
+ reading from RING_OFFSET, the address as the 8390 sees it. This will always
+ follow the read of the 8390 header.
+*/
+#define ei_reset_8390 (ei_local->reset_8390)
+#define ei_block_output (ei_local->block_output)
+#define ei_block_input (ei_local->block_input)
+#define ei_get_8390_hdr (ei_local->get_8390_hdr)
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifndef ei_debug
+int ei_debug = 1;
+#endif
+
+/* Index to functions. */
+static void ei_tx_intr(struct net_device *dev);
+static void ei_tx_err(struct net_device *dev);
+static void ei_tx_timeout(struct net_device *dev);
+static void ei_receive(struct net_device *dev);


+static void ei_rx_overrun(struct net_device *dev);
+

+/* Routines generic to NS8390-based boards. */


+static void NS8390_trigger_send(struct net_device *dev, unsigned int length,

+ int start_page);
+static void set_multicast_list(struct net_device *dev);
+static void do_set_multicast_list(struct net_device *dev);
+
+/*
+ * SMP and the 8390 setup.
+ *
+ * The 8390 isnt exactly designed to be multithreaded on RX/TX. There is
+ * a page register that controls bank and packet buffer access. We guard
+ * this with ei_local->page_lock. Nobody should assume or set the page other
+ * than zero when the lock is not held. Lock holders must restore page 0
+ * before unlocking. Even pure readers must take the lock to protect in
+ * page 0.
+ *
+ * To make life difficult the chip can also be very slow. We therefore can't
+ * just use spinlocks. For the longer lockups we disable the irq the device
+ * sits on and hold the lock. We must hold the lock because there is a dual
+ * processor case other than interrupts (get stats/set multicast list in
+ * parallel with each other and transmit).
+ *
+ * Note: in theory we can just disable the irq on the card _but_ there is
+ * a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs"
+ * enter lock, take the queued irq. So we waddle instead of flying.
+ *
+ * Finally by special arrangement for the purpose of being generally
+ * annoying the transmit function is called bh atomic. That places
+ * restrictions on the user context callers as disable_irq won't save
+ * them.
+ */
+
+
+
+/**
+ * ei_open - Open/initialize the board.
+ * @dev: network device to initialize
+ *
+ * This routine goes all-out, setting everything
+ * up anew at each open, even though many of these registers should only
+ * need to be set once at boot.
+ */
+static int ei_open(struct net_device *dev)


+{
+ unsigned long flags;

+ struct ei_device *ei_local = (struct ei_device *) dev->priv;
+

+ /* This can't happen unless somebody forgot to call ethdev_init(). */
+ if (ei_local == NULL)
+ {
+ printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name);
+ return -ENXIO;
+ }
+
+#ifdef HAVE_TX_TIMEOUT
+ /* The card I/O part of the driver (e.g. 3c503) can hook a Tx timeout
+ wrapper that does e.g. media check & then calls ei_tx_timeout. */
+ if (dev->tx_timeout == NULL)
+ dev->tx_timeout = ei_tx_timeout;
+ if (dev->watchdog_timeo <= 0)
+ dev->watchdog_timeo = TX_TIMEOUT;
+#endif
+
+ /*
+ * Grab the page lock so we own the register set, then call
+ * the init function.
+ */
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);
+ NS8390_init(dev, 1);
+ /* Set the flag before we drop the lock, That way the IRQ arrives
+ after its set and we get no silly warnings */
+ netif_mark_up(dev);
+ netif_start_queue(dev);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+ ei_local->irqlock = 0;


+ return 0;
+}
+

+/**
+ * ei_close - shut down network device
+ * @dev: network device to close
+ *
+ * Opposite of ei_open(). Only used when "ifconfig <devname> down" is done.
+ */
+static int ei_close(struct net_device *dev)


+{
+ unsigned long flags;
+

+ /*
+ * Hold the page lock during close
+ */
+


+ spin_lock_irqsave(&((struct ei_device *)dev->priv)->page_lock, flags);

+ NS8390_init(dev, 0);


+ spin_unlock_irqrestore(&((struct ei_device *)dev->priv)->page_lock, flags);

+ netif_stop_queue(dev);


+ return 0;
+}
+

+/**
+ * ei_tx_timeout - handle transmit time out condition
+ * @dev: network device which has apparently fallen asleep
+ *
+ * Called by kernel when device never acknowledges a transmit has
+ * completed (or failed) - i.e. never posted a Tx related interrupt.
+ */
+
+void ei_tx_timeout(struct net_device *dev)


+{
+ long e8390_base = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *) dev->priv;

+ int txsr, isr, tickssofar = jiffies - dev->trans_start;


+ unsigned long flags;
+

+ ei_local->stat.tx_errors++;
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);
+ txsr = inb(e8390_base+EN0_TSR);
+ isr = inb(e8390_base+EN0_ISR);


+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+

+ printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
+ dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
+ (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
+
+ if (!isr && !ei_local->stat.tx_packets)
+ {
+ /* The 8390 probably hasn't gotten on the cable yet. */
+ ei_local->interface_num ^= 1; /* Try a different xcvr. */
+ }
+
+ /* Ugly but a reset can be slow, yet must be protected */
+
+ disable_irq_nosync(dev->irq);
+ spin_lock(&ei_local->page_lock);
+
+ /* Try to restart the card. Perhaps the user has fixed something. */
+ ei_reset_8390(dev);
+ NS8390_init(dev, 1);


+
+ spin_unlock(&ei_local->page_lock);
+ enable_irq(dev->irq);

+ netif_wake_queue(dev);
+}
+
+/**

+ * ei_start_xmit - begin packet transmission
+ * @skb: packet to be sent
+ * @dev: network device to which packet is sent
+ *
+ * Sends a packet to an 8390 network device.
+ */
+
+static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)


+{
+ long e8390_base = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *) dev->priv;

+ int length, send_length, output_page;


+ unsigned long flags;
+

+ netif_stop_queue(dev);
+ skb_tx_check(dev, skb);
+
+ length = skb->len;
+
+ /* Mask interrupts from the ethercard.
+ SMP: We have to grab the lock here otherwise the IRQ handler
+ on another CPU can flip window and race the IRQ mask set. We end
+ up trashing the mcast filter not disabling irqs if we dont lock */
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);


+ outb_p(0x00, e8390_base + EN0_IMR);

+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+
+ /*
+ * Slow phase with lock held.
+ */
+
+ disable_irq_nosync(dev->irq);


+
+ spin_lock(&ei_local->page_lock);
+

+ ei_local->irqlock = 1;
+

+ send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
+
+#ifdef EI_PINGPONG
+
+ /*
+ * We have two Tx slots available for use. Find the first free
+ * slot, and then perform some sanity checks. With two Tx bufs,


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

echo 'End of part 053'
echo 'File patch-2.4.15 is continued in part 054'
echo "054" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:48 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part072

#!/bin/sh -x
# this is part 072 of a 115 - part archive


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

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

X #include "matroxfb_misc.h"
X #include "matroxfb_DAC1064.h"
@@ -31,36 +43,53 @@
X 3
X };
X
+static const struct matrox_pll_features g550_pll = {
+ 135000,
+ 27000,
+ 4, 127,
+ 0, 9,
+ 3
+};
+
X static void DAC1064_calcclock(unsigned int freq, unsigned int fmax,
- unsigned int* in, unsigned int* feed, unsigned int* post) {
+ unsigned int* in, unsigned int* feed, unsigned int* post,
+ unsigned int timmings) {
X unsigned int fvco;
X unsigned int p;
X
- fvco = matroxfb_PLL_calcclock(&maven_pll, freq, fmax, in, feed, &p);
- /* 0 => 100 ... 275 MHz
- 1 => 243 ... 367 MHz
- 2 => 320 ... 475 MHz
- 3 => 453 ... 556 MHz
- 4 => 540 ... 594 MHz
- 5 => 588 ... 621 MHz
- 6 => 626 ... 637 MHz
- 7 => 631 ... 642 MHz
-
- As you can see, never choose frequency > 621 MHz, there is unavailable gap...
- Just to be sure, currently driver uses 110 ... 500 MHz range.
- */
- if (fvco <= 260000)
- ;
- else if (fvco <= 350000)
- p |= 0x08;
- else if (fvco <= 460000)
- p |= 0x10;
- else if (fvco <= 550000)
- p |= 0x18;
- else if (fvco <= 590000)
- p |= 0x20;
- else
- p |= 0x28;
+ switch (timmings) {
+ default:
+ fvco = matroxfb_PLL_calcclock(&maven_pll, freq, fmax, in, feed, &p);
+ /* 0 => 100 ... 275 MHz
+ 1 => 243 ... 367 MHz
+ 2 => 320 ... 475 MHz
+ 3 => 453 ... 556 MHz
+ 4 => 540 ... 594 MHz
+ 5 => 588 ... 621 MHz
+ 6 => 626 ... 637 MHz
+ 7 => 631 ... 642 MHz
+
+ As you can see, never choose frequency > 621 MHz, there is unavailable gap...
+ Just to be sure, currently driver uses 110 ... 500 MHz range.
+ */
+ if (fvco <= 260000)
+ ;
+ else if (fvco <= 350000)
+ p |= 0x08;
+ else if (fvco <= 460000)
+ p |= 0x10;
+ else if (fvco <= 550000)
+ p |= 0x18;
+ else if (fvco <= 590000)
+ p |= 0x20;
+ else
+ p |= 0x28;


+ break;
+ case 1:

+ fvco = matroxfb_PLL_calcclock(&g550_pll, freq, fmax, in, feed, &p);
+ /* p |= 0x00; */
+ break;
+ }
X *post = p;
X return;
X }
@@ -70,7 +99,7 @@
X struct mavenregs* m) {
X unsigned int a, b, c;
X
- DAC1064_calcclock(mt->pixclock, 500000, &a, &b, &c);
+ DAC1064_calcclock(mt->pixclock, 300000, &a, &b, &c, m2info->timmings);
X m->regs[0x80] = a;
X m->regs[0x81] = b;
X m->regs[0x82] = c;
@@ -139,6 +168,7 @@
X ACCESS_FBINFO(altout.output) = &matroxfb_g450_altout;
X up_write(&ACCESS_FBINFO(altout.lock));
X ACCESS_FBINFO(output.all) |= MATROXFB_OUTPUT_CONN_SECONDARY;
+ matroxfb_switch(ACCESS_FBINFO(currcon), (struct fb_info*)MINFO);

X return 0;
X }
X

@@ -171,6 +201,11 @@
X }
X memset(m2info, 0, sizeof(*m2info));
X m2info->primary_dev = MINFO;
+ if (ACCESS_FBINFO(devflags.g550dac)) {
+ m2info->timmings = 1;
+ } else {
+ m2info->timmings = 0;
+ }
X if (matroxfb_g450_connect(m2info)) {
X kfree(m2info);
X printk(KERN_ERR "matroxfb_g450: G450 DAC failed to initialize\n");
@@ -198,7 +233,8 @@
X matroxfb_unregister_driver(&g450);
X }
X
-MODULE_AUTHOR("(c) 2000 Petr Vandrovec <vand...@vc.cvut.cz>");
+MODULE_AUTHOR("(c) 2000-2001 Petr Vandrovec <vand...@vc.cvut.cz>");
X MODULE_DESCRIPTION("Matrox G450 secondary output driver");
+MODULE_LICENSE("GPL");
X module_init(matroxfb_g450_init);
X module_exit(matroxfb_g450_exit);
diff -u --recursive --new-file v2.4.14/linux/drivers/video/matrox/matroxfb_g450.h linux/drivers/video/matrox/matroxfb_g450.h
--- v2.4.14/linux/drivers/video/matrox/matroxfb_g450.h Fri Dec 29 14:07:23 2000
+++ linux/drivers/video/matrox/matroxfb_g450.h Fri Nov 9 14:07:41 2001
@@ -6,6 +6,7 @@
X
X struct matroxfb_g450_info {
X struct matrox_fb_info* primary_dev;
+ unsigned int timmings;
X };
X
X #endif /* __MATROXFB_MAVEN_H__ */
diff -u --recursive --new-file v2.4.14/linux/drivers/video/matrox/matroxfb_maven.c linux/drivers/video/matrox/matroxfb_maven.c
--- v2.4.14/linux/drivers/video/matrox/matroxfb_maven.c Sun Jul 9 22:16:28 2000
+++ linux/drivers/video/matrox/matroxfb_maven.c Fri Nov 9 14:07:41 2001
@@ -1,3 +1,15 @@
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
+ *
+ * (c) 1998-2001 Petr Vandrovec <vand...@vc.cvut.cz>
+ *
+ * Version: 1.51 2001/01/19
+ *
+ * See matroxfb_base.c for contributors.


+ *
+ */
+

X #include "matroxfb_maven.h"
X #include "matroxfb_misc.h"
X #include "matroxfb_DAC1064.h"
@@ -1030,8 +1042,9 @@
X i2c_del_driver(&maven_driver);
X }
X
-MODULE_AUTHOR("(c) 1999,2000 Petr Vandrovec <vand...@vc.cvut.cz>");
+MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec <vand...@vc.cvut.cz>");
X MODULE_DESCRIPTION("Matrox G200/G400 Matrox MGA-TVO driver");
+MODULE_LICENSE("GPL");
X module_init(matroxfb_maven_init);
X module_exit(matroxfb_maven_exit);
X /* we do not have __setup() yet */
diff -u --recursive --new-file v2.4.14/linux/drivers/video/matrox/matroxfb_misc.c linux/drivers/video/matrox/matroxfb_misc.c
--- v2.4.14/linux/drivers/video/matrox/matroxfb_misc.c Tue Oct 9 17:06:53 2001
+++ linux/drivers/video/matrox/matroxfb_misc.c Fri Nov 9 14:07:41 2001
@@ -657,3 +657,7 @@
X EXPORT_SYMBOL(matroxfb_fastfont_init); /* DAC1064, Ti3026 */
X EXPORT_SYMBOL(matroxfb_vgaHWinit); /* DAC1064, Ti3026 */
X EXPORT_SYMBOL(matroxfb_vgaHWrestore); /* DAC1064, Ti3026 */
+
+MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec <vand...@vc.cvut.cz>");
+MODULE_DESCRIPTION("Miscellaneous support for Matrox video cards");
+MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/video/platinumfb.c linux/drivers/video/platinumfb.c
--- v2.4.14/linux/drivers/video/platinumfb.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/platinumfb.c Wed Nov 14 14:52:20 2001
@@ -841,7 +841,7 @@
X if (!options || !*options)
X return 0;
X
- while (this_opt = strsep(&options, ",")) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {
X if (!strncmp(this_opt, "font:", 5)) {
X char *p;
X int i;
diff -u --recursive --new-file v2.4.14/linux/drivers/video/radeonfb.c linux/drivers/video/radeonfb.c
--- v2.4.14/linux/drivers/video/radeonfb.c Mon Nov 5 15:55:33 2001
+++ linux/drivers/video/radeonfb.c Wed Nov 14 14:52:20 2001
@@ -642,7 +642,9 @@
X if (!options || !*options)
X return 0;
X
- while (this_opt = strsep (&options, ",")) {
+ while ((this_opt = strsep (&options, ",")) != NULL) {
+ if (!*this_opt)
+ continue;
X if (!strncmp (this_opt, "font:", 5)) {
X char *p;
X int i;
@@ -889,7 +891,7 @@
X rinfo->palette[i].blue = default_blu[j];
X }
X
- pdev->driver_data = rinfo;
+ pci_set_drvdata(pdev, rinfo);
X
X if (register_framebuffer ((struct fb_info *) rinfo) < 0) {
X printk ("radeonfb: could not register framebuffer\n");
@@ -930,7 +932,7 @@
X
X static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
X {
- struct radeonfb_info *rinfo = pdev->driver_data;
+ struct radeonfb_info *rinfo = pci_get_drvdata(pdev);
X
X if (!rinfo)
X return;
diff -u --recursive --new-file v2.4.14/linux/drivers/video/retz3fb.c linux/drivers/video/retz3fb.c
--- v2.4.14/linux/drivers/video/retz3fb.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/retz3fb.c Wed Nov 14 14:52:20 2001
@@ -1348,7 +1348,9 @@
X if (!options || !*options)
X return 0;
X
- while (this_opt = strsep(&options, ",")) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!*this_opt)
+ continue;
X if (!strcmp(this_opt, "inverse")) {
X z3fb_inverse = 1;
X fb_invert_cmaps();
diff -u --recursive --new-file v2.4.14/linux/drivers/video/riva/fbdev.c linux/drivers/video/riva/fbdev.c
--- v2.4.14/linux/drivers/video/riva/fbdev.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/riva/fbdev.c Wed Nov 14 14:52:20 2001
@@ -2045,7 +2045,9 @@
X if (!options || !*options)
X return 0;
X
- while (this_opt = strsep(&options, ",")) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!*this_opt)
+ continue;
X if (!strncmp(this_opt, "font:", 5)) {
X char *p;
X int i;
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sa1100fb.c linux/drivers/video/sa1100fb.c
--- v2.4.14/linux/drivers/video/sa1100fb.c Mon Nov 5 15:55:33 2001
+++ linux/drivers/video/sa1100fb.c Wed Nov 14 14:52:20 2001
@@ -2369,7 +2369,7 @@
X if (!options || !*options)
X return 0;
X
- while (this_opt = strsep(&options, ",")) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {
X
X if (!strncmp(this_opt, "bpp:", 4))
X current_par.max_bpp =
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sgivwfb.c linux/drivers/video/sgivwfb.c
--- v2.4.14/linux/drivers/video/sgivwfb.c Tue Oct 23 22:48:53 2001
+++ linux/drivers/video/sgivwfb.c Wed Nov 14 14:52:20 2001
@@ -660,6 +660,7 @@
X
X /* XXX FIXME - should try to pick best refresh rate */
X /* for now, pick closest dot-clock within 3MHz*/
+#error "Floating point not allowed in kernel"
X req_dot = (int)((1.0e3/1.0e6) / (1.0e-12 * (float)var->pixclock));
X printk(KERN_INFO "sgivwfb: requested pixclock=%d ps (%d KHz)\n", var->pixclock,
X req_dot);
@@ -862,7 +863,7 @@
X if (!options || !*options)
X return 0;
X
- while (this_opt = strsep(&options, ",")) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {
X if (!strncmp(this_opt, "font:", 5))
X strcpy(fb_info.fontname, this_opt+5);
X }
@@ -954,6 +955,8 @@


X }
X
X #ifdef MODULE

+MODULE_LICENSE("GPL");
+
X int init_module(void)
X {
X return sgivwfb_init();
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/300vtbl.h linux/drivers/video/sis/300vtbl.h
--- v2.4.14/linux/drivers/video/sis/300vtbl.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/sis/300vtbl.h Fri Nov 9 14:11:14 2001
@@ -0,0 +1,1522 @@
+typedef struct _SiS300_StStruct {
+ UCHAR St_ModeID;
+ USHORT St_ModeFlag;
+ UCHAR St_StTableIndex;
+ UCHAR St_CRT2CRTC;
+ UCHAR St_ResInfo;
+ UCHAR VB_StTVFlickerIndex;
+ UCHAR VB_StTVEdgeIndex;
+ UCHAR VB_StTVYFilterIndex;
+} SiS300_StStruct;
+
+SiS300_StStruct SiS300_SModeIDTable[] =
+{
+ {0x01, 0x9208, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x01, 0x1210, 0x14, 0x01, 0x01, 0x00, 0x00, 0x00},
+ {0x01, 0x1010, 0x17, 0x02, 0x02, 0x00, 0x00, 0x00},
+ {0x03, 0x8208, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x03, 0x0210, 0x16, 0x01, 0x01, 0x00, 0x00, 0x00},
+ {0x03, 0x0010, 0x18, 0x02, 0x02, 0x00, 0x00, 0x00},
+ {0x05, 0x9209, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x06, 0x8209, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x07, 0x0000, 0x07, 0x03, 0x03, 0x00, 0x00, 0x00},
+ {0x07, 0x0000, 0x19, 0x02, 0x02, 0x00, 0x00, 0x00},
+ {0x0d, 0x920a, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x0e, 0x820a, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x0f, 0x0202, 0x11, 0x01, 0x01, 0x00, 0x00, 0x00},
+ {0x10, 0x0212, 0x12, 0x01, 0x01, 0x00, 0x00, 0x00},
+ {0x11, 0x0212, 0x1a, 0x04, 0x04, 0x00, 0x00, 0x00},
+ {0x12, 0x0212, 0x1b, 0x04, 0x04, 0x00, 0x00, 0x00},
+ {0x13, 0x021b, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x12, 0x0210, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x12, 0x0210, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00},
+ {0xff, 0, 0, 0, 0, 0, 0, 0}
+};
+
+typedef struct _SiS300_StandTableStruct {
+ UCHAR CRT_COLS;
+ UCHAR ROWS;
+ UCHAR CHAR_HEIGHT;
+ USHORT CRT_LEN;
+ UCHAR SR[4];
+ UCHAR MISC;
+ UCHAR CRTC[0x19];
+ UCHAR ATTR[0x14];
+ UCHAR GRC[9];
+} SiS300_StandTableStruct;
+
+SiS300_StandTableStruct SiS300_StandTable[] = {
+ {0x28, 0x18, 0x08, 0x0800,
+ {0x09, 0x03, 0x00, 0x02},
+ 0x63,
+ {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f,
+ 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}},
+ {0x28, 0x18, 0x08, 0x0800,
+ {0x09, 0x03, 0x00, 0x02},
+ 0x63,
+ {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f,
+ 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}},
+ {0x50, 0x18, 0x08, 0x1000,
+ {0x01, 0x03, 0x00, 0x02},
+ 0x63,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}},
+ {0x50, 0x18, 0x08, 0x1000,
+ {0x01, 0x03, 0x00, 0x02},
+ 0x63,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}},
+ {0x28, 0x18, 0x08, 0x4000,
+ {0x09, 0x03, 0x00, 0x02},
+ 0x63,
+ {0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f,
+ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2,
+ 0xff},
+ {0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x01, 0x00, 0x03, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x00,
+ 0xff}},
+ {0x28, 0x18, 0x08, 0x4000,
+ {0x09, 0x03, 0x00, 0x02},
+ 0x63,
+ {0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f,
+ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2,
+ 0xff},
+ {0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x01, 0x00, 0x03, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x00,
+ 0xff}},
+ {0x50, 0x18, 0x08, 0x4000,
+ {0x01, 0x01, 0x00, 0x06},
+ 0x63,
+ {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
+ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xc2,
+ 0xff},
+ {0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+ 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+ 0x01, 0x00, 0x01, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00,
+ 0xff}},
+ {0x50, 0x18, 0x0e, 0x1000,
+ {0x00, 0x03, 0x00, 0x03},
+ 0xa6,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x83, 0x85, 0x5d, 0x28, 0x0d, 0x63, 0xba, 0xa3,
+ 0xff},
+ {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x0e, 0x00, 0x0f, 0x08},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x00,
+ 0xff}},
+/* MDA_DAC*/
+ {0x00, 0x00, 0x00, 0x0000,
+ {0x00, 0x00, 0x00, 0x15},
+ 0x15,
+ {0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
+ 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3f, 0x3f,
+ 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00,
+ 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x15, 0x15,
+ 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
+ 0x15, 0x15, 0x15, 0x15},
+ {0x15, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+ 0x3f}},
+/* CGA_DAC*/
+ {0x00, 0x10, 0x04, 0x0114,
+ {0x11, 0x09, 0x15, 0x00},
+ 0x10,
+ {0x04, 0x14, 0x01, 0x11, 0x09, 0x15, 0x2a, 0x3a,
+ 0x2e, 0x3e, 0x2b, 0x3b, 0x2f, 0x3f, 0x2a, 0x3a,
+ 0x2e, 0x3e, 0x2b, 0x3b, 0x2f, 0x3f, 0x00, 0x10,
+ 0x04},
+ {0x14, 0x01, 0x11, 0x09, 0x15, 0x00, 0x10, 0x04,
+ 0x14, 0x01, 0x11, 0x09, 0x15, 0x2a, 0x3a, 0x2e,
+ 0x3e, 0x2b, 0x3b, 0x2f},
+ {0x3f, 0x2a, 0x3a, 0x2e, 0x3e, 0x2b, 0x3b, 0x2f,
+ 0x3f}},
+/* EGA_DAC*/
+ {0x00, 0x10, 0x04, 0x0114,
+ {0x11, 0x05, 0x15, 0x20},
+ 0x30,
+ {0x24, 0x34, 0x21, 0x31, 0x25, 0x35, 0x08, 0x18,
+ 0x0c, 0x1c, 0x09, 0x19, 0x0d, 0x1d, 0x28, 0x38,
+ 0x2c, 0x3c, 0x29, 0x39, 0x2d, 0x3d, 0x02, 0x12,
+ 0x06},
+ {0x16, 0x03, 0x13, 0x07, 0x17, 0x22, 0x32, 0x26,
+ 0x36, 0x23, 0x33, 0x27, 0x37, 0x0a, 0x1a, 0x0e,
+ 0x1e, 0x0b, 0x1b, 0x0f},
+ {0x1f, 0x2a, 0x3a, 0x2e, 0x3e, 0x2b, 0x3b, 0x2f,
+ 0x3f}},
+/* VGA_DAC*/
+ {0x00, 0x10, 0x04, 0x0114,
+ {0x11, 0x09, 0x15, 0x2a},
+ 0x3a,
+ {0x2e, 0x3e, 0x2b, 0x3b, 0x2f, 0x3f, 0x00, 0x05,
+ 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x18, 0x1c, 0x20,
+ 0x24, 0x28, 0x2d, 0x32, 0x38, 0x3f, 0x00, 0x10,
+ 0x1f},
+ {0x2f, 0x3f, 0x1f, 0x27, 0x2f, 0x37, 0x3f, 0x2d,
+ 0x31, 0x36, 0x3a, 0x3f, 0x00, 0x07, 0x0e, 0x15,
+ 0x1c, 0x0e, 0x11, 0x15},
+ {0x18, 0x1c, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x00,
+ 0x04}},
+ {0x08, 0x0c, 0x10, 0x0a08,
+ {0x0c, 0x0e, 0x10, 0x0b},
+ 0x0c,
+ {0x0d, 0x0f, 0x10, 0x10, 0x01, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x01, 0x00,
+ 0x04, 0x04, 0x01, 0x00, 0x05, 0x02, 0x05, 0x00,
+ 0x06},
+ {0x01, 0x06, 0x05, 0x06, 0x00, 0x08, 0x01, 0x08,
+ 0x00, 0x07, 0x02, 0x07, 0x06, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00}},
+ {0x28, 0x18, 0x08, 0x2000,
+ {0x09, 0x0f, 0x00, 0x06},
+ 0x63,
+ {0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f,
+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xe3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x01, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
+ 0xff}},
+ {0x50, 0x18, 0x08, 0x4000,
+ {0x01, 0x0f, 0x00, 0x06},
+ 0x63,
+ {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xe3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x01, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
+ 0xff}},
+ {0x00, 0x00, 0x00, 0x0000,
+ {0x01, 0x0f, 0x00, 0x0e},
+ 0x23,
+ {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x01, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
+ 0xff}},
+ {0x4a, 0x36, 0x00, 0x00c0,
+ {0x00, 0x00, 0x00, 0x00},
+ 0x00,
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3a,
+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1a, 0x00, 0x57, 0x39, 0x00, 0xc0,
+ 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}},
+ {0x50, 0x18, 0x0e, 0x8000,
+ {0x01, 0x0f, 0x00, 0x06},
+ 0xa2,
+ {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3,
+ 0xff},
+ {0x00, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
+ 0x0b, 0x00, 0x05, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05,
+ 0xff}},
+ {0x50, 0x18, 0x0e, 0x8000,
+ {0x01, 0x0f, 0x00, 0x06},
+ 0xa3,
+ {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x01, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
+ 0xff}},
+ {0x28, 0x18, 0x0e, 0x0800,
+ {0x09, 0x03, 0x00, 0x02},
+ 0xa3,
+ {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f,
+ 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x83, 0x85, 0x5d, 0x14, 0x1f, 0x63, 0xba, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}},
+ {0x28, 0x18, 0x0e, 0x0800,
+ {0x09, 0x03, 0x00, 0x02},
+ 0xa3,
+ {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f,
+ 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x83, 0x85, 0x5d, 0x14, 0x1f, 0x63, 0xba, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}},
+ {0x50, 0x18, 0x0e, 0x1000,
+ {0x01, 0x03, 0x00, 0x02},
+ 0xa3,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x83, 0x85, 0x5d, 0x28, 0x1f, 0x63, 0xba, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}},
+ {0x50, 0x18, 0x0e, 0x1000,
+ {0x01, 0x03, 0x00, 0x02},
+ 0xa3,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x83, 0x85, 0x5d, 0x28, 0x1f, 0x63, 0xba, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}},
+ {0x28, 0x18, 0x10, 0x0800,
+ {0x08, 0x03, 0x00, 0x02},
+ 0x67,
+ {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f,
+ 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x0c, 0x00, 0x0f, 0x08},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}},
+ {0x50, 0x18, 0x10, 0x1000,
+ {0x00, 0x03, 0x00, 0x02},
+ 0x67,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x0c, 0x00, 0x0f, 0x08},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}},
+ {0x50, 0x18, 0x10, 0x1000,
+ {0x00, 0x03, 0x00, 0x02},
+ 0x66,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x0f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x0e, 0x00, 0x0f, 0x08},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x00,
+ 0xff}},
+ {0x50, 0x1d, 0x10, 0xa000,
+ {0x01, 0x0f, 0x00, 0x06},
+ 0xe3,
+ {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xc3,
+ 0xff},
+ {0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+ 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+ 0x01, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01,
+ 0xff}},
+ {0x50, 0x1d, 0x10, 0xa000,
+ {0x01, 0x0f, 0x00, 0x06},
+ 0xe3,
+ {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x01, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
+ 0xff}},
+ {0x28, 0x18, 0x08, 0x2000,
+ {0x01, 0x0f, 0x00, 0x0e},
+ 0x63,
+ {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
+ 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x41, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
+ 0xff}}
+};
+
+typedef struct _SiS300_ExtStruct {
+ UCHAR Ext_ModeID;
+ USHORT Ext_ModeFlag;
+ USHORT Ext_ModeInfo;
+ USHORT Ext_Point;
+ USHORT Ext_VESAID;
+ UCHAR Ext_VESAMEMSize;
+ UCHAR Ext_RESINFO;
+ UCHAR VB_ExtTVFlickerIndex;
+ UCHAR VB_ExtTVEdgeIndex;
+ UCHAR VB_ExtTVYFilterIndex;
+ UCHAR REFindex;
+} SiS300_ExtStruct;
+SiS300_ExtStruct SiS300_EModeIDTable[] = {
+ {0x6a, 0x2212, 0x47, 0x3563, 0x0102, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00},
+ {0x2e, 0x0a1b, 0x36, 0x3539, 0x0101, 0x08, 0x06, 0x00, 0x00, 0x00, 0x08},
+ {0x2f, 0x021b, 0x35, 0x3532, 0x0100, 0x08, 0x05, 0x00, 0x00, 0x00, 0x10},
+ {0x30, 0x2a1b, 0x47, 0x3563, 0x0103, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00},
+ {0x31, 0x0a1b, 0xad, 0x3630, 0x0000, 0x08, 0x0c, 0x00, 0x00, 0x00, 0x11},
+ {0x32, 0x2a1b, 0xae, 0x3637, 0x0000, 0x08, 0x0d, 0x00, 0x00, 0x00, 0x12},
+ {0x33, 0x0a1d, 0xad, 0x3630, 0x0000, 0x08, 0x0c, 0x00, 0x00, 0x00, 0x11},
+ {0x34, 0x2a1d, 0xae, 0x3637, 0x0000, 0x08, 0x0d, 0x00, 0x00, 0x00, 0x12},
+ {0x35, 0x0a1f, 0xad, 0x3630, 0x0000, 0x08, 0x0c, 0x00, 0x00, 0x00, 0x11},
+ {0x36, 0x2a1f, 0xae, 0x3637, 0x0000, 0x08, 0x0d, 0x00, 0x00, 0x00, 0x12},
+ {0x37, 0x0212, 0x58, 0x358d, 0x0104, 0x08, 0x08, 0x00, 0x00, 0x00, 0x13},
+ {0x38, 0x0a1b, 0x58, 0x358d, 0x0105, 0x08, 0x08, 0x00, 0x00, 0x00, 0x13},
+ {0x3a, 0x0e3b, 0x69, 0x35be, 0x0107, 0x08, 0x09, 0x00, 0x00, 0x00, 0x1a},
+ {0x3c, 0x063b, 0x7a, 0x35d4, 0x0130, 0x08, 0x0a, 0x00, 0x00, 0x00, 0x1e},
+ {0x3d, 0x067d, 0x7a, 0x35d4, 0x0131, 0x08, 0x0a, 0x00, 0x00, 0x00, 0x1e},
+ {0x40, 0x921c, 0x00, 0x3516, 0x010d, 0x08, 0x00, 0x00, 0x00, 0x00, 0x23},
+ {0x41, 0x921d, 0x00, 0x3516, 0x010e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x23},
+ {0x43, 0x0a1c, 0x36, 0x3539, 0x0110, 0x08, 0x06, 0x00, 0x00, 0x00, 0x08},
+ {0x44, 0x0a1d, 0x36, 0x3539, 0x0111, 0x08, 0x06, 0x00, 0x00, 0x00, 0x08},
+ {0x46, 0x2a1c, 0x47, 0x3563, 0x0113, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00},
+ {0x47, 0x2a1d, 0x47, 0x3563, 0x0114, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00},
+ {0x49, 0x0a3c, 0x58, 0x358d, 0x0116, 0x08, 0x08, 0x00, 0x00, 0x00, 0x13},
+ {0x4a, 0x0a3d, 0x58, 0x358d, 0x0117, 0x08, 0x08, 0x00, 0x00, 0x00, 0x13},
+ {0x4c, 0x0e7c, 0x69, 0x35be, 0x0119, 0x08, 0x09, 0x00, 0x00, 0x00, 0x1a},
+ {0x4d, 0x0e7d, 0x69, 0x35be, 0x011a, 0x08, 0x09, 0x00, 0x00, 0x00, 0x1a},
+ {0x50, 0x921b, 0x01, 0x351d, 0x0132, 0x08, 0x01, 0x00, 0x00, 0x00, 0x24},
+ {0x51, 0x921b, 0x13, 0x3524, 0x0133, 0x08, 0x03, 0x00, 0x00, 0x00, 0x25},
+ {0x52, 0x921b, 0x24, 0x352b, 0x0134, 0x08, 0x04, 0x00, 0x00, 0x00, 0x26},
+ {0x56, 0x921d, 0x01, 0x351d, 0x0135, 0x08, 0x01, 0x00, 0x00, 0x00, 0x24},
+ {0x57, 0x921d, 0x13, 0x3524, 0x0136, 0x08, 0x03, 0x00, 0x00, 0x00, 0x25},
+ {0x58, 0x921d, 0x24, 0x352b, 0x0137, 0x08, 0x04, 0x00, 0x00, 0x00, 0x26},
+ {0x59, 0x921b, 0x00, 0x3516, 0x0138, 0x08, 0x00, 0x00, 0x00, 0x00, 0x23},
+ {0x5d, 0x021d, 0x35, 0x3532, 0x0139, 0x08, 0x05, 0x00, 0x00, 0x00, 0x10},
+ {0x62, 0x0a3f, 0x36, 0x3539, 0x013a, 0x08, 0x06, 0x00, 0x00, 0x00, 0x08},
+ {0x63, 0x2a3f, 0x47, 0x3563, 0x013b, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00},
+ {0x64, 0x0a7f, 0x58, 0x358d, 0x013c, 0x08, 0x08, 0x00, 0x00, 0x00, 0x13},
+ {0x65, 0x0eff, 0x69, 0x35be, 0x013d, 0x08, 0x09, 0x00, 0x00, 0x00, 0x1a},
+ {0x66, 0x06ff, 0x7a, 0x35d4, 0x013e, 0x08, 0x0a, 0x00, 0x00, 0x00, 0x1e},
+ {0x68, 0x067b, 0x8b, 0x35ef, 0x013f, 0x08, 0x0b, 0x00, 0x00, 0x00, 0x27},
+ {0x69, 0x06fd, 0x8b, 0x35ef, 0x0140, 0x08, 0x0b, 0x00, 0x00, 0x00, 0x27},
+ {0x6b, 0x07ff, 0x8b, 0x35ef, 0x0000, 0x10, 0x0b, 0x00, 0x00, 0x00, 0x27},
+ {0x6c, 0x067b, 0x9c, 0x35f6, 0x0000, 0x08, 0x0c, 0x00, 0x00, 0x00, 0x28},
+ {0x6d, 0x06fd, 0x9c, 0x35f6, 0x0000, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x28},
+ {0x6e, 0x0e3b, 0x6f, 0x35b2, 0x0000, 0x08, 0x0e, 0x00, 0x00, 0x00, 0x29},
+ {0x6f, 0x0e7d, 0x6f, 0x35b2, 0x0000, 0x08, 0x0e, 0x00, 0x00, 0x00, 0x29},
+ {0x7b, 0x0eff, 0x6f, 0x35b2, 0x0000, 0x08, 0x0e, 0x00, 0x00, 0x00, 0x29},
+ {0x7c, 0x221b, 0xb3, 0x363e, 0x0000, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x2b},
+ {0x7d, 0x221d, 0xb3, 0x363e, 0x0000, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x2b},
+ {0x7e, 0x223f, 0xb3, 0x363e, 0x0000, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x2b},
+ {0xff, 0x0000, 0x00, 0x0000, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+typedef struct _SiS300_Ext2Struct {
+ USHORT Ext_InfoFlag;
+ UCHAR Ext_CRT1CRTC;
+ UCHAR Ext_CRTVCLK;
+ UCHAR Ext_CRT2CRTC;
+ UCHAR ModeID;
+ USHORT XRes;
+ USHORT YRes;
+ USHORT ROM_OFFSET;
+} SiS300_Ext2Struct;
+SiS300_Ext2Struct SiS300_RefIndex[] = {
+ {0x085f, 0x0d, 0x03, 0x05, 0x6a, 800, 600, 0x3563},
+ {0x0467, 0x0e, 0x44, 0x05, 0x6a, 800, 600, 0x3568},
+ {0x0067, 0x4f, 0x07, 0x48, 0x6a, 800, 600, 0x356d},
+ {0x0067, 0x10, 0x06, 0x8b, 0x6a, 800, 600, 0x3572},
+ {0x0147, 0x11, 0x08, 0x00, 0x6a, 800, 600, 0x3577},
+ {0x0147, 0x12, 0x0c, 0x00, 0x6a, 800, 600, 0x357c},
+ {0x0047, 0x51, 0x4e, 0x00, 0x6a, 800, 600, 0x3581},
+ {0x0047, 0x11, 0x13, 0x00, 0x6a, 800, 600, 0x3586},
+ {0xc85f, 0x05, 0x00, 0x04, 0x2e, 640, 480, 0x3539},
+ {0xc067, 0x06, 0x02, 0x04, 0x2e, 640, 480, 0x353e},
+ {0xc067, 0x07, 0x02, 0x47, 0x2e, 640, 480, 0x3543},
+ {0xc067, 0x08, 0x03, 0x8a, 0x2e, 640, 480, 0x3548},
+ {0xc047, 0x09, 0x05, 0x00, 0x2e, 640, 480, 0x354d},
+ {0xc047, 0x0a, 0x08, 0x00, 0x2e, 640, 480, 0x3552},
+ {0xc047, 0x0b, 0x0a, 0x00, 0x2e, 640, 480, 0x3557},
+ {0xc047, 0x0c, 0x10, 0x00, 0x2e, 640, 480, 0x355c},
+ {0x487f, 0x04, 0x00, 0x00, 0x2f, 640, 400, 0x3532},
+ {0xc00f, 0x31, 0x01, 0x06, 0x31, 2048, 1536, 0x3630},
+ {0x000f, 0x32, 0x03, 0x06, 0x32, 720, 480, 0x3637},
+ {0x0187, 0x15, 0x05, 0x00, 0x37, 1024, 768, 0x358d},
+ {0xc877, 0x16, 0x09, 0x06, 0x37, 1024, 768, 0x3592},
+ {0xc067, 0x97, 0x0b, 0x49, 0x37, 1024, 768, 0x3597},
+ {0x0267, 0x18, 0x0d, 0x00, 0x37, 1024, 768, 0x359c},
+ {0x0047, 0x59, 0x11, 0x8c, 0x37, 1024, 768, 0x35a1},
+ {0x0047, 0x1a, 0x52, 0x00, 0x37, 1024, 768, 0x35a6},
+ {0x0047, 0x5b, 0x16, 0x00, 0x37, 1024, 768, 0x35ab},
+ {0x0387, 0x5c, 0x4d, 0x00, 0x3a, 1280, 1024, 0x35be},
+ {0x0077, 0x1d, 0x14, 0x07, 0x3a, 1280, 1024, 0x35c3},
+ {0x0047, 0x1e, 0x17, 0x00, 0x3a, 1280, 1024, 0x35c8},
+ {0x0007, 0x1f, 0x98, 0x00, 0x3a, 1280, 1024, 0x35cd},
+ {0x0007, 0x60, 0x59, 0x00, 0x3c, 1600, 1200, 0x35d4},
+ {0x0007, 0x21, 0x5a, 0x00, 0x3c, 1600, 1200, 0x35d9},
+ {0x0007, 0x22, 0x1b, 0x00, 0x3c, 1600, 1200, 0x35de},
+ {0x0007, 0x63, 0x1d, 0x00, 0x3c, 1600, 1200, 0x35e3},
+ {0x0007, 0x24, 0x1e, 0x00, 0x3c, 1600, 1200, 0x35e8},
+ {0x407f, 0x00, 0x00, 0x00, 0x40, 320, 200, 0x3516},
+ {0xc07f, 0x01, 0x00, 0x04, 0x50, 320, 240, 0x351d},
+ {0x0077, 0x02, 0x04, 0x05, 0x51, 400, 300, 0x3524},
+ {0xc077, 0x03, 0x09, 0x06, 0x52, 512, 384, 0x352b},
+ {0x8207, 0x25, 0x1f, 0x00, 0x68, 1920, 1440, 0x35ef},
+ {0x0007, 0x26, 0x20, 0x00, 0x6c, 2048, 1536, 0x35f6},
+ {0x0027, 0x27, 0x14, 0x08, 0x6e, 720, 576, 0x35b2},
+ {0x0027, 0x27, 0x14, 0x08, 0x6e, 720, 576, 0x35b7},
+ {0x00df, 0x33, 0x28, 0x00, 0x7c, 1280, 960, 0x363e},
+ {0xc05f, 0x34, 0x28, 0x00, 0x7c, 1280, 960, 0x3643},
+ {0xffff, 0, 0, 0, 0, 0, 0, 0}
+};
+
+/*add for 300 oem util*/
+typedef struct _SiS_VBModeIDTableStruct {
+ UCHAR ModeID;
+ UCHAR VB_TVDelayIndex;
+ UCHAR VB_TVFlickerIndex;
+ UCHAR VB_TVPhaseIndex;
+ UCHAR VB_TVYFilterIndex;
+ UCHAR VB_LCDDelayIndex;
+ UCHAR _VB_LCDHIndex;
+ UCHAR _VB_LCDVIndex;
+} SiS_VBModeIDTableStruct;
+SiS_VBModeIDTableStruct SiS300_VBModeIDTable[] = {
+ {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+ {0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02},
+ {0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00},
+ {0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01},
+ {0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x02},
+ {0x05, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00},
+ {0x06, 0x00, 0x00, 0x01, 0x05, 0x00, 0x02, 0x00},
+ {0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x01},
+ {0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x02},
+ {0x0d, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00},
+ {0x0e, 0x00, 0x00, 0x01, 0x05, 0x00, 0x02, 0x00},
+ {0x0f, 0x00, 0x00, 0x01, 0x05, 0x00, 0x02, 0x01},
+ {0x10, 0x00, 0x00, 0x01, 0x05, 0x00, 0x02, 0x01},
+ {0x11, 0x00, 0x00, 0x01, 0x05, 0x00, 0x02, 0x03},
+ {0x12, 0x00, 0x00, 0x01, 0x05, 0x00, 0x02, 0x03},
+ {0x13, 0x00, 0x00, 0x01, 0x04, 0x00, 0x04, 0x00},
+ {0x6a, 0x00, 0x00, 0x01, 0x07, 0x00, 0x08, 0x0a},
+ {0x2e, 0x00, 0x00, 0x01, 0x05, 0x00, 0x06, 0x08},
+ {0x2f, 0x00, 0x00, 0x01, 0x05, 0x00, 0x06, 0x06},
+ {0x30, 0x00, 0x00, 0x01, 0x07, 0x00, 0x08, 0x0a},
+ {0x31, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00},
+ {0x32, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00},
+ {0x37, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x0c},
+ {0x38, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x0c},
+ {0x3a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x0d},
+ {0x40, 0x00, 0x00, 0x01, 0x04, 0x00, 0x05, 0x05},
+ {0x41, 0x00, 0x00, 0x01, 0x04, 0x00, 0x05, 0x05},
+ {0x43, 0x00, 0x00, 0x01, 0x05, 0x00, 0x06, 0x08},
+ {0x44, 0x00, 0x00, 0x01, 0x05, 0x00, 0x06, 0x08},
+ {0x46, 0x00, 0x00, 0x01, 0x07, 0x00, 0x08, 0x0a},
+ {0x47, 0x00, 0x00, 0x01, 0x07, 0x00, 0x08, 0x0a},
+ {0x49, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x0c},
+ {0x4a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x0c},
+ {0x4c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x0d},
+ {0x4d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x0d},
+ {0x50, 0x00, 0x00, 0x01, 0x04, 0x00, 0x05, 0x07},
+ {0x51, 0x00, 0x00, 0x01, 0x07, 0x00, 0x07, 0x09},
+ {0x52, 0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x0b},
+ {0x56, 0x00, 0x00, 0x01, 0x04, 0x00, 0x05, 0x07},
+ {0x57, 0x00, 0x00, 0x01, 0x07, 0x00, 0x07, 0x09},
+ {0x58, 0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x0b},
+ {0x59, 0x00, 0x00, 0x01, 0x04, 0x00, 0x05, 0x05},
+ {0x5d, 0x00, 0x00, 0x01, 0x07, 0x00, 0x06, 0x06},
+ {0x62, 0x00, 0x00, 0x01, 0x05, 0x00, 0x06, 0x08},
+ {0x63, 0x00, 0x00, 0x01, 0x07, 0x00, 0x08, 0x0a},
+ {0x64, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x0c},
+ {0x65, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x0d},
+ {0x6e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x0d},
+ {0x6f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x0d},
+ {0x7b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x0d}
+};
+/*end*/
+
+typedef struct _SiS300_CRT1TableStruct {
+ UCHAR CR[17];
+} SiS300_CRT1TableStruct;
+SiS300_CRT1TableStruct SiS300_CRT1Table[] = {
+ {{0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0xbf, 0x1f,
+ 0x9c, 0x8e, 0x8f, 0x96, 0xb9, 0x30, 0x00, 0x04,
+ 0x00}},
+ {{0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0x0b, 0x3e,
+ 0xe9, 0x8b, 0xdf, 0xe7, 0x04, 0x00, 0x00, 0x04,
+ 0x00}},
+ {{0x3d, 0x31, 0x31, 0x81, 0x37, 0x1f, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x57, 0x73, 0x20, 0x00, 0x05,
+ 0x01}},
+ {{0x4f, 0x3f, 0x3f, 0x93, 0x45, 0x0d, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0xff, 0x25, 0x10, 0x00, 0x01,
+ 0x01}},
+ {{0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x9c, 0x8e, 0x8f, 0x96, 0xb9, 0x30, 0x00, 0x05,
+ 0x00}},
+ {{0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0x0b, 0x3e,
+ 0xe9, 0x8b, 0xdf, 0xe7, 0x04, 0x00, 0x00, 0x05,
+ 0x00}},
+ {{0x63, 0x4f, 0x50, 0x86, 0x56, 0x9b, 0x06, 0x3e,
+ 0xe8, 0x8b, 0xdf, 0xe7, 0xff, 0x10, 0x00, 0x01,
+ 0x00}},
+ {{0x64, 0x4f, 0x4f, 0x88, 0x55, 0x9d, 0xf2, 0x1f,
+ 0xe0, 0x83, 0xdf, 0xdf, 0xf3, 0x10, 0x00, 0x01,
+ 0x00}},
+ {{0x63, 0x4f, 0x4f, 0x87, 0x5a, 0x81, 0xfb, 0x1f,
+ 0xe0, 0x83, 0xdf, 0xdf, 0xfc, 0x10, 0x00, 0x05,
+ 0x00}},
+ {{0x66, 0x4f, 0x4f, 0x86, 0x56, 0x9e, 0x03, 0x3e,
+ 0xe4, 0x87, 0xdf, 0xdf, 0x04, 0x00, 0x00, 0x01,
+ 0x00}},
+ {{0x6c, 0x4f, 0x4f, 0x83, 0x59, 0x9e, 0x00, 0x3e,
+ 0xe5, 0x8d, 0xdf, 0xdf, 0x01, 0x00, 0x00, 0x01,
+ 0x00}},
+ {{0x63, 0x4f, 0x4f, 0x87, 0x56, 0x9d, 0xfb, 0x1f,
+ 0xe0, 0x83, 0xdf, 0xdf, 0xfc, 0x10, 0x00, 0x01,
+ 0x00}},
+ {{0x65, 0x4f, 0x4f, 0x89, 0x57, 0x9f, 0xfb, 0x1f,
+ 0xe6, 0x8a, 0xe5, 0xe5, 0xfc, 0x00, 0x00, 0x01,
+ 0x00}},
+ {{0x7b, 0x63, 0x63, 0x9f, 0x6a, 0x93, 0x6f, 0xf0,
+ 0x58, 0x8a, 0x57, 0x57, 0x70, 0x20, 0x00, 0x05,
+ 0x01}},
+ {{0x7f, 0x63, 0x63, 0x83, 0x6c, 0x1c, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x57, 0x73, 0x20, 0x00, 0x06,
+ 0x01}},
+ {{0x7d, 0x63, 0x63, 0x81, 0x6e, 0x1d, 0x98, 0xf0,
+ 0x7c, 0x82, 0x57, 0x57, 0x99, 0x00, 0x00, 0x06,
+ 0x01}},
+ {{0x7f, 0x63, 0x63, 0x83, 0x69, 0x13, 0x6f, 0xf0,
+ 0x58, 0x8b, 0x57, 0x57, 0x70, 0x20, 0x00, 0x06,
+ 0x01}},
+ {{0x7e, 0x63, 0x63, 0x82, 0x6b, 0x13, 0x75, 0xf0,
+ 0x58, 0x8b, 0x57, 0x57, 0x76, 0x20, 0x00, 0x06,
+ 0x01}},
+ {{0x8c, 0x63, 0x63, 0x87, 0x72, 0x16, 0x7e, 0xf0,
+ 0x59, 0x8d, 0x57, 0x57, 0x7f, 0x00, 0x00, 0x06,
+ 0x01}},
+ {{0x7e, 0x63, 0x63, 0x82, 0x6c, 0x14, 0x75, 0xe0,
+ 0x58, 0x0b, 0x57, 0x57, 0x76, 0x20, 0x00, 0x06,
+ 0x01}},
+ {{0x7e, 0x63, 0x63, 0x82, 0x6c, 0x14, 0x75, 0xe0,
+ 0x58, 0x0b, 0x57, 0x57, 0x76, 0x20, 0x00, 0x06,
+ 0x01}},
+ {{0x99, 0x7f, 0x7f, 0x9d, 0x84, 0x1a, 0x96, 0x1f,
+ 0x7f, 0x83, 0x7f, 0x7f, 0x97, 0x10, 0x00, 0x02,
+ 0x00}},
+ {{0xa3, 0x7f, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0xff, 0x25, 0x10, 0x00, 0x02,
+ 0x01}},
+ {{0xa1, 0x7f, 0x7f, 0x85, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0xff, 0x25, 0x10, 0x00, 0x02,
+ 0x01}},
+ {{0x9f, 0x7f, 0x7f, 0x83, 0x85, 0x91, 0x1e, 0xf5,
+ 0x00, 0x83, 0xff, 0xff, 0x1f, 0x10, 0x00, 0x02,
+ 0x01}},
+ {{0xa7, 0x7f, 0x7f, 0x8b, 0x89, 0x95, 0x26, 0xf5,
+ 0x00, 0x83, 0xff, 0xff, 0x27, 0x10, 0x00, 0x02,
+ 0x01}},
+ {{0x9f, 0x7f, 0x7f, 0x83, 0x83, 0x93, 0x1e, 0xf5,
+ 0x00, 0x84, 0xff, 0xff, 0x1f, 0x10, 0x00, 0x02,
+ 0x01}},
+ {{0xa2, 0x7f, 0x7f, 0x86, 0x84, 0x94, 0x37, 0xf5,
+ 0x0b, 0x82, 0xff, 0xff, 0x38, 0x10, 0x00, 0x02,
+ 0x01}},
+ {{0xcf, 0x9f, 0x9f, 0x93, 0xb2, 0x01, 0x14, 0xba,
+ 0x00, 0x83, 0xff, 0xff, 0x15, 0x00, 0x00, 0x03,
+ 0x00}},
+ {{0xce, 0x9f, 0x9f, 0x92, 0xa9, 0x17, 0x28, 0x5a,
+ 0x00, 0x83, 0xff, 0xff, 0x29, 0x09, 0x00, 0x07,
+ 0x01}},
+ {{0xce, 0x9f, 0x9f, 0x92, 0xa5, 0x17, 0x28, 0x5a,
+ 0x00, 0x83, 0xff, 0xff, 0x29, 0x09, 0x00, 0x07,
+ 0x01}},
+ {{0xd3, 0x9f, 0x9f, 0x97, 0xab, 0x1f, 0x2e, 0x5a,
+ 0x00, 0x83, 0xff, 0xff, 0x2f, 0x09, 0x00, 0x07,
+ 0x01}},
+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,
+ 0x00}},
+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,
+ 0x00}},
+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,
+ 0x00}},
+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,
+ 0x00}},
+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,
+ 0x00}},
+ {{0x3f, 0xef, 0xef, 0x83, 0xfd, 0x1a, 0xda, 0x1f,
+ 0xa0, 0x84, 0x9f, 0x9f, 0xdb, 0x1f, 0x01, 0x01,
+ 0x00}},
+ {{0x55, 0xff, 0xff, 0x99, 0x0d, 0x0c, 0x3e, 0xba,
+ 0x00, 0x84, 0xff, 0xff, 0x3f, 0x0f, 0x41, 0x05,
+ 0x00}},
+ {{0xdc, 0x9f, 0x9f, 0x00, 0xab, 0x19, 0xe6, 0xef,
+ 0xc0, 0xc3, 0xbf, 0xbf, 0xe7, 0x10, 0x00, 0x07,
+ 0x01}},
+ {{0x7f, 0x63, 0x63, 0x83, 0x6c, 0x1c, 0x72, 0xba,
+ 0x27, 0x8b, 0xdf, 0xdf, 0x73, 0x00, 0x00, 0x06,
+ 0x01}},
+ {{0x7f, 0x63, 0x63, 0x83, 0x69, 0x13, 0x6f, 0xba,
+ 0x26, 0x89, 0xdf, 0xdf, 0x6f, 0x00, 0x00, 0x06,
+ 0x01}},
+ {{0x7f, 0x63, 0x63, 0x82, 0x6b, 0x13, 0x75, 0xba,
+ 0x29, 0x8c, 0xdf, 0xdf, 0x75, 0x00, 0x00, 0x06,
+ 0x01}},
+ {{0xa3, 0x7f, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf1,
+ 0xaf, 0x85, 0x3f, 0x3f, 0x25, 0x30, 0x00, 0x02,
+ 0x01}},
+ {{0x9f, 0x7f, 0x7f, 0x83, 0x85, 0x91, 0x1e, 0xf1,
+ 0xad, 0x81, 0x3f, 0x3f, 0x1f, 0x30, 0x00, 0x02,
+ 0x01}},
+ {{0xa7, 0x7f, 0x7f, 0x88, 0x89, 0x15, 0x26, 0xf1,
+ 0xb1, 0x85, 0x3f, 0x3f, 0x27, 0x30, 0x00, 0x02,
+ 0x01}},
+ {{0xce, 0x9f, 0x9f, 0x92, 0xa9, 0x17, 0x28, 0xc4,
+ 0x7a, 0x8e, 0xcf, 0xcf, 0x29, 0x21, 0x00, 0x07,
+ 0x01}},
+ {{0xce, 0x9f, 0x9f, 0x92, 0xa5, 0x17, 0x28, 0xd4,
+ 0x7a, 0x8e, 0xcf, 0xcf, 0x29, 0x21, 0x00, 0x07,
+ 0x01}},
+ {{0xd3, 0x9f, 0x9f, 0x97, 0xab, 0x1f, 0x2e, 0xd4,
+ 0x7d, 0x81, 0xcf, 0xcf, 0x2f, 0x21, 0x00, 0x07,
+ 0x01}},
+ {{0x6b, 0x59, 0x59, 0x8f, 0x5e, 0x8c, 0x0b, 0x3e,
+ 0xe9, 0x8b, 0xdf, 0xe7, 0x04, 0x00, 0x00, 0x05,
+ 0x00}},
+ {{0x7b, 0x59, 0x63, 0x9f, 0x6a, 0x93, 0x6f, 0xf0,
+ 0x58, 0x8a, 0x3f, 0x57, 0x70, 0x20, 0x00, 0x05,
+ 0x01}},
+ {{0x86, 0x6a, 0x6a, 0x8a, 0x74, 0x06, 0x8c, 0x15,
+ 0x4f, 0x83, 0xef, 0xef, 0x8d, 0x30, 0x00, 0x02,
+ 0x00}},
+ {{0x81, 0x6a, 0x6a, 0x85, 0x70, 0x00, 0x0f, 0x3e,
+ 0xeb, 0x8e, 0xdf, 0xdf, 0x10, 0x00, 0x00, 0x02,
+ 0x00}}
+};
+
+typedef struct _SiS300_MCLKDataStruct {
+ UCHAR SR28, SR29, SR2A;
+ USHORT CLOCK;
+} SiS300_MCLKDataStruct;
+SiS300_MCLKDataStruct SiS300_MCLKData[] = {
+ {0x5a, 0x64, 0x80, 66},
+ {0xb3, 0x45, 0x80, 83},
+ {0x37, 0x61, 0x80, 100},
+ {0x37, 0x22, 0x80, 133},
+ {0x37, 0x61, 0x80, 100},
+ {0x37, 0x61, 0x80, 100},
+ {0x37, 0x61, 0x80, 100},
+ {0x37, 0x61, 0x80, 100}
+};
+
+typedef struct _SiS300_ECLKDataStruct {
+ UCHAR SR2E, SR2F, SR30;
+ USHORT CLOCK;
+} SiS300_ECLKDataStruct;
+SiS300_ECLKDataStruct SiS300_ECLKData[] = {
+ {0x54, 0x43, 0x80, 100},
+ {0x53, 0x43, 0x80, 100},
+ {0x55, 0x43, 0x80, 100},
+ {0x52, 0x43, 0x80, 100},
+ {0x3f, 0x42, 0x80, 100},
+ {0x54, 0x43, 0x80, 100},
+ {0x54, 0x43, 0x80, 100},
+ {0x54, 0x43, 0x80, 100}
+};
+
+typedef struct _SiS300_VCLKDataStruct {
+ UCHAR SR2B, SR2C;
+ USHORT CLOCK;
+} SiS300_VCLKDataStruct;
+SiS300_VCLKDataStruct SiS300_VCLKData[] = {
+ {0x1b, 0xe1, 25},
+ {0x4e, 0xe4, 28},
+ {0x57, 0xe4, 32},
+ {0xc3, 0xc8, 36},
+ {0x42, 0xc3, 40},
+ {0x5d, 0xc4, 45},
+ {0x52, 0x65, 50},
+ {0x53, 0x65, 50},
+ {0x6d, 0x66, 56},
+ {0x5a, 0x64, 65},
+ {0x46, 0x44, 68},
+ {0x3e, 0x43, 75},
+ {0x6d, 0x46, 76},
+ {0x41, 0x43, 79},
+ {0x31, 0x42, 79},
+ {0x46, 0x25, 85},
+ {0x78, 0x29, 87},
+ {0x62, 0x44, 95},
+ {0x2b, 0x22, 105},
+ {0x49, 0x24, 106},
+ {0xc3, 0x28, 108},
+ {0x3c, 0x23, 109},
+ {0xf7, 0x2c, 132},
+ {0xd4, 0x28, 136},
+ {0x41, 0x05, 158},
+ {0x43, 0x05, 162},
+ {0xe1, 0x0f, 175},
+ {0xfc, 0x12, 189},
+ {0xde, 0x26, 194},
+ {0x54, 0x05, 203},
+ {0x3f, 0x03, 230},
+ {0x30, 0x02, 234},
+ {0x24, 0x01, 266},
+ {0x52, 0x2a, 54},
+ {0x52, 0x6a, 27},
+ {0x62, 0x24, 70},
+ {0x62, 0x64, 70},
+ {0xa8, 0x4c, 30},
+ {0x20, 0x26, 33},
+ {0x31, 0xc2, 39},
+ {0xbf, 0xc8, 35},
+ {0x60, 0x36, 30},
+ {0x40, 0x4a, 28},
+ {0x9f, 0x46, 44},
+ {0x97, 0x2c, 26},
+ {0x44, 0xe4, 25},
+ {0x7e, 0x32, 47},
+ {0x8a, 0x24, 31},
+ {0x97, 0x2c, 26},
+ {0xce, 0x3c, 39},
+ {0x52, 0x4a, 36},
+ {0x34, 0x61, 95},
+ {0x78, 0x27, 108},
+ {0xff, 0x1b, 6625}
+};
+
+UCHAR SiS300_ScreenOffset[] =
+ { 0x14, 0x19, 0x20, 0x28, 0x32, 0x40, 0x50, 0x64, 0x78, 0x80, 0x2d, 0x35,
+ 0xff };
+
+typedef struct _SiS300_StResInfoStruct {
+ USHORT HTotal;
+ USHORT VTotal;
+} SiS300_StResInfoStruct;
+SiS300_StResInfoStruct SiS300_StResInfo[] = {
+ {640, 400},
+ {640, 350},
+ {720, 400},
+ {720, 350},
+ {640, 480}
+};
+
+typedef struct _SiS300_ModeResInfoStruct {
+ USHORT HTotal;
+ USHORT VTotal;
+ UCHAR XChar;
+ UCHAR YChar;
+} SiS300_ModeResInfoStruct;
+SiS300_ModeResInfoStruct SiS300_ModeResInfo[] = {
+ {320, 200, 8, 8},
+ {320, 240, 8, 8},
+ {320, 400, 8, 8},
+ {400, 300, 8, 8},
+ {512, 384, 8, 8},
+ {640, 400, 8, 16},
+ {640, 480, 8, 16},
+ {800, 600, 8, 16},
+ {1024, 768, 8, 16},
+ {1280, 1024, 8, 16},
+ {1600, 1200, 8, 16},
+ {1920, 1440, 8, 16},
+ {720, 480, 8, 16},
+ {720, 576, 8, 16},
+ {1280, 960, 8, 16}
+};
+
+UCHAR SiS300_OutputSelect = 0x40;
+UCHAR SiS300_SoftSetting = 30;
+UCHAR SiS300_SR07 = 0x10;
+UCHAR SiS300_SR15[8][4] = {
+ {0x1, 0x9, 0xa3, 0x0},
+ {0x43, 0x43, 0x43, 0x0},
+ {0x1e, 0x1e, 0x1e, 0x0},
+ {0x2a, 0x2a, 0x2a, 0x0},
+ {0x6, 0x6, 0x6, 0x0},
+ {0x0, 0x0, 0x0, 0x0},
+ {0x0, 0x0, 0x0, 0x0},
+ {0x0, 0x0, 0x0, 0x0}
+};
+UCHAR SiS300_SR1F = 0x0;
+UCHAR SiS300_SR21 = 0x16;
+UCHAR SiS300_SR22 = 0xb2;
+UCHAR SiS300_SR23 = 0xf6;
+UCHAR SiS300_SR24 = 0xd;
+UCHAR SiS300_SR25[] = { 0x0, 0x0 };
+UCHAR SiS300_SR31 = 0x0;
+UCHAR SiS300_SR32 = 0x11;
+UCHAR SiS300_SR33 = 0x0;
+UCHAR SiS300_CRT2Data_1_2 = 0x40;
+UCHAR SiS300_CRT2Data_4_D = 0x0;
+UCHAR SiS300_CRT2Data_4_E = 0x0;
+UCHAR SiS300_CRT2Data_4_10 = 0x80;
+USHORT SiS300_RGBSenseData = 0xd1;
+USHORT SiS300_VideoSenseData = 0xb3;
+USHORT SiS300_YCSenseData = 0xb9;
+USHORT SiS300_RGBSenseData2 = 0x0190; /*301b */
+USHORT SiS300_VideoSenseData2 = 0x0174;
+USHORT SiS300_YCSenseData2 = 0x016b;
+
+UCHAR SiS300_CR40[5][4];
+UCHAR SiS300_CR49[2];
+UCHAR SiS300_NTSCPhase[] = { 0x21, 0xed, 0x8a, 0x8 };
+UCHAR SiS300_PALPhase[] = { 0x2a, 0x5, 0xd3, 0x0 };
+UCHAR SiS300_NTSCPhase2[] = { 0x21, 0xF0, 0x7B, 0xD6 }; /*301b */
+UCHAR SiS300_PALPhase2[] = { 0x2a, 0x09, 0x86, 0xe9 };
+UCHAR SiS300_PALMPhase[] = { 0x21, 0xE4, 0x2E, 0x9B }; /*palmn */
+UCHAR SiS300_PALNPhase[] = { 0x21, 0xF4, 0x3E, 0xBA };
+
+typedef struct _SiS300_PanelDelayTblStruct {
+ UCHAR timer[2];
+} SiS300_PanelDelayTblStruct;
+SiS300_PanelDelayTblStruct SiS300_PanelDelayTbl[] = {
+ {{0x05, 0xaa}},
+ {{0x05, 0x14}},
+ {{0x05, 0x36}},
+ {{0x05, 0x14}},
+ {{0x05, 0x14}},
+ {{0x05, 0x14}},
+ {{0x05, 0x90}},
+ {{0x05, 0x90}},
+ {{0x05, 0x14}},
+ {{0x05, 0x14}},
+ {{0x05, 0x14}},
+ {{0x05, 0x14}},
+ {{0x05, 0x64}},
+ {{0x05, 0x14}},
+ {{0x05, 0x14}},
+ {{0x05, 0x14}}
+};
+
+typedef struct _SiS300_LCDDataStruct {
+ USHORT RVBHCMAX;
+ USHORT RVBHCFACT;
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;
+} SiS300_LCDDataStruct;
+SiS300_LCDDataStruct SiS300_StLCD1024x768Data[] = {
+ {66, 31, 992, 510, 1320, 816},
+ {66, 31, 992, 510, 1320, 816},
+ {176, 75, 900, 510, 1320, 816},
+ {176, 75, 900, 510, 1320, 816},
+ {66, 31, 992, 510, 1320, 816},
+ {27, 16, 1024, 650, 1350, 832},
+ {1, 1, 1344, 806, 1344, 806}
+};
+
+SiS300_LCDDataStruct SiS300_ExtLCD1024x768Data[] = {
+ {12, 5, 896, 512, 1344, 806},
+ {12, 5, 896, 510, 1344, 806},
+ {32, 15, 1008, 505, 1344, 806},
+ {32, 15, 1008, 514, 1344, 806},
+ {12, 5, 896, 500, 1344, 806},
+ {42, 25, 1024, 625, 1344, 806},
+ {1, 1, 1344, 806, 1344, 806},
+ {12, 5, 896, 500, 1344, 806},
+ {42, 25, 1024, 625, 1344, 806},
+ {1, 1, 1344, 806, 1344, 806},
+ {12, 5, 896, 500, 1344, 806},
+ {42, 25, 1024, 625, 1344, 806},
+ {1, 1, 1344, 806, 1344, 806}
+};
+
+SiS300_LCDDataStruct SiS300_St2LCD1024x768Data[] = {
+ {62, 25, 800, 546, 1344, 806},
+ {32, 15, 930, 546, 1344, 806},
+ {32, 15, 930, 546, 1344, 806},
+ {104, 45, 945, 496, 1344, 806},
+ {62, 25, 800, 546, 1344, 806},
+ {31, 18, 1008, 624, 1344, 806},
+ {1, 1, 1344, 806, 1344, 806}
+};
+
+SiS300_LCDDataStruct SiS300_StLCD1280x1024Data[] = {
+ {4, 1, 880, 510, 1650, 1088},
+ {4, 1, 880, 510, 1650, 1088},
+ {176, 45, 900, 510, 1650, 1088},
+ {176, 45, 900, 510, 1650, 1088},
+ {4, 1, 880, 510, 1650, 1088},
+ {13, 5, 1024, 675, 1560, 1152},
+ {16, 9, 1266, 804, 1688, 1072},
+ {1, 1, 1688, 1066, 1688, 1066}
+};
+
+SiS300_LCDDataStruct SiS300_ExtLCD1280x1024Data[] = {
+ {211, 60, 1024, 501, 1688, 1066},
+ {211, 60, 1024, 508, 1688, 1066},
+ {211, 60, 1024, 501, 1688, 1066},
+ {211, 60, 1024, 508, 1688, 1066},
+ {211, 60, 1024, 500, 1688, 1066},
+ {211, 75, 1024, 625, 1688, 1066},
+ {211, 120, 1280, 798, 1688, 1066},
+ {1, 1, 1688, 1066, 1688, 1066}
+};
+
+SiS300_LCDDataStruct SiS300_St2LCD1280x1024Data[] = {
+ {22, 5, 800, 510, 1650, 1088},
+ {22, 5, 800, 510, 1650, 1088},
+ {176, 45, 900, 510, 1650, 1088},
+ {176, 45, 900, 510, 1650, 1088},
+ {22, 5, 800, 510, 1650, 1088},
+ {13, 5, 1024, 675, 1560, 1152},
+ {16, 9, 1266, 804, 1688, 1072},
+ {1, 1, 1688, 1066, 1688, 1066}
+};
+
+SiS300_LCDDataStruct SiS300_NoScaleData[] = {
+ {1, 1, 800, 449, 800, 449},
+ {1, 1, 800, 449, 800, 449},
+ {1, 1, 900, 449, 900, 449},
+ {1, 1, 900, 449, 900, 449},
+ {1, 1, 800, 525, 800, 525},
+ {1, 1, 1056, 628, 1056, 628},
+ {1, 1, 1344, 806, 1344, 806},
+ {1, 1, 1688, 1066, 1688, 1066}
+};
+
+SiS300_LCDDataStruct SiS300_LCD1280x960Data[] = {
+ {9, 2, 800, 500, 1800, 1000},
+ {9, 2, 800, 500, 1800, 1000},
+ {4, 1, 900, 500, 1800, 1000},
+ {4, 1, 900, 500, 1800, 1000},
+ {9, 2, 800, 500, 1800, 1000},
+ {30, 11, 1056, 625, 1800, 1000},
+ {5, 3, 1350, 800, 1800, 1000},
+ {1, 1, 1576, 1050, 1576, 1050},
+ {1, 1, 1800, 1000, 1800, 1000}
+};
+
+typedef struct _SiS300_TVDataStruct {
+ USHORT RVBHCMAX;
+ USHORT RVBHCFACT;
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT TVHDE;
+ USHORT TVVDE;
+ USHORT RVBHRS;
+ UCHAR FlickerMode;
+ USHORT HALFRVBHRS;
+ UCHAR RY1COE;
+ UCHAR RY2COE;
+ UCHAR RY3COE;
+ UCHAR RY4COE;
+} SiS300_TVDataStruct;
+SiS300_TVDataStruct SiS300_StPALData[] = {
+ {1, 1, 864, 525, 1270, 400, 100, 0, 760, 0xf4, 0xff, 0x1c, 0x22},
+ {1, 1, 864, 525, 1270, 350, 100, 0, 760, 0xf4, 0xff, 0x1c, 0x22},
+ {1, 1, 864, 525, 1270, 400, 0, 0, 720, 0xf1, 0x04, 0x1f, 0x18},
+ {1, 1, 864, 525, 1270, 350, 0, 0, 720, 0xf4, 0x0b, 0x1c, 0x0a},
+ {1, 1, 864, 525, 1270, 480, 50, 0, 760, 0xf4, 0xff, 0x1c, 0x22},
+ {1, 1, 864, 525, 1270, 600, 50, 0, 0, 0xf4, 0xff, 0x1c, 0x22}
+};
+
+SiS300_TVDataStruct SiS300_ExtPALData[] = {
+ {27, 10, 848, 448, 1270, 530, 50, 0, 50, 0xf4, 0xff, 0x1c, 0x22},
+ {108, 35, 848, 398, 1270, 530, 50, 0, 50, 0xf4, 0xff, 0x1c, 0x22},
+ {12, 5, 954, 448, 1270, 530, 50, 0, 50, 0xf1, 0x04, 0x1f, 0x18},
+ {9, 4, 960, 463, 1644, 438, 50, 0, 50, 0xf4, 0x0b, 0x1c, 0x0a},
+ {9, 4, 848, 528, 1270, 530, 0, 0, 50, 0xf5, 0xfb, 0x1b, 0x2a},
+ {36, 25, 1060, 648, 1316, 530, 438, 0, 438, 0xeb, 0x05, 0x25, 0x16},
+ {3, 2, 1080, 619, 1270, 540, 438, 0, 438, 0xf3, 0x00, 0x1d, 0x20},
+ {1, 1, 1170, 821, 1270, 520, 686, 0, 686, 0xF3, 0x00, 0x1D, 0x20} /*301b */
+
+};
+
+SiS300_TVDataStruct SiS300_StNTSCData[] = {
+ {1, 1, 858, 525, 1270, 400, 50, 0, 760, 0xf1, 0x04, 0x1f, 0x18},
+ {1, 1, 858, 525, 1270, 350, 50, 0, 640, 0xf1, 0x04, 0x1f, 0x18},
+ {1, 1, 858, 525, 1270, 400, 0, 0, 720, 0xf1, 0x04, 0x1f, 0x18},
+ {1, 1, 858, 525, 1270, 350, 0, 0, 720, 0xf4, 0x0b, 0x1c, 0x0a},
+ {1, 1, 858, 525, 1270, 480, 0, 0, 760, 0xf1, 0x04, 0x1f, 0x18}
+};
+
+SiS300_TVDataStruct SiS300_ExtNTSCData[] = {
+ {143, 65, 858, 443, 1270, 440, 171, 0, 171, 0xf1, 0x04, 0x1f, 0x18},
+ {88, 35, 858, 393, 1270, 440, 171, 0, 171, 0xf1, 0x04, 0x1f, 0x18},
+ {143, 70, 924, 443, 1270, 440, 92, 0, 92, 0xf1, 0x04, 0x1f, 0x18},
+ {143, 70, 924, 393, 1270, 440, 92, 0, 92, 0xf4, 0x0b, 0x1c, 0x0a},
+ {143, 76, 836, 523, 1270, 440, 224, 0, 0, 0xf1, 0x05, 0x1f, 0x16},
+ {143, 120, 1056, 643, 1270, 440, 0, 128, 0, 0xf4, 0x10, 0x1c, 0x00},
+ {143, 76, 836, 523, 1270, 440, 0, 128, 0, 0xee, 0x0c, 0x22, 0x08},
+ {65, 64, 1056, 791, 1270, 480, 638, 0, 0, 0xf1, 0x04, 0x1f, 0x18} /*301b */
+};
+
+SiS_TVDataStruct SiS300_St1HiTVData[] = {
+
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00}
+};
+
+SiS_TVDataStruct SiS300_St2HiTVData[] = {
+
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00}
+};
+
+SiS_TVDataStruct SiS300_ExtHiTVData[] = {
+
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00}
+};
+
+UCHAR SiS300_NTSCTiming[] = {
+ 0x17, 0x1d, 0x03, 0x09, 0x05, 0x06, 0x0c, 0x0c,
+ 0x94, 0x49, 0x01, 0x0a, 0x06, 0x0d, 0x04, 0x0a,
+ 0x06, 0x14, 0x0d, 0x04, 0x0a, 0x00, 0x85, 0x1b,
+ 0x0c, 0x50, 0x00, 0x97, 0x00, 0xda, 0x4a, 0x17,
+ 0x7d, 0x05, 0x4b, 0x00, 0x00, 0xe2, 0x00, 0x02,
+ 0x03, 0x0a, 0x65, 0x9d, 0x08, 0x92, 0x8f, 0x40,
+ 0x60, 0x80, 0x14, 0x90, 0x8c, 0x60, 0x14, 0x50,
+ 0x00, 0x40, 0x44, 0x00, 0xdb, 0x02, 0x3b, 0x00
+};
+
+UCHAR SiS300_PALTiming[] = {
+ 0x19, 0x52, 0x35, 0x6e, 0x04, 0x38, 0x3d, 0x70,
+ 0x94, 0x49, 0x01, 0x12, 0x06, 0x3e, 0x35, 0x6d,
+ 0x06, 0x14, 0x3e, 0x35, 0x6d, 0x00, 0x45, 0x2b,
+ 0x70, 0x50, 0x00, 0x9b, 0x00, 0xd9, 0x5d, 0x17,
+ 0x7d, 0x05, 0x45, 0x00, 0x00, 0xe8, 0x00, 0x02,
+ 0x0d, 0x00, 0x68, 0xb0, 0x0b, 0x92, 0x8f, 0x40,
+ 0x60, 0x80, 0x14, 0x90, 0x8c, 0x60, 0x14, 0x63,
+ 0x00, 0x40, 0x3e, 0x00, 0xe1, 0x02, 0x28, 0x00
+};
+
+UCHAR SiS300_HiTVExtTiming[] = { 0x00 };
+
+UCHAR SiS300_HiTVSt1Timing[] = { 0x00 };
+
+UCHAR SiS300_HiTVSt2Timing[] = { 0x00 };
+
+UCHAR SiS300_HiTVTextTiming[] = { 0x00 };
+
+UCHAR SiS300_HiTVGroup3Data[] = { 0x00 };
+
+UCHAR SiS300_HiTVGroup3Simu[] = { 0x00 };
+
+UCHAR SiS300_HiTVGroup3Text[] = { 0x00 };
+
+typedef struct _SiS300_LVDSDataStruct {
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;
+} SiS300_LVDSDataStruct;
+SiS300_LVDSDataStruct SiS300_LVDS800x600Data_1[] = {
+ {0x00, 0x00, 0x00, 0x00}
+};
+
+SiS300_LVDSDataStruct SiS300_LVDS800x600Data_2[] = {
+ {0x00, 0x00, 0x00, 0x00}
+};
+
+SiS300_LVDSDataStruct SiS300_LVDS1024x768Data_1[] = {
+ {0x00, 0x00, 0x00, 0x00}
+};
+
+SiS300_LVDSDataStruct SiS300_LVDS1024x768Data_2[] = {
+ {0x00, 0x00, 0x00, 0x00}
+};
+
+SiS300_LVDSDataStruct SiS300_LVDS1280x1024Data_1[] = {
+ {0x00, 0x00, 0x00, 0x00}
+};
+
+SiS300_LVDSDataStruct SiS300_LVDS1280x1024Data_2[] = {
+ {0x00, 0x00, 0x00, 0x00}
+};
+
+SiS300_LVDSDataStruct SiS300_LVDS640x480Data_1[] = {
+ {0x00, 0x00, 0x00, 0x00}
+};
+
+SiS300_LVDSDataStruct SiS300_CHTVUNTSCData[] = {
+ {0x00, 0x00, 0x00, 0x00}
+};
+
+SiS300_LVDSDataStruct SiS300_CHTVONTSCData[] = {
+ {0x00, 0x00, 0x00, 0x00}
+};
+
+SiS300_LVDSDataStruct SiS300_CHTVUPALData[] = {
+ {0x00, 0x00, 0x00, 0x00}
+};
+
+SiS300_LVDSDataStruct SiS300_CHTVOPALData[] = {
+ {0x00, 0x00, 0x00, 0x00}
+};
+
+typedef struct _SiS300_LVDSDesStruct {
+ USHORT LCDHDES;
+ USHORT LCDVDES;
+} SiS300_LVDSDesStruct;
+SiS300_LVDSDesStruct SiS300_PanelType00_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType01_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType02_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType03_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType04_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType05_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType06_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType07_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType08_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType09_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType0a_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType0b_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType0c_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType0d_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType0e_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType0f_1[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType00_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType01_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType02_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType03_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType04_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType05_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType06_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType07_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType08_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType09_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType0a_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType0b_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType0c_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType0d_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType0e_2[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_PanelType0f_2[] = {
+ {0x00, 0x00}
+};
+
+/*301b*/
+SiS300_LVDSDesStruct SiS300_PanelType1076_1[] = {
+ {0x00, 0x00}
+};
+SiS300_LVDSDesStruct SiS300_PanelType1210_1[] = {
+ {0x00, 0x00}
+};
+SiS300_LVDSDesStruct SiS300_PanelType1296_1[] = {
+ {0x00, 0x00}
+};
+SiS300_LVDSDesStruct SiS300_PanelType1076_2[] = {
+ {0x00, 0x00}
+};
+SiS300_LVDSDesStruct SiS300_PanelType1210_2[] = {
+ {0x00, 0x00}
+};
+SiS300_LVDSDesStruct SiS300_PanelType1296_2[] = {
+ {0x00, 0x00}
+};
+/*end 301b*/
+
+SiS300_LVDSDesStruct SiS300_CHTVUNTSCDesData[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_CHTVONTSCDesData[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_CHTVUPALDesData[] = {
+ {0x00, 0x00}
+};
+
+SiS300_LVDSDesStruct SiS300_CHTVOPALDesData[] = {
+ {0x00, 0x00}
+};
+
+typedef struct _SiS300_LVDSCRT1DataStruct {
+ UCHAR CR[15];
+} SiS300_LVDSCRT1DataStruct;
+SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_1[] = {
+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+
+SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1[] = {
+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+
+SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1[] = {
+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+
+SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_1_H[] = {
+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+
+SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1_H[] = {
+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+
+SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1_H[] = {
+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+
+SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_2[] = {
+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+
+SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2[] = {
+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+
+SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2[] = {
+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+
+SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_2_H[] = {
+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+
+SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2_H[] = {
+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+
+SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2_H[] = {
+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,


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

echo 'End of part 072'
echo 'File patch-2.4.15 is continued in part 073'
echo "073" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:40 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part064

#!/bin/sh -x
# this is part 064 of a 115 - part archive


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

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

+ pci_read_config_byte(dev, 0x44, &tmp);
+ /* bit 1: allow individual 875 configuration */
+ tmp |= 0x2;
+ pci_write_config_byte(dev, 0x44, tmp);
+ pci_read_config_byte(dev, 0x45, &tmp);
+ /* bit 2: drive individual 875 interrupts to the bus */
+ tmp |= 0x4;
+ pci_write_config_byte(dev, 0x45, tmp);
+
+ pqs_bus[index] = PciBusNumber(dev);
+ }
+}
+#endif /* SYM_CONF_PQS_PDS_SUPPORT */
+
+/*
+ * Read and check the PCI configuration for any detected NCR
+ * boards and save data for attaching after all boards have
+ * been detected.


+ */
+static int __init

+sym53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, sym_device *device)
+{
+ u_short vendor_id, device_id, command, status_reg;
+ u_char cache_line_size;
+ u_char suggested_cache_line_size = 0;
+ u_char pci_fix_up = SYM_SETUP_PCI_FIX_UP;
+ u_char revision;
+ u_int irq;
+ u_long base, base_2, io_port;
+ u_long base_c, base_2_c;
+ int i;
+ sym_chip *chip;
+
+ /* Choose some short name for this device */
+ sprintf(device->s.inst_name, "sym.%d.%d.%d",
+ PciBusNumber(pdev),
+ (int) (PciDeviceFn(pdev) & 0xf8) >> 3,
+ (int) (PciDeviceFn(pdev) & 7));
+
+ /*
+ * Read needed minimal info from the PCI config space.
+ */
+ vendor_id = PciVendorId(pdev);
+ device_id = PciDeviceId(pdev);
+ irq = PciIrqLine(pdev);
+
+ i = pci_get_base_address(pdev, 0, &io_port);
+ io_port = pci_get_base_cookie(pdev, 0);
+
+ base_c = pci_get_base_cookie(pdev, i);
+ i = pci_get_base_address(pdev, i, &base);
+
+ base_2_c = pci_get_base_cookie(pdev, i);
+ (void) pci_get_base_address(pdev, i, &base_2);
+
+ io_port &= PCI_BASE_ADDRESS_IO_MASK;
+ base &= PCI_BASE_ADDRESS_MEM_MASK;
+ base_2 &= PCI_BASE_ADDRESS_MEM_MASK;
+
+ pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
+
+ /*
+ * If user excluded this chip, donnot initialize it.
+ */
+ if (io_port) {
+ for (i = 0 ; i < 8 ; i++) {
+ if (sym_driver_setup.excludes[i] == io_port)


+ return -1;
+ }
+ }
+

+ /*
+ * Leave here if another driver attached the chip.
+ */
+ if (io_port && check_region (io_port, 128)) {
+ printf_info("%s: IO region 0x%lx[0..127] is in use\n",
+ sym_name(device), (long) io_port);


+ return -1;
+ }
+

+ /*
+ * Check if the chip is supported.
+ */
+ chip = sym_lookup_pci_chip_table(device_id, revision);
+ if (!chip) {
+ printf_info("%s: device not supported\n", sym_name(device));


+ return -1;
+ }
+

+ /*
+ * Check if the chip has been assigned resources we need.
+ */
+#ifdef SYM_CONF_IOMAPPED
+ if (!io_port) {
+ printf_info("%s: IO base address disabled.\n",
+ sym_name(device));
+ return -1;
+ }
+#else
+ if (!base) {
+ printf_info("%s: MMIO base address disabled.\n",
+ sym_name(device));


+ return -1;
+ }
+#endif

+
+ /*
+ * Ignore Symbios chips controlled by various RAID controllers.
+ * These controllers set value 0x52414944 at RAM end - 16.
+ */
+#if defined(__i386__) && !defined(SYM_OPT_NO_BUS_MEMORY_MAPPING)
+ if (base_2_c) {
+ unsigned int ram_size, ram_val;
+ u_long ram_ptr;
+
+ if (chip->features & FE_RAM8K)
+ ram_size = 8192;
+ else
+ ram_size = 4096;
+
+ ram_ptr = pci_map_mem(base_2_c, ram_size);
+ if (ram_ptr) {
+ ram_val = readl_raw(ram_ptr + ram_size - 16);
+ pci_unmap_mem(ram_ptr, ram_size);
+ if (ram_val == 0x52414944) {
+ printf_info("%s: not initializing, "
+ "driven by RAID controller.\n",
+ sym_name(device));


+ return -1;
+ }
+ }
+ }

+#endif /* i386 and PCI MEMORY accessible */
+
+ /*
+ * Copy the chip description to our device structure,
+ * so we can make it match the actual device and options.
+ */
+ bcopy(chip, &device->chip, sizeof(device->chip));
+ device->chip.revision_id = revision;
+
+ /*
+ * Read additionnal info from the configuration space.
+ */
+ pci_read_config_word(pdev, PCI_COMMAND, &command);
+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size);
+
+ /*
+ * Enable missing capabilities in the PCI COMMAND register.
+ */
+#ifdef SYM_CONF_IOMAPPED
+#define PCI_COMMAND_BITS_TO_ENABLE (PCI_COMMAND_IO | \
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_PARITY)
+#else
+#define PCI_COMMAND_BITS_TO_ENABLE \
+ (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_PARITY)
+#endif
+ if ((command & PCI_COMMAND_BITS_TO_ENABLE)
+ != PCI_COMMAND_BITS_TO_ENABLE) {
+ printf_info("%s: setting%s%s%s%s...\n", sym_name(device),
+ (command & PCI_COMMAND_IO) ? "" : " PCI_COMMAND_IO",
+ (command & PCI_COMMAND_MEMORY) ? "" : " PCI_COMMAND_MEMORY",
+ (command & PCI_COMMAND_MASTER) ? "" : " PCI_COMMAND_MASTER",
+ (command & PCI_COMMAND_PARITY) ? "" : " PCI_COMMAND_PARITY");
+ command |= PCI_COMMAND_BITS_TO_ENABLE;
+ pci_write_config_word(pdev, PCI_COMMAND, command);
+ }
+#undef PCI_COMMAND_BITS_TO_ENABLE
+
+ /*
+ * If cache line size is not configured, suggest
+ * a value for well known CPUs.
+ */
+#if defined(__i386__) && !defined(MODULE)
+ if (!cache_line_size && boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
+ switch(boot_cpu_data.x86) {
+ case 4: suggested_cache_line_size = 4; break;
+ case 6: if (boot_cpu_data.x86_model > 8) break;
+ case 5: suggested_cache_line_size = 8; break;
+ }
+ }
+#endif /* __i386__ */
+
+ /*
+ * Some features are required to be enabled in order to
+ * work around some chip problems. :) ;)
+ * (ITEM 12 of a DEL about the 896 I haven't yet).
+ * We must ensure the chip will use WRITE AND INVALIDATE.
+ * The revision number limit is for now arbitrary.
+ */
+ if (device_id == PCI_DEVICE_ID_NCR_53C896 && revision < 0x4) {
+ chip->features |= (FE_WRIE | FE_CLSE);
+ pci_fix_up |= 3; /* Force appropriate PCI fix-up */
+ }
+
+#ifdef SYM_CONF_PCI_FIX_UP
+ /*
+ * Try to fix up PCI config according to wished features.
+ */
+ if ((pci_fix_up & 1) && (chip->features & FE_CLSE) &&
+ !cache_line_size && suggested_cache_line_size) {
+ cache_line_size = suggested_cache_line_size;
+ pci_write_config_byte(pdev,
+ PCI_CACHE_LINE_SIZE, cache_line_size);
+ printf_info("%s: PCI_CACHE_LINE_SIZE set to %d.\n",
+ sym_name(device), cache_line_size);
+ }
+
+ if ((pci_fix_up & 2) && cache_line_size &&
+ (chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) {
+ printf_info("%s: setting PCI_COMMAND_INVALIDATE.\n",
+ sym_name(device));
+ command |= PCI_COMMAND_INVALIDATE;
+ pci_write_config_word(pdev, PCI_COMMAND, command);
+ }
+#endif /* SYM_CONF_PCI_FIX_UP */
+
+ /*
+ * Work around for errant bit in 895A. The 66Mhz
+ * capable bit is set erroneously. Clear this bit.
+ * (Item 1 DEL 533)
+ *
+ * Make sure Config space and Features agree.
+ *
+ * Recall: writes are not normal to status register -
+ * write a 1 to clear and a 0 to leave unchanged.
+ * Can only reset bits.
+ */
+ pci_read_config_word(pdev, PCI_STATUS, &status_reg);
+ if (chip->features & FE_66MHZ) {
+ if (!(status_reg & PCI_STATUS_66MHZ))
+ chip->features &= ~FE_66MHZ;
+ }
+ else {
+ if (status_reg & PCI_STATUS_66MHZ) {
+ status_reg = PCI_STATUS_66MHZ;
+ pci_write_config_word(pdev, PCI_STATUS, status_reg);
+ pci_read_config_word(pdev, PCI_STATUS, &status_reg);


+ }
+ }
+
+ /*

+ * Initialise device structure with items required by sym_attach.
+ */
+ device->pdev = pdev;
+ device->s.bus = PciBusNumber(pdev);
+ device->s.device_fn = PciDeviceFn(pdev);
+ device->s.base = base;
+ device->s.base_2 = base_2;
+ device->s.base_c = base_c;
+ device->s.base_2_c = base_2_c;
+ device->s.io_port = io_port;
+ device->s.irq = irq;
+ device->attach_done = 0;
+


+ return 0;
+}
+
+/*

+ * List of supported NCR chip ids
+ */
+static u_short sym_chip_ids[] __initdata = {
+ PCI_ID_SYM53C810,
+ PCI_ID_SYM53C815,
+ PCI_ID_SYM53C825,
+ PCI_ID_SYM53C860,
+ PCI_ID_SYM53C875,
+ PCI_ID_SYM53C875_2,
+ PCI_ID_SYM53C885,
+ PCI_ID_SYM53C875A,
+ PCI_ID_SYM53C895,
+ PCI_ID_SYM53C896,
+ PCI_ID_SYM53C895A,
+ PCI_ID_LSI53C1510D,
+ PCI_ID_LSI53C1010,
+ PCI_ID_LSI53C1010_2
+};
+
+/*
+ * Detect all 53c8xx hosts and then attach them.
+ *
+ * If we are using NVRAM, once all hosts are detected, we need to
+ * check any NVRAM for boot order in case detect and boot order
+ * differ and attach them using the order in the NVRAM.
+ *
+ * If no NVRAM is found or data appears invalid attach boards in
+ * the the order they are detected.
+ */
+int __init sym53c8xx_detect(Scsi_Host_Template *tpnt)
+{
+ pcidev_t pcidev;
+ int i, j, chips, hosts, count;
+ int attach_count = 0;
+ sym_device *devtbl, *devp;
+ sym_nvram nvram;
+#if SYM_CONF_NVRAM_SUPPORT
+ sym_nvram nvram0, *nvp;
+#endif
+
+ /*
+ * PCI is required.
+ */
+ if (!pci_present())
+ return 0;
+
+ /*
+ * Initialize driver general stuff.
+ */
+#ifdef SYM_LINUX_PROC_INFO_SUPPORT
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
+ tpnt->proc_dir = &proc_scsi_sym53c8xx;
+#else
+ tpnt->proc_name = NAME53C8XX;
+#endif
+ tpnt->proc_info = sym53c8xx_proc_info;
+#endif
+
+#ifdef SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT
+#ifdef MODULE
+if (sym53c8xx)
+ sym53c8xx_setup(sym53c8xx);
+#endif
+#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
+ sym_debug_flags = sym_driver_setup.debug;
+#endif
+ if (boot_verbose >= 2)
+ sym53c8xx_print_driver_setup();


+#endif /* SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT */
+

+ /*
+ * Allocate the device table since we donnot want to
+ * overflow the kernel stack.
+ * 1 x 4K PAGE is enough for more than 40 devices for i386.
+ */
+ devtbl = sym_calloc(PAGE_SIZE, "DEVTBL");
+ if (!devtbl)
+ return 0;
+
+ /*
+ * Detect all NCR PQS/PDS memory controllers.
+ */
+#ifdef SYM_CONF_PQS_PDS_SUPPORT
+ sym_detect_pqs_pds();
+#endif
+
+ /*
+ * Detect all 53c8xx hosts.
+ * Save the first Symbios NVRAM content if any
+ * for the boot order.
+ */
+ chips = sizeof(sym_chip_ids) / sizeof(sym_chip_ids[0]);
+ hosts = PAGE_SIZE / sizeof(*devtbl);
+#if SYM_CONF_NVRAM_SUPPORT
+ nvp = (sym_driver_setup.use_nvram & 0x1) ? &nvram0 : 0;
+#endif
+ j = 0;
+ count = 0;
+ pcidev = PCIDEV_NULL;
+ while (1) {
+ char *msg = "";
+ if (count >= hosts)
+ break;
+ if (j >= chips)
+ break;
+ i = sym_driver_setup.reverse_probe ? chips - 1 - j : j;
+ pcidev = pci_find_device(PCI_VENDOR_ID_NCR, sym_chip_ids[i],
+ pcidev);
+ if (pcidev == PCIDEV_NULL) {
+ ++j;
+ continue;
+ }
+ /* This one is guaranteed by AC to do nothing :-) */
+ if (pci_enable_device(pcidev))
+ continue;
+ /* Some HW as the HP LH4 may report twice PCI devices */
+ for (i = 0; i < count ; i++) {
+ if (devtbl[i].s.bus == PciBusNumber(pcidev) &&
+ devtbl[i].s.device_fn == PciDeviceFn(pcidev))
+ break;
+ }
+ if (i != count) /* Ignore this device if we already have it */
+ continue;
+ devp = &devtbl[count];
+ devp->host_id = SYM_SETUP_HOST_ID;
+ devp->attach_done = 0;
+ if (sym53c8xx_pci_init(tpnt, pcidev, devp)) {
+ continue;
+ }
+ ++count;
+#if SYM_CONF_NVRAM_SUPPORT
+ if (nvp) {
+ sym_get_nvram(devp, nvp);
+ switch(nvp->type) {
+ case SYM_SYMBIOS_NVRAM:
+ /*
+ * Switch to the other nvram buffer, so that
+ * nvram0 will contain the first Symbios
+ * format NVRAM content with boot order.
+ */
+ nvp = &nvram;
+ msg = "with Symbios NVRAM";
+ break;
+ case SYM_TEKRAM_NVRAM:
+ msg = "with Tekram NVRAM";
+ break;
+ }
+ }
+#endif
+#ifdef SYM_CONF_PQS_PDS_SUPPORT
+ /*
+ * Match the BUS number for PQS/PDS devices.
+ * Read the SCSI ID from a special register mapped
+ * into the configuration space of the individual
+ * 875s. This register is set up by the PQS bios
+ */
+ for(i = 0; i < SYM_CONF_MAX_PQS_BUS && pqs_bus[i] != -1; i++) {
+ u_char tmp;
+ if (pqs_bus[i] == PciBusNumber(pcidev)) {
+ pci_read_config_byte(pcidev, 0x84, &tmp);
+ devp->pqs_pds = 1;
+ devp->host_id = tmp;
+ break;
+ }
+ }
+ if (devp->pqs_pds)
+ msg = "(NCR PQS/PDS)";
+#endif
+ if (boot_verbose)
+ printf_info("%s: 53c%s detected %s\n",
+ sym_name(devp), devp->chip.name, msg);
+ }
+
+ /*
+ * If we have found a SYMBIOS NVRAM, use first the NVRAM boot
+ * sequence as device boot order.
+ * check devices in the boot record against devices detected.
+ * attach devices if we find a match. boot table records that
+ * do not match any detected devices will be ignored.
+ * devices that do not match any boot table will not be attached
+ * here but will attempt to be attached during the device table
+ * rescan.
+ */
+#if SYM_CONF_NVRAM_SUPPORT
+ if (!nvp || nvram0.type != SYM_SYMBIOS_NVRAM)
+ goto next;


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

+ Symbios_host *h = &nvram0.data.Symbios.host[i];
+ for (j = 0 ; j < count ; j++) {
+ devp = &devtbl[j];
+ if (h->device_fn != devp->s.device_fn ||
+ h->bus_nr != devp->s.bus ||
+ h->device_id != devp->chip.device_id)
+ continue;
+ if (devp->attach_done)
+ continue;
+ if (h->flags & SYMBIOS_INIT_SCAN_AT_BOOT) {
+ sym_get_nvram(devp, nvp);
+ if (!sym_attach (tpnt, attach_count, devp))
+ attach_count++;
+ }
+ else if (!(sym_driver_setup.use_nvram & 0x80))
+ printf_info(
+ "%s: 53c%s state OFF thus not attached\n",
+ sym_name(devp), devp->chip.name);
+ else
+ continue;
+
+ devp->attach_done = 1;
+ break;
+ }
+ }
+next:
+#endif
+
+ /*
+ * Rescan device list to make sure all boards attached.
+ * Devices without boot records will not be attached yet
+ * so try to attach them here.
+ */
+ for (i= 0; i < count; i++) {
+ devp = &devtbl[i];
+ if (!devp->attach_done) {
+ devp->nvram = &nvram;
+ nvram.type = 0;
+#if SYM_CONF_NVRAM_SUPPORT
+ sym_get_nvram(devp, nvp);
+#endif
+ if (!sym_attach (tpnt, attach_count, devp))
+ attach_count++;
+ }
+ }
+
+ sym_mfree(devtbl, PAGE_SIZE, "DEVTBL");
+
+ return attach_count;
+}
+
+
+
+#ifdef MODULE
+/*
+ * Linux release module stuff.
+ *
+ * Called before unloading the module.
+ * Detach the host.
+ * We have to free resources and halt the NCR chip.
+ *
+ */
+static int sym_detach(hcb_p np)
+{
+ printk("%s: detaching ...\n", sym_name(np));
+
+ /*
+ * Try to delete the timer.
+ * In the unlikely situation where this failed,
+ * try to synchronize with the timer handler.
+ */
+#if LINUX_VERSION_CODE < LinuxVersionCode(2, 4, 0)
+ np->s.release_stage = 1;
+ if (!del_timer(&np->s.timer)) {
+ int i = 1000;
+ int k = 1;
+ while (1) {
+ u_long flags;
+ SYM_LOCK_HCB(np, flags);
+ k = np->s.release_stage;
+ SYM_UNLOCK_HCB(np, flags);
+ if (k == 2 || !--i)
+ break;
+ MDELAY(5);
+ }
+ if (!i)
+ printk("%s: failed to kill timer!\n", sym_name(np));
+ }


+ np->s.release_stage = 2;

+#else
+ (void)del_timer_sync(&np->s.timer);
+#endif
+
+ /*
+ * Reset NCR chip.
+ * We should use sym_soft_reset(), but we donnot want to do
+ * so, since we may not be safe if interrupts occur.
+ */
+ printk("%s: resetting chip\n", sym_name(np));
+ OUTB (nc_istat, SRST);
+ UDELAY (10);
+ OUTB (nc_istat, 0);
+
+ /*
+ * Free host resources
+ */
+ sym_free_resources(np);
+


+ return 1;
+}
+

+int sym53c8xx_release(struct Scsi_Host *host)
+{
+ sym_detach(((struct host_data *) host->hostdata)->ncb);


+
+ return 0;
+}

+#endif /* MODULE */
+
+/*
+ * For bigots to keep silent. :)
+ */
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("Dual BSD/GPL");
+#endif
+
+/*
+ * Driver host template.
+ */
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
+static
+#endif
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) || defined(MODULE)
+Scsi_Host_Template driver_template = SYM53C8XX;
+#include "../scsi_module.c"
+#endif
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_glue.h linux/drivers/scsi/sym53c8xx_2/sym_glue.h
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_glue.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym_glue.h Thu Nov 22 10:41:14 2001
@@ -0,0 +1,676 @@


+/*
+ * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family
+ * of PCI-SCSI IO processors.
+ *
+ * Copyright (C) 1999-2001 Gerard Roudier <grou...@free.fr>

+ *


+ * This driver is derived from the Linux sym53c8xx driver.
+ * Copyright (C) 1998-2000 Gerard Roudier

+ *


+ * The sym53c8xx driver is derived from the ncr53c8xx driver that had been
+ * a port of the FreeBSD ncr driver to Linux-1.2.13.

+ *

+#ifndef SYM_GLUE_H
+#define SYM_GLUE_H
+
+#if 0
+#define SYM_CONF_DMA_ADDRESSING_MODE 2
+#endif
+
+#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < LinuxVersionCode(2, 2, 0)
+#error "This driver requires a kernel version not lower than 2.2.0"
+#endif
+
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,17)
+#include <linux/spinlock.h>
+#else
+#include <asm/spinlock.h>
+#endif
+#include <linux/delay.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+#include <linux/stat.h>
+
+#include <linux/blk.h>
+
+#ifdef __sparc__
+# include <asm/irq.h>
+#endif
+#include <linux/init.h>
+
+#ifndef __init
+#define __init
+#endif
+#ifndef __initdata
+#define __initdata
+#endif
+
+#include "../scsi.h"
+#include "../hosts.h"
+#include "../constants.h"
+#include "../sd.h"
+
+#include <linux/types.h>
+
+/*
+ * Define BITS_PER_LONG for earlier linux versions.
+ */
+#ifndef BITS_PER_LONG
+#if (~0UL) == 0xffffffffUL
+#define BITS_PER_LONG 32
+#else
+#define BITS_PER_LONG 64
+#endif
+#endif
+
+typedef u_long vm_offset_t;
+
+#ifndef bcopy
+#define bcopy(s, d, n) memcpy((d), (s), (n))
+#endif
+
+#ifndef bzero
+#define bzero(d, n) memset((d), 0, (n))
+#endif
+
+#ifndef bcmp
+#define bcmp(a, b, n) memcmp((a), (b), (n))
+#endif
+
+/*
+ * General driver includes.
+ */
+#include "sym53c8xx.h"
+#include "sym_misc.h"
+#include "sym_conf.h"
+#include "sym_defs.h"
+
+/*
+ * Configuration addendum for Linux.
+ */
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,47)
+#define SYM_LINUX_DYNAMIC_DMA_MAPPING
+#endif
+
+#define SYM_CONF_TIMER_INTERVAL ((HZ+1)/2)
+
+#define SYM_OPT_HANDLE_DIR_UNKNOWN
+#define SYM_OPT_HANDLE_DEVICE_QUEUEING
+#define SYM_OPT_NVRAM_PRE_READ
+#define SYM_OPT_SNIFF_INQUIRY
+#define SYM_OPT_LIMIT_COMMAND_REORDERING
+#define SYM_OPT_ANNOUNCE_TRANSFER_RATE
+
+#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING
+#define SYM_OPT_BUS_DMA_ABSTRACTION
+#endif
+
+/*
+ * Print a message with severity.
+ */
+#define printf_emerg(args...) printk(KERN_EMERG args)
+#define printf_alert(args...) printk(KERN_ALERT args)
+#define printf_crit(args...) printk(KERN_CRIT args)
+#define printf_err(args...) printk(KERN_ERR args)
+#define printf_warning(args...) printk(KERN_WARNING args)
+#define printf_notice(args...) printk(KERN_NOTICE args)
+#define printf_info(args...) printk(KERN_INFO args)
+#define printf_debug(args...) printk(KERN_DEBUG args)
+#define printf(args...) printk(args)


+
+/*
+ * Insert a delay in micro-seconds and milli-seconds.
+ */

+void sym_udelay(int us);
+void sym_mdelay(int ms);
+
+/*
+ * Let the compiler know about driver data structure names.
+ */
+typedef struct sym_tcb *tcb_p;
+typedef struct sym_lcb *lcb_p;
+typedef struct sym_ccb *ccb_p;
+typedef struct sym_hcb *hcb_p;
+typedef struct sym_stcb *stcb_p;
+typedef struct sym_slcb *slcb_p;
+typedef struct sym_sccb *sccb_p;
+typedef struct sym_shcb *shcb_p;
+
+/*
+ * Define a reference to the O/S dependant IO request.
+ */
+typedef Scsi_Cmnd *cam_ccb_p; /* Generic */
+typedef Scsi_Cmnd *cam_scsiio_p;/* SCSI I/O */
+
+
+/*
+ * IO functions definition for big/little endian CPU support.
+ * For now, PCI chips are only supported in little endian addressing mode,
+ */
+
+#ifdef __BIG_ENDIAN
+
+#define inw_l2b inw
+#define inl_l2b inl
+#define outw_b2l outw
+#define outl_b2l outl
+#define readw_l2b readw
+#define readl_l2b readl
+#define writew_b2l writew
+#define writel_b2l writel
+
+#else /* little endian */
+
+#if defined(__i386__) /* i386 implements full FLAT memory/MMIO model */
+#define inw_raw inw
+#define inl_raw inl
+#define outw_raw outw
+#define outl_raw outl
+#define readb_raw(a) (*(volatile unsigned char *) (a))
+#define readw_raw(a) (*(volatile unsigned short *) (a))
+#define readl_raw(a) (*(volatile unsigned int *) (a))
+#define writeb_raw(b,a) ((*(volatile unsigned char *) (a)) = (b))
+#define writew_raw(b,a) ((*(volatile unsigned short *) (a)) = (b))
+#define writel_raw(b,a) ((*(volatile unsigned int *) (a)) = (b))
+
+#else /* Other little-endian */
+#define inw_raw inw
+#define inl_raw inl
+#define outw_raw outw
+#define outl_raw outl
+#define readw_raw readw
+#define readl_raw readl
+#define writew_raw writew
+#define writel_raw writel
+
+#endif
+#endif
+
+#ifdef SYM_CONF_CHIP_BIG_ENDIAN
+#error "Chips in BIG ENDIAN addressing mode are not (yet) supported"
+#endif
+
+
+/*
+ * If the chip uses big endian addressing mode over the
+ * PCI, actual io register addresses for byte and word
+ * accesses must be changed according to lane routing.
+ * Btw, sym_offb() and sym_offw() macros only apply to
+ * constants and so donnot generate bloated code.
+ */
+
+#if defined(SYM_CONF_CHIP_BIG_ENDIAN)
+
+#define sym_offb(o) (((o)&~3)+((~((o)&3))&3))
+#define sym_offw(o) (((o)&~3)+((~((o)&3))&2))
+
+#else
+
+#define sym_offb(o) (o)
+#define sym_offw(o) (o)
+
+#endif
+
+/*
+ * If the CPU and the chip use same endian-ness adressing,
+ * no byte reordering is needed for script patching.
+ * Macro cpu_to_scr() is to be used for script patching.
+ * Macro scr_to_cpu() is to be used for getting a DWORD
+ * from the script.
+ */
+
+#if defined(__BIG_ENDIAN) && !defined(SYM_CONF_CHIP_BIG_ENDIAN)
+
+#define cpu_to_scr(dw) cpu_to_le32(dw)
+#define scr_to_cpu(dw) le32_to_cpu(dw)
+
+#elif defined(__LITTLE_ENDIAN) && defined(SYM_CONF_CHIP_BIG_ENDIAN)
+
+#define cpu_to_scr(dw) cpu_to_be32(dw)
+#define scr_to_cpu(dw) be32_to_cpu(dw)
+
+#else
+
+#define cpu_to_scr(dw) (dw)
+#define scr_to_cpu(dw) (dw)
+
+#endif
+
+/*
+ * Access to the controller chip.
+ *
+ * If SYM_CONF_IOMAPPED is defined, the driver will use
+ * normal IOs instead of the MEMORY MAPPED IO method
+ * recommended by PCI specifications.
+ * If all PCI bridges, host brigdes and architectures
+ * would have been correctly designed for PCI, this
+ * option would be useless.
+ *
+ * If the CPU and the chip use same endian-ness adressing,
+ * no byte reordering is needed for accessing chip io
+ * registers. Functions suffixed by '_raw' are assumed
+ * to access the chip over the PCI without doing byte
+ * reordering. Functions suffixed by '_l2b' are
+ * assumed to perform little-endian to big-endian byte
+ * reordering, those suffixed by '_b2l' blah, blah,
+ * blah, ...
+ */
+
+#if defined(SYM_CONF_IOMAPPED)
+
+/*
+ * IO mapped only input / ouput
+ */
+
+#define INB_OFF(o) inb (np->s.io_port + sym_offb(o))
+#define OUTB_OFF(o, val) outb ((val), np->s.io_port + sym_offb(o))
+
+#if defined(__BIG_ENDIAN) && !defined(SYM_CONF_CHIP_BIG_ENDIAN)
+
+#define INW_OFF(o) inw_l2b (np->s.io_port + sym_offw(o))
+#define INL_OFF(o) inl_l2b (np->s.io_port + (o))
+
+#define OUTW_OFF(o, val) outw_b2l ((val), np->s.io_port + sym_offw(o))
+#define OUTL_OFF(o, val) outl_b2l ((val), np->s.io_port + (o))
+
+#elif defined(__LITTLE_ENDIAN) && defined(SYM_CONF_CHIP_BIG_ENDIAN)
+
+#define INW_OFF(o) inw_b2l (np->s.io_port + sym_offw(o))
+#define INL_OFF(o) inl_b2l (np->s.io_port + (o))
+
+#define OUTW_OFF(o, val) outw_l2b ((val), np->s.io_port + sym_offw(o))
+#define OUTL_OFF(o, val) outl_l2b ((val), np->s.io_port + (o))
+
+#else
+
+#define INW_OFF(o) inw_raw (np->s.io_port + sym_offw(o))
+#define INL_OFF(o) inl_raw (np->s.io_port + (o))
+
+#define OUTW_OFF(o, val) outw_raw ((val), np->s.io_port + sym_offw(o))
+#define OUTL_OFF(o, val) outl_raw ((val), np->s.io_port + (o))
+
+#endif /* ENDIANs */
+
+#else /* defined SYM_CONF_IOMAPPED */
+
+/*
+ * MEMORY mapped IO input / output
+ */
+
+#define INB_OFF(o) readb((char *)np->s.mmio_va + sym_offb(o))
+#define OUTB_OFF(o, val) writeb((val), (char *)np->s.mmio_va + sym_offb(o))
+
+#if defined(__BIG_ENDIAN) && !defined(SYM_CONF_CHIP_BIG_ENDIAN)
+
+#define INW_OFF(o) readw_l2b((char *)np->s.mmio_va + sym_offw(o))
+#define INL_OFF(o) readl_l2b((char *)np->s.mmio_va + (o))
+
+#define OUTW_OFF(o, val) writew_b2l((val), (char *)np->s.mmio_va + sym_offw(o))
+#define OUTL_OFF(o, val) writel_b2l((val), (char *)np->s.mmio_va + (o))
+
+#elif defined(__LITTLE_ENDIAN) && defined(SYM_CONF_CHIP_BIG_ENDIAN)
+
+#define INW_OFF(o) readw_b2l((char *)np->s.mmio_va + sym_offw(o))
+#define INL_OFF(o) readl_b2l((char *)np->s.mmio_va + (o))
+
+#define OUTW_OFF(o, val) writew_l2b((val), (char *)np->s.mmio_va + sym_offw(o))
+#define OUTL_OFF(o, val) writel_l2b((val), (char *)np->s.mmio_va + (o))
+
+#else
+
+#define INW_OFF(o) readw_raw((char *)np->s.mmio_va + sym_offw(o))
+#define INL_OFF(o) readl_raw((char *)np->s.mmio_va + (o))
+
+#define OUTW_OFF(o, val) writew_raw((val), (char *)np->s.mmio_va + sym_offw(o))
+#define OUTL_OFF(o, val) writel_raw((val), (char *)np->s.mmio_va + (o))
+
+#endif
+
+#endif /* defined SYM_CONF_IOMAPPED */
+
+#define OUTRAM_OFF(o, a, l) memcpy_toio(np->s.ram_va + (o), (a), (l))
+
+/*
+ * Remap some status field values.
+ */
+#define CAM_REQ_CMP DID_OK
+#define CAM_SEL_TIMEOUT DID_NO_CONNECT
+#define CAM_CMD_TIMEOUT DID_TIME_OUT
+#define CAM_REQ_ABORTED DID_ABORT
+#define CAM_UNCOR_PARITY DID_PARITY
+#define CAM_SCSI_BUS_RESET DID_RESET
+#define CAM_REQUEUE_REQ DID_SOFT_ERROR
+#define CAM_UNEXP_BUSFREE DID_ERROR
+#define CAM_SCSI_BUSY DID_BUS_BUSY
+
+#define CAM_DEV_NOT_THERE DID_NO_CONNECT
+#define CAM_REQ_INVALID DID_ERROR
+#define CAM_REQ_TOO_BIG DID_ERROR
+
+#define CAM_RESRC_UNAVAIL DID_ERROR
+
+/*
+ * Remap SCSI data direction values.
+ */
+#ifndef SCSI_DATA_UNKNOWN
+#define SCSI_DATA_UNKNOWN 0
+#define SCSI_DATA_WRITE 1
+#define SCSI_DATA_READ 2
+#define SCSI_DATA_NONE 3
+#endif
+#define CAM_DIR_NONE SCSI_DATA_NONE
+#define CAM_DIR_IN SCSI_DATA_READ
+#define CAM_DIR_OUT SCSI_DATA_WRITE
+#define CAM_DIR_UNKNOWN SCSI_DATA_UNKNOWN
+
+/*
+ * These ones are used as return code from
+ * error recovery handlers under Linux.
+ */
+#define SCSI_SUCCESS SUCCESS
+#define SCSI_FAILED FAILED
+
+/*
+ * System specific target data structure.
+ * None for now, under Linux.
+ */
+/* #define SYM_HAVE_STCB */
+
+/*
+ * System specific lun data structure.
+ */
+#define SYM_HAVE_SLCB
+struct sym_slcb {
+ u_short reqtags; /* Number of tags requested by user */
+ u_short scdev_depth; /* Queue depth set in select_queue_depth() */
+};
+
+/*
+ * System specific command data structure.
+ * Not needed under Linux.
+ */
+/* struct sym_sccb */
+
+/*
+ * System specific host data structure.
+ */
+struct sym_shcb {
+ /*
+ * Chip and controller indentification.
+ */
+ int unit;
+ char inst_name[16];
+ char chip_name[8];
+ struct pci_dev *device;
+
+ u_char bus; /* PCI BUS number */
+ u_char device_fn; /* PCI BUS device and function */
+
+ spinlock_t smp_lock; /* Lock for SMP threading */
+
+ vm_offset_t mmio_va; /* MMIO kernel virtual address */
+ vm_offset_t ram_va; /* RAM kernel virtual address */
+ u32 io_port; /* IO port address */
+ u_short io_ws; /* IO window size */
+ int irq; /* IRQ number */
+
+ SYM_QUEHEAD wait_cmdq; /* Awaiting SCSI commands */
+ SYM_QUEHEAD busy_cmdq; /* Enqueued SCSI commands */
+
+ struct timer_list timer; /* Timer handler link header */
+ u_long lasttime;
+ u_long settle_time; /* Resetting the SCSI BUS */
+ u_char settle_time_valid;


+#if LINUX_VERSION_CODE < LinuxVersionCode(2, 4, 0)

+ u_char release_stage; /* Synchronisation on release */
+#endif
+};
+
+/*
+ * Return the name of the controller.
+ */
+#define sym_name(np) (np)->s.inst_name
+
+/*
+ * Data structure used as input for the NVRAM reading.
+ * Must resolve the IO macros and sym_name(), when
+ * used as sub-field 's' of another structure.
+ */
+typedef struct {
+ int bus;
+ u_char device_fn;
+ u_long base;
+ u_long base_2;
+ u_long base_c;
+ u_long base_2_c;
+ int irq;
+/* port and address fields to fit INB, OUTB macros */
+ u_long io_port;
+ vm_offset_t mmio_va;
+ char inst_name[16];
+} sym_slot;
+
+typedef struct sym_nvram sym_nvram;
+typedef struct sym_pci_chip sym_chip;
+
+typedef struct {
+ struct pci_dev *pdev;
+ sym_slot s;
+ sym_chip chip;
+ sym_nvram *nvram;
+ u_short device_id;
+ u_char host_id;
+#ifdef SYM_CONF_PQS_PDS_SUPPORT
+ u_char pqs_pds;
+#endif
+ int attach_done;
+} sym_device;
+
+typedef sym_device *sdev_p;
+
+/*
+ * The driver definitions (sym_hipd.h) must know about a
+ * couple of things related to the memory allocator.
+ */
+typedef u_long m_addr_t; /* Enough bits to represent any address */
+#define SYM_MEM_PAGE_ORDER 0 /* 1 PAGE maximum */
+#define SYM_MEM_CLUSTER_SHIFT (PAGE_SHIFT+SYM_MEM_PAGE_ORDER)
+#ifdef MODULE
+#define SYM_MEM_FREE_UNUSED /* Free unused pages immediately */
+#endif
+#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING
+typedef struct pci_dev *m_pool_ident_t;
+#endif
+
+/*
+ * Include driver soft definitions.
+ */
+#include "sym_fw.h"
+#include "sym_hipd.h"
+
+/*
+ * Memory allocator related stuff.
+ */
+
+#define SYM_MEM_GFP_FLAGS GFP_ATOMIC
+#define SYM_MEM_WARN 1 /* Warn on failed operations */
+
+#define sym_get_mem_cluster() \
+ __get_free_pages(SYM_MEM_GFP_FLAGS, SYM_MEM_PAGE_ORDER)
+#define sym_free_mem_cluster(p) \
+ free_pages(p, SYM_MEM_PAGE_ORDER)
+
+void *sym_calloc(int size, char *name);


+void sym_mfree(void *m, int size, char *name);
+

+#ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING
+/*
+ * Simple case.
+ * All the memory assummed DMAable and O/S providing virtual
+ * to bus physical address translation.
+ */
+#define __sym_calloc_dma(pool_id, size, name) sym_calloc(size, name)
+#define __sym_mfree_dma(pool_id, m, size, name) sym_mfree(m, size, name)
+#define __vtobus(b, p) virt_to_bus(p)
+
+#else /* SYM_LINUX_DYNAMIC_DMA_MAPPING */
+/*
+ * Complex case.
+ * We have to provide the driver memory allocator with methods for
+ * it to maintain virtual to bus physical address translations.
+ */
+
+#define sym_m_pool_match(mp_id1, mp_id2) (mp_id1 == mp_id2)
+
+static __inline m_addr_t sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
+{
+ void *vaddr = 0;
+ dma_addr_t baddr = 0;
+
+ vaddr = pci_alloc_consistent(mp->dev_dmat,SYM_MEM_CLUSTER_SIZE, &baddr);
+ if (vaddr) {
+ vbp->vaddr = (m_addr_t) vaddr;
+ vbp->baddr = (m_addr_t) baddr;
+ }
+ return (m_addr_t) vaddr;
+}
+
+static __inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
+{
+ pci_free_consistent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE,
+ (void *)vbp->vaddr, (dma_addr_t)vbp->baddr);
+}
+
+#define sym_m_create_dma_mem_tag(mp) (0)
+
+#define sym_m_delete_dma_mem_tag(mp) do { ; } while (0)
+
+void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name);
+void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name);


+m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m);
+

+#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */
+
+/*

+ * Set the status field of a CAM CCB.
+ */
+static __inline void
+sym_set_cam_status(Scsi_Cmnd *ccb, int status)
+{
+ ccb->result &= ~(0xff << 16);
+ ccb->result |= (status << 16);
+}
+
+/*
+ * Get the status field of a CAM CCB.
+ */
+static __inline int
+sym_get_cam_status(Scsi_Cmnd *ccb)
+{
+ return ((ccb->result >> 16) & 0xff);
+}
+
+/*
+ * The dma mapping is mostly handled by the
+ * SCSI layer and the driver glue under Linux.
+ */
+#define sym_data_dmamap_create(np, cp) (0)
+#define sym_data_dmamap_destroy(np, cp) do { ; } while (0)
+#define sym_data_dmamap_unload(np, cp) do { ; } while (0)
+#define sym_data_dmamap_presync(np, cp) do { ; } while (0)
+#define sym_data_dmamap_postsync(np, cp) do { ; } while (0)
+
+/*
+ * Async handler for negotiations.
+ */
+void sym_xpt_async_nego_wide(hcb_p np, int target);
+#define sym_xpt_async_nego_sync(np, target) \
+ sym_announce_transfer_rate(np, target)
+#define sym_xpt_async_nego_ppr(np, target) \
+ sym_announce_transfer_rate(np, target)
+
+/*
+ * Build CAM result for a successful IO and for a failed IO.
+ */
+static __inline void sym_set_cam_result_ok(hcb_p np, ccb_p cp, int resid)
+{


+ Scsi_Cmnd *cmd = cp->cam_ccb;
+

+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,99)
+ cmd->resid = resid;
+#endif
+ cmd->result = (((DID_OK) << 16) + ((cp->ssss_status) & 0x7f));
+}


+void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid);
+

+/*
+ * Other O/S specific methods.
+ */
+#define sym_cam_target_id(ccb) (ccb)->target
+#define sym_cam_target_lun(ccb) (ccb)->lun
+#define sym_freeze_cam_ccb(ccb) do { ; } while (0)
+void sym_xpt_done(hcb_p np, cam_ccb_p ccb);
+void sym_xpt_done2(hcb_p np, cam_ccb_p ccb, int cam_status);
+void sym_print_addr (ccb_p cp);
+void sym_xpt_async_bus_reset(hcb_p np);
+void sym_xpt_async_sent_bdr(hcb_p np, int target);
+int sym_setup_data_and_start (hcb_p np, cam_scsiio_p csio, ccb_p cp);
+void sym_log_bus_error(hcb_p np);
+#ifdef SYM_OPT_SNIFF_INQUIRY
+void sym_sniff_inquiry(hcb_p np, Scsi_Cmnd *cmd, int resid);
+#endif
+
+#endif /* SYM_GLUE_H */
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_hipd.c linux/drivers/scsi/sym53c8xx_2/sym_hipd.c
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_hipd.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym_hipd.c Fri Nov 9 15:22:54 2001
@@ -0,0 +1,6007 @@


+/*
+ * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family
+ * of PCI-SCSI IO processors.
+ *
+ * Copyright (C) 1999-2001 Gerard Roudier <grou...@free.fr>

+ *


+ * This driver is derived from the Linux sym53c8xx driver.
+ * Copyright (C) 1998-2000 Gerard Roudier

+ *


+ * The sym53c8xx driver is derived from the ncr53c8xx driver that had been
+ * a port of the FreeBSD ncr driver to Linux-1.2.13.

+ *

+#define SYM_DRIVER_NAME "sym-2.1.16a"


+
+#ifdef __FreeBSD__
+#include <dev/sym/sym_glue.h>
+#else
+#include "sym_glue.h"
+#endif
+

+#if 0
+#define SYM_DEBUG_GENERIC_SUPPORT
+#endif
+
+/*
+ * Needed function prototypes.
+ */
+static void sym_int_ma (hcb_p np);
+static void sym_int_sir (hcb_p np);
+static ccb_p sym_alloc_ccb(hcb_p np);
+static ccb_p sym_ccb_from_dsa(hcb_p np, u32 dsa);
+static void sym_alloc_lcb_tags (hcb_p np, u_char tn, u_char ln);
+static void sym_complete_error (hcb_p np, ccb_p cp);
+static void sym_complete_ok (hcb_p np, ccb_p cp);
+static int sym_compute_residual(hcb_p np, ccb_p cp);
+
+/*
+ * Returns the name of this driver.
+ */
+char *sym_driver_name(void)
+{
+ return SYM_DRIVER_NAME;
+}
+/*
+ * Print a buffer in hexadecimal format.
+ */
+static void sym_printb_hex (u_char *p, int n)
+{
+ while (n-- > 0)
+ printf (" %x", *p++);
+}
+
+/*
+ * Same with a label at beginning and .\n at end.
+ */
+static void sym_printl_hex (char *label, u_char *p, int n)
+{
+ printf ("%s", label);
+ sym_printb_hex (p, n);
+ printf (".\n");
+}
+
+/*
+ * Print something which allows to retrieve the controler type,
+ * unit, target, lun concerned by a kernel message.
+ */
+static void sym_print_target (hcb_p np, int target)
+{
+ printf ("%s:%d:", sym_name(np), target);
+}
+
+static void sym_print_lun(hcb_p np, int target, int lun)
+{
+ printf ("%s:%d:%d:", sym_name(np), target, lun);
+}
+
+/*
+ * Print out the content of a SCSI message.
+ */
+static int sym_show_msg (u_char * msg)
+{
+ u_char i;
+ printf ("%x",*msg);
+ if (*msg==M_EXTENDED) {
+ for (i=1;i<8;i++) {
+ if (i-1>msg[1]) break;
+ printf ("-%x",msg[i]);
+ };
+ return (i+1);
+ } else if ((*msg & 0xf0) == 0x20) {
+ printf ("-%x",msg[1]);
+ return (2);


+ };
+ return (1);
+}
+

+static void sym_print_msg (ccb_p cp, char *label, u_char *msg)
+{
+ PRINT_ADDR(cp);
+ if (label)
+ printf ("%s: ", label);
+
+ (void) sym_show_msg (msg);
+ printf (".\n");
+}
+
+static void sym_print_nego_msg (hcb_p np, int target, char *label, u_char *msg)
+{
+ PRINT_TARGET(np, target);
+ if (label)
+ printf ("%s: ", label);
+
+ (void) sym_show_msg (msg);
+ printf (".\n");
+}
+
+/*
+ * Print something that tells about extended errors.
+ */
+void sym_print_xerr(ccb_p cp, int x_status)
+{
+ if (x_status & XE_PARITY_ERR) {
+ PRINT_ADDR(cp);
+ printf ("unrecovered SCSI parity error.\n");
+ }
+ if (x_status & XE_EXTRA_DATA) {
+ PRINT_ADDR(cp);
+ printf ("extraneous data discarded.\n");
+ }
+ if (x_status & XE_BAD_PHASE) {
+ PRINT_ADDR(cp);
+ printf ("illegal scsi phase (4/5).\n");
+ }
+ if (x_status & XE_SODL_UNRUN) {
+ PRINT_ADDR(cp);
+ printf ("ODD transfer in DATA OUT phase.\n");
+ }
+ if (x_status & XE_SWIDE_OVRUN) {
+ PRINT_ADDR(cp);
+ printf ("ODD transfer in DATA IN phase.\n");
+ }
+}
+
+/*
+ * Return a string for SCSI BUS mode.
+ */
+static char *sym_scsi_bus_mode(int mode)
+{
+ switch(mode) {
+ case SMODE_HVD: return "HVD";
+ case SMODE_SE: return "SE";
+ case SMODE_LVD: return "LVD";
+ }
+ return "??";
+}
+
+/*
+ * Soft reset the chip.
+ *
+ * Raising SRST when the chip is running may cause
+ * problems on dual function chips (see below).
+ * On the other hand, LVD devices need some delay
+ * to settle and report actual BUS mode in STEST4.
+ */
+static void sym_chip_reset (hcb_p np)
+{
+ OUTB (nc_istat, SRST);
+ UDELAY (10);
+ OUTB (nc_istat, 0);
+ UDELAY(2000); /* For BUS MODE to settle */
+}
+
+/*
+ * Really soft reset the chip.:)
+ *
+ * Some 896 and 876 chip revisions may hang-up if we set
+ * the SRST (soft reset) bit at the wrong time when SCRIPTS
+ * are running.
+ * So, we need to abort the current operation prior to
+ * soft resetting the chip.
+ */
+static void sym_soft_reset (hcb_p np)
+{
+ u_char istat;
+ int i;
+
+ if (!(np->features & FE_ISTAT1) || !(INB (nc_istat1) & SCRUN))
+ goto do_chip_reset;
+
+ OUTB (nc_istat, CABRT);
+ for (i = 100000 ; i ; --i) {
+ istat = INB (nc_istat);
+ if (istat & SIP) {
+ INW (nc_sist);
+ }
+ else if (istat & DIP) {
+ if (INB (nc_dstat) & ABRT);
+ break;
+ }
+ UDELAY(5);
+ }
+ OUTB (nc_istat, 0);
+ if (!i)
+ printf("%s: unable to abort current chip operation, "
+ "ISTAT=0x%02x.\n", sym_name(np), istat);
+do_chip_reset:
+ sym_chip_reset (np);
+}
+
+/*
+ * Start reset process.
+ *
+ * The interrupt handler will reinitialize the chip.
+ */
+static void sym_start_reset(hcb_p np)
+{
+ (void) sym_reset_scsi_bus(np, 1);
+}
+
+int sym_reset_scsi_bus(hcb_p np, int enab_int)
+{
+ u32 term;
+ int retv = 0;
+
+ sym_soft_reset(np); /* Soft reset the chip */
+ if (enab_int)
+ OUTW (nc_sien, RST);
+ /*
+ * Enable Tolerant, reset IRQD if present and
+ * properly set IRQ mode, prior to resetting the bus.
+ */
+ OUTB (nc_stest3, TE);
+ OUTB (nc_dcntl, (np->rv_dcntl & IRQM));
+ OUTB (nc_scntl1, CRST);
+ UDELAY (200);
+
+ if (!SYM_SETUP_SCSI_BUS_CHECK)


+ goto out;
+ /*

+ * Check for no terminators or SCSI bus shorts to ground.
+ * Read SCSI data bus, data parity bits and control signals.
+ * We are expecting RESET to be TRUE and other signals to be
+ * FALSE.
+ */
+ term = INB(nc_sstat0);
+ term = ((term & 2) << 7) + ((term & 1) << 17); /* rst sdp0 */
+ term |= ((INB(nc_sstat2) & 0x01) << 26) | /* sdp1 */
+ ((INW(nc_sbdl) & 0xff) << 9) | /* d7-0 */
+ ((INW(nc_sbdl) & 0xff00) << 10) | /* d15-8 */
+ INB(nc_sbcl); /* req ack bsy sel atn msg cd io */
+
+ if (!(np->features & FE_WIDE))
+ term &= 0x3ffff;
+
+ if (term != (2<<7)) {
+ printf("%s: suspicious SCSI data while resetting the BUS.\n",
+ sym_name(np));
+ printf("%s: %sdp0,d7-0,rst,req,ack,bsy,sel,atn,msg,c/d,i/o = "
+ "0x%lx, expecting 0x%lx\n",
+ sym_name(np),
+ (np->features & FE_WIDE) ? "dp1,d15-8," : "",
+ (u_long)term, (u_long)(2<<7));
+ if (SYM_SETUP_SCSI_BUS_CHECK == 1)
+ retv = 1;
+ }
+out:
+ OUTB (nc_scntl1, 0);
+ /* MDELAY(100); */
+ return retv;
+}
+
+/*
+ * Select SCSI clock frequency
+ */
+static void sym_selectclock(hcb_p np, u_char scntl3)
+{
+ /*
+ * If multiplier not present or not selected, leave here.
+ */
+ if (np->multiplier <= 1) {
+ OUTB(nc_scntl3, scntl3);
+ return;
+ }
+


+ if (sym_verbose >= 2)

+ printf ("%s: enabling clock multiplier\n", sym_name(np));
+
+ OUTB(nc_stest1, DBLEN); /* Enable clock multiplier */
+ /*
+ * Wait for the LCKFRQ bit to be set if supported by the chip.
+ * Otherwise wait 50 micro-seconds (at least).
+ */
+ if (np->features & FE_LCKFRQ) {
+ int i = 20;
+ while (!(INB(nc_stest4) & LCKFRQ) && --i > 0)
+ UDELAY (20);
+ if (!i)
+ printf("%s: the chip cannot lock the frequency\n",
+ sym_name(np));
+ } else
+ UDELAY ((50+10));
+ OUTB(nc_stest3, HSC); /* Halt the scsi clock */
+ OUTB(nc_scntl3, scntl3);
+ OUTB(nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */
+ OUTB(nc_stest3, 0x00); /* Restart scsi clock */
+}
+
+
+/*
+ * Determine the chip's clock frequency.
+ *
+ * This is essential for the negotiation of the synchronous
+ * transfer rate.
+ *
+ * Note: we have to return the correct value.
+ * THERE IS NO SAFE DEFAULT VALUE.
+ *
+ * Most NCR/SYMBIOS boards are delivered with a 40 Mhz clock.
+ * 53C860 and 53C875 rev. 1 support fast20 transfers but
+ * do not have a clock doubler and so are provided with a
+ * 80 MHz clock. All other fast20 boards incorporate a doubler
+ * and so should be delivered with a 40 MHz clock.
+ * The recent fast40 chips (895/896/895A/1010) use a 40 Mhz base
+ * clock and provide a clock quadrupler (160 Mhz).
+ */
+
+/*
+ * calculate SCSI clock frequency (in KHz)
+ */
+static unsigned getfreq (hcb_p np, int gen)
+{
+ unsigned int ms = 0;
+ unsigned int f;
+
+ /*
+ * Measure GEN timer delay in order
+ * to calculate SCSI clock frequency
+ *
+ * This code will never execute too
+ * many loop iterations (if DELAY is
+ * reasonably correct). It could get
+ * too low a delay (too high a freq.)
+ * if the CPU is slow executing the
+ * loop for some reason (an NMI, for
+ * example). For this reason we will
+ * if multiple measurements are to be
+ * performed trust the higher delay
+ * (lower frequency returned).
+ */
+ OUTW (nc_sien , 0); /* mask all scsi interrupts */
+ (void) INW (nc_sist); /* clear pending scsi interrupt */
+ OUTB (nc_dien , 0); /* mask all dma interrupts */
+ (void) INW (nc_sist); /* another one, just to be sure :) */
+ /*
+ * The C1010-33 core does not report GEN in SIST,
+ * if this interrupt is masked in SIEN.
+ * I don't know yet if the C1010-66 behaves the same way.
+ */
+ if (np->features & FE_C10) {
+ OUTW (nc_sien, GEN);
+ OUTB (nc_istat1, SIRQD);
+ }
+ OUTB (nc_scntl3, 4); /* set pre-scaler to divide by 3 */
+ OUTB (nc_stime1, 0); /* disable general purpose timer */
+ OUTB (nc_stime1, gen); /* set to nominal delay of 1<<gen * 125us */
+ while (!(INW(nc_sist) & GEN) && ms++ < 100000)
+ UDELAY (1000/4);/* count in 1/4 of ms */
+ OUTB (nc_stime1, 0); /* disable general purpose timer */
+ /*
+ * Undo C1010-33 specific settings.
+ */
+ if (np->features & FE_C10) {
+ OUTW (nc_sien, 0);
+ OUTB (nc_istat1, 0);
+ }
+ /*
+ * set prescaler to divide by whatever 0 means
+ * 0 ought to choose divide by 2, but appears
+ * to set divide by 3.5 mode in my 53c810 ...
+ */
+ OUTB (nc_scntl3, 0);
+
+ /*
+ * adjust for prescaler, and convert into KHz
+ */
+ f = ms ? ((1 << gen) * (4340*4)) / ms : 0;
+
+ /*
+ * The C1010-33 result is biased by a factor
+ * of 2/3 compared to earlier chips.
+ */
+ if (np->features & FE_C10)
+ f = (f * 2) / 3;
+


+ if (sym_verbose >= 2)

+ printf ("%s: Delay (GEN=%d): %u msec, %u KHz\n",
+ sym_name(np), gen, ms/4, f);
+
+ return f;
+}
+
+static unsigned sym_getfreq (hcb_p np)
+{
+ u_int f1, f2;
+ int gen = 8;
+
+ (void) getfreq (np, gen); /* throw away first result */
+ f1 = getfreq (np, gen);
+ f2 = getfreq (np, gen);
+ if (f1 > f2) f1 = f2; /* trust lower result */
+ return f1;
+}
+
+/*
+ * Get/probe chip SCSI clock frequency
+ */
+static void sym_getclock (hcb_p np, int mult)
+{
+ unsigned char scntl3 = np->sv_scntl3;
+ unsigned char stest1 = np->sv_stest1;
+ unsigned f1;
+
+ np->multiplier = 1;
+ f1 = 40000;
+ /*
+ * True with 875/895/896/895A with clock multiplier selected
+ */
+ if (mult > 1 && (stest1 & (DBLEN+DBLSEL)) == DBLEN+DBLSEL) {


+ if (sym_verbose >= 2)

+ printf ("%s: clock multiplier found\n", sym_name(np));
+ np->multiplier = mult;
+ }
+
+ /*
+ * If multiplier not found or scntl3 not 7,5,3,
+ * reset chip and get frequency from general purpose timer.
+ * Otherwise trust scntl3 BIOS setting.
+ */
+ if (np->multiplier != mult || (scntl3 & 7) < 3 || !(scntl3 & 1)) {
+ OUTB (nc_stest1, 0); /* make sure doubler is OFF */
+ f1 = sym_getfreq (np);
+
+ if (sym_verbose)
+ printf ("%s: chip clock is %uKHz\n", sym_name(np), f1);
+
+ if (f1 < 45000) f1 = 40000;
+ else if (f1 < 55000) f1 = 50000;
+ else f1 = 80000;
+
+ if (f1 < 80000 && mult > 1) {


+ if (sym_verbose >= 2)

+ printf ("%s: clock multiplier assumed\n",
+ sym_name(np));
+ np->multiplier = mult;
+ }
+ } else {
+ if ((scntl3 & 7) == 3) f1 = 40000;
+ else if ((scntl3 & 7) == 5) f1 = 80000;
+ else f1 = 160000;
+
+ f1 /= np->multiplier;
+ }
+
+ /*
+ * Compute controller synchronous parameters.
+ */
+ f1 *= np->multiplier;
+ np->clock_khz = f1;
+}
+
+/*
+ * Get/probe PCI clock frequency
+ */
+static int sym_getpciclock (hcb_p np)
+{
+ int f = 0;
+
+ /*
+ * For now, we only need to know about the actual
+ * PCI BUS clock frequency for C1010-66 chips.
+ */
+#if 1
+ if (np->features & FE_66MHZ) {
+#else
+ if (1) {
+#endif
+ OUTB (nc_stest1, SCLK); /* Use the PCI clock as SCSI clock */
+ f = (int) sym_getfreq (np);
+ OUTB (nc_stest1, 0);
+ }
+ np->pciclk_khz = f;
+
+ return f;
+}
+
+/*
+ * SYMBIOS chip clock divisor table.
+ *
+ * Divisors are multiplied by 10,000,000 in order to make
+ * calculations more simple.
+ */
+#define _5M 5000000
+static u32 div_10M[] = {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M};
+
+/*
+ * Get clock factor and sync divisor for a given
+ * synchronous factor period.
+ */
+static int
+sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp, u_char *fakp)
+{
+ u32 clk = np->clock_khz; /* SCSI clock frequency in kHz */
+ int div = np->clock_divn; /* Number of divisors supported */
+ u32 fak; /* Sync factor in sxfer */
+ u32 per; /* Period in tenths of ns */
+ u32 kpc; /* (per * clk) */
+ int ret;
+
+ /*
+ * Compute the synchronous period in tenths of nano-seconds
+ */
+ if (dt && sfac <= 9) per = 125;
+ else if (sfac <= 10) per = 250;
+ else if (sfac == 11) per = 303;
+ else if (sfac == 12) per = 500;
+ else per = 40 * sfac;
+ ret = per;
+
+ kpc = per * clk;
+ if (dt)
+ kpc <<= 1;
+
+ /*
+ * For earliest C10 revision 0, we cannot use extra
+ * clocks for the setting of the SCSI clocking.
+ * Note that this limits the lowest sync data transfer
+ * to 5 Mega-transfers per second and may result in
+ * using higher clock divisors.
+ */
+#if 1
+ if ((np->features & (FE_C10|FE_U3EN)) == FE_C10) {
+ /*
+ * Look for the lowest clock divisor that allows an
+ * output speed not faster than the period.
+ */
+ while (div > 0) {
+ --div;
+ if (kpc > (div_10M[div] << 2)) {
+ ++div;
+ break;
+ }
+ }
+ fak = 0; /* No extra clocks */
+ if (div == np->clock_divn) { /* Are we too fast ? */
+ ret = -1;
+ }
+ *divp = div;
+ *fakp = fak;
+ return ret;


+ }
+#endif
+
+ /*

+ * Look for the greatest clock divisor that allows an
+ * input speed faster than the period.
+ */
+ while (div-- > 0)
+ if (kpc >= (div_10M[div] << 2)) break;
+
+ /*
+ * Calculate the lowest clock factor that allows an output
+ * speed not faster than the period, and the max output speed.
+ * If fak >= 1 we will set both XCLKH_ST and XCLKH_DT.
+ * If fak >= 2 we will also set XCLKS_ST and XCLKS_DT.
+ */
+ if (dt) {
+ fak = (kpc - 1) / (div_10M[div] << 1) + 1 - 2;
+ /* ret = ((2+fak)*div_10M[div])/np->clock_khz; */
+ }
+ else {
+ fak = (kpc - 1) / div_10M[div] + 1 - 4;
+ /* ret = ((4+fak)*div_10M[div])/np->clock_khz; */
+ }
+
+ /*
+ * Check against our hardware limits, or bugs :).
+ */
+ if (fak < 0) {fak = 0; ret = -1;}
+ if (fak > 2) {fak = 2; ret = -1;}
+
+ /*
+ * Compute and return sync parameters.
+ */
+ *divp = div;
+ *fakp = fak;
+
+ return ret;
+}
+
+/*
+ * SYMBIOS chips allow burst lengths of 2, 4, 8, 16, 32, 64,
+ * 128 transfers. All chips support at least 16 transfers
+ * bursts. The 825A, 875 and 895 chips support bursts of up
+ * to 128 transfers and the 895A and 896 support bursts of up
+ * to 64 transfers. All other chips support up to 16
+ * transfers bursts.
+ *
+ * For PCI 32 bit data transfers each transfer is a DWORD.
+ * It is a QUADWORD (8 bytes) for PCI 64 bit data transfers.
+ *
+ * We use log base 2 (burst length) as internal code, with
+ * value 0 meaning "burst disabled".
+ */
+
+/*
+ * Burst length from burst code.
+ */
+#define burst_length(bc) (!(bc))? 0 : 1 << (bc)
+
+/*
+ * Burst code from io register bits.
+ */
+#define burst_code(dmode, ctest4, ctest5) \
+ (ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ((ctest5) & 0x04) + 1
+
+/*
+ * Set initial io register bits from burst code.
+ */
+static __inline void sym_init_burst(hcb_p np, u_char bc)
+{
+ np->rv_ctest4 &= ~0x80;
+ np->rv_dmode &= ~(0x3 << 6);
+ np->rv_ctest5 &= ~0x4;
+
+ if (!bc) {
+ np->rv_ctest4 |= 0x80;
+ }
+ else {
+ --bc;
+ np->rv_dmode |= ((bc & 0x3) << 6);
+ np->rv_ctest5 |= (bc & 0x4);


+ }
+}
+
+
+/*

+ * Print out the list of targets that have some flag disabled by user.
+ */
+static void sym_print_targets_flag(hcb_p np, int mask, char *msg)
+{
+ int cnt;
+ int i;
+
+ for (cnt = 0, i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {
+ if (i == np->myaddr)
+ continue;
+ if (np->target[i].usrflags & mask) {
+ if (!cnt++)
+ printf("%s: %s disabled for targets",
+ sym_name(np), msg);
+ printf(" %d", i);
+ }
+ }
+ if (cnt)
+ printf(".\n");
+}
+
+/*
+ * Save initial settings of some IO registers.
+ * Assumed to have been set by BIOS.
+ * We cannot reset the chip prior to reading the
+ * IO registers, since informations will be lost.
+ * Since the SCRIPTS processor may be running, this
+ * is not safe on paper, but it seems to work quite
+ * well. :)
+ */
+static void sym_save_initial_setting (hcb_p np)
+{
+ np->sv_scntl0 = INB(nc_scntl0) & 0x0a;
+ np->sv_scntl3 = INB(nc_scntl3) & 0x07;
+ np->sv_dmode = INB(nc_dmode) & 0xce;
+ np->sv_dcntl = INB(nc_dcntl) & 0xa8;
+ np->sv_ctest3 = INB(nc_ctest3) & 0x01;
+ np->sv_ctest4 = INB(nc_ctest4) & 0x80;
+ np->sv_gpcntl = INB(nc_gpcntl);
+ np->sv_stest1 = INB(nc_stest1);
+ np->sv_stest2 = INB(nc_stest2) & 0x20;
+ np->sv_stest4 = INB(nc_stest4);
+ if (np->features & FE_C10) { /* Always large DMA fifo + ultra3 */
+ np->sv_scntl4 = INB(nc_scntl4);
+ np->sv_ctest5 = INB(nc_ctest5) & 0x04;
+ }
+ else
+ np->sv_ctest5 = INB(nc_ctest5) & 0x24;
+}
+
+/*
+ * Prepare io register values used by sym_start_up()
+ * according to selected and supported features.
+ */
+static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
+{
+ u_char burst_max;
+ u32 period;
+ int i;
+
+ /*
+ * Wide ?
+ */
+ np->maxwide = (np->features & FE_WIDE)? 1 : 0;
+
+ /*
+ * Guess the frequency of the chip's clock.
+ */
+ if (np->features & (FE_ULTRA3 | FE_ULTRA2))
+ np->clock_khz = 160000;
+ else if (np->features & FE_ULTRA)
+ np->clock_khz = 80000;
+ else
+ np->clock_khz = 40000;
+
+ /*
+ * Get the clock multiplier factor.
+ */
+ if (np->features & FE_QUAD)
+ np->multiplier = 4;
+ else if (np->features & FE_DBLR)
+ np->multiplier = 2;
+ else
+ np->multiplier = 1;
+
+ /*
+ * Measure SCSI clock frequency for chips
+ * it may vary from assumed one.
+ */
+ if (np->features & FE_VARCLK)
+ sym_getclock(np, np->multiplier);
+
+ /*
+ * Divisor to be used for async (timer pre-scaler).
+ */
+ i = np->clock_divn - 1;
+ while (--i >= 0) {
+ if (10ul * SYM_CONF_MIN_ASYNC * np->clock_khz > div_10M[i]) {
+ ++i;
+ break;
+ }
+ }
+ np->rv_scntl3 = i+1;
+
+ /*
+ * The C1010 uses hardwired divisors for async.
+ * So, we just throw away, the async. divisor.:-)
+ */
+ if (np->features & FE_C10)
+ np->rv_scntl3 = 0;
+
+ /*
+ * Minimum synchronous period factor supported by the chip.
+ * Btw, 'period' is in tenths of nanoseconds.
+ */
+ period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz;
+ if (period <= 250) np->minsync = 10;
+ else if (period <= 303) np->minsync = 11;
+ else if (period <= 500) np->minsync = 12;
+ else np->minsync = (period + 40 - 1) / 40;
+
+ /*
+ * Check against chip SCSI standard support (SCSI-2,ULTRA,ULTRA2).
+ */
+ if (np->minsync < 25 &&
+ !(np->features & (FE_ULTRA|FE_ULTRA2|FE_ULTRA3)))
+ np->minsync = 25;
+ else if (np->minsync < 12 &&
+ !(np->features & (FE_ULTRA2|FE_ULTRA3)))
+ np->minsync = 12;
+
+ /*
+ * Maximum synchronous period factor supported by the chip.
+ */
+ period = (11 * div_10M[np->clock_divn - 1]) / (4 * np->clock_khz);
+ np->maxsync = period > 2540 ? 254 : period / 10;
+
+ /*
+ * If chip is a C1010, guess the sync limits in DT mode.
+ */
+ if ((np->features & (FE_C10|FE_ULTRA3)) == (FE_C10|FE_ULTRA3)) {
+ if (np->clock_khz == 160000) {
+ np->minsync_dt = 9;
+ np->maxsync_dt = 50;
+ np->maxoffs_dt = nvram->type ? 62 : 31;


+ }
+ }
+
+ /*

+ * 64 bit addressing (895A/896/1010) ?
+ */
+ if (np->features & FE_DAC) {
+#if SYM_CONF_DMA_ADDRESSING_MODE == 0
+ np->rv_ccntl1 |= (DDAC);
+#elif SYM_CONF_DMA_ADDRESSING_MODE == 1
+ if (!np->use_dac)
+ np->rv_ccntl1 |= (DDAC);
+ else
+ np->rv_ccntl1 |= (XTIMOD | EXTIBMV);


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

echo 'End of part 064'
echo 'File patch-2.4.15 is continued in part 065'
echo "065" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:33 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part057

#!/bin/sh -x
# this is part 057 of a 115 - part archive


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

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

- * <dah...@users.sourceforge.net>. Portions created by David A. Hinds


- * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL. If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the MPL or the GPL.
- */
-

-#ifndef _RSRC_MGR_H
-#define _RSRC_MGR_H
-
-#endif /* _RSRC_MGR_H */
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/smc34c90.h linux/drivers/pcmcia/smc34c90.h
--- v2.4.14/linux/drivers/pcmcia/smc34c90.h Fri Feb 16 16:02:36 2001
+++ linux/drivers/pcmcia/smc34c90.h Wed Dec 31 16:00:00 1969
@@ -1,52 +0,0 @@
-/*
- * smc34c90.h 1.7 1999/10/25 20:03:34

-#ifndef _LINUX_SMC34C90_H
-#define _LINUX_SMC34C90_H
-
-#ifndef PCI_VENDOR_ID_SMC
-#define PCI_VENDOR_ID_SMC 0x10b3
-#endif
-
-#ifndef PCI_DEVICE_ID_SMC_34C90
-#define PCI_DEVICE_ID_SMC_34C90 0xb106
-#endif
-
-/* Register definitions for SMC 34C90 PCI-to-CardBus bridge */
-
-/* EEPROM Information Register */
-#define SMC34C90_EEINFO 0x0088
-#define SMC34C90_EEINFO_ONE_SOCKET 0x0001
-#define SMC34C90_EEINFO_5V_ONLY 0x0002
-#define SMC34C90_EEINFO_ISA_IRQ 0x0004
-#define SMC34C90_EEINFO_ZV_PORT 0x0008
-#define SMC34C90_EEINFO_RING 0x0010
-#define SMC34C90_EEINFO_LED 0x0020
-
-#endif /* _LINUX_SMC34C90_H */
diff -u --recursive --new-file v2.4.14/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c
--- v2.4.14/linux/drivers/pcmcia/yenta.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/pcmcia/yenta.c Tue Nov 20 23:19:48 2001
@@ -673,6 +673,9 @@
X {
X yenta_config_init(socket);
X yenta_clear_maps(socket);
+
+ /* Re-enable interrupts */
+ cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK);


X return 0;
X }
X

@@ -680,6 +683,9 @@
X {
X yenta_set_socket(socket, &dead_socket);
X
+ /* Disable interrupts */
+ cb_writel(socket, CB_SOCKET_MASK, 0x0);
+
X /*
X * This does not work currently. The controller
X * loses too much informationduring D3 to come up
@@ -764,6 +770,7 @@
X {
X /* Disable all events so we don't die in an IRQ storm */
X cb_writel(sock, CB_SOCKET_MASK, 0x0);
+ exca_writeb(sock, I365_CSCINT, 0);
X
X if (sock->cb_irq)
X free_irq(sock->cb_irq, sock);
diff -u --recursive --new-file v2.4.14/linux/drivers/pnp/isapnp.c linux/drivers/pnp/isapnp.c
--- v2.4.14/linux/drivers/pnp/isapnp.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/pnp/isapnp.c Mon Nov 12 10:02:54 2001
@@ -25,6 +25,9 @@
X * 2001-06-03 Added release_region calls to correspond with
X * request_region calls when a failure occurs. Also
X * added KERN_* constants to printk() calls.
+ * 2001-11-07 Added isapnp_{,un}register_driver calls along the lines
+ * of the pci driver interface
+ * Kai Germaschewski <kai.germ...@gmx.de>


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

@@ -2162,6 +2165,89 @@
X #endif
X }
X
+static int isapnp_announce_device(struct isapnp_driver *drv,
+ struct pci_dev *dev)
+{
+ const struct isapnp_device_id *id;
+ int ret = 0;
+
+ if (drv->id_table) {
+ id = isapnp_match_dev(drv->id_table, dev);
+ if (!id) {
+ ret = 0;
+ goto out;
+ }
+ } else
+ id = NULL;
+
+ if (drv->probe(dev, id) >= 0) {
+ dev->driver = (struct pci_driver *) drv;
+ ret = 1;
+ }
+out:


+ return ret;
+}
+

+/**
+ * isapnp_dev_driver - get the isapnp_driver of a device
+ * @dev: the device to query
+ *
+ * Returns the appropriate isapnp_driver structure or %NULL if there is no
+ * registered driver for the device.
+ */
+static struct isapnp_driver *isapnp_dev_driver(const struct pci_dev *dev)
+{
+ return (struct isapnp_driver *) dev->driver;
+}
+
+static LIST_HEAD(isapnp_drivers);
+
+/**
+ * isapnp_register_driver - register a new ISAPnP driver
+ * @drv: the driver structure to register
+ *
+ * Adds the driver structure to the list of registered ISAPnP drivers
+ * Returns the number of isapnp devices which were claimed by the driver
+ * during registration. The driver remains registered even if the
+ * return value is zero.
+ */
+int isapnp_register_driver(struct isapnp_driver *drv)
+{
+ struct pci_dev *dev;
+ int count = 0;
+
+ list_add_tail(&drv->node, &isapnp_drivers);
+
+ isapnp_for_each_dev(dev) {
+ if (!isapnp_dev_driver(dev))
+ count += isapnp_announce_device(drv, dev);
+ }
+ return count;
+}
+
+/**
+ * isapnp_unregister_driver - unregister an isapnp driver
+ * @drv: the driver structure to unregister
+ *
+ * Deletes the driver structure from the list of registered ISAPnP drivers,
+ * gives it a chance to clean up by calling its remove() function for
+ * each device it was responsible for, and marks those devices as
+ * driverless.
+ */
+void isapnp_unregister_driver(struct isapnp_driver *drv)
+{


+ struct pci_dev *dev;
+

+ list_del(&drv->node);
+ isapnp_for_each_dev(dev) {
+ if (dev->driver == (struct pci_driver *) drv) {
+ if (drv->remove)
+ drv->remove(dev);


+ dev->driver = NULL;

+ }
+ }
+}
+
X EXPORT_SYMBOL(isapnp_cards);
X EXPORT_SYMBOL(isapnp_devices);
X EXPORT_SYMBOL(isapnp_present);
@@ -2183,6 +2269,8 @@
X EXPORT_SYMBOL(isapnp_probe_devs);
X EXPORT_SYMBOL(isapnp_activate_dev);
X EXPORT_SYMBOL(isapnp_resource_change);
+EXPORT_SYMBOL(isapnp_register_driver);
+EXPORT_SYMBOL(isapnp_unregister_driver);
X
X int __init isapnp_init(void)
X {
diff -u --recursive --new-file v2.4.14/linux/drivers/s390/block/dasd.c linux/drivers/s390/block/dasd.c
--- v2.4.14/linux/drivers/s390/block/dasd.c Mon Nov 5 15:55:31 2001
+++ linux/drivers/s390/block/dasd.c Fri Nov 9 14:05:02 2001
@@ -117,6 +117,8 @@
X /* SECTION: Constant definitions to be used within this file */
X
X #define PRINTK_HEADER DASD_NAME":"
+#undef DASD_PROFILE /* fill profile information - used for */
+ /* statistics and perfomance */
X
X #define DASD_MIN_SIZE_FOR_QUEUE 32
X #undef CONFIG_DYNAMIC_QUEUE_MIN_SIZE
@@ -525,6 +527,8 @@
X val = simple_strtoul (buffer, &buffer, 16);
X
X /* check for features - e.g. (ro) ; the '\0', ')' and '-' stops check */
+ *features = DASD_DEFAULT_FEATURES;
+
X if (temp[i]=='(') {
X
X while (temp[i]!='\0' && temp[i]!=')'&&temp[i]!='-') {
@@ -561,7 +565,7 @@
X {
X char *temp;
X int from, to;
- int features = 0;
+ int features;
X int rc = 0;
X
X if (*str) {


@@ -1008,6 +1012,7 @@
X

X static dasd_profile_info_t dasd_global_profile;
X
+#ifdef DASD_PROFILE
X /*
X * macro: dasd_profile_add_counter
X * increments counter in global and local profiling structures
@@ -1032,13 +1037,20 @@
X void
X dasd_profile_add (ccw_req_t * cqr)
X {
- long strtime, irqtime, endtime, tottime;
+ long strtime, irqtime, endtime, tottime; /* in microsecnds*/
X long tottimeps, sectors;
X dasd_device_t *device = cqr->device;
X
X if (!cqr->req) /* safeguard against abnormal cqrs */
X return;
- sectors = ((struct request *) (cqr->req))->nr_sectors;
+
+ if ((!cqr->buildclk) ||
+ (!cqr->startclk) ||
+ (!cqr->stopclk ) ||
+ (!cqr->endclk ) ||
+ (!(sectors = ((struct request *) (cqr->req))->nr_sectors)))
+ return;
+
X strtime = ((cqr->startclk - cqr->buildclk) >> 12);
X irqtime = ((cqr->stopclk - cqr->startclk) >> 12);
X endtime = ((cqr->endclk - cqr->stopclk) >> 12);
@@ -1064,7 +1076,7 @@
X dasd_profile_add_counter (irqtime / sectors, dasd_io_time2ps, device);
X dasd_profile_add_counter (endtime, dasd_io_time3, device);
X }
-
+#endif
X
X /* SECTION: All the gendisk stuff */
X
@@ -1506,6 +1518,11 @@
X dasd_get_queue (kdev_t kdev)
X {
X dasd_device_t *device = dasd_device_from_kdev (kdev);
+
+ if (!device) {


+ return NULL;
+ }
+

X return device->request_queue;
X }
X

@@ -1544,7 +1561,9 @@
X

X asm volatile ("STCK %0":"=m" (cqr->endclk));
X if (cqr->req) {
+#ifdef DASD_PROFILE
X dasd_profile_add (cqr);
+#endif
X dasd_end_request (cqr->req, (cqr->status == CQR_STATUS_DONE));
X /* free request if nobody is waiting on it */
X dasd_free_request (cqr, cqr->device);
@@ -2294,18 +2313,6 @@
X rc = put_user(ver, (int *) data);
X break;


X }
- case BLKGETSIZE:{ /* Return device size */

- unsigned long blocks = major_info->gendisk.sizes
- [MINOR (inp->i_rdev)] << 1;
- rc = put_user(blocks, (unsigned long *) data);


- break;
- }
- case BLKGETSIZE64:{

- u64 blocks = major_info->gendisk.sizes
- [MINOR (inp->i_rdev)];
- rc = put_user(blocks << 10, (u64 *) data);
- break;
- }
X case BLKRRPART:{
X if (!capable (CAP_SYS_ADMIN)) {
X rc = -EACCES;
@@ -2501,6 +2508,8 @@
X break;
X }
X #endif /* 0 */


+ case BLKGETSIZE:
+ case BLKGETSIZE64:

X case BLKSSZGET:


X case BLKROSET:
X case BLKROGET:

@@ -2577,7 +2586,7 @@
X }
X spin_lock_irqsave(&discipline_lock,flags);
X device = dasd_device_from_kdev (inp->i_rdev);
- if (device == NULL ) {
+ if (!device) {
X printk (KERN_WARNING PRINTK_HEADER
X "No device registered as (%d:%d)\n",
X MAJOR (inp->i_rdev),
@@ -2618,7 +2627,7 @@
X goto out;
X }
X device = dasd_device_from_kdev (inp->i_rdev);
- if (device == NULL) {
+ if (!device) {
X printk (KERN_WARNING PRINTK_HEADER
X "No device registered as %d:%d\n",
X MAJOR (inp->i_rdev),
@@ -2638,6 +2647,7 @@
X invalidate_buffers (inp->i_rdev);
X if ( device->discipline->owner )
X __MOD_DEC_USE_COUNT(device->discipline->owner);
+ MOD_DEC_USE_COUNT;
X } else if ( count == -1 ) { /* paranoia only */
X atomic_set (&device->open_count,0);
X printk (KERN_WARNING PRINTK_HEADER
@@ -2661,7 +2671,11 @@
X dasd_fillgeo(int kdev,struct hd_geometry *geo)
X {
X dasd_device_t *device = dasd_device_from_kdev (kdev);
- if (!device->discipline->fill_geometry)
+
+ if (!device)
+ return -EINVAL;
+
+ if (!device->discipline->fill_geometry)
X return -EINVAL;
X
X device->discipline->fill_geometry (device, geo);
@@ -3094,8 +3108,10 @@
X #endif
X }
X goto out;
+#ifdef CONFIG_ARCH_S390X
X noidal:
X free_page ((long) device->lowmem_ccws);
+#endif
X noccw:
X kfree(device);
X out:
@@ -3308,16 +3324,16 @@


X int rc = 0;

X unsigned long flags;
X

- if ( device->init_cqr != NULL ) {
+ s390irq_spin_lock_irqsave (device->devinfo.irq, flags);
+ if ( device->init_cqr != NULL && atomic_read(&dasd_init_pending) != 0 ) {
X if ( device->discipline->term_IO == NULL )
X BUG();
- s390irq_spin_lock_irqsave (device->devinfo.irq, flags);
X device->discipline->term_IO (device->init_cqr);
- s390irq_spin_unlock_irqrestore(device->devinfo.irq, flags);
X atomic_dec (&dasd_init_pending);
X dasd_free_request (device->init_cqr, device);
X device->init_cqr = NULL;
X }
+ s390irq_spin_unlock_irqrestore(device->devinfo.irq, flags);
X memset(&device->sizes,0,sizeof(dasd_sizes_t));
X device->level = DASD_STATE_ACCEPT;
X return rc;
@@ -3632,19 +3648,30 @@
X for (i = 0; i < 1 << (MINORBITS - DASD_PARTN_BITS); i++) {
X dasd_device_t *device;
X int devno = dasd_devno_from_devindex(index+i);
+ int features;
+
X if ( devno == -ENODEV )
X continue;
+
+ features = dasd_features_from_devno(devno);
+ if (features < DASD_DEFAULT_FEATURES)
+ features = DASD_DEFAULT_FEATURES;
+
X device = temp->dasd_device[i];
X if (device) {
+
X len += sprintf (info->data + len,
- "%04x(%s) at (%3d:%3d) is %7s:",
+ "%04x(%s) at (%3d:%3d) is %-7s%4s: ",
X device->devinfo.devno,
X device->discipline ?
X device->
X discipline->name : "none",
X temp->gendisk.major,
X i << DASD_PARTN_BITS,
- device->name);
+ device->name,
+ (features & DASD_FEATURE_READONLY) ?
+ "(ro)" : " ");
+
X switch (device->level) {
X case DASD_STATE_NEW:
X len +=
@@ -3709,10 +3736,12 @@
X "%04x",devno);
X }
X len += sprintf (info->data + len,
- "(none) at (%3d:%3d) is %7s: unknown",
+ "(none) at (%3d:%3d) is %-7s%4s: unknown",
X temp->gendisk.major,
X i << DASD_PARTN_BITS,
- buffer);
+ buffer,
+ (features & DASD_FEATURE_READONLY) ?
+ "(ro)" : " ");
X }
X if ( dasd_probeonly )
X len += sprintf(info->data + len,"(probeonly)");
@@ -3753,7 +3782,7 @@
X int off = 0;
X char *temp;
X dasd_range_t range;
- int features = 0;
+ int features;
X
X if (buffer == NULL)
X return -ENOMEM;
@@ -3906,7 +3935,7 @@
X }
X len += sprintf (info->data + len, "\n");
X
- len += sprintf (info->data + len, "Histogram of I/O times\n");
+ len += sprintf (info->data + len, "Histogram of I/O times (microseconds)\n");
X for (i = 0; i < 16; i++) {
X len += sprintf (info->data + len, "%7d ",
X dasd_global_profile.dasd_io_times[i] >> shift);
diff -u --recursive --new-file v2.4.14/linux/drivers/s390/block/dasd_3990_erp.c linux/drivers/s390/block/dasd_3990_erp.c
--- v2.4.14/linux/drivers/s390/block/dasd_3990_erp.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/s390/block/dasd_3990_erp.c Fri Nov 9 14:05:02 2001
@@ -55,7 +55,7 @@
X while (loop_cqr != NULL) {
X
X DASD_MESSAGE (KERN_ERR, device,
- "(%s) ERP chain report for req: %p\n",
+ "(%s) ERP chain report for req: %p",
X caller == 0 ? "EXAMINE" : "ACTION",
X loop_cqr);
X
@@ -66,7 +66,7 @@
X
X DASD_MESSAGE (KERN_ERR, device,
X "%p: %02x%02x%02x%02x %02x%02x%02x%02x "
- "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+ "%02x%02x%02x%02x %02x%02x%02x%02x",
X nl,
X nl[0], nl[1], nl[2], nl[3],
X nl[4], nl[5], nl[6], nl[7],
@@ -80,13 +80,13 @@
X if (loop_cqr->cplength > 40) { /* log only parts of the CP */
X
X DASD_MESSAGE (KERN_ERR, device, "%s",
- "Start of channel program:\n");
+ "Start of channel program:");
X
X for (i = 0; i < 20; i += 2) {
X
X DASD_MESSAGE (KERN_ERR, device,
X "%p: %02x%02x%02x%02x %02x%02x%02x%02x "
- "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+ "%02x%02x%02x%02x %02x%02x%02x%02x",
X nl,
X nl[0], nl[1], nl[2], nl[3],
X nl[4], nl[5], nl[6], nl[7],
@@ -97,7 +97,7 @@
X }
X
X DASD_MESSAGE (KERN_ERR, device, "%s",
- "End of channel program:\n");
+ "End of channel program:");
X
X nl = (char *) loop_cqr->cpaddr;
X nl += ((loop_cqr->cplength - 10) * 8);
@@ -106,7 +106,7 @@
X
X DASD_MESSAGE (KERN_ERR, device,
X "%p: %02x%02x%02x%02x %02x%02x%02x%02x "
- "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+ "%02x%02x%02x%02x %02x%02x%02x%02x",
X nl,
X nl[0], nl[1], nl[2], nl[3],
X nl[4], nl[5], nl[6], nl[7],
@@ -119,13 +119,13 @@
X } else { /* log the whole CP */
X
X DASD_MESSAGE (KERN_ERR, device, "%s",
- "Channel program (complete):\n");
+ "Channel program (complete):");
X
X for (i = 0; i < (loop_cqr->cplength + 4); i += 2) {
X
X DASD_MESSAGE (KERN_ERR, device,
X "%p: %02x%02x%02x%02x %02x%02x%02x%02x "
- "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+ "%02x%02x%02x%02x %02x%02x%02x%02x",
X nl,
X nl[0], nl[1], nl[2], nl[3],
X nl[4], nl[5], nl[6], nl[7],
@@ -151,14 +151,14 @@
X nl -= 10*8; /* start some bytes before */
X
X DASD_MESSAGE (KERN_ERR, device,
- "Failed CCW (%p) (area):\n",
+ "Failed CCW (%p) (area):",
X (void *)(long)cpa);
X
X for (i = 0; i < 20; i += 2) {
X
X DASD_MESSAGE (KERN_ERR, device,
X "%p: %02x%02x%02x%02x %02x%02x%02x%02x "
- "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+ "%02x%02x%02x%02x %02x%02x%02x%02x",
X nl,
X nl[0], nl[1], nl[2], nl[3],
X nl[4], nl[5], nl[6], nl[7],
@@ -171,7 +171,7 @@
X } else {
X
X DASD_MESSAGE (KERN_ERR, device,
- "Failed CCW (%p) already logged\n",
+ "Failed CCW (%p) already logged",
X (void *)(long)cpa);
X }
X }
diff -u --recursive --new-file v2.4.14/linux/drivers/s390/block/dasd_eckd.c linux/drivers/s390/block/dasd_eckd.c
--- v2.4.14/linux/drivers/s390/block/dasd_eckd.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/s390/block/dasd_eckd.c Fri Nov 9 14:05:02 2001
@@ -631,7 +631,7 @@
X }
X }
X if (device->sizes.bp_block == 0) {
- DASD_MESSAGE (KERN_WARNING, device, "%s\n",
+ DASD_MESSAGE (KERN_WARNING, device, "%s",
X "Volume has incompatible disk layout");
X return -EMEDIUMTYPE;
X }
@@ -746,7 +746,7 @@
X (fdata->start_unit / private->rdc_data.no_cyl) %
X (private->rdc_data.no_cyl / 20))) {
X DASD_MESSAGE (KERN_INFO, device,
- "Format Cylinder: %d Flags: %d\n",
+ "Format Cylinder: %d Flags: %d",
X fdata->start_unit / private->rdc_data.trk_per_cyl, fdata->intensity);
X }
X if ((fdata->intensity & ~0x8) & 0x04) {
diff -u --recursive --new-file v2.4.14/linux/drivers/s390/char/tape34xx.c linux/drivers/s390/char/tape34xx.c
--- v2.4.14/linux/drivers/s390/char/tape34xx.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/s390/char/tape34xx.c Fri Nov 9 14:05:02 2001
@@ -1631,7 +1631,7 @@
X tapestate_set (ti, TS_DONE);
X ti->rc = 0;
X ti->wanna_wakeup=1;
- wake_up_interruptible (&ti->wq);
+ wake_up (&ti->wq);
X }
X
X void
@@ -2050,8 +2050,13 @@
X return;
X case 0x38:
X // Physical end of tape. A read/write operation reached the physical end of tape.
- if (tapestate_get(ti)==TS_WRI_INIT) {
+ if (tapestate_get(ti)==TS_WRI_INIT ||
+ tapestate_get(ti)==TS_DSE_INIT ||
+ tapestate_get(ti)==TS_EGA_INIT ||
+ tapestate_get(ti)==TS_WTM_INIT){
X tape34xx_error_recovery_has_failed(ti,ENOSPC);
+ } else {
+ tape34xx_error_recovery_has_failed(ti,EIO);
X }
X return;
X case 0x39:
diff -u --recursive --new-file v2.4.14/linux/drivers/s390/char/tapechar.c linux/drivers/s390/char/tapechar.c
--- v2.4.14/linux/drivers/s390/char/tapechar.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/s390/char/tapechar.c Fri Nov 9 14:05:02 2001
@@ -704,7 +704,7 @@
X long lockflags;
X tape_info_t *ti,*lastti;
X ccw_req_t *cqr = NULL;
- int rc;


+ int rc = 0;

X
X ti = first_tape_info;
X while ((ti != NULL) && (ti->rew_minor != MINOR (inode->i_rdev)) && (ti->nor_minor != MINOR (inode->i_rdev)))
@@ -718,13 +718,14 @@
X lastti->next=ti->next;
X }
X kfree(ti);
- return 0;
+ goto out;
X }
X if ((ti == NULL) || (tapestate_get (ti) != TS_IDLE)) {
X #ifdef TAPE_DEBUG
X debug_text_event (tape_debug_area,6,"c:notidle!");
X #endif
- return -ENXIO; /* error in tape_release */
+ rc = -ENXIO; /* error in tape_release */
+ goto out;
X }
X #ifdef TAPE_DEBUG
X debug_text_event (tape_debug_area,6,"c:release:");
@@ -750,8 +751,9 @@
X s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
X tapestate_set (ti, TS_UNUSED);
X s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
+out:
X #ifdef MODULE
X MOD_DEC_USE_COUNT;


X #endif /* MODULE */

- return 0;
+ return rc;
X }
diff -u --recursive --new-file v2.4.14/linux/drivers/s390/misc/chandev.c linux/drivers/s390/misc/chandev.c
--- v2.4.14/linux/drivers/s390/misc/chandev.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/s390/misc/chandev.c Fri Nov 9 14:05:02 2001
@@ -2428,8 +2428,7 @@
X else if(ints[0]==2)
X ints[3]=ints[2];
X chandev_add_parms(ints[1],ints[2],ints[3],currstr);
-// currstr=currstr+strlen(currstr)+1;
- continue;
+ goto NextOption;
X }
X else
X goto BadArgs;
@@ -2696,6 +2695,7 @@
X }
X else
X goto BadArgs;
+ NextOption:
X if(cnt<strcnt)
X {
X /* eat up stuff till next string */
diff -u --recursive --new-file v2.4.14/linux/drivers/s390/s390io.c linux/drivers/s390/s390io.c
--- v2.4.14/linux/drivers/s390/s390io.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/s390/s390io.c Thu Nov 22 10:41:14 2001
@@ -33,7 +33,7 @@
X #include <linux/signal.h>
X #include <linux/sched.h>
X #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
X #include <linux/string.h>
X #include <linux/smp.h>
X #include <linux/threads.h>
diff -u --recursive --new-file v2.4.14/linux/drivers/s390/s390mach.c linux/drivers/s390/s390mach.c
--- v2.4.14/linux/drivers/s390/s390mach.c Sun Aug 12 13:28:00 2001
+++ linux/drivers/s390/s390mach.c Fri Nov 9 14:05:02 2001
@@ -170,7 +170,7 @@
X static int s390_machine_check_handler( void *parm)
X {
X struct semaphore *sem = parm;
- int flags;
+ unsigned long flags;
X mache_t *pmache;
X
X int found = 0;
diff -u --recursive --new-file v2.4.14/linux/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c
--- v2.4.14/linux/drivers/sbus/char/su.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/sbus/char/su.c Tue Nov 13 09:16:05 2001
@@ -1,4 +1,4 @@
-/* $Id: su.c,v 1.53 2001/10/13 08:27:50 davem Exp $
+/* $Id: su.c,v 1.54 2001/11/07 14:52:30 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)
@@ -2252,7 +2252,7 @@
X */
X static __inline__ void __init show_su_version(void)
X {
- char *revision = "$Revision: 1.53 $";
+ char *revision = "$Revision: 1.54 $";
X char *version, *p;
X
X version = strchr(revision, ' ');
@@ -3027,14 +3027,16 @@
X int __init su_serial_console_init(void)
X {
X extern int con_is_present(void);
+ int index;
X
X if (con_is_present())
X return 0;
X if (serial_console == 0)
X return 0;
- if (su_table[0].port == 0 || su_table[0].port_node == 0)
+ index = serial_console - 1;
+ if (su_table[index].port == 0 || su_table[index].port_node == 0)
X return 0;
- sercons.index = 0;
+ sercons.index = index;
X register_console(&sercons);
X su_console_registered = 1;
X return 0;
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/3w-xxxx.c linux/drivers/scsi/3w-xxxx.c
--- v2.4.14/linux/drivers/scsi/3w-xxxx.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/scsi/3w-xxxx.c Fri Nov 9 14:05:02 2001
@@ -4,6 +4,7 @@
X Written By: Adam Radford <li...@3ware.com>
X Modifications By: Joel Jacobson <li...@3ware.com>
X Arnaldo Carvalho de Melo <ac...@conectiva.com.br>
+ Brad Strand <li...@3ware.com>
X
X Copyright (C) 1999-2001 3ware Inc.
X
@@ -100,6 +101,11 @@
X Fix possible null pointer dereference in tw_aen_drain_queue()
X during initialization.
X Clear pci parity errors during initialization and during io.
+ 1.02.00.009 - Remove redundant increment in tw_state_request_start().
+ Add ioctl support for direct ATA command passthru.
+ Add entire aen code string list.
+ 1.02.00.010 - Cleanup queueing code, fix jbod thoughput.
+ Fix get_param for specific units.
X */
X
X #include <linux/module.h>
@@ -147,7 +153,7 @@
X };
X
X /* Globals */
-char *tw_driver_version="1.02.00.008";
+char *tw_driver_version="1.02.00.010";
X TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
X int tw_device_extension_count = 0;


X
@@ -169,23 +175,18 @@

X dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen);
X
X /* Print some useful info when certain aen codes come out */
- switch (aen & 0x0ff) {
- case TW_AEN_APORT_TIMEOUT:
- printk(KERN_WARNING "3w-xxxx: scsi%d: Received drive timeout AEN on port %d, check drive and drive cables.\n", tw_dev->host->host_no, aen >> 8);
- break;
- case TW_AEN_DRIVE_ERROR:
- printk(KERN_WARNING "3w-xxxx: scsi%d: Received drive error AEN on port %d, check/replace cabling, or possible bad drive.\n", tw_dev->host->host_no, aen >> 8);
- break;
- case TW_AEN_SMART_FAIL:
- printk(KERN_WARNING "3w-xxxx: scsi%d: Received S.M.A.R.T. threshold AEN on port %d, check drive/cooling, or possible bad drive.\n", tw_dev->host->host_no, aen >> 8);
- break;
- case TW_AEN_SBUF_FAIL:
- printk(KERN_WARNING "3w-xxxx: scsi%d: Received SBUF integrity check failure AEN, reseat card or bad card.\n", tw_dev->host->host_no);
- break;
- default:
- printk(KERN_WARNING "3w-xxxx: Received AEN 0x%x\n", aen);
+ if (aen == 0x0ff) {
+ printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: AEN queue overflow.\n", tw_dev->host->host_no);
+ } else {
+ if ((aen & 0x0ff) < TW_AEN_STRING_MAX) {
+ if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
+ printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s%d.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff], aen >> 8);
+ } else {
+ printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff]);
+ }
+ } else
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Received AEN %d.\n", tw_dev->host->host_no, aen);
X }
-
X tw_dev->aen_count++;
X
X /* Now queue the code */
@@ -235,7 +236,7 @@
X response_que_addr = tw_dev->registers.response_que_addr;
X
X if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT, 15)) {
- printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d.\n", tw_device_extension_count);
+ dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d.\n", tw_device_extension_count);


X return 1;
X }
X

@@ -291,7 +292,7 @@
X mdelay(5);
X status_reg_value = inl(status_reg_addr);
X if (tw_check_bits(status_reg_value)) {
- printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n");
+ dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n");
X tw_decode_bits(tw_dev, status_reg_value);
X return 1;
X }
@@ -308,7 +309,8 @@
X if (command_packet->status != 0) {
X if (command_packet->flags != TW_AEN_TABLE_UNDEFINED) {
X /* Bad response */
- printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+ dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+ tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
X return 1;
X } else {
X /* We know this is a 3w-1x00, and doesn't support aen's */
@@ -428,7 +430,7 @@
X
X status_reg_value = inl(status_reg_addr);
X if (tw_check_bits(status_reg_value)) {
- printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
+ dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
X tw_decode_bits(tw_dev, status_reg_value);
X return 1;
X }
@@ -525,11 +527,11 @@
X int tw_check_bits(u32 status_reg_value)
X {
X if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) {
- printk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value);
+ dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value);
X return 1;
X }
X if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) {
- printk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value);
+ dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value);


X return 1;
X }
X

@@ -633,8 +635,12 @@
X case 0x51:
X printk(KERN_WARNING "3w-xxxx: scsi%d: Unrecoverable drive error on unit %d, check/replace cabling, or possible bad drive.\n", tw_dev->host->host_no, unit);
X break;
+ default:
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Controller error: status = 0x%x, flags = 0x%x, unit #%d.\n", tw_dev->host->host_no, status, flags, unit);
X }
X break;
+ default:
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Controller error: status = 0x%x, flags = 0x%x, unit #%d.\n", tw_dev->host->host_no, status, flags, unit);
X }
X } /* End tw_decode_error() */
X
@@ -660,7 +666,7 @@
X status_reg_value = inl(status_reg_addr);
X
X if (tw_check_bits(status_reg_value)) {
- printk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n");
+ dprintk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n");
X tw_decode_bits(tw_dev, status_reg_value);
X return 1;
X }
@@ -669,7 +675,7 @@
X response_que_value = inl(response_que_addr);
X status_reg_value = inl(status_reg_addr);
X if (tw_check_bits(status_reg_value)) {
- printk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n");
+ dprintk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n");
X tw_decode_bits(tw_dev, status_reg_value);
X return 1;
X }
@@ -817,9 +823,20 @@
X continue;
X }
X
- /* Calculate max cmds per lun */
- if (tw_dev->num_units > 0)
- tw_host->cmd_per_lun = (TW_Q_LENGTH-2)/tw_dev->num_units;
+ /* Calculate max cmds per lun, and setup queues */
+ if (tw_dev->num_units > 0) {
+ if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) {
+ tw_host->cmd_per_lun = (TW_MAX_BOUNCEBUF-1)/tw_dev->num_units;
+ tw_dev->free_head = TW_Q_START;
+ tw_dev->free_tail = TW_MAX_BOUNCEBUF - 1;
+ tw_dev->free_wrap = TW_MAX_BOUNCEBUF - 1;
+ } else {
+ tw_host->cmd_per_lun = (TW_Q_LENGTH-1)/tw_dev->num_units;
+ tw_dev->free_head = TW_Q_START;
+ tw_dev->free_tail = TW_Q_LENGTH - 1;
+ tw_dev->free_wrap = TW_Q_LENGTH - 1;
+ }
+ }
X
X /* Register the card with the kernel SCSI layer */
X host = scsi_register(tw_host, sizeof(TW_Device_Extension));
@@ -889,7 +906,7 @@
X }
X
X if (numcards == 0)
- printk(KERN_WARNING "3w-xxxx: tw_findcards(): No cards found.\n");
+ printk(KERN_WARNING "3w-xxxx: No cards with valid units found.\n");
X else
X register_reboot_notifier(&tw_notifier);
X
@@ -899,18 +916,19 @@
X /* This function will free up device extension resources */
X void tw_free_device_extension(TW_Device_Extension *tw_dev)
X {
- int i, imax;
- imax = TW_Q_LENGTH;
+ int i;
X
X dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n");
X /* Free command packet and generic buffer memory */
- for (i=0;i<imax;i++) {
+ for (i=0;i<TW_Q_LENGTH;i++) {
X if (tw_dev->command_packet_virtual_address[i])
X kfree(tw_dev->command_packet_virtual_address[i]);
X
X if (tw_dev->alignment_virtual_address[i])
X kfree(tw_dev->alignment_virtual_address[i]);
X
+ }
+ for (i=0;i<TW_MAX_BOUNCEBUF;i++) {
X if (tw_dev->bounce_buffer[i])
X kfree(tw_dev->bounce_buffer[i]);
X }
@@ -922,7 +940,7 @@
X int i;
X
X for (i=0;i<tw_device_extension_count;i++) {
- printk(KERN_NOTICE "3w-xxxx: Notifying card #%d\n", i);
+ printk(KERN_NOTICE "3w-xxxx: Shutting down card %d.\n", i);
X tw_shutdown_device(tw_device_extension_list[i]);
X }
X unregister_reboot_notifier(&tw_notifier);
@@ -981,7 +999,7 @@
X mdelay(5);
X status_reg_value = inl(status_reg_addr);
X if (tw_check_bits(status_reg_value)) {
- printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected bits.\n");
+ dprintk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected bits.\n");
X tw_decode_bits(tw_dev, status_reg_value);
X return 1;
X }
@@ -995,7 +1013,8 @@
X }
X if (command_packet->status != 0) {
X /* bad response */
- printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+ dprintk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+ tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
X return 1;
X }
X break; /* Response was okay, so we exit */
@@ -1043,8 +1062,6 @@
X tw_dev->num_units = 0;
X tw_dev->num_aborts = 0;
X tw_dev->num_resets = 0;
- tw_dev->free_head = TW_Q_START;
- tw_dev->free_tail = TW_Q_LENGTH - 1;
X tw_dev->posted_request_count = 0;
X tw_dev->max_posted_request_count = 0;
X tw_dev->max_sgl_entries = 0;
@@ -1135,7 +1152,7 @@
X mdelay(5);
X status_reg_value = inl(status_reg_addr);
X if (tw_check_bits(status_reg_value)) {
- printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
+ dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
X tw_decode_bits(tw_dev, status_reg_value);
X return 1;
X }
@@ -1149,7 +1166,8 @@
X }
X if (command_packet->status != 0) {
X /* bad response */
- printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+ dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+ tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
X return 1;
X }
X found = 1;
@@ -1181,7 +1199,7 @@
X tw_dev->num_units = num_units;
X
X if (num_units == 0) {
- printk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): No units found.\n");
+ dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): No units found.\n");


X return 1;
X }
X

@@ -1238,7 +1256,7 @@
X mdelay(5);
X status_reg_value = inl(status_reg_addr);
X if (tw_check_bits(status_reg_value)) {
- printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
+ dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
X tw_decode_bits(tw_dev, status_reg_value);
X return 1;
X }
@@ -1252,7 +1270,8 @@
X }
X if (command_packet->status != 0) {
X /* bad response */
- printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+ dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+ tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
X return 1;
X }
X found = 1;
@@ -1277,10 +1296,10 @@
X
X /* Now allocate raid5 bounce buffers */
X if ((num_raid_five != 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) {
- for (i=0;i<TW_Q_LENGTH;i++) {
+ for (i=0;i<TW_MAX_BOUNCEBUF;i++) {
X tw_allocate_memory(tw_dev, i, sizeof(TW_Sector)*TW_MAX_SECTORS, 2);
X if (tw_dev->bounce_buffer[i] == NULL) {
- printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bounce buffer allocation failed.\n");
+ printk(KERN_WARNING "3w-xxxx: Bounce buffer allocation failed.\n");
X return 1;
X }
X memset(tw_dev->bounce_buffer[i], 0, sizeof(TW_Sector)*TW_MAX_SECTORS);
@@ -1342,7 +1361,7 @@
X tw_state_request_start(tw_dev, &request_id);
X error = tw_aen_read_queue(tw_dev, request_id);
X if (error) {
- printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Error reading aen queue.\n");
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Error reading aen queue.\n", tw_dev->host->host_no);
X tw_dev->state[request_id] = TW_S_COMPLETED;
X tw_state_request_finish(tw_dev, request_id);
X }
@@ -1354,7 +1373,7 @@
X while (tw_dev->pending_request_count > 0) {
X request_id = tw_dev->pending_queue[tw_dev->pending_head];
X if (tw_dev->state[request_id] != TW_S_PENDING) {
- printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found request id that wasn't pending.\n");
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no);
X break;
X }
X if (tw_post_command_packet(tw_dev, request_id)==0) {
@@ -1382,12 +1401,12 @@
X command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
X error = 0;
X if (command_packet->status != 0) {
- printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Bad response, status = 0x%x, flags = 0x%x, unit = 0x%x.\n", command_packet->status, command_packet->flags, command_packet->byte3.unit);
+ dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Bad response, status = 0x%x, flags = 0x%x, unit = 0x%x.\n", command_packet->status, command_packet->flags, command_packet->byte3.unit);
X tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
X error = 1;
X }
X if (tw_dev->state[request_id] != TW_S_POSTED) {
- printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", request_id, command_packet->byte0.opcode);
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", tw_dev->host->host_no, request_id, command_packet->byte0.opcode);
X error = 1;
X }
X if (TW_STATUS_ERRORS(status_reg_value)) {
@@ -1400,24 +1419,22 @@
X dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");
X error = tw_aen_complete(tw_dev, request_id);
X if (error) {
- printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Error completing aen.\n");
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no);
X }
X status_reg_value = inl(status_reg_addr);
X if (tw_check_bits(status_reg_value)) {
- printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
+ dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
X tw_decode_bits(tw_dev, status_reg_value);
X }
X } else {
X switch (tw_dev->srb[request_id]->cmnd[0]) {
X case READ_10:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10\n");
X case READ_6:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_6\n");
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n");
X break;
X case WRITE_10:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10\n");
X case WRITE_6:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_6\n");
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n");
X break;
X case INQUIRY:
X dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n");
@@ -1432,7 +1449,7 @@
X error = tw_ioctl_complete(tw_dev, request_id);
X break;
X default:
- printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unknown scsi opcode: 0x%x.\n", tw_dev->srb[request_id]->cmnd[0]);
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x.\n", tw_dev->host->host_no, tw_dev->srb[request_id]->cmnd[0]);
X tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);
X tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
X }
@@ -1450,7 +1467,7 @@
X tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
X status_reg_value = inl(status_reg_addr);
X if (tw_check_bits(status_reg_value)) {
- printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
+ dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
X tw_decode_bits(tw_dev, status_reg_value);
X }
X }
@@ -1471,6 +1488,7 @@
X TW_Command *command_packet;
X u32 param_value;
X TW_Ioctl *ioctl = NULL;
+ TW_Passthru *passthru = NULL;
X int tw_aen_code;
X
X ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer;
@@ -1519,6 +1537,7 @@
X case TW_OP_GET_PARAM:
X dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_GET_PARAM.\n");
X command_packet->byte0.opcode = TW_OP_GET_PARAM;
+ command_packet->byte3.unit = ioctl->unit_index;
X param->table_id = ioctl->table_id;
X param->parameter_id = ioctl->parameter_id;
X param->parameter_size_bytes = ioctl->parameter_size_bytes;
@@ -1562,7 +1581,26 @@
X tw_dev->srb[request_id]->result = (DID_OK << 16);
X tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
X return 0;
- case TW_CMD_PACKET:
+ case TW_ATA_PASSTHRU:
+ if (ioctl->data != NULL) {
+ memcpy(command_packet, ioctl->data, sizeof(TW_Command));
+ command_packet->request_id = request_id;
+ } else {
+ printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");


+ return 1;
+ }
+

+ passthru = (TW_Passthru *)tw_dev->command_packet_virtual_address[request_id];
+ passthru->sg_list[0].length = passthru->sector_count*512;
+ if (passthru->sg_list[0].length > TW_MAX_PASSTHRU_BYTES) {
+ printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Passthru size (%ld) too big.\n", passthru->sg_list[0].length);
+ return 1;
+ }
+ passthru->sg_list[0].address = virt_to_bus(tw_dev->alignment_virtual_address[request_id]);
+ tw_post_command_packet(tw_dev, request_id);
+ return 0;
+ case TW_CMD_PACKET:
+ dprintk(KERN_WARNING "3w-xxxx: tw_ioctl(): caught TW_CMD_PACKET.\n");
X if (ioctl->data != NULL) {
X memcpy(command_packet, ioctl->data, sizeof(TW_Command));
X command_packet->request_id = request_id;
@@ -1596,7 +1634,6 @@
X command_packet->byte0.sgl_offset = 2;
X command_packet->size = 4;
X command_packet->request_id = request_id;
- command_packet->byte3.unit = 0;
X command_packet->byte3.host_id = 0;
X command_packet->status = 0;
X command_packet->flags = 0;
@@ -1614,7 +1651,10 @@
X unsigned char *param_data;
X unsigned char *buff;
X TW_Param *param;
+ TW_Ioctl *ioctl = NULL;
+ TW_Passthru *passthru = NULL;
X
+ ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer;
X dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete()\n");
X buff = tw_dev->srb[request_id]->request_buffer;
X if (buff == NULL) {
@@ -1622,16 +1662,23 @@
X return 1;
X }
X dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete(): Request_bufflen = %d\n", tw_dev->srb[request_id]->request_bufflen);
- memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
- param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
- if (param == NULL) {
- printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");
- return 1;
- }
- param_data = &(param->data[0]);
-
- memcpy(buff, param_data, tw_dev->ioctl_size[request_id]);
X
+ ioctl = (TW_Ioctl *)buff;
+ switch (ioctl->opcode) {
+ case TW_ATA_PASSTHRU:
+ passthru = (TW_Passthru *)ioctl->data;
+ memcpy(buff, tw_dev->alignment_virtual_address[request_id], passthru->sector_count * 512);
+ break;
+ default:
+ memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
+ param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+ if (param == NULL) {
+ printk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): Bad alignment virtual address.\n");
+ return 1;
+ }
+ param_data = &(param->data[0]);
+ memcpy(buff, param_data, tw_dev->ioctl_size[request_id]);
+ }
X return 0;
X } /* End tw_ioctl_complete() */
X
@@ -1659,7 +1706,7 @@
X status_reg_value = inl(status_reg_addr);
X do_gettimeofday(&timeout);
X if (before.tv_sec + seconds < timeout.tv_sec) {
- printk(KERN_WARNING "3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag);
+ dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag);
X return 1;
X }
X mdelay(1);
@@ -1680,7 +1727,7 @@
X status_reg_value = inl(status_reg_addr);
X
X if (tw_check_bits(status_reg_value)) {
- printk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");
+ dprintk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");
X tw_decode_bits(tw_dev, status_reg_value);
X }
X
@@ -1724,7 +1771,7 @@
X imax = TW_Q_LENGTH;
X
X if (tw_reset_sequence(tw_dev)) {
- printk(KERN_WARNING "3w-xxxx: tw_reset_device_extension(): Reset sequence failed for card %d.\n", tw_dev->host->host_no);
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no);


X return 1;
X }
X

@@ -1772,14 +1819,14 @@
X
X error = tw_aen_drain_queue(tw_dev);
X if (error) {
- printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): No attention interrupt for card %d.\n", tw_dev->host->host_no);
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Card not responding, retrying.\n", tw_dev->host->host_no);
X tries++;
X continue;
X }
X
X /* Check for controller errors */
X if (tw_check_errors(tw_dev)) {
- printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Controller errors found, soft resetting card %d.\n", tw_dev->host->host_no);
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors found, retrying.\n", tw_dev->host->host_no);
X tries++;
X continue;
X }
@@ -1787,7 +1834,7 @@
X /* Empty the response queue again */
X error = tw_empty_response_que(tw_dev);
X if (error) {
- printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't empty response queue for card %d.\n", tw_dev->host->host_no);
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Couldn't empty response queue, retrying.\n", tw_dev->host->host_no);
X tries++;
X continue;
X }
@@ -1797,13 +1844,13 @@
X }
X
X if (tries >= TW_MAX_RESET_TRIES) {
- printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Controller error or no attention interrupt: giving up for card %d.\n", tw_dev->host->host_no);
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors, card not responding, check all cabling.\n", tw_dev->host->host_no);


X return 1;
X }
X

X error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS);
X if (error) {
- printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't initconnection for card %d.\n", tw_dev->host->host_no);
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Connection initialization failed.\n", tw_dev->host->host_no);


X return 1;
X }
X

@@ -1893,14 +1940,14 @@
X for (i=0;i<TW_Q_LENGTH;i++) {
X if (tw_dev->srb[i] == SCpnt) {
X if (tw_dev->state[i] == TW_S_STARTED) {
- printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort succeeded for started Scsi_Cmnd 0x%x\n", (u32)tw_dev->srb[i]);
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, (u32)SCpnt);
X tw_dev->state[i] = TW_S_COMPLETED;
X tw_state_request_finish(tw_dev, i);
X spin_unlock(&tw_dev->tw_lock);
X return (SUCCESS);
X }
X if (tw_dev->state[i] == TW_S_PENDING) {
- printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort succeeded for pending Scsi_Cmnd 0x%x\n", (u32)tw_dev->srb[i]);
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, (u32)SCpnt);
X if (tw_dev->pending_head == TW_Q_LENGTH-1) {
X tw_dev->pending_head = TW_Q_START;
X } else {
@@ -1916,10 +1963,9 @@
X }
X
X /* If the command has already been posted, we have to reset the card */
- printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort failed for unknown Scsi_Cmnd 0x%x, resetting card %d.\n", (u32)SCpnt, tw_dev->host->host_no);
-
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, (u32)SCpnt);
X if (tw_reset_device_extension(tw_dev)) {
- printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no);
+ dprintk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no);
X spin_unlock(&tw_dev->tw_lock);
X return (FAILED);
X }
@@ -1956,11 +2002,11 @@
X
X /* Now reset the card and some of the device extension data */
X if (tw_reset_device_extension(tw_dev)) {
- printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Reset failed for card %d.\n", tw_dev->host->host_no);
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no);
X spin_unlock(&tw_dev->tw_lock);
X return (FAILED);
X }
- printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Reset succeeded for card %d.\n", tw_dev->host->host_no);
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Reset succeeded.\n", tw_dev->host->host_no);
X spin_unlock(&tw_dev->tw_lock);
X
X return (SUCCESS);
@@ -2073,13 +2119,10 @@
X
X switch (*command) {
X case READ_10:
- dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_10.\n");
X case READ_6:
- dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_6.\n");
X case WRITE_10:
- dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught WRITE_10.\n");
X case WRITE_6:
- dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught WRITE_6.\n");
+ dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ/WRITE.\n");
X error = tw_scsiop_read_write(tw_dev, request_id);
X break;
X case TEST_UNIT_READY:
@@ -2103,7 +2146,7 @@
X error = tw_ioctl(tw_dev, request_id);
X break;
X default:
- printk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): Unknown scsi opcode: 0x%x\n", *command);
+ printk(KERN_NOTICE "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x\n", tw_dev->host->host_no, *command);
X tw_dev->state[request_id] = TW_S_COMPLETED;
X tw_state_request_finish(tw_dev, request_id);
X SCpnt->result = (DID_BAD_TARGET << 16);
@@ -2569,7 +2612,7 @@
X mdelay(5);
X status_reg_value = inl(status_reg_addr);
X if (tw_check_bits(status_reg_value)) {
- printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected bits.\n");
+ dprintk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected bits.\n");
X tw_decode_bits(tw_dev, status_reg_value);
X return 1;
X }
@@ -2583,7 +2626,8 @@
X }
X if (command_packet->status != 0) {
X /* bad response */
- printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+ dprintk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+ tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
X return 1;
X }
X break; /* Response was okay, so we exit */
@@ -2603,7 +2647,7 @@
X error = request_irq(tw_dev->tw_pci_dev->irq, tw_interrupt, SA_SHIRQ, device, tw_dev);


X
X if (error < 0) {

- printk(KERN_WARNING "3w-xxxx: tw_setup_irq(): Error requesting IRQ: %d for card %d.\n", tw_dev->tw_pci_dev->irq, tw_dev->host->host_no);
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Error requesting IRQ: %d.\n", tw_dev->host->host_no, tw_dev->tw_pci_dev->irq);
X return 1;
X }
X return 0;
@@ -2621,9 +2665,9 @@
X /* poke the board */
X error = tw_initconnection(tw_dev, 1);
X if (error) {
- printk(KERN_WARNING "3w-xxxx: tw_shutdown_device(): Couldn't initconnection for card %d.\n", tw_dev->host->host_no);
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Connection shutdown failed.\n", tw_dev->host->host_no);
X } else {
- printk(KERN_NOTICE "3w-xxxx shutdown succeeded\n");
+ printk(KERN_NOTICE "3w-xxxx: Shutdown complete.\n");
X }
X
X /* Re-enable interrupts */
@@ -2654,7 +2698,7 @@
X dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_finish()\n");
X
X do {
- if (tw_dev->free_tail == TW_Q_LENGTH-1) {
+ if (tw_dev->free_tail == tw_dev->free_wrap) {
X tw_dev->free_tail = TW_Q_START;
X } else {
X tw_dev->free_tail = tw_dev->free_tail + 1;
@@ -2678,23 +2722,14 @@
X
X /* Obtain next free request_id */
X do {
- if (tw_dev->free_head == TW_Q_LENGTH - 1) {
+ if (tw_dev->free_head == tw_dev->free_wrap) {
X tw_dev->free_head = TW_Q_START;
X } else {
X tw_dev->free_head = tw_dev->free_head + 1;
X }
- } while ((tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_STARTED) ||
- (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_POSTED) ||
- (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_PENDING) ||
- (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_COMPLETED));
+ } while (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] & TW_START_MASK);
X
X id = tw_dev->free_queue[tw_dev->free_head];
-
- if (tw_dev->free_head == TW_Q_LENGTH - 1) {
- tw_dev->free_head = TW_Q_START;
- } else {
- tw_dev->free_head = tw_dev->free_head + 1;
- }
X
X dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start(): id = %d.\n", id);
X *request_id = id;
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/3w-xxxx.h linux/drivers/scsi/3w-xxxx.h
--- v2.4.14/linux/drivers/scsi/3w-xxxx.h Sun Sep 23 11:40:59 2001
+++ linux/drivers/scsi/3w-xxxx.h Fri Nov 9 14:05:02 2001
@@ -4,6 +4,7 @@
X Written By: Adam Radford <li...@3ware.com>
X Modifications By: Joel Jacobson <li...@3ware.com>
X Arnaldo Carvalho de Melo <ac...@conectiva.com.br>
+ Brad Strand <li...@3ware.com>
X
X Copyright (C) 1999-2001 3ware Inc.
X
@@ -57,6 +58,43 @@
X #include <linux/types.h>
X #include <linux/kdev_t.h>
X
+/* AEN strings */
+static char *tw_aen_string[] = {
+ "AEN queue empty", // 0x000
+ "Soft reset occurred", // 0x001
+ "Mirorr degraded: Unit #", // 0x002
+ "Controller error", // 0x003
+ "Rebuild failed: Unit #", // 0x004
+ "Rebuild complete: Unit #", // 0x005
+ "Incomplete unit detected: Unit #", // 0x006
+ "Initialization complete: Unit #", // 0x007
+ "Unclean shutdown detected: Unit #", // 0x008
+ "ATA port timeout: Port #", // 0x009
+ "Drive error: Port #", // 0x00A


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

echo 'End of part 057'
echo 'File patch-2.4.15 is continued in part 058'
echo "058" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:49 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part073

#!/bin/sh -x
# this is part 073 of a 115 - part archive


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

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

+ 0x00, 0x00, 0x00, 0x00}}
+};
+

+SiS300_LVDSCRT1DataStruct SiS300_CHTVCRT1UNTSC[] = {


+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+

+SiS300_LVDSCRT1DataStruct SiS300_CHTVCRT1ONTSC[] = {


+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+

+SiS300_LVDSCRT1DataStruct SiS300_CHTVCRT1UPAL[] = {


+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+

+SiS300_LVDSCRT1DataStruct SiS300_CHTVCRT1OPAL[] = {


+
+ {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}}
+};
+

+typedef struct _SiS300_CHTVRegDataStruct {
+ UCHAR Reg[5];
+} SiS300_CHTVRegDataStruct;
+SiS300_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] = {
+ {{0x00, 0x00, 0x00, 0x00, 0x00}}
+};
+
+SiS300_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] = {
+ {{0x00, 0x00, 0x00, 0x00, 0x00}}
+};
+
+SiS300_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] = {
+ {{0x00, 0x00, 0x00, 0x00, 0x00}}
+};
+
+SiS300_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] = {
+ {{0x00, 0x00, 0x00, 0x00, 0x00}}
+};
+
+UCHAR SiS300_CHTVVCLKUNTSC[] = { 0x00 };
+
+UCHAR SiS300_CHTVVCLKONTSC[] = { 0x00 };
+
+UCHAR SiS300_CHTVVCLKUPAL[] = { 0x00 };
+
+UCHAR SiS300_CHTVVCLKOPAL[] = { 0x00 };
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/310vtbl.h linux/drivers/video/sis/310vtbl.h
--- v2.4.14/linux/drivers/video/sis/310vtbl.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/sis/310vtbl.h Fri Nov 9 14:11:14 2001
@@ -0,0 +1,2604 @@
+typedef struct _SiS310_StStruct {


+ UCHAR St_ModeID;
+ USHORT St_ModeFlag;
+ UCHAR St_StTableIndex;
+ UCHAR St_CRT2CRTC;
+ UCHAR St_ResInfo;
+ UCHAR VB_StTVFlickerIndex;
+ UCHAR VB_StTVEdgeIndex;
+ UCHAR VB_StTVYFilterIndex;

+} SiS310_StStruct;
+
+SiS310_StStruct SiS310_SModeIDTable[] =
+{
+ {0x01, 0x9208, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
+ {0x01, 0x1210, 0x14, 0x01, 0x01, 0x00, 0x01, 0x00},
+ {0x01, 0x1010, 0x17, 0x02, 0x02, 0x00, 0x01, 0x01},
+ {0x03, 0x8208, 0x03, 0x00, 0x00, 0x00, 0x01, 0x02},
+ {0x03, 0x0210, 0x16, 0x01, 0x01, 0x00, 0x01, 0x02},
+ {0x03, 0x0010, 0x18, 0x02, 0x02, 0x00, 0x01, 0x03},
+ {0x05, 0x9209, 0x05, 0x00, 0x00, 0x00, 0x00, 0x04},
+ {0x06, 0x8209, 0x06, 0x00, 0x00, 0x00, 0x00, 0x05},
+ {0x07, 0x0000, 0x07, 0x03, 0x03, 0x00, 0x01, 0x03},
+ {0x07, 0x0000, 0x19, 0x02, 0x02, 0x00, 0x01, 0x03},
+ {0x0d, 0x920a, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x04},
+ {0x0e, 0x820a, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x05},
+ {0x0f, 0x0202, 0x11, 0x01, 0x01, 0x00, 0x00, 0x05},
+ {0x10, 0x0212, 0x12, 0x01, 0x01, 0x00, 0x00, 0x05},
+ {0x11, 0x0212, 0x1a, 0x04, 0x04, 0x00, 0x00, 0x05},
+ {0x12, 0x0212, 0x1b, 0x04, 0x04, 0x00, 0x00, 0x05},
+ {0x13, 0x021b, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x04},
+ {0x12, 0x0010, 0x18, 0x02, 0x02, 0x00, 0x00, 0x05},
+ {0x12, 0x0210, 0x18, 0x01, 0x01, 0x00, 0x00, 0x05},
+ {0xff, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+typedef struct _SiS310_StandTableStruct {


+ UCHAR CRT_COLS;
+ UCHAR ROWS;
+ UCHAR CHAR_HEIGHT;
+ USHORT CRT_LEN;
+ UCHAR SR[4];
+ UCHAR MISC;
+ UCHAR CRTC[0x19];
+ UCHAR ATTR[0x14];
+ UCHAR GRC[9];

+} SiS310_StandTableStruct;
+
+SiS310_StandTableStruct SiS310_StandTable[] = {
+/* MD_0_200 */
+ {


+ 0x28, 0x18, 0x08, 0x0800,
+ {0x09, 0x03, 0x00, 0x02},
+ 0x63,
+ {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f,
+ 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}

+ },
+/* MD_1_200 */
+ {


+ 0x28, 0x18, 0x08, 0x0800,
+ {0x09, 0x03, 0x00, 0x02},
+ 0x63,
+ {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f,
+ 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}

+ },
+/* MD_2_200 */
+ {


+ 0x50, 0x18, 0x08, 0x1000,
+ {0x01, 0x03, 0x00, 0x02},
+ 0x63,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}

+ },
+/* MD_3_200 */
+ {


+ 0x50, 0x18, 0x08, 0x1000,
+ {0x01, 0x03, 0x00, 0x02},
+ 0x63,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}

+ },
+/* MD_4 */
+ {


+ 0x28, 0x18, 0x08, 0x4000,
+ {0x09, 0x03, 0x00, 0x02},
+ 0x63,

+ {0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0xbf, 0x1f,


+ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2,
+ 0xff},
+ {0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x01, 0x00, 0x03, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x00,
+ 0xff}

+ },
+/* MD_5 */
+ {


+ 0x28, 0x18, 0x08, 0x4000,
+ {0x09, 0x03, 0x00, 0x02},
+ 0x63,

+ {0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0xbf, 0x1f,


+ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2,
+ 0xff},
+ {0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x01, 0x00, 0x03, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x00,
+ 0xff}

+ },
+/* MD_6 */
+ {


+ 0x50, 0x18, 0x08, 0x4000,
+ {0x01, 0x01, 0x00, 0x06},
+ 0x63,

+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,

+ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xc2,
+ 0xff},
+ {0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+ 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+ 0x01, 0x00, 0x01, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00,
+ 0xff}

+ },
+/* MD_7 */
+ {


+ 0x50, 0x18, 0x0e, 0x1000,
+ {0x00, 0x03, 0x00, 0x03},
+ 0xa6,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x83, 0x85, 0x5d, 0x28, 0x0d, 0x63, 0xba, 0xa3,
+ 0xff},
+ {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x0e, 0x00, 0x0f, 0x08},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x00,
+ 0xff}

+ },
+/* MDA_DAC */
+ {
+ 0x00, 0x00, 0x00, 0x0000,


+ {0x00, 0x00, 0x00, 0x15},
+ 0x15,
+ {0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
+ 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3f, 0x3f,
+ 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00,
+ 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x15, 0x15,
+ 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
+ 0x15, 0x15, 0x15, 0x15},
+ {0x15, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+ 0x3f}

+ },
+/* CGA_DAC */
+ {


+ 0x00, 0x10, 0x04, 0x0114,
+ {0x11, 0x09, 0x15, 0x00},
+ 0x10,
+ {0x04, 0x14, 0x01, 0x11, 0x09, 0x15, 0x2a, 0x3a,
+ 0x2e, 0x3e, 0x2b, 0x3b, 0x2f, 0x3f, 0x2a, 0x3a,
+ 0x2e, 0x3e, 0x2b, 0x3b, 0x2f, 0x3f, 0x00, 0x10,
+ 0x04},
+ {0x14, 0x01, 0x11, 0x09, 0x15, 0x00, 0x10, 0x04,
+ 0x14, 0x01, 0x11, 0x09, 0x15, 0x2a, 0x3a, 0x2e,
+ 0x3e, 0x2b, 0x3b, 0x2f},
+ {0x3f, 0x2a, 0x3a, 0x2e, 0x3e, 0x2b, 0x3b, 0x2f,
+ 0x3f}

+ },
+/* EGA_DAC */
+ {


+ 0x00, 0x10, 0x04, 0x0114,
+ {0x11, 0x05, 0x15, 0x20},
+ 0x30,
+ {0x24, 0x34, 0x21, 0x31, 0x25, 0x35, 0x08, 0x18,
+ 0x0c, 0x1c, 0x09, 0x19, 0x0d, 0x1d, 0x28, 0x38,
+ 0x2c, 0x3c, 0x29, 0x39, 0x2d, 0x3d, 0x02, 0x12,
+ 0x06},
+ {0x16, 0x03, 0x13, 0x07, 0x17, 0x22, 0x32, 0x26,
+ 0x36, 0x23, 0x33, 0x27, 0x37, 0x0a, 0x1a, 0x0e,
+ 0x1e, 0x0b, 0x1b, 0x0f},
+ {0x1f, 0x2a, 0x3a, 0x2e, 0x3e, 0x2b, 0x3b, 0x2f,
+ 0x3f}

+ },
+/* VGA_DAC */
+ {


+ 0x00, 0x10, 0x04, 0x0114,
+ {0x11, 0x09, 0x15, 0x2a},
+ 0x3a,
+ {0x2e, 0x3e, 0x2b, 0x3b, 0x2f, 0x3f, 0x00, 0x05,
+ 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x18, 0x1c, 0x20,
+ 0x24, 0x28, 0x2d, 0x32, 0x38, 0x3f, 0x00, 0x10,
+ 0x1f},
+ {0x2f, 0x3f, 0x1f, 0x27, 0x2f, 0x37, 0x3f, 0x2d,
+ 0x31, 0x36, 0x3a, 0x3f, 0x00, 0x07, 0x0e, 0x15,
+ 0x1c, 0x0e, 0x11, 0x15},
+ {0x18, 0x1c, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x00,
+ 0x04}

+ },
+ {


+ 0x08, 0x0c, 0x10, 0x0a08,
+ {0x0c, 0x0e, 0x10, 0x0b},
+ 0x0c,
+ {0x0d, 0x0f, 0x10, 0x10, 0x01, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x01, 0x00,
+ 0x04, 0x04, 0x01, 0x00, 0x05, 0x02, 0x05, 0x00,
+ 0x06},
+ {0x01, 0x06, 0x05, 0x06, 0x00, 0x08, 0x01, 0x08,
+ 0x00, 0x07, 0x02, 0x07, 0x06, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00}

+ },
+/* MD_D */
+ {


+ 0x28, 0x18, 0x08, 0x2000,
+ {0x09, 0x0f, 0x00, 0x06},
+ 0x63,

+ {0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0xbf, 0x1f,


+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xe3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x01, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
+ 0xff}

+ },
+/* MD_E */
+ {


+ 0x50, 0x18, 0x08, 0x4000,
+ {0x01, 0x0f, 0x00, 0x06},
+ 0x63,

+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,

+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xe3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x01, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
+ 0xff}

+ },
+/* ExtVGATable */
+ {
+ 0x00, 0x00, 0x00, 0x0000,


+ {0x01, 0x0f, 0x00, 0x0e},
+ 0x23,
+ {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x01, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
+ 0xff}

+ },
+/* ROM_SAVEPTR */
+ {
+ 0x9f, 0x3b, 0x00, 0x00c0,


+ {0x00, 0x00, 0x00, 0x00},
+ 0x00,

+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x3f,


+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

+ 0x00, 0x00, 0x1a, 0x00, 0xac, 0x3e, 0x00, 0xc0,


+ 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}

+ },
+/* MD_F */
+ {


+ 0x50, 0x18, 0x0e, 0x8000,
+ {0x01, 0x0f, 0x00, 0x06},
+ 0xa2,

+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,

+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

+ 0x82, 0x84, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3,


+ 0xff},
+ {0x00, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
+ 0x0b, 0x00, 0x05, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05,
+ 0xff}

+ },
+/* MD_10 */
+ {


+ 0x50, 0x18, 0x0e, 0x8000,
+ {0x01, 0x0f, 0x00, 0x06},
+ 0xa3,

+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,

+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

+ 0x82, 0x84, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3,


+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x01, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
+ 0xff}

+ },
+/* MD_0_350 */
+ {


+ 0x28, 0x18, 0x0e, 0x0800,
+ {0x09, 0x03, 0x00, 0x02},
+ 0xa3,

+ {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xb1, 0xbf, 0x1f,


+ 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x83, 0x85, 0x5d, 0x14, 0x1f, 0x63, 0xba, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}

+ },
+/* MD_1_350 */
+ {


+ 0x28, 0x18, 0x0e, 0x0800,
+ {0x09, 0x03, 0x00, 0x02},
+ 0xa3,
+ {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f,
+ 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x83, 0x85, 0x5d, 0x14, 0x1f, 0x63, 0xba, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}

+ },
+/* MD_2_350 */
+ {


+ 0x50, 0x18, 0x0e, 0x1000,
+ {0x01, 0x03, 0x00, 0x02},
+ 0xa3,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x83, 0x85, 0x5d, 0x28, 0x1f, 0x63, 0xba, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}

+ },
+/* MD_3_350 */
+ {


+ 0x50, 0x18, 0x0e, 0x1000,
+ {0x01, 0x03, 0x00, 0x02},
+ 0xa3,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x83, 0x85, 0x5d, 0x28, 0x1f, 0x63, 0xba, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x08, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}

+ },
+/* MD_0_1_400 */
+ {


+ 0x28, 0x18, 0x10, 0x0800,
+ {0x08, 0x03, 0x00, 0x02},
+ 0x67,

+ {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xb1, 0xbf, 0x1f,


+ 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x0c, 0x00, 0x0f, 0x08},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}

+ },
+/* MD_2_3_400 */
+ {
+ 0x50, 0x18, 0x10, 0x1000,


+ {0x00, 0x03, 0x00, 0x02},
+ 0x67,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x0c, 0x00, 0x0f, 0x08},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
+ 0xff}

+ },
+/* MD_7_400 */
+ {
+ 0x50, 0x18, 0x10, 0x1000,


+ {0x00, 0x03, 0x00, 0x02},
+ 0x66,
+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x0f, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x0e, 0x00, 0x0f, 0x08},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x00,
+ 0xff}

+ },
+/* MD_11 */
+ {


+ 0x50, 0x1d, 0x10, 0xa000,
+ {0x01, 0x0f, 0x00, 0x06},
+ 0xe3,

+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0x0b, 0x3e,


+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

+ 0xe9, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xc3,


+ 0xff},
+ {0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+ 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+ 0x01, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01,
+ 0xff}

+ },
+/* ExtEGATable */
+ {


+ 0x50, 0x1d, 0x10, 0xa000,
+ {0x01, 0x0f, 0x00, 0x06},
+ 0xe3,

+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0x0b, 0x3e,


+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

+ 0xe9, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,


+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x01, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
+ 0xff}

+ },
+/* MD_13 */
+ {


+ 0x28, 0x18, 0x08, 0x2000,
+ {0x01, 0x0f, 0x00, 0x0e},
+ 0x63,

+ {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,

+ 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0x8e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x41, 0x00, 0x0f, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
+ 0xff}
+ }

+};
+
+typedef struct _SiS310_ExtStruct {


+ UCHAR Ext_ModeID;
+ USHORT Ext_ModeFlag;
+ USHORT Ext_ModeInfo;
+ USHORT Ext_Point;
+ USHORT Ext_VESAID;
+ UCHAR Ext_VESAMEMSize;
+ UCHAR Ext_RESINFO;
+ UCHAR VB_ExtTVFlickerIndex;
+ UCHAR VB_ExtTVEdgeIndex;
+ UCHAR VB_ExtTVYFilterIndex;
+ UCHAR REFindex;

+} SiS310_ExtStruct;
+SiS310_ExtStruct SiS310_EModeIDTable[] = {
+
+ {0x6a, 0x2212, 0x0407, 0x3a81, 0x0102, 0x08, 0x07, 0x00, 0x00, 0x07,
+ 0x00},
+ {0x2e, 0x0a1b, 0x0306, 0x3a57, 0x0101, 0x08, 0x06, 0x00, 0x00, 0x05,
+ 0x08},
+ {0x2f, 0x0a1b, 0x0305, 0x3a50, 0x0100, 0x08, 0x05, 0x00, 0x00, 0x05,
+ 0x10},
+ {0x30, 0x2a1b, 0x0407, 0x3a81, 0x0103, 0x08, 0x07, 0x00, 0x00, 0x07,
+ 0x00},
+ {0x31, 0x0a1b, 0x030d, 0x3b85, 0x0000, 0x08, 0x0d, 0x00, 0x00, 0x06,
+ 0x11},
+ {0x32, 0x0a1b, 0x0a0e, 0x3b8c, 0x0000, 0x08, 0x0e, 0x00, 0x00, 0x06,
+ 0x12},
+ {0x33, 0x0a1d, 0x0a0d, 0x3b85, 0x0000, 0x08, 0x0d, 0x00, 0x00, 0x06,
+ 0x11},
+ {0x34, 0x2a1d, 0x0a0e, 0x3b8c, 0x0000, 0x08, 0x0e, 0x00, 0x00, 0x06,
+ 0x12},
+ {0x35, 0x0a1f, 0x0a0d, 0x3b85, 0x0000, 0x08, 0x0d, 0x00, 0x00, 0x06,
+ 0x11},
+ {0x36, 0x2a1f, 0x0a0e, 0x3b8c, 0x0000, 0x08, 0x0e, 0x00, 0x00, 0x06,
+ 0x12},
+ {0x37, 0x0212, 0x0508, 0x3aab, 0x0104, 0x08, 0x08, 0x00, 0x00, 0x00,
+ 0x13},
+ {0x38, 0x0a1b, 0x0508, 0x3aab, 0x0105, 0x08, 0x08, 0x00, 0x00, 0x00,
+ 0x13},
+ {0x3a, 0x0e3b, 0x0609, 0x3adc, 0x0107, 0x08, 0x09, 0x00, 0x00, 0x00,
+ 0x1a},
+ {0x3c, 0x063b, 0x070a, 0x3af2, 0x0130, 0x08, 0x0a, 0x00, 0x00, 0x00,
+ 0x1e},
+ {0x3d, 0x067d, 0x070a, 0x3af2, 0x0131, 0x08, 0x0a, 0x00, 0x00, 0x00,
+ 0x1e},
+ {0x40, 0x9a1c, 0x0000, 0x3a34, 0x010d, 0x08, 0x00, 0x00, 0x00, 0x04,
+ 0x25},
+ {0x41, 0x9a1d, 0x0000, 0x3a34, 0x010e, 0x08, 0x00, 0x00, 0x00, 0x04,
+ 0x25},
+ {0x43, 0x0a1c, 0x0306, 0x3a57, 0x0110, 0x08, 0x06, 0x00, 0x00, 0x05,
+ 0x08},
+ {0x44, 0x0a1d, 0x0306, 0x3a57, 0x0111, 0x08, 0x06, 0x00, 0x00, 0x05,
+ 0x08},
+ {0x46, 0x2a1c, 0x0407, 0x3a81, 0x0113, 0x08, 0x07, 0x00, 0x00, 0x07,
+ 0x00},
+ {0x47, 0x2a1d, 0x0407, 0x3a81, 0x0114, 0x08, 0x07, 0x00, 0x00, 0x07,
+ 0x00},
+ {0x49, 0x0a3c, 0x0508, 0x3aab, 0x0116, 0x08, 0x08, 0x00, 0x00, 0x00,
+ 0x13},
+ {0x4a, 0x0a3d, 0x0508, 0x3aab, 0x0117, 0x08, 0x08, 0x00, 0x00, 0x00,
+ 0x13},
+ {0x4c, 0x0e7c, 0x0609, 0x3adc, 0x0119, 0x08, 0x09, 0x00, 0x00, 0x00,
+ 0x1a},
+ {0x4d, 0x0e7d, 0x0609, 0x3adc, 0x011a, 0x08, 0x09, 0x00, 0x00, 0x00,
+ 0x1a},
+ {0x50, 0x9a1b, 0x0001, 0x3a3b, 0x0132, 0x08, 0x01, 0x00, 0x00, 0x04,
+ 0x26},
+ {0x51, 0xba1b, 0x0103, 0x3a42, 0x0133, 0x08, 0x03, 0x00, 0x00, 0x07,
+ 0x27},
+ {0x52, 0x9a1b, 0x0204, 0x3a49, 0x0134, 0x08, 0x04, 0x00, 0x00, 0x00,
+ 0x28},
+ {0x56, 0x9a1d, 0x0001, 0x3a3b, 0x0135, 0x08, 0x01, 0x00, 0x00, 0x04,
+ 0x26},
+ {0x57, 0xba1d, 0x0103, 0x3a42, 0x0136, 0x08, 0x03, 0x00, 0x00, 0x07,
+ 0x27},
+ {0x58, 0x9a1d, 0x0204, 0x3a49, 0x0137, 0x08, 0x04, 0x00, 0x00, 0x00,
+ 0x28},
+ {0x59, 0x9a1b, 0x0000, 0x3a34, 0x0138, 0x08, 0x00, 0x00, 0x00, 0x04,
+ 0x25},
+ {0x5d, 0x0a1d, 0x0305, 0x3a50, 0x0139, 0x08, 0x05, 0x00, 0x00, 0x07,
+ 0x10},
+ {0x62, 0x0a3f, 0x0306, 0x3a57, 0x013a, 0x08, 0x06, 0x00, 0x00, 0x05,
+ 0x08},
+ {0x63, 0x2a3f, 0x0407, 0x3a81, 0x013b, 0x08, 0x07, 0x00, 0x00, 0x07,
+ 0x00},
+ {0x64, 0x0a7f, 0x0508, 0x3aab, 0x013c, 0x08, 0x08, 0x00, 0x00, 0x00,
+ 0x13},
+ {0x65, 0x0eff, 0x0609, 0x3adc, 0x013d, 0x08, 0x09, 0x00, 0x00, 0x00,
+ 0x1a},
+ {0x66, 0x06ff, 0x070a, 0x3af2, 0x013e, 0x08, 0x0a, 0x00, 0x00, 0x00,
+ 0x1e},
+ {0x68, 0x067b, 0x080b, 0x3b17, 0x013f, 0x08, 0x0b, 0x00, 0x00, 0x00,
+ 0x29},
+ {0x69, 0x06fd, 0x080b, 0x3b17, 0x0140, 0x08, 0x0b, 0x00, 0x00, 0x00,
+ 0x29},
+ {0x6b, 0x07ff, 0x080b, 0x3b17, 0x0141, 0x10, 0x0b, 0x00, 0x00, 0x00,
+ 0x29},
+ {0x6c, 0x067b, 0x090c, 0x3b37, 0x0000, 0x08, 0x0c, 0x00, 0x00, 0x00,
+ 0x2f},
+ {0x6d, 0x06fd, 0x090c, 0x3b37, 0x0000, 0x10, 0x0c, 0x00, 0x00, 0x00,
+ 0x2f},
+ {0x6e, 0x07ff, 0x090c, 0x3b37, 0x0000, 0x10, 0x0c, 0x00, 0x00, 0x00,
+ 0x2f},
+ {0x70, 0x2a1b, 0x0410, 0x3b52, 0x0000, 0x08, 0x10, 0x00, 0x00, 0x07,
+ 0x34},
+ {0x71, 0x0a1b, 0x0511, 0x3b63, 0x0000, 0x08, 0x11, 0x00, 0x00, 0x00,
+ 0x37},
+ {0x74, 0x0a1d, 0x0511, 0x3b63, 0x0000, 0x08, 0x11, 0x00, 0x00, 0x00,
+ 0x37},
+ {0x75, 0x0a3d, 0x0612, 0x3b74, 0x0000, 0x08, 0x12, 0x00, 0x00, 0x00,
+ 0x3a},
+ {0x76, 0x2a1f, 0x0410, 0x3b52, 0x0000, 0x08, 0x10, 0x00, 0x00, 0x07,
+ 0x34},
+ {0x77, 0x0a1f, 0x0511, 0x3b63, 0x0000, 0x08, 0x11, 0x00, 0x00, 0x00,
+ 0x37},
+ {0x78, 0x0a3f, 0x0612, 0x3b74, 0x0000, 0x08, 0x12, 0x00, 0x00, 0x00,
+ 0x3a},
+ {0x79, 0x0a3b, 0x0612, 0x3b74, 0x0000, 0x08, 0x12, 0x00, 0x00, 0x00,
+ 0x3a},
+ {0x7a, 0x2a1d, 0x0410, 0x3b52, 0x0000, 0x08, 0x10, 0x00, 0x00, 0x07,
+ 0x34},
+ {0x7b, 0x0e3b, 0x060f, 0x3ad0, 0x0000, 0x08, 0x0f, 0x00, 0x00, 0x00,
+ 0x3d},
+ {0x7c, 0x0e7d, 0x060f, 0x3ad0, 0x0000, 0x08, 0x0f, 0x00, 0x00, 0x00,
+ 0x3d},
+ {0x7d, 0x0eff, 0x060f, 0x3ad0, 0x0000, 0x08, 0x0f, 0x00, 0x00, 0x00,
+ 0x3d},
+ {0xff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00}
+};
+
+typedef struct _SiS310_Ext2Struct {


+ USHORT Ext_InfoFlag;
+ UCHAR Ext_CRT1CRTC;
+ UCHAR Ext_CRTVCLK;
+ UCHAR Ext_CRT2CRTC;
+ UCHAR ModeID;
+ USHORT XRes;
+ USHORT YRes;
+ USHORT ROM_OFFSET;

+} SiS310_Ext2Struct;
+SiS310_Ext2Struct SiS310_RefIndex[] = {
+ {0x005f, 0x0d, 0x03, 0x05, 0x6a, 800, 600, 0x3a81}, /* 0x0 */
+ {0x0467, 0x0e, 0x04, 0x05, 0x6a, 800, 600, 0x3a86}, /* 0x1 */
+ {0x0067, 0x0f, 0x08, 0x48, 0x6a, 800, 600, 0x3a8b}, /* 0x2 */
+ {0x0067, 0x10, 0x07, 0x8b, 0x6a, 800, 600, 0x3a90}, /* 0x3 */
+ {0x0147, 0x11, 0x0a, 0x00, 0x6a, 800, 600, 0x3a95}, /* 0x4 */
+ {0x4147, 0x12, 0x0d, 0x00, 0x6a, 800, 600, 0x3a9a}, /* 0x5 */
+ {0x4047, 0x13, 0x13, 0x00, 0x6a, 800, 600, 0x3a9f}, /* 0x6 */
+ {0x4047, 0x14, 0x1c, 0x00, 0x6a, 800, 600, 0x3aa4}, /* 0x7 */
+ {0xc05f, 0x05, 0x00, 0x04, 0x2e, 640, 480, 0x3a57}, /* 0x8 */
+ {0xc067, 0x06, 0x02, 0x04, 0x2e, 640, 480, 0x3a5c}, /* 0x9 */
+ {0xc067, 0x07, 0x02, 0x47, 0x2e, 640, 480, 0x3a61}, /* 0xa */
+ {0xc067, 0x08, 0x03, 0x8a, 0x2e, 640, 480, 0x3a66}, /* 0xb */
+ {0x4047, 0x09, 0x05, 0x00, 0x2e, 640, 480, 0x3a6b}, /* 0xc */
+ {0x4047, 0x0a, 0x09, 0x00, 0x2e, 640, 480, 0x3a70}, /* 0xd */
+ {0x4047, 0x0b, 0x0e, 0x00, 0x2e, 640, 480, 0x3a75}, /* 0xe */
+ {0xc047, 0x0c, 0x15, 0x00, 0x2e, 640, 480, 0x3a7a}, /* 0xf */
+ {0x407f, 0x04, 0x00, 0x00, 0x2f, 640, 400, 0x3a50}, /* 0x10 */
+ {0xc00f, 0x3c, 0x01, 0x06, 0x31, 720, 480, 0x3b85}, /* 0x11 */
+ {0x000f, 0x3d, 0x03, 0x06, 0x32, 720, 576, 0x3b8c}, /* 0x12 */
+ {0x0187, 0x15, 0x06, 0x00, 0x37, 1024, 768, 0x3aab}, /* 0x13 */
+ {0xc877, 0x16, 0x0b, 0x06, 0x37, 1024, 768, 0x3ab0}, /* 0x14 301b TV1024x768 */
+ {0xc067, 0x17, 0x0f, 0x49, 0x37, 1024, 768, 0x3ab5}, /* 0x15 */
+ {0x0267, 0x18, 0x11, 0x00, 0x37, 1024, 768, 0x3aba}, /* 0x16 */
+ {0x0047, 0x19, 0x16, 0x8c, 0x37, 1024, 768, 0x3abf}, /* 0x17 */
+ {0x4047, 0x1a, 0x1b, 0x00, 0x37, 1024, 768, 0x3ac4}, /* 0x18 */
+ {0x4047, 0x1b, 0x1f, 0x00, 0x37, 1024, 768, 0x3ac9}, /* 0x19 */
+ {0x0387, 0x1c, 0x11, 0x00, 0x3a, 1280, 1024, 0x3adc}, /* 0x1a */
+ {0x0077, 0x1d, 0x19, 0x07, 0x3a, 1280, 1024, 0x3ae1}, /* 0x1b */
+ {0x0047, 0x1e, 0x1e, 0x00, 0x3a, 1280, 1024, 0x3ae6}, /* 0x1c */
+ {0x0007, 0x1f, 0x20, 0x00, 0x3a, 1280, 1024, 0x3aeb}, /* 0x1d */
+ {0x0007, 0x20, 0x21, 0x00, 0x3c, 1600, 1200, 0x3af2}, /* 0x1e */
+ {0x0007, 0x21, 0x22, 0x00, 0x3c, 1600, 1200, 0x3af7}, /* 0x1f */
+ {0x0007, 0x22, 0x23, 0x00, 0x3c, 1600, 1200, 0x3afc}, /* 0x20 */
+ {0x0007, 0x23, 0x25, 0x00, 0x3c, 1600, 1200, 0x3b01}, /* 0x21 */
+ {0x0007, 0x24, 0x26, 0x00, 0x3c, 1600, 1200, 0x3b06}, /* 0x22 */
+ {0x0007, 0x25, 0x2c, 0x00, 0x3c, 1600, 1200, 0x3b0b}, /* 0x23 */
+ {0x0007, 0x26, 0x34, 0x00, 0x3c, 1600, 1200, 0x3b10}, /* 0x24 */
+ {0x407f, 0x00, 0x00, 0x00, 0x40, 320, 200, 0x3a34}, /* 0x25 */
+ {0xc07f, 0x01, 0x00, 0x04, 0x50, 320, 240, 0x3a3b}, /* 0x26 */
+ {0x007f, 0x02, 0x04, 0x05, 0x51, 400, 300, 0x3a42}, /* 0x27 */
+ {0xc077, 0x03, 0x0b, 0x06, 0x52, 512, 384, 0x3a49}, /* 0x28 */
+ {0x8007, 0x27, 0x27, 0x00, 0x68, 1920, 1440, 0x3b17}, /* 0x29 */
+ {0x4007, 0x28, 0x29, 0x00, 0x68, 1920, 1440, 0x3b1c}, /* 0x2a */
+ {0x4007, 0x29, 0x2e, 0x00, 0x68, 1920, 1440, 0x3b21}, /* 0x2b */
+ {0x4007, 0x2a, 0x30, 0x00, 0x68, 1920, 1440, 0x3b26}, /* 0x2c */
+ {0x4007, 0x2b, 0x35, 0x00, 0x68, 1920, 1440, 0x3b2b}, /* 0x2d */
+ {0x4005, 0x2c, 0x39, 0x00, 0x68, 1920, 1440, 0x3b30}, /* 0x2e */
+ {0x4007, 0x2d, 0x2b, 0x00, 0x6c, 2048, 1536, 0x3b37}, /* 0x2f */
+ {0x4007, 0x2e, 0x31, 0x00, 0x6c, 2048, 1536, 0x3b3c}, /* 0x30 */
+ {0x4007, 0x2f, 0x33, 0x00, 0x6c, 2048, 1536, 0x3b41}, /* 0x31 */
+ {0x4007, 0x30, 0x37, 0x00, 0x6c, 2048, 1536, 0x3b46}, /* 0x32 */
+ {0x4005, 0x31, 0x38, 0x00, 0x6c, 2048, 1536, 0x3b4b}, /* 0x33 */
+ {0x0057, 0x32, 0x40, 0x08, 0x70, 800, 480, 0x3b52}, /* 0x34 */
+ {0x0047, 0x33, 0x07, 0x08, 0x70, 800, 480, 0x3b57}, /* 0x35 */
+ {0x0047, 0x34, 0x0a, 0x08, 0x70, 800, 480, 0x3b5c}, /* 0x36 */
+ {0x0057, 0x35, 0x0b, 0x09, 0x71, 1024, 576, 0x3b63}, /* 0x37 */
+ {0x0047, 0x36, 0x11, 0x09, 0x71, 1024, 576, 0x3b68}, /* 0x38 */
+ {0x0047, 0x37, 0x16, 0x09, 0x71, 1024, 576, 0x3b6d}, /* 0x39 */
+ {0x0057, 0x38, 0x19, 0x0a, 0x75, 1280, 720, 0x3b74}, /* 0x3a */
+ {0x0047, 0x39, 0x1e, 0x0a, 0x75, 1280, 720, 0x3b79}, /* 0x3b */
+ {0x0047, 0x3a, 0x20, 0x0a, 0x75, 1280, 720, 0x3b7e}, /* 0x3c */
+ {0x0027, 0x3b, 0x19, 0x08, 0x7b, 1280, 960, 0x3ad0}, /* 0x3d */
+ {0x0027, 0x3b, 0x19, 0x08, 0x7b, 1280, 960, 0x3ad5}, /* 0x3e */
+ {0xffff, 0x00, 0x00, 0x00, 0x00, 0000, 0000, 0x0000}
+};
+
+typedef struct _SiS310_CRT1TableStruct {
+ UCHAR CR[17];
+} SiS310_CRT1TableStruct;
+
+SiS310_CRT1TableStruct SiS310_CRT1Table[] = {


+ {{0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0xbf, 0x1f,

+ 0x9c, 0x8e, 0x8f, 0x96, 0xb9, 0x30, 0x00, 0x00,
+ 0x00}}, /* 0x0 */


+ {{0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0x0b, 0x3e,

+ 0xe9, 0x8b, 0xdf, 0xe7, 0x04, 0x00, 0x00, 0x00,
+ 0x00}}, /* 0x1 */


+ {{0x3d, 0x31, 0x31, 0x81, 0x37, 0x1f, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x57, 0x73, 0x20, 0x00, 0x05,

+ 0x01}}, /* 0x2 */


+ {{0x4f, 0x3f, 0x3f, 0x93, 0x45, 0x0d, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0xff, 0x25, 0x10, 0x00, 0x01,

+ 0x01}}, /* 0x3 */


+ {{0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+ 0x9c, 0x8e, 0x8f, 0x96, 0xb9, 0x30, 0x00, 0x05,

+ 0x00}}, /* 0x4 */


+ {{0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0x0b, 0x3e,
+ 0xe9, 0x8b, 0xdf, 0xe7, 0x04, 0x00, 0x00, 0x05,

+ 0x00}}, /* 0x5 */


+ {{0x63, 0x4f, 0x50, 0x86, 0x56, 0x9b, 0x06, 0x3e,
+ 0xe8, 0x8b, 0xdf, 0xe7, 0xff, 0x10, 0x00, 0x01,

+ 0x00}}, /* 0x6 */


+ {{0x64, 0x4f, 0x4f, 0x88, 0x55, 0x9d, 0xf2, 0x1f,
+ 0xe0, 0x83, 0xdf, 0xdf, 0xf3, 0x10, 0x00, 0x01,

+ 0x00}}, /* 0x7 */


+ {{0x63, 0x4f, 0x4f, 0x87, 0x5a, 0x81, 0xfb, 0x1f,
+ 0xe0, 0x83, 0xdf, 0xdf, 0xfc, 0x10, 0x00, 0x05,

+ 0x00}}, /* 0x8 */
+ {{0x65, 0x4f, 0x4f, 0x89, 0x58, 0x80, 0xfb, 0x1f,
+ 0xe0, 0x83, 0xdf, 0xdf, 0xfc, 0x00, 0x00, 0x05,
+ 0x61}}, /* 0x9 */
+ {{0x65, 0x4f, 0x4f, 0x89, 0x58, 0x80, 0x01, 0x3e,
+ 0xe0, 0x83, 0xdf, 0xdf, 0x02, 0x00, 0x00, 0x05,
+ 0x61}}, /* 0xa */
+ {{0x67, 0x4f, 0x4f, 0x8b, 0x58, 0x81, 0x0d, 0x3e,
+ 0xe0, 0x83, 0xdf, 0xdf, 0x0e, 0x10, 0x00, 0x05,
+ 0x61}}, /* 0xb */


+ {{0x65, 0x4f, 0x4f, 0x89, 0x57, 0x9f, 0xfb, 0x1f,
+ 0xe6, 0x8a, 0xe5, 0xe5, 0xfc, 0x00, 0x00, 0x01,

+ 0x00}}, /* 0xc */


+ {{0x7b, 0x63, 0x63, 0x9f, 0x6a, 0x93, 0x6f, 0xf0,
+ 0x58, 0x8a, 0x57, 0x57, 0x70, 0x20, 0x00, 0x05,

+ 0x01}}, /* 0xd */


+ {{0x7f, 0x63, 0x63, 0x83, 0x6c, 0x1c, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x57, 0x73, 0x20, 0x00, 0x06,

+ 0x01}}, /* 0xe */


+ {{0x7d, 0x63, 0x63, 0x81, 0x6e, 0x1d, 0x98, 0xf0,
+ 0x7c, 0x82, 0x57, 0x57, 0x99, 0x00, 0x00, 0x06,

+ 0x01}}, /* 0xf */


+ {{0x7f, 0x63, 0x63, 0x83, 0x69, 0x13, 0x6f, 0xf0,
+ 0x58, 0x8b, 0x57, 0x57, 0x70, 0x20, 0x00, 0x06,

+ 0x01}}, /* 0x10 */


+ {{0x7e, 0x63, 0x63, 0x82, 0x6b, 0x13, 0x75, 0xf0,
+ 0x58, 0x8b, 0x57, 0x57, 0x76, 0x20, 0x00, 0x06,

+ 0x01}}, /* 0x11 */
+ {{0x81, 0x63, 0x63, 0x85, 0x6d, 0x18, 0x7a, 0xf0,
+ 0x58, 0x8b, 0x57, 0x57, 0x7b, 0x20, 0x00, 0x06,
+ 0x61}}, /* 0x12 */
+ {{0x83, 0x63, 0x63, 0x87, 0x6e, 0x19, 0x81, 0xf0,
+ 0x58, 0x8b, 0x57, 0x57, 0x82, 0x20, 0x00, 0x06,
+ 0x61}}, /* 0x13 */
+ {{0x85, 0x63, 0x63, 0x89, 0x6f, 0x1a, 0x91, 0xf0,
+ 0x58, 0x8b, 0x57, 0x57, 0x92, 0x20, 0x00, 0x06,
+ 0x61}}, /* 0x14 */


+ {{0x99, 0x7f, 0x7f, 0x9d, 0x84, 0x1a, 0x96, 0x1f,
+ 0x7f, 0x83, 0x7f, 0x7f, 0x97, 0x10, 0x00, 0x02,

+ 0x00}}, /* 0x15 */


+ {{0xa3, 0x7f, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0xff, 0x25, 0x10, 0x00, 0x02,

+ 0x01}}, /* 0x16 */


+ {{0xa1, 0x7f, 0x7f, 0x85, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0xff, 0x25, 0x10, 0x00, 0x02,

+ 0x01}}, /* 0x17 */


+ {{0x9f, 0x7f, 0x7f, 0x83, 0x85, 0x91, 0x1e, 0xf5,
+ 0x00, 0x83, 0xff, 0xff, 0x1f, 0x10, 0x00, 0x02,

+ 0x01}}, /* 0x18 */


+ {{0xa7, 0x7f, 0x7f, 0x8b, 0x89, 0x95, 0x26, 0xf5,
+ 0x00, 0x83, 0xff, 0xff, 0x27, 0x10, 0x00, 0x02,

+ 0x01}}, /* 0x19 */
+ {{0xa9, 0x7f, 0x7f, 0x8d, 0x8c, 0x9a, 0x2c, 0xf5,
+ 0x00, 0x83, 0xff, 0xff, 0x2d, 0x14, 0x00, 0x02,
+ 0x62}}, /* 0x1a */
+ {{0xab, 0x7f, 0x7f, 0x8f, 0x8d, 0x9b, 0x35, 0xf5,
+ 0x00, 0x83, 0xff, 0xff, 0x36, 0x14, 0x00, 0x02,
+ 0x62}}, /* 0x1b */


+ {{0xcf, 0x9f, 0x9f, 0x93, 0xb2, 0x01, 0x14, 0xba,
+ 0x00, 0x83, 0xff, 0xff, 0x15, 0x00, 0x00, 0x03,

+ 0x00}}, /* 0x1c */


+ {{0xce, 0x9f, 0x9f, 0x92, 0xa9, 0x17, 0x28, 0x5a,
+ 0x00, 0x83, 0xff, 0xff, 0x29, 0x09, 0x00, 0x07,

+ 0x01}}, /* 0x1d */


+ {{0xce, 0x9f, 0x9f, 0x92, 0xa5, 0x17, 0x28, 0x5a,
+ 0x00, 0x83, 0xff, 0xff, 0x29, 0x09, 0x00, 0x07,

+ 0x01}}, /* 0x1e */


+ {{0xd3, 0x9f, 0x9f, 0x97, 0xab, 0x1f, 0x2e, 0x5a,
+ 0x00, 0x83, 0xff, 0xff, 0x2f, 0x09, 0x00, 0x07,

+ 0x01}}, /* 0x1f */


+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,

+ 0x00}}, /* 0x20 */


+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,

+ 0x00}}, /* 0x21 */


+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,

+ 0x00}}, /* 0x22 */


+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,

+ 0x00}}, /* 0x23 */


+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,

+ 0x00}}, /* 0x24 */


+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,

+ 0x00}}, /* 0x25 */


+ {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10,
+ 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04,

+ 0x00}}, /* 0x26 */
+ {{0x40, 0xef, 0xef, 0x84, 0x03, 0x1d, 0xda, 0x1f,
+ 0xa0, 0x83, 0x9f, 0x9f, 0xdb, 0x1f, 0x41, 0x01,
+ 0x00}}, /* 0x27 */
+ {{0x43, 0xef, 0xef, 0x87, 0x06, 0x00, 0xd4, 0x1f,
+ 0xa0, 0x83, 0x9f, 0x9f, 0xd5, 0x1f, 0x41, 0x05,
+ 0x63}}, /* 0x28 */
+ {{0x45, 0xef, 0xef, 0x89, 0x07, 0x01, 0xd9, 0x1f,
+ 0xa0, 0x83, 0x9f, 0x9f, 0xda, 0x1f, 0x41, 0x05,
+ 0x63}}, /* 0x29 */
+ {{0x40, 0xef, 0xef, 0x84, 0x03, 0x1d, 0xda, 0x1f,
+ 0xa0, 0x83, 0x9f, 0x9f, 0xdb, 0x1f, 0x41, 0x01,
+ 0x00}}, /* 0x2a */
+ {{0x40, 0xef, 0xef, 0x84, 0x03, 0x1d, 0xda, 0x1f,
+ 0xa0, 0x83, 0x9f, 0x9f, 0xdb, 0x1f, 0x41, 0x01,
+ 0x00}}, /* 0x2b */
+ {{0x40, 0xef, 0xef, 0x84, 0x03, 0x1d, 0xda, 0x1f,
+ 0xa0, 0x83, 0x9f, 0x9f, 0xdb, 0x1f, 0x41, 0x01,
+ 0x00}}, /* 0x2c */
+ {{0x59, 0xff, 0xff, 0x9d, 0x17, 0x13, 0x33, 0xba,
+ 0x00, 0x83, 0xff, 0xff, 0x34, 0x0f, 0x41, 0x05,
+ 0x44}}, /* 0x2d */
+ {{0x5b, 0xff, 0xff, 0x9f, 0x18, 0x14, 0x38, 0xba,
+ 0x00, 0x83, 0xff, 0xff, 0x39, 0x0f, 0x41, 0x05,
+ 0x44}}, /* 0x2e */
+ {{0x5b, 0xff, 0xff, 0x9f, 0x18, 0x14, 0x3d, 0xba,
+ 0x00, 0x83, 0xff, 0xff, 0x3e, 0x0f, 0x41, 0x05,
+ 0x44}}, /* 0x2f */
+ {{0x5d, 0xff, 0xff, 0x81, 0x19, 0x95, 0x41, 0xba,
+ 0x00, 0x84, 0xff, 0xff, 0x42, 0x0f, 0x41, 0x05,
+ 0x44}}, /* 0x30 */


+ {{0x55, 0xff, 0xff, 0x99, 0x0d, 0x0c, 0x3e, 0xba,
+ 0x00, 0x84, 0xff, 0xff, 0x3f, 0x0f, 0x41, 0x05,

+ 0x00}}, /* 0x31 */


+ {{0x7f, 0x63, 0x63, 0x83, 0x6c, 0x1c, 0x72, 0xba,
+ 0x27, 0x8b, 0xdf, 0xdf, 0x73, 0x00, 0x00, 0x06,

+ 0x01}}, /* 0x32 */


+ {{0x7f, 0x63, 0x63, 0x83, 0x69, 0x13, 0x6f, 0xba,
+ 0x26, 0x89, 0xdf, 0xdf, 0x6f, 0x00, 0x00, 0x06,

+ 0x01}}, /* 0x33 */


+ {{0x7f, 0x63, 0x63, 0x82, 0x6b, 0x13, 0x75, 0xba,
+ 0x29, 0x8c, 0xdf, 0xdf, 0x75, 0x00, 0x00, 0x06,

+ 0x01}}, /* 0x34 */


+ {{0xa3, 0x7f, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf1,
+ 0xaf, 0x85, 0x3f, 0x3f, 0x25, 0x30, 0x00, 0x02,

+ 0x01}}, /* 0x35 */


+ {{0x9f, 0x7f, 0x7f, 0x83, 0x85, 0x91, 0x1e, 0xf1,
+ 0xad, 0x81, 0x3f, 0x3f, 0x1f, 0x30, 0x00, 0x02,

+ 0x01}}, /* 0x36 */


+ {{0xa7, 0x7f, 0x7f, 0x88, 0x89, 0x15, 0x26, 0xf1,
+ 0xb1, 0x85, 0x3f, 0x3f, 0x27, 0x30, 0x00, 0x02,

+ 0x01}}, /* 0x37 */


+ {{0xce, 0x9f, 0x9f, 0x92, 0xa9, 0x17, 0x28, 0xc4,
+ 0x7a, 0x8e, 0xcf, 0xcf, 0x29, 0x21, 0x00, 0x07,

+ 0x01}}, /* 0x38 */


+ {{0xce, 0x9f, 0x9f, 0x92, 0xa5, 0x17, 0x28, 0xd4,
+ 0x7a, 0x8e, 0xcf, 0xcf, 0x29, 0x21, 0x00, 0x07,

+ 0x01}}, /* 0x39 */


+ {{0xd3, 0x9f, 0x9f, 0x97, 0xab, 0x1f, 0x2e, 0xd4,
+ 0x7d, 0x81, 0xcf, 0xcf, 0x2f, 0x21, 0x00, 0x07,

+ 0x01}}, /* 0x3a */


+ {{0xdc, 0x9f, 0x9f, 0x00, 0xab, 0x19, 0xe6, 0xef,
+ 0xc0, 0xc3, 0xbf, 0xbf, 0xe7, 0x10, 0x00, 0x07,

+ 0x01}}, /* 0x3b */


+ {{0x6b, 0x59, 0x59, 0x8f, 0x5e, 0x8c, 0x0b, 0x3e,
+ 0xe9, 0x8b, 0xdf, 0xe7, 0x04, 0x00, 0x00, 0x05,

+ 0x00}}, /* 0x3c */


+ {{0x7b, 0x59, 0x63, 0x9f, 0x6a, 0x93, 0x6f, 0xf0,
+ 0x58, 0x8a, 0x3f, 0x57, 0x70, 0x20, 0x00, 0x05,

+ 0x01}} /* 0x3d */
+};
+
+typedef struct _SiS310_MCLKDataStruct {


+ UCHAR SR28, SR29, SR2A;
+ USHORT CLOCK;

+} SiS310_MCLKDataStruct;
+SiS310_MCLKDataStruct SiS310_MCLKData[] = {
+ {0x5c, 0x23, 0x01, 166},
+ {0x5c, 0x23, 0x01, 166},
+ {0x5c, 0x23, 0x01, 166},
+ {0x5c, 0x23, 0x01, 166}
+};
+
+typedef struct _SiS310_ECLKDataStruct {


+ UCHAR SR2E, SR2F, SR30;
+ USHORT CLOCK;

+} SiS310_ECLKDataStruct;
+SiS310_ECLKDataStruct SiS310_ECLKData[] = {
+ {0x5c, 0x23, 0x01, 166},
+ {0x5c, 0x23, 0x01, 166},
+ {0x5c, 0x23, 0x01, 166},
+ {0x5c, 0x23, 0x01, 166}
+};
+
+typedef struct _SiS310_VCLKDataStruct {


+ UCHAR SR2B, SR2C;
+ USHORT CLOCK;

+} SiS310_VCLKDataStruct;
+SiS310_VCLKDataStruct SiS310_VCLKData[] = {
+ {0x1b, 0xe1, 25}, /* 0x0 */
+ {0x4e, 0xe4, 28}, /* 0x1 */
+ {0x57, 0xe4, 31}, /* 0x2 */
+ {0xc3, 0xc8, 36}, /* 0x3 */
+ {0x42, 0xe2, 40}, /* 0x4 */
+ {0xfe, 0xcd, 43}, /* 0x5 */
+ {0x5d, 0xc4, 44}, /* 0x6 */
+ {0x52, 0xe2, 49}, /* 0x7 */
+ {0x53, 0xe2, 50}, /* 0x8 */
+ {0x74, 0x67, 52}, /* 0x9 */
+ {0x6d, 0x66, 56}, /* 0xa */
+ {0x6c, 0xc3, 65}, /* 0xb */
+ {0x46, 0x44, 67}, /* 0xc */
+ {0xb1, 0x46, 68}, /* 0xd */
+ {0xd3, 0x4a, 72}, /* 0xe */
+ {0x29, 0x61, 75}, /* 0xf */
+ {0x6e, 0x46, 76}, /* 0x10 */
+ {0x2b, 0x61, 78}, /* 0x11 */
+ {0x31, 0x42, 79}, /* 0x12 */
+ {0xab, 0x44, 83}, /* 0x13 */
+ {0x46, 0x25, 84}, /* 0x14 */
+ {0x78, 0x29, 86}, /* 0x15 */
+ {0x62, 0x44, 94}, /* 0x16 */
+ {0x2b, 0x41, 104}, /* 0x17 */
+ {0x3a, 0x23, 105}, /* 0x18 */
+ {0x70, 0x44, 108}, /* 0x19 */
+ {0x3c, 0x23, 109}, /* 0x1a */
+ {0x5e, 0x43, 113}, /* 0x1b */
+ {0xbc, 0x44, 116}, /* 0x1c */
+ {0xe0, 0x46, 132}, /* 0x1d */
+ {0x54, 0x42, 135}, /* 0x1e */
+ {0xea, 0x2a, 139}, /* 0x1f */
+ {0x41, 0x22, 157}, /* 0x20 */
+ {0x70, 0x24, 162}, /* 0x21 */
+ {0x30, 0x21, 175}, /* 0x22 */
+ {0x4e, 0x22, 189}, /* 0x23 */
+ {0xde, 0x26, 194}, /* 0x24 */
+ {0x62, 0x06, 202}, /* 0x25 */
+ {0x3f, 0x03, 229}, /* 0x26 */
+ {0xb8, 0x06, 234}, /* 0x27 */
+ {0x34, 0x02, 253}, /* 0x28 */
+ {0x58, 0x04, 255}, /* 0x29 */
+ {0x24, 0x01, 265}, /* 0x2a */
+ {0x9b, 0x02, 267}, /* 0x2b */
+ {0x70, 0x05, 270}, /* 0x2c */
+ {0x25, 0x01, 272}, /* 0x2d */
+ {0x9c, 0x02, 277}, /* 0x2e */
+ {0x27, 0x01, 286}, /* 0x2f */
+ {0x3c, 0x02, 291}, /* 0x30 */
+ {0xef, 0x0a, 292}, /* 0x31 */
+ {0xf6, 0x0a, 310}, /* 0x32 */
+ {0x95, 0x01, 315}, /* 0x33 */
+ {0xf0, 0x09, 324}, /* 0x34 */
+ {0xfe, 0x0a, 331}, /* 0x35 */
+ {0xf3, 0x09, 332}, /* 0x36 */
+ {0xea, 0x08, 340}, /* 0x37 */
+ {0xe8, 0x07, 376}, /* 0x38 */
+ {0xde, 0x06, 389}, /* 0x39 */
+ {0x52, 0x2a, 54}, /* 0x3a */
+ {0x52, 0x6a, 27}, /* 0x3b */
+ {0x62, 0x24, 70}, /* 0x3c */
+ {0x62, 0x64, 70}, /* 0x3d */
+ {0xa8, 0x4c, 30}, /* 0x3e */
+ {0x20, 0x26, 33}, /* 0x3f */
+ {0x31, 0xc2, 39} /* 0x40 */
+};
+
+typedef struct _SiS310_VBVCLKDataStruct {
+ UCHAR Part4_A, Part4_B;
+ USHORT CLOCK;
+} SiS310_VBVCLKDataStruct;
+SiS310_VBVCLKDataStruct SiS310_VBVCLKData[] = {
+ {0x1b, 0xe1, 25}, /* 0x0 */
+ {0x4e, 0xe4, 28}, /* 0x1 */
+ {0x57, 0xe4, 31}, /* 0x2 */
+ {0xc3, 0xc8, 36}, /* 0x3 */
+ {0x42, 0x47, 40}, /* 0x4 */
+ {0xfe, 0xcd, 43}, /* 0x5 */
+ {0x5d, 0xc4, 44}, /* 0x6 */
+ {0x52, 0x47, 49}, /* 0x7 */
+ {0x53, 0x47, 50}, /* 0x8 */
+ {0x74, 0x67, 52}, /* 0x9 */
+ {0x6d, 0x66, 56}, /* 0xa */
+ {0x5a, 0x64, 65}, /* 0xb */
+ {0x46, 0x44, 67}, /* 0xc */
+ {0xb1, 0x46, 68}, /* 0xd */
+ {0xd3, 0x4a, 72}, /* 0xe */
+ {0x29, 0x61, 75}, /* 0xf */
+ {0x6d, 0x46, 75}, /* 0x10 */
+ {0x41, 0x43, 78}, /* 0x11 */
+ {0x31, 0x42, 79}, /* 0x12 */
+ {0xab, 0x44, 83}, /* 0x13 */
+ {0x46, 0x25, 84}, /* 0x14 */
+ {0x78, 0x29, 86}, /* 0x15 */
+ {0x62, 0x44, 94}, /* 0x16 */
+ {0x2b, 0x22, 104}, /* 0x17 */
+ {0x49, 0x24, 105}, /* 0x18 */
+ {0xf8, 0x2f, 108}, /* 0x19 */
+ {0x3c, 0x23, 109}, /* 0x1a */
+ {0x5e, 0x43, 113}, /* 0x1b */
+ {0xbc, 0x44, 116}, /* 0x1c */
+ {0xe0, 0x46, 132}, /* 0x1d */
+ {0xd4, 0x28, 135}, /* 0x1e */
+ {0xea, 0x2a, 139}, /* 0x1f */
+ {0x41, 0x22, 157}, /* 0x20 */
+ {0x70, 0x24, 162}, /* 0x21 */
+ {0x30, 0x21, 175}, /* 0x22 */
+ {0x4e, 0x22, 189}, /* 0x23 */
+ {0xde, 0x26, 194}, /* 0x24 */
+ {0x70, 0x07, 202}, /* 0x25 */
+ {0x3f, 0x03, 229}, /* 0x26 */
+ {0xb8, 0x06, 234}, /* 0x27 */
+ {0x34, 0x02, 253}, /* 0x28 */
+ {0x58, 0x04, 255}, /* 0x29 */
+ {0x24, 0x01, 265}, /* 0x2a */
+ {0x9b, 0x02, 267}, /* 0x2b */
+ {0x70, 0x05, 270}, /* 0x2c */
+ {0x25, 0x01, 272}, /* 0x2d */
+ {0x9c, 0x02, 277}, /* 0x2e */
+ {0x27, 0x01, 286}, /* 0x2f */
+ {0x3c, 0x02, 291}, /* 0x30 */
+ {0xef, 0x0a, 292}, /* 0x31 */
+ {0xf6, 0x0a, 310}, /* 0x32 */
+ {0x95, 0x01, 315}, /* 0x33 */
+ {0xf0, 0x09, 324}, /* 0x34 */
+ {0xfe, 0x0a, 331}, /* 0x35 */
+ {0xf3, 0x09, 332}, /* 0x36 */
+ {0xea, 0x08, 340}, /* 0x37 */
+ {0xe8, 0x07, 376}, /* 0x38 */
+ {0xde, 0x06, 389}, /* 0x39 */
+ {0x52, 0x2a, 54}, /* 0x3a */
+ {0x52, 0x6a, 27}, /* 0x3b */
+ {0x62, 0x24, 70}, /* 0x3c */
+ {0x62, 0x64, 70}, /* 0x3d */
+ {0xa8, 0x4c, 30}, /* 0x3e */
+ {0x20, 0x26, 33}, /* 0x3f */
+ {0x31, 0xc2, 39} /* 0x40 */
+};
+
+UCHAR SiS310_ScreenOffset[] =
+ { 0x14, 0x19, 0x20, 0x28, 0x32, 0x40, 0x50, 0x64, 0x78, 0x80, 0x2d, 0x35 };
+
+typedef struct _SiS310_StResInfoStruct {


+ USHORT HTotal;
+ USHORT VTotal;

+} SiS310_StResInfoStruct;
+SiS310_StResInfoStruct SiS310_StResInfo[] = {


+ {640, 400},
+ {640, 350},
+ {720, 400},
+ {720, 350},
+ {640, 480}
+};
+

+typedef struct _SiS310_ModeResInfoStruct {


+ USHORT HTotal;
+ USHORT VTotal;
+ UCHAR XChar;
+ UCHAR YChar;

+} SiS310_ModeResInfoStruct;
+SiS310_ModeResInfoStruct SiS310_ModeResInfo[] = {


+ {320, 200, 8, 8},
+ {320, 240, 8, 8},
+ {320, 400, 8, 8},
+ {400, 300, 8, 8},
+ {512, 384, 8, 8},
+ {640, 400, 8, 16},
+ {640, 480, 8, 16},
+ {800, 600, 8, 16},
+ {1024, 768, 8, 16},
+ {1280, 1024, 8, 16},
+ {1600, 1200, 8, 16},
+ {1920, 1440, 8, 16},

+ {2048, 1536, 8, 16},


+ {720, 480, 8, 16},
+ {720, 576, 8, 16},

+ {1280, 960, 8, 16},
+ {800, 480, 8, 16},
+ {1024, 576, 8, 16},
+ {1280, 720, 8, 16}
+};
+
+UCHAR SiS310_OutputSelect = 0x40;
+UCHAR SiS310_SoftSetting = 30;
+UCHAR SiS310_SR07 = 0x18;
+UCHAR SiS310_SR15[8][4] = {
+ {0x0, 0x4, 0x60, 0x60},
+ {0xf, 0xf, 0xf, 0xf},
+ {0xba, 0xba, 0xba, 0xba},
+ {0xa9, 0xa9, 0xac, 0xac},
+ {0xa0, 0xa0, 0xa0, 0xa8},
+ {0x0, 0x0, 0x2, 0x2},
+ {0x30, 0x30, 0x40, 0x40},
+ {0x0, 0xa5, 0xfb, 0xf6}
+};
+UCHAR SiS310_CR40[5][4] = {
+ {0x77, 0x77, 0x33, 0x33},
+ {0x77, 0x77, 0x33, 0x33},


+ {0x0, 0x0, 0x0, 0x0},

+ {0x5b, 0x5b, 0x3, 0x3},
+ {0x0, 0x0, 0xf0, 0xf8}
+};
+UCHAR SiS310_CR49[] = { 0xaa, 0x88 };
+UCHAR SiS310_SR1F = 0x0;
+UCHAR SiS310_SR21 = 0xa5;
+UCHAR SiS310_SR22 = 0xfb;
+UCHAR SiS310_SR23 = 0xf6;
+UCHAR SiS310_SR24 = 0xd;
+UCHAR SiS310_SR25[] = { 0x33, 0x3 };
+UCHAR SiS310_SR31 = 0x0;
+UCHAR SiS310_SR32 = 0x11;
+UCHAR SiS310_SR33 = 0x0;
+UCHAR SiS310_CRT2Data_1_2 = 0x0;
+UCHAR SiS310_CRT2Data_4_D = 0x0;
+UCHAR SiS310_CRT2Data_4_E = 0x0;
+UCHAR SiS310_CRT2Data_4_10 = 0x80;
+USHORT SiS310_RGBSenseData = 0xd1;
+USHORT SiS310_VideoSenseData = 0xb9;
+USHORT SiS310_YCSenseData = 0xb3;
+USHORT SiS310_RGBSenseData2 = 0x0190; /*301b */
+USHORT SiS310_VideoSenseData2 = 0x0174;
+USHORT SiS310_YCSenseData2 = 0x016b;
+UCHAR SiS310_NTSCPhase[] = { 0x21, 0xed, 0x8a, 0x8 };
+UCHAR SiS310_PALPhase[] = { 0x2a, 0x5, 0xd3, 0x0 };
+UCHAR SiS310_NTSCPhase2[] = { 0x21, 0xF0, 0x7B, 0xD6 }; /*301b */
+UCHAR SiS310_PALPhase2[] = { 0x2a, 0x09, 0x86, 0xe9 };
+UCHAR SiS310_PALMPhase[] = { 0x21, 0xE4, 0x2E, 0x9B }; /*palmn */
+UCHAR SiS310_PALNPhase[] = { 0x21, 0xF4, 0x3E, 0xBA };
+
+typedef struct _SiS310_LCDDataStruct {


+ USHORT RVBHCMAX;
+ USHORT RVBHCFACT;
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;

+} SiS310_LCDDataStruct;
+SiS310_LCDDataStruct SiS310_StLCD1024x768Data[] = {


+ {62, 25, 800, 546, 1344, 806},
+ {32, 15, 930, 546, 1344, 806},
+ {32, 15, 930, 546, 1344, 806},
+ {104, 45, 945, 496, 1344, 806},
+ {62, 25, 800, 546, 1344, 806},
+ {31, 18, 1008, 624, 1344, 806},
+ {1, 1, 1344, 806, 1344, 806}
+};
+

+SiS310_LCDDataStruct SiS310_ExtLCD1024x768Data[] = {


+ {12, 5, 896, 512, 1344, 806},
+ {12, 5, 896, 510, 1344, 806},
+ {32, 15, 1008, 505, 1344, 806},
+ {32, 15, 1008, 514, 1344, 806},
+ {12, 5, 896, 500, 1344, 806},
+ {42, 25, 1024, 625, 1344, 806},
+ {1, 1, 1344, 806, 1344, 806},
+ {12, 5, 896, 500, 1344, 806},
+ {42, 25, 1024, 625, 1344, 806},
+ {1, 1, 1344, 806, 1344, 806},
+ {12, 5, 896, 500, 1344, 806},
+ {42, 25, 1024, 625, 1344, 806},
+ {1, 1, 1344, 806, 1344, 806}
+};
+

+SiS310_LCDDataStruct SiS310_St2LCD1024x768Data[] = {


+ {62, 25, 800, 546, 1344, 806},
+ {32, 15, 930, 546, 1344, 806},
+ {32, 15, 930, 546, 1344, 806},
+ {104, 45, 945, 496, 1344, 806},
+ {62, 25, 800, 546, 1344, 806},
+ {31, 18, 1008, 624, 1344, 806},
+ {1, 1, 1344, 806, 1344, 806}
+};
+

+SiS310_LCDDataStruct SiS310_StLCD1280x1024Data[] = {


+ {22, 5, 800, 510, 1650, 1088},
+ {22, 5, 800, 510, 1650, 1088},
+ {176, 45, 900, 510, 1650, 1088},
+ {176, 45, 900, 510, 1650, 1088},
+ {22, 5, 800, 510, 1650, 1088},
+ {13, 5, 1024, 675, 1560, 1152},
+ {16, 9, 1266, 804, 1688, 1072},
+ {1, 1, 1688, 1066, 1688, 1066}
+};
+

+SiS310_LCDDataStruct SiS310_ExtLCD1280x1024Data[] = {


+ {211, 60, 1024, 501, 1688, 1066},
+ {211, 60, 1024, 508, 1688, 1066},
+ {211, 60, 1024, 501, 1688, 1066},
+ {211, 60, 1024, 508, 1688, 1066},
+ {211, 60, 1024, 500, 1688, 1066},
+ {211, 75, 1024, 625, 1688, 1066},
+ {211, 120, 1280, 798, 1688, 1066},
+ {1, 1, 1688, 1066, 1688, 1066}
+};
+

+SiS310_LCDDataStruct SiS310_St2LCD1280x1024Data[] = {


+ {22, 5, 800, 510, 1650, 1088},
+ {22, 5, 800, 510, 1650, 1088},
+ {176, 45, 900, 510, 1650, 1088},
+ {176, 45, 900, 510, 1650, 1088},
+ {22, 5, 800, 510, 1650, 1088},
+ {13, 5, 1024, 675, 1560, 1152},
+ {16, 9, 1266, 804, 1688, 1072},
+ {1, 1, 1688, 1066, 1688, 1066}
+};
+

+SiS310_LCDDataStruct SiS310_NoScaleData[] = {


+ {1, 1, 800, 449, 800, 449},
+ {1, 1, 800, 449, 800, 449},
+ {1, 1, 900, 449, 900, 449},
+ {1, 1, 900, 449, 900, 449},
+ {1, 1, 800, 525, 800, 525},
+ {1, 1, 1056, 628, 1056, 628},
+ {1, 1, 1344, 806, 1344, 806},
+ {1, 1, 1688, 1066, 1688, 1066}
+};
+

+SiS310_LCDDataStruct SiS310_LCD1280x960Data[] = {


+ {9, 2, 800, 500, 1800, 1000},
+ {9, 2, 800, 500, 1800, 1000},
+ {4, 1, 900, 500, 1800, 1000},
+ {4, 1, 900, 500, 1800, 1000},
+ {9, 2, 800, 500, 1800, 1000},
+ {30, 11, 1056, 625, 1800, 1000},
+ {5, 3, 1350, 800, 1800, 1000},
+ {1, 1, 1576, 1050, 1576, 1050},
+ {1, 1, 1800, 1000, 1800, 1000}
+};
+

+typedef struct _SiS310_TVDataStruct {


+ USHORT RVBHCMAX;
+ USHORT RVBHCFACT;
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT TVHDE;
+ USHORT TVVDE;
+ USHORT RVBHRS;
+ UCHAR FlickerMode;
+ USHORT HALFRVBHRS;
+ UCHAR RY1COE;
+ UCHAR RY2COE;
+ UCHAR RY3COE;
+ UCHAR RY4COE;

+} SiS310_TVDataStruct;
+SiS310_TVDataStruct SiS310_StPALData[] = {


+ {1, 1, 864, 525, 1270, 400, 100, 0, 760, 0xf4, 0xff, 0x1c, 0x22},
+ {1, 1, 864, 525, 1270, 350, 100, 0, 760, 0xf4, 0xff, 0x1c, 0x22},
+ {1, 1, 864, 525, 1270, 400, 0, 0, 720, 0xf1, 0x04, 0x1f, 0x18},
+ {1, 1, 864, 525, 1270, 350, 0, 0, 720, 0xf4, 0x0b, 0x1c, 0x0a},
+ {1, 1, 864, 525, 1270, 480, 50, 0, 760, 0xf4, 0xff, 0x1c, 0x22},
+ {1, 1, 864, 525, 1270, 600, 50, 0, 0, 0xf4, 0xff, 0x1c, 0x22}
+};
+

+SiS310_TVDataStruct SiS310_ExtPALData[] = {


+ {27, 10, 848, 448, 1270, 530, 50, 0, 50, 0xf4, 0xff, 0x1c, 0x22},
+ {108, 35, 848, 398, 1270, 530, 50, 0, 50, 0xf4, 0xff, 0x1c, 0x22},
+ {12, 5, 954, 448, 1270, 530, 50, 0, 50, 0xf1, 0x04, 0x1f, 0x18},
+ {9, 4, 960, 463, 1644, 438, 50, 0, 50, 0xf4, 0x0b, 0x1c, 0x0a},
+ {9, 4, 848, 528, 1270, 530, 0, 0, 50, 0xf5, 0xfb, 0x1b, 0x2a},
+ {36, 25, 1060, 648, 1316, 530, 438, 0, 438, 0xeb, 0x05, 0x25, 0x16},
+ {3, 2, 1080, 619, 1270, 540, 438, 0, 438, 0xf3, 0x00, 0x1d, 0x20},
+ {1, 1, 1170, 821, 1270, 520, 686, 0, 686, 0xF3, 0x00, 0x1D, 0x20} /*301b */
+};
+

+SiS310_TVDataStruct SiS310_StNTSCData[] = {


+ {1, 1, 858, 525, 1270, 400, 50, 0, 760, 0xf1, 0x04, 0x1f, 0x18},
+ {1, 1, 858, 525, 1270, 350, 50, 0, 640, 0xf1, 0x04, 0x1f, 0x18},
+ {1, 1, 858, 525, 1270, 400, 0, 0, 720, 0xf1, 0x04, 0x1f, 0x18},
+ {1, 1, 858, 525, 1270, 350, 0, 0, 720, 0xf4, 0x0b, 0x1c, 0x0a},
+ {1, 1, 858, 525, 1270, 480, 0, 0, 760, 0xf1, 0x04, 0x1f, 0x18}
+};
+

+SiS310_TVDataStruct SiS310_ExtNTSCData[] = {


+ {143, 65, 858, 443, 1270, 440, 171, 0, 171, 0xf1, 0x04, 0x1f, 0x18},
+ {88, 35, 858, 393, 1270, 440, 171, 0, 171, 0xf1, 0x04, 0x1f, 0x18},
+ {143, 70, 924, 443, 1270, 440, 92, 0, 92, 0xf1, 0x04, 0x1f, 0x18},
+ {143, 70, 924, 393, 1270, 440, 92, 0, 92, 0xf4, 0x0b, 0x1c, 0x0a},
+ {143, 76, 836, 523, 1270, 440, 224, 0, 0, 0xf1, 0x05, 0x1f, 0x16},
+ {143, 120, 1056, 643, 1270, 440, 0, 128, 0, 0xf4, 0x10, 0x1c, 0x00},

+ {2, 1, 858, 503, 1270, 480, 0, 128, 0, 0xee, 0x0c, 0x22, 0x08},
+ {65, 64, 1056, 791, 1270, 480, 638, 0, 0, 0xEE, 0x0C, 0x22, 0x08} /*301b */
+};
+
+SiS310_TVDataStruct SiS310_St1HiTVData[] = {
+ {0x00}
+};
+
+SiS310_TVDataStruct SiS310_St2HiTVData[] = {
+ {0x00}
+};
+
+SiS310_TVDataStruct SiS310_ExtHiTVData[] = {
+ {0x00}
+};
+
+UCHAR SiS310_NTSCTiming[] = {


+ 0x17, 0x1d, 0x03, 0x09, 0x05, 0x06, 0x0c, 0x0c,
+ 0x94, 0x49, 0x01, 0x0a, 0x06, 0x0d, 0x04, 0x0a,
+ 0x06, 0x14, 0x0d, 0x04, 0x0a, 0x00, 0x85, 0x1b,
+ 0x0c, 0x50, 0x00, 0x97, 0x00, 0xda, 0x4a, 0x17,
+ 0x7d, 0x05, 0x4b, 0x00, 0x00, 0xe2, 0x00, 0x02,
+ 0x03, 0x0a, 0x65, 0x9d, 0x08, 0x92, 0x8f, 0x40,
+ 0x60, 0x80, 0x14, 0x90, 0x8c, 0x60, 0x14, 0x50,
+ 0x00, 0x40, 0x44, 0x00, 0xdb, 0x02, 0x3b, 0x00
+};
+

+UCHAR SiS310_PALTiming[] = {


+ 0x19, 0x52, 0x35, 0x6e, 0x04, 0x38, 0x3d, 0x70,
+ 0x94, 0x49, 0x01, 0x12, 0x06, 0x3e, 0x35, 0x6d,
+ 0x06, 0x14, 0x3e, 0x35, 0x6d, 0x00, 0x45, 0x2b,
+ 0x70, 0x50, 0x00, 0x9b, 0x00, 0xd9, 0x5d, 0x17,
+ 0x7d, 0x05, 0x45, 0x00, 0x00, 0xe8, 0x00, 0x02,
+ 0x0d, 0x00, 0x68, 0xb0, 0x0b, 0x92, 0x8f, 0x40,
+ 0x60, 0x80, 0x14, 0x90, 0x8c, 0x60, 0x14, 0x63,
+ 0x00, 0x40, 0x3e, 0x00, 0xe1, 0x02, 0x28, 0x00
+};
+

+UCHAR SiS310_HiTVExtTiming[] = { 0x00 };
+
+UCHAR SiS310_HiTVSt1Timing[] = { 0x00 };
+
+UCHAR SiS310_HiTVSt2Timing[] = { 0x00 };
+
+UCHAR SiS310_HiTVTextTiming[] = { 0x00 };
+
+UCHAR SiS310_HiTVGroup3Data[] = { 0x00 };
+
+UCHAR SiS310_HiTVGroup3Simu[] = { 0x00 };
+
+UCHAR SiS310_HiTVGroup3Text[] = { 0x00 };
+
+typedef struct _SiS310_PanelDelayTblStruct {
+ UCHAR timer[2];
+} SiS310_PanelDelayTblStruct;
+SiS310_PanelDelayTblStruct SiS310_PanelDelayTbl[] = {
+ {{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}}
+};
+
+typedef struct _SiS310_LVDSDataStruct {


+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;

+} SiS310_LVDSDataStruct;
+SiS310_LVDSDataStruct SiS310_LVDS800x600Data_1[] = {
+ {848, 433, 1060, 629},
+ {848, 389, 1060, 629},
+ {848, 433, 1060, 629},
+ {848, 389, 1060, 629},
+ {848, 518, 1060, 629},
+ {1056, 628, 1056, 628},
+ {1056, 628, 1056, 628},
+ {800, 449, 1000, 644},
+ {800, 525, 1000, 635}
+};
+
+SiS310_LVDSDataStruct SiS310_LVDS800x600Data_2[] = {
+ {1056, 628, 1056, 628},
+ {1056, 628, 1056, 628},
+ {1056, 628, 1056, 628},
+ {1056, 628, 1056, 628},
+ {1056, 628, 1056, 628},
+ {1056, 628, 1056, 628},
+ {1056, 628, 1056, 628},
+ {800, 449, 1000, 644},
+ {800, 525, 1000, 635}
+};
+
+SiS310_LVDSDataStruct SiS310_LVDS1024x768Data_1[] = {
+ {840, 438, 1344, 806},
+ {840, 409, 1344, 806},
+ {840, 438, 1344, 806},
+ {840, 409, 1344, 806},
+ {840, 518, 1344, 806},
+ {1050, 638, 1344, 806},
+ {1344, 806, 1344, 806},
+ {800, 449, 1280, 801},
+ {800, 525, 1280, 813}
+};
+
+SiS310_LVDSDataStruct SiS310_LVDS1024x768Data_2[] = {
+ {1344, 806, 1344, 806},
+ {1344, 806, 1344, 806},
+ {1344, 806, 1344, 806},
+ {1344, 806, 1344, 806},
+ {1344, 806, 1344, 806},
+ {1344, 806, 1344, 806},
+ {1344, 806, 1344, 806},
+ {800, 449, 1280, 801},
+ {800, 525, 1280, 813}
+};
+
+SiS310_LVDSDataStruct SiS310_LVDS1280x1024Data_1[] = {
+ {840, 438, 1344, 806},
+ {840, 409, 1344, 806},
+ {840, 438, 1344, 806},
+ {840, 409, 1344, 806},
+ {840, 518, 1344, 806},
+ {1050, 638, 1344, 806},
+ {1344, 806, 1344, 806},
+ {800, 449, 1280, 801},
+ {800, 525, 1280, 813}
+};
+
+SiS310_LVDSDataStruct SiS310_LVDS1280x1024Data_2[] = {
+ {1344, 806, 1344, 806},
+ {1344, 806, 1344, 806},
+ {1344, 806, 1344, 806},
+ {1344, 806, 1344, 806},
+ {1344, 806, 1344, 806},
+ {1344, 806, 1344, 806},
+ {1344, 806, 1344, 806},
+ {800, 449, 1280, 801},
+ {800, 525, 1280, 813}
+};
+
+SiS310_LVDSDataStruct SiS310_LVDS640x480Data_1[] = {
+ {800, 449, 800, 449},
+ {800, 449, 800, 449},
+ {800, 449, 800, 449},
+ {800, 449, 800, 449},
+ {800, 525, 800, 525},
+ {1056, 628, 1056, 628},
+ {1056, 628, 1056, 628},
+ {1056, 628, 1056, 628},
+ {1056, 628, 1056, 628}
+};
+
+SiS310_LVDSDataStruct SiS310_CHTVUNTSCData[] = {
+ {840, 600, 840, 600},
+ {840, 600, 840, 600},
+ {840, 600, 840, 600},
+ {840, 600, 840, 600},
+ {784, 600, 784, 600},
+ {1064, 750, 1064, 750}
+};
+
+SiS310_LVDSDataStruct SiS310_CHTVONTSCData[] = {
+ {840, 525, 840, 525},
+ {840, 525, 840, 525},
+ {840, 525, 840, 525},
+ {840, 525, 840, 525},
+ {784, 525, 784, 525},
+ {1040, 700, 1040, 700}
+};
+
+SiS310_LVDSDataStruct SiS310_CHTVUPALData[] = {
+ {1008, 625, 1008, 625},
+ {1008, 625, 1008, 625},
+ {1008, 625, 1008, 625},
+ {1008, 625, 1008, 625},
+ {840, 750, 840, 750},
+ {936, 836, 936, 836}
+};
+
+SiS310_LVDSDataStruct SiS310_CHTVOPALData[] = {
+ {1008, 625, 1008, 625},
+ {1008, 625, 1008, 625},
+ {1008, 625, 1008, 625},
+ {1008, 625, 1008, 625},
+ {840, 625, 840, 625},
+ {960, 750, 960, 750}
+};
+
+typedef struct _SiS310_LVDSDesStruct {


+ USHORT LCDHDES;
+ USHORT LCDVDES;

+} SiS310_LVDSDesStruct;
+SiS310_LVDSDesStruct SiS310_PanelType00_1[] = {
+ {0, 626},
+ {0, 624},
+ {0, 626},
+ {0, 624},
+ {0, 624},
+ {0, 627},
+ {0, 627},
+ {0, 0},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType01_1[] = {
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType02_1[] = {
+ {0, 626},
+ {0, 624},
+ {0, 626},
+ {0, 624},
+ {0, 624},
+ {0, 627},
+ {0, 627},
+ {0, 0},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType03_1[] = {
+ {8, 436},
+ {8, 440},
+ {8, 436},
+ {8, 440},
+ {8, 512},
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType04_1[] = {
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType05_1[] = {
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType06_1[] = {
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType07_1[] = {
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType08_1[] = {
+ {1059, 626},
+ {1059, 624},
+ {1059, 626},
+ {1059, 624},
+ {1059, 624},
+ {0, 627},
+ {0, 627},
+ {0, 0},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType09_1[] = {
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType0a_1[] = {
+ {1059, 626},
+ {1059, 624},
+ {1059, 626},
+ {1059, 624},
+ {1059, 624},
+ {0, 627},
+ {0, 627},
+ {0, 0},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType0b_1[] = {
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType0c_1[] = {
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType0d_1[] = {
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType0e_1[] = {
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType0f_1[] = {
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType00_2[] = {
+ {976, 527},
+ {976, 502},
+ {976, 527},
+ {976, 502},
+ {976, 567},
+ {0, 627},
+ {0, 627},
+ {0, 0},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType01_2[] = {
+ {1152, 622},
+ {1152, 597},
+ {1152, 622},
+ {1152, 597},
+ {1152, 662},
+ {1232, 722},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType02_2[] = {
+ {976, 527},
+ {976, 502},
+ {976, 527},
+ {976, 502},
+ {976, 567},
+ {0, 627},
+ {0, 627},
+ {0, 0},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType03_2[] = {
+ {1152, 622},
+ {1152, 597},
+ {1152, 622},
+ {1152, 597},
+ {1152, 662},
+ {1232, 722},
+ {0, 805},
+ {1152, 622},
+ {1152, 597}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType04_2[] = {
+ {1152, 622},
+ {1152, 597},
+ {1152, 622},
+ {1152, 597},
+ {1152, 662},
+ {1232, 722},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType05_2[] = {
+ {1152, 622},
+ {1152, 597},
+ {1152, 622},
+ {1152, 597},
+ {1152, 662},
+ {1232, 722},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType06_2[] = {
+ {1152, 622},
+ {1152, 597},
+ {1152, 622},
+ {1152, 597},
+ {1152, 662},
+ {1232, 722},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType07_2[] = {
+ {1152, 622},
+ {1152, 597},
+ {1152, 622},
+ {1152, 597},
+ {1152, 662},
+ {1232, 722},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType08_2[] = {
+ {976, 527},
+ {976, 502},
+ {976, 527},
+ {976, 502},
+ {976, 567},
+ {0, 627},
+ {0, 627},
+ {0, 0},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType09_2[] = {
+ {1152, 622},
+ {1152, 597},
+ {1152, 622},
+ {1152, 597},
+ {1152, 662},
+ {1232, 722},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType0a_2[] = {
+ {976, 527},
+ {976, 502},
+ {976, 527},
+ {976, 502},
+ {976, 567},
+ {0, 627},
+ {0, 627},
+ {0, 0},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType0b_2[] = {
+ {1152, 622},
+ {1152, 597},
+ {1152, 622},
+ {1152, 597},
+ {1152, 662},
+ {1232, 722},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType0c_2[] = {
+ {1152, 622},
+ {1152, 597},
+ {1152, 622},
+ {1152, 597},
+ {1152, 662},
+ {1232, 722},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType0d_2[] = {
+ {1152, 622},
+ {1152, 597},
+ {1152, 622},
+ {1152, 597},
+ {1152, 662},
+ {1232, 722},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType0e_2[] = {
+ {1152, 622},
+ {1152, 597},
+ {1152, 622},
+ {1152, 597},
+ {1152, 662},
+ {1232, 722},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType0f_2[] = {
+ {1152, 622},
+ {1152, 597},
+ {1152, 622},
+ {1152, 597},
+ {1152, 662},
+ {1232, 722},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+/*301b*/
+SiS310_LVDSDesStruct SiS310_PanelType1076_1[] = {
+ {0x00, 0x00}
+};
+SiS310_LVDSDesStruct SiS310_PanelType1210_1[] = {
+ {0x00, 0x00}
+};
+SiS310_LVDSDesStruct SiS310_PanelType1296_1[] = {
+ {0x00, 0x00}
+};
+SiS310_LVDSDesStruct SiS310_PanelType1076_2[] = {
+ {0x00, 0x00}
+};
+SiS310_LVDSDesStruct SiS310_PanelType1210_2[] = {
+ {0x00, 0x00}
+};
+SiS310_LVDSDesStruct SiS310_PanelType1296_2[] = {


+ {0x00, 0x00}
+};
+/*end 301b*/
+

+SiS310_LVDSDesStruct SiS310_CHTVUNTSCDesData[] = {
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_CHTVONTSCDesData[] = {
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_CHTVUPALDesData[] = {
+ {256, 0},
+ {256, 0},
+ {256, 0},
+ {256, 0},
+ {0, 0},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_CHTVOPALDesData[] = {
+ {256, 0},
+ {256, 0},
+ {256, 0},
+ {256, 0},
+ {0, 0},
+ {0, 0}
+};
+
+/*add for LCDA*/
+typedef struct _SiS310_LCDACRT1DataStruct {
+ UCHAR CR[17];


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

echo 'End of part 073'
echo 'File patch-2.4.15 is continued in part 074'
echo "074" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:43 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part067

#!/bin/sh -x
# this is part 067 of a 115 - part archive


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

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

+ tp->tinfo.curr.period != tp->tinfo.goal.period ||
+ tp->tinfo.curr.offset != tp->tinfo.goal.offset ||
+ tp->tinfo.curr.options != tp->tinfo.goal.options) {
+ if (!tp->nego_cp && lp)
+ msglen += sym_prepare_nego(np, cp, 0, msgptr + msglen);
+ }
+
+ /*
+ * Startqueue
+ */
+ cp->phys.head.go.start = cpu_to_scr(SCRIPTA_BA (np, select));
+ cp->phys.head.go.restart = cpu_to_scr(SCRIPTA_BA (np, resel_dsa));
+
+ /*
+ * select
+ */
+ cp->phys.select.sel_id = cp->target;
+ cp->phys.select.sel_scntl3 = tp->head.wval;
+ cp->phys.select.sel_sxfer = tp->head.sval;
+ cp->phys.select.sel_scntl4 = tp->head.uval;
+
+ /*
+ * message
+ */
+ cp->phys.smsg.addr = cpu_to_scr(CCB_BA (cp, scsi_smsg));


+ cp->phys.smsg.size = cpu_to_scr(msglen);
+
+ /*

+ * status
+ */


+ cp->host_xflags = 0;
+ cp->host_status = cp->nego_status ? HS_NEGOTIATE : HS_BUSY;
+ cp->ssss_status = S_ILLEGAL;

+ cp->xerr_status = 0;

+ cp->host_flags = 0;


+ cp->extra_bytes = 0;
+

+ /*
+ * extreme data pointer.
+ * shall be positive, so -1 is lower than lowest.:)
+ */
+ cp->ext_sg = -1;
+ cp->ext_ofs = 0;
+
+ /*
+ * Build the CDB and DATA descriptor block
+ * and start the IO.
+ */
+ return sym_setup_data_and_start(np, csio, cp);
+}
+
+/*
+ * Reset a SCSI target (all LUNs of this target).
+ */
+int sym_reset_scsi_target(hcb_p np, int target)
+{
+ tcb_p tp;
+
+ if (target == np->myaddr || (u_int)target >= SYM_CONF_MAX_TARGET)
+ return -1;
+


+ tp = &np->target[target];

+ tp->to_reset = 1;
+
+ np->istat_sem = SEM;
+ OUTB (nc_istat, SIGP|SEM);

+
+ return 0;
+}
+
+/*

+ * Abort a SCSI IO.
+ */
+int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out)
+{
+ /*
+ * Check that the IO is active.
+ */
+ if (!cp || !cp->host_status || cp->host_status == HS_WAIT)
+ return -1;
+
+ /*
+ * If a previous abort didn't succeed in time,
+ * perform a BUS reset.
+ */
+ if (cp->to_abort) {
+ sym_reset_scsi_bus(np, 1);


+ return 0;
+ }
+
+ /*

+ * Mark the CCB for abort and allow time for.
+ */
+ cp->to_abort = timed_out ? 2 : 1;
+
+ /*
+ * Tell the SCRIPTS processor to stop and synchronize with us.
+ */


+ np->istat_sem = SEM;
+ OUTB (nc_istat, SIGP|SEM);

+ return 0;
+}
+

+int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out)
+{
+ ccb_p cp;
+ SYM_QUEHEAD *qp;
+
+ /*
+ * Look up our CCB control block.
+ */


+ cp = 0;
+ FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {

+ ccb_p cp2 = sym_que_entry(qp, struct sym_ccb, link_ccbq);
+ if (cp2->cam_ccb == ccb) {
+ cp = cp2;


+ break;
+ }
+ }
+

+ return sym_abort_ccb(np, cp, timed_out);
+}
+
+/*
+ * Complete execution of a SCSI command with extented
+ * error, SCSI status error, or having been auto-sensed.
+ *
+ * The SCRIPTS processor is not running there, so we
+ * can safely access IO registers and remove JOBs from
+ * the START queue.


+ * SCRATCHA is assumed to have been loaded with STARTPOS
+ * before the SCRIPTS called the C code.
+ */

+void sym_complete_error (hcb_p np, ccb_p cp)
+{


+ tcb_p tp;
+ lcb_p lp;

+ int resid;


+ int i;
+
+ /*

+ * Paranoid check. :)
+ */
+ if (!cp || !cp->cam_ccb)
+ return;
+
+ if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_RESULT)) {
+ printf ("CCB=%lx STAT=%x/%x/%x DEV=%d/%d\n", (unsigned long)cp,
+ cp->host_status, cp->ssss_status, cp->host_flags,
+ cp->target, cp->lun);
+ MDELAY(100);
+ }
+
+ /*
+ * Get target and lun pointers.


+ */
+ tp = &np->target[cp->target];

+ lp = sym_lp(np, tp, cp->lun);
+
+ /*

+ * Check for extended errors.
+ */
+ if (cp->xerr_status) {
+ if (sym_verbose)
+ sym_print_xerr(cp, cp->xerr_status);
+ if (cp->host_status == HS_COMPLETE)
+ cp->host_status = HS_COMP_ERR;
+ }
+
+ /*
+ * Calculate the residual.
+ */
+ resid = sym_compute_residual(np, cp);
+
+ if (!SYM_SETUP_RESIDUAL_SUPPORT) {/* If user does not want residuals */
+ resid = 0; /* throw them away. :) */
+ cp->sv_resid = 0;
+ }
+#ifdef DEBUG_2_0_X
+if (resid)
+ printf("XXXX RESID= %d - 0x%x\n", resid, resid);
+#endif
+
+ /*


+ * Dequeue all queued CCBs for that device

+ * not yet started by SCRIPTS.


+ */
+ i = (INL (nc_scratcha) - np->squeue_ba) / 4;

+ i = sym_dequeue_from_squeue(np, i, cp->target, cp->lun, -1);
+
+ /*

+ * Restart the SCRIPTS processor.
+ */
+ OUTL_DSP (SCRIPTA_BA (np, start));
+
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING


+ if (cp->host_status == HS_COMPLETE &&

+ cp->ssss_status == S_QUEUE_FULL) {
+ if (!lp || lp->started_tags - i < 2)
+ goto weirdness;
+ /*
+ * Decrease queue depth as needed.
+ */
+ lp->started_max = lp->started_tags - i - 1;
+ lp->num_sgood = 0;
+
+ if (sym_verbose >= 2) {


+ PRINT_LUN(np, cp->target, cp->lun);

+ printf(" queue depth is now %d\n", lp->started_max);
+ }
+
+ /*
+ * Repair the CCB.
+ */
+ cp->host_status = HS_BUSY;


+ cp->ssss_status = S_ILLEGAL;
+

+ /*
+ * Let's requeue it to device.
+ */
+ sym_set_cam_status(cp->cam_ccb, CAM_REQUEUE_REQ);
+ goto finish;
+ }
+weirdness:
+#endif
+ /*
+ * Synchronize DMA map if needed.
+ */
+ sym_data_dmamap_postsync(np, cp);
+
+ /*
+ * Build result in CAM ccb.
+ */
+ sym_set_cam_result_error(np, cp, resid);
+
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+finish:
+#endif
+ /*
+ * Add this one to the COMP queue.
+ */
+ sym_remque(&cp->link_ccbq);
+ sym_insque_head(&cp->link_ccbq, &np->comp_ccbq);
+
+ /*
+ * Complete all those commands with either error
+ * or requeue condition.


+ */
+ sym_flush_comp_queue(np, 0);
+

+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ /*
+ * Donnot start more than 1 command after an error.
+ */
+ if (lp)
+ sym_start_next_ccbs(np, lp, 1);
+#endif
+}
+
+/*
+ * Complete execution of a successful SCSI command.
+ *
+ * Only successful commands go to the DONE queue,
+ * since we need to have the SCRIPTS processor
+ * stopped on any error condition.
+ * The SCRIPTS processor is running while we are
+ * completing successful commands.
+ */
+void sym_complete_ok (hcb_p np, ccb_p cp)
+{
+ tcb_p tp;
+ lcb_p lp;
+ cam_ccb_p ccb;
+ int resid;
+
+ /*
+ * Paranoid check. :)
+ */
+ if (!cp || !cp->cam_ccb)
+ return;
+ assert (cp->host_status == HS_COMPLETE);
+
+ /*
+ * Get user command.
+ */


+ ccb = cp->cam_ccb;
+

+ /*
+ * Get target and lun pointers.


+ */
+ tp = &np->target[cp->target];

+ lp = sym_lp(np, tp, cp->lun);
+
+ /*

+ * Assume device discovered on first success.


+ */
+ if (!lp)

+ sym_set_bit(tp->lun_map, cp->lun);
+
+ /*
+ * If all data have been transferred, given than no
+ * extended error did occur, there is no residual.
+ */
+ resid = 0;
+ if (cp->phys.head.lastp != sym_goalp(cp))
+ resid = sym_compute_residual(np, cp);
+
+ /*
+ * Wrong transfer residuals may be worse than just always
+ * returning zero. User can disable this feature from
+ * sym_conf.h. Residual support is enabled by default.
+ */
+ if (!SYM_SETUP_RESIDUAL_SUPPORT)
+ resid = 0;
+#ifdef DEBUG_2_0_X
+if (resid)
+ printf("XXXX RESID= %d - 0x%x\n", resid, resid);
+#endif
+
+ /*
+ * Synchronize DMA map if needed.
+ */
+ sym_data_dmamap_postsync(np, cp);
+
+ /*
+ * Build result in CAM ccb.
+ */
+ sym_set_cam_result_ok(np, cp, resid);
+
+#ifdef SYM_OPT_SNIFF_INQUIRY
+ /*
+ * On standard INQUIRY response (EVPD and CmDt
+ * not set), sniff out device capabilities.
+ */
+ if (cp->cdb_buf[0] == 0x12 && !(cp->cdb_buf[1] & 0x3))
+ sym_sniff_inquiry(np, cp->cam_ccb, resid);
+#endif
+
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ /*
+ * If max number of started ccbs had been reduced,
+ * increase it if 200 good status received.
+ */
+ if (lp && lp->started_max < lp->started_limit) {
+ ++lp->num_sgood;
+ if (lp->num_sgood >= 200) {
+ lp->num_sgood = 0;
+ ++lp->started_max;


+ if (sym_verbose >= 2) {

+ PRINT_LUN(np, cp->target, cp->lun);

+ printf(" queue depth is now %d\n",
+ lp->started_max);
+ }
+ }


+ }
+#endif
+
+ /*

+ * Free our CCB.
+ */
+ sym_free_ccb (np, cp);


+
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ /*

+ * Requeue a couple of awaiting scsi commands.
+ */
+ if (lp && !sym_que_empty(&lp->waiting_ccbq))
+ sym_start_next_ccbs(np, lp, 2);
+#endif
+ /*
+ * Complete the command.
+ */
+ sym_xpt_done(np, ccb);
+}
+
+/*
+ * Soft-attach the controller.
+ */
+#ifdef SYM_OPT_NVRAM_PRE_READ
+int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram)
+#else
+int sym_hcb_attach(hcb_p np, struct sym_fw *fw)
+#endif
+{
+#ifndef SYM_OPT_NVRAM_PRE_READ
+ struct sym_nvram nvram_buf, *nvram = &nvram_buf;
+#endif


+ int i;
+
+ /*

+ * Get some info about the firmware.
+ */
+ np->scripta_sz = fw->a_size;
+ np->scriptb_sz = fw->b_size;
+ np->scriptz_sz = fw->z_size;
+ np->fw_setup = fw->setup;
+ np->fw_patch = fw->patch;
+ np->fw_name = fw->name;
+
+ /*
+ * Save setting of some IO registers, so we will
+ * be able to probe specific implementations.
+ */
+ sym_save_initial_setting (np);
+
+ /*
+ * Reset the chip now, since it has been reported
+ * that SCSI clock calibration may not work properly
+ * if the chip is currently active.
+ */
+ sym_chip_reset (np);
+
+ /*
+ * Try to read the user set-up.
+ */
+#ifndef SYM_OPT_NVRAM_PRE_READ
+ (void) sym_read_nvram(np, nvram);
+#endif
+
+ /*
+ * Prepare controller and devices settings, according
+ * to chip features, user set-up and driver set-up.
+ */
+ (void) sym_prepare_setting(np, nvram);
+
+ /*
+ * Check the PCI clock frequency.
+ * Must be performed after prepare_setting since it destroys
+ * STEST1 that is used to probe for the clock doubler.
+ */
+ i = sym_getpciclock(np);
+ if (i > 37000 && !(np->features & FE_66MHZ))
+ printf("%s: PCI BUS clock seems too high: %u KHz.\n",
+ sym_name(np), i);
+
+ /*
+ * Allocate the start queue.
+ */
+ np->squeue = (u32 *) sym_calloc_dma(sizeof(u32)*(MAX_QUEUE*2),"SQUEUE");
+ if (!np->squeue)
+ goto attach_failed;
+ np->squeue_ba = vtobus(np->squeue);
+
+ /*
+ * Allocate the done queue.
+ */
+ np->dqueue = (u32 *) sym_calloc_dma(sizeof(u32)*(MAX_QUEUE*2),"DQUEUE");
+ if (!np->dqueue)
+ goto attach_failed;
+ np->dqueue_ba = vtobus(np->dqueue);
+
+ /*
+ * Allocate the target bus address array.
+ */
+ np->targtbl = (u32 *) sym_calloc_dma(256, "TARGTBL");
+ if (!np->targtbl)
+ goto attach_failed;
+ np->targtbl_ba = vtobus(np->targtbl);
+
+ /*
+ * Allocate SCRIPTS areas.
+ */
+ np->scripta0 = sym_calloc_dma(np->scripta_sz, "SCRIPTA0");
+ np->scriptb0 = sym_calloc_dma(np->scriptb_sz, "SCRIPTB0");
+ np->scriptz0 = sym_calloc_dma(np->scriptz_sz, "SCRIPTZ0");
+ if (!np->scripta0 || !np->scriptb0 || !np->scriptz0)
+ goto attach_failed;
+
+ /*
+ * Initialyze the CCB free and busy queues.
+ */
+ sym_que_init(&np->free_ccbq);
+ sym_que_init(&np->busy_ccbq);
+ sym_que_init(&np->comp_ccbq);
+
+ /*
+ * Initializations for optional handling
+ * of IO timeouts and device queueing.
+ */
+#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
+ sym_que_init(&np->tmo0_ccbq);
+ np->tmo_ccbq =
+ sym_calloc(2*SYM_CONF_TIMEOUT_ORDER_MAX*sizeof(SYM_QUEHEAD),
+ "TMO_CCBQ");
+ for (i = 0 ; i < 2*SYM_CONF_TIMEOUT_ORDER_MAX ; i++)
+ sym_que_init(&np->tmo_ccbq[i]);
+#endif
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ sym_que_init(&np->dummy_ccbq);
+#endif
+ /*
+ * Allocate some CCB. We need at least ONE.
+ */
+ if (!sym_alloc_ccb(np))
+ goto attach_failed;
+
+ /*
+ * Calculate BUS addresses where we are going
+ * to load the SCRIPTS.
+ */
+ np->scripta_ba = vtobus(np->scripta0);
+ np->scriptb_ba = vtobus(np->scriptb0);
+ np->scriptz_ba = vtobus(np->scriptz0);
+
+ if (np->ram_ba) {
+ np->scripta_ba = np->ram_ba;


+ if (np->features & FE_RAM8K) {
+ np->ram_ws = 8192;

+ np->scriptb_ba = np->scripta_ba + 4096;
+#if 0 /* May get useful for 64 BIT PCI addressing */
+ np->scr_ram_seg = cpu_to_scr(np->scripta_ba >> 32);
+#endif
+ }
+ else
+ np->ram_ws = 4096;
+ }
+
+ /*
+ * Copy scripts to controller instance.
+ */
+ bcopy(fw->a_base, np->scripta0, np->scripta_sz);
+ bcopy(fw->b_base, np->scriptb0, np->scriptb_sz);
+ bcopy(fw->z_base, np->scriptz0, np->scriptz_sz);
+
+ /*
+ * Setup variable parts in scripts and compute
+ * scripts bus addresses used from the C code.
+ */
+ np->fw_setup(np, fw);
+
+ /*
+ * Bind SCRIPTS with physical addresses usable by the
+ * SCRIPTS processor (as seen from the BUS = BUS addresses).
+ */
+ sym_fw_bind_script(np, (u32 *) np->scripta0, np->scripta_sz);
+ sym_fw_bind_script(np, (u32 *) np->scriptb0, np->scriptb_sz);
+ sym_fw_bind_script(np, (u32 *) np->scriptz0, np->scriptz_sz);


+
+#ifdef SYM_CONF_IARB_SUPPORT
+ /*

+ * If user wants IARB to be set when we win arbitration
+ * and have other jobs, compute the max number of consecutive
+ * settings of IARB hints before we leave devices a chance to
+ * arbitrate for reselection.
+ */
+#ifdef SYM_SETUP_IARB_MAX
+ np->iarb_max = SYM_SETUP_IARB_MAX;
+#else
+ np->iarb_max = 4;
+#endif
+#endif
+
+ /*
+ * Prepare the idle and invalid task actions.
+ */
+ np->idletask.start = cpu_to_scr(SCRIPTA_BA (np, idle));
+ np->idletask.restart = cpu_to_scr(SCRIPTB_BA (np, bad_i_t_l));
+ np->idletask_ba = vtobus(&np->idletask);
+
+ np->notask.start = cpu_to_scr(SCRIPTA_BA (np, idle));
+ np->notask.restart = cpu_to_scr(SCRIPTB_BA (np, bad_i_t_l));
+ np->notask_ba = vtobus(&np->notask);
+
+ np->bad_itl.start = cpu_to_scr(SCRIPTA_BA (np, idle));
+ np->bad_itl.restart = cpu_to_scr(SCRIPTB_BA (np, bad_i_t_l));
+ np->bad_itl_ba = vtobus(&np->bad_itl);
+
+ np->bad_itlq.start = cpu_to_scr(SCRIPTA_BA (np, idle));
+ np->bad_itlq.restart = cpu_to_scr(SCRIPTB_BA (np,bad_i_t_l_q));
+ np->bad_itlq_ba = vtobus(&np->bad_itlq);
+
+ /*
+ * Allocate and prepare the lun JUMP table that is used
+ * for a target prior the probing of devices (bad lun table).
+ * A private table will be allocated for the target on the
+ * first INQUIRY response received.
+ */
+ np->badluntbl = sym_calloc_dma(256, "BADLUNTBL");
+ if (!np->badluntbl)
+ goto attach_failed;
+
+ np->badlun_sa = cpu_to_scr(SCRIPTB_BA (np, resel_bad_lun));
+ for (i = 0 ; i < 64 ; i++) /* 64 luns/target, no less */
+ np->badluntbl[i] = cpu_to_scr(vtobus(&np->badlun_sa));
+
+ /*
+ * Prepare the bus address array that contains the bus
+ * address of each target control block.
+ * For now, assume all logical units are wrong. :)


+ */
+ for (i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {

+ np->targtbl[i] = cpu_to_scr(vtobus(&np->target[i]));
+ np->target[i].head.luntbl_sa =
+ cpu_to_scr(vtobus(np->badluntbl));
+ np->target[i].head.lun0_sa =
+ cpu_to_scr(vtobus(&np->badlun_sa));
+ }
+
+ /*
+ * Now check the cache handling of the pci chipset.
+ */
+ if (sym_snooptest (np)) {
+ printf("%s: CACHE INCORRECTLY CONFIGURED.\n", sym_name(np));
+ goto attach_failed;
+ };
+
+ /*
+ * Sigh! we are done.
+ */


+ return 0;
+
+ /*

+ * We have failed.
+ * We will try to free all the resources we have
+ * allocated, but if we are a boot device, this
+ * will not help that much.;)
+ */
+attach_failed:
+ sym_hcb_free(np);
+ return ENXIO;
+}
+
+/*
+ * Free everything that has been allocated for this device.
+ */
+void sym_hcb_free(hcb_p np)


+{
+ SYM_QUEHEAD *qp;
+ ccb_p cp;
+ tcb_p tp;

+ lcb_p lp;
+ int target, lun;
+
+ if (np->scriptz0)
+ sym_mfree_dma(np->scriptz0, np->scriptz_sz, "SCRIPTZ0");
+ if (np->scriptb0)
+ sym_mfree_dma(np->scriptb0, np->scriptb_sz, "SCRIPTB0");
+ if (np->scripta0)
+ sym_mfree_dma(np->scripta0, np->scripta_sz, "SCRIPTA0");
+#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
+ if (np->tmo_ccbq)
+ sym_mfree(np->tmo_ccbq,
+ 2*SYM_CONF_TIMEOUT_ORDER_MAX*sizeof(SYM_QUEHEAD),
+ "TMO_CCBQ");
+#endif
+ if (np->squeue)
+ sym_mfree_dma(np->squeue, sizeof(u32)*(MAX_QUEUE*2), "SQUEUE");
+ if (np->dqueue)
+ sym_mfree_dma(np->dqueue, sizeof(u32)*(MAX_QUEUE*2), "DQUEUE");
+
+ if (np->actccbs) {
+ while ((qp = sym_remque_head(&np->free_ccbq)) != 0) {


+ cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);

+ sym_data_dmamap_destroy(np, cp);
+ sym_mfree_dma(cp->sns_bbuf, SYM_SNS_BBUF_LEN,
+ "SNS_BBUF");


+ sym_mfree_dma(cp, sizeof(*cp), "CCB");
+ }
+ }

+
+ if (np->badluntbl)
+ sym_mfree_dma(np->badluntbl, 256,"BADLUNTBL");
+
+ for (target = 0; target < SYM_CONF_MAX_TARGET ; target++) {


+ tp = &np->target[target];

+ for (lun = 0 ; lun < SYM_CONF_MAX_LUN ; lun++) {
+ lp = sym_lp(np, tp, lun);
+ if (!lp)
+ continue;
+ if (lp->itlq_tbl)
+ sym_mfree_dma(lp->itlq_tbl, SYM_CONF_MAX_TASK*4,
+ "ITLQ_TBL");
+ if (lp->cb_tags)
+ sym_mfree(lp->cb_tags, SYM_CONF_MAX_TASK,
+ "CB_TAGS");
+ sym_mfree_dma(lp, sizeof(*lp), "LCB");
+ }
+#if SYM_CONF_MAX_LUN > 1
+ if (tp->lunmp)
+ sym_mfree(tp->lunmp, SYM_CONF_MAX_LUN*sizeof(lcb_p),
+ "LUNMP");
+#endif
+ }
+ if (np->targtbl)
+ sym_mfree_dma(np->targtbl, 256, "TARGTBL");
+}
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_hipd.h linux/drivers/scsi/sym53c8xx_2/sym_hipd.h
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_hipd.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym_hipd.h Fri Nov 9 15:22:54 2001
@@ -0,0 +1,1445 @@


+/*
+ * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family
+ * of PCI-SCSI IO processors.
+ *
+ * Copyright (C) 1999-2001 Gerard Roudier <grou...@free.fr>

+ *


+ * This driver is derived from the Linux sym53c8xx driver.
+ * Copyright (C) 1998-2000 Gerard Roudier

+ *


+ * The sym53c8xx driver is derived from the ncr53c8xx driver that had been
+ * a port of the FreeBSD ncr driver to Linux-1.2.13.

+ *

+#ifndef SYM_HIPD_H
+#define SYM_HIPD_H
+
+/*
+ * Generic driver options.
+ *
+ * They may be defined in platform specific headers, if they
+ * are useful.
+ *
+ * SYM_OPT_NO_BUS_MEMORY_MAPPING
+ * When this option is set, the driver will not load the
+ * on-chip RAM using MMIO, but let the SCRIPTS processor
+ * do the work using MOVE MEMORY instructions.
+ * (set for Linux/PPC)
+ *
+ * SYM_OPT_HANDLE_DIR_UNKNOWN
+ * When this option is set, the SCRIPTS used by the driver
+ * are able to handle SCSI transfers with direction not
+ * supplied by user.
+ * (set for Linux-2.0.X)
+ *
+ * SYM_OPT_HANDLE_DEVICE_QUEUEING
+ * When this option is set, the driver will use a queue per
+ * device and handle QUEUE FULL status requeuing internally.
+ *
+ * SYM_OPT_BUS_DMA_ABSTRACTION
+ * When this option is set, the driver allocator is responsible
+ * of maintaining bus physical addresses and so provides virtual
+ * to bus physical address translation of driver data structures.
+ * (set for FreeBSD-4 and Linux 2.3)
+ *
+ * SYM_OPT_SNIFF_INQUIRY
+ * When this option is set, the driver sniff out successful
+ * INQUIRY response and performs negotiations accordingly.
+ * (set for Linux)
+ *
+ * SYM_OPT_LIMIT_COMMAND_REORDERING
+ * When this option is set, the driver tries to limit tagged
+ * command reordering to some reasonnable value.
+ * (set for Linux)
+ */
+#if 0
+#define SYM_OPT_NO_BUS_MEMORY_MAPPING
+#define SYM_OPT_HANDLE_DIR_UNKNOWN
+#define SYM_OPT_HANDLE_DEVICE_QUEUEING
+#define SYM_OPT_BUS_DMA_ABSTRACTION
+#define SYM_OPT_SNIFF_INQUIRY
+#define SYM_OPT_LIMIT_COMMAND_REORDERING
+#endif
+
+/*
+ * Active debugging tags and verbosity.
+ * Both DEBUG_FLAGS and sym_verbose can be redefined
+ * by the platform specific code to something else.
+ */
+#define DEBUG_ALLOC (0x0001)
+#define DEBUG_PHASE (0x0002)
+#define DEBUG_POLL (0x0004)
+#define DEBUG_QUEUE (0x0008)
+#define DEBUG_RESULT (0x0010)
+#define DEBUG_SCATTER (0x0020)
+#define DEBUG_SCRIPT (0x0040)
+#define DEBUG_TINY (0x0080)
+#define DEBUG_TIMING (0x0100)
+#define DEBUG_NEGO (0x0200)
+#define DEBUG_TAGS (0x0400)
+#define DEBUG_POINTER (0x0800)
+
+#ifndef DEBUG_FLAGS
+#define DEBUG_FLAGS (0x0000)
+#endif
+
+#ifndef sym_verbose
+#define sym_verbose (np->verbose)
+#endif
+
+/*
+ * These ones should have been already defined.
+ */
+#ifndef offsetof
+#define offsetof(t, m) ((size_t) (&((t *)0)->m))
+#endif
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef assert
+#define assert(expression) { \
+ if (!(expression)) { \
+ (void)panic( \
+ "assertion \"%s\" failed: file \"%s\", line %d\n", \
+ #expression, \
+ __FILE__, __LINE__); \
+ } \
+}
+#endif
+
+/*
+ * Number of tasks per device we want to handle.
+ */
+#if SYM_CONF_MAX_TAG_ORDER > 8
+#error "more than 256 tags per logical unit not allowed."
+#endif
+#define SYM_CONF_MAX_TASK (1<<SYM_CONF_MAX_TAG_ORDER)
+
+/*
+ * Donnot use more tasks that we can handle.
+ */
+#ifndef SYM_CONF_MAX_TAG
+#define SYM_CONF_MAX_TAG SYM_CONF_MAX_TASK
+#endif
+#if SYM_CONF_MAX_TAG > SYM_CONF_MAX_TASK
+#undef SYM_CONF_MAX_TAG
+#define SYM_CONF_MAX_TAG SYM_CONF_MAX_TASK
+#endif
+
+/*
+ * This one means 'NO TAG for this job'
+ */
+#define NO_TAG (256)
+
+/*
+ * Number of SCSI targets.
+ */
+#if SYM_CONF_MAX_TARGET > 16
+#error "more than 16 targets not allowed."
+#endif
+
+/*
+ * Number of logical units per target.
+ */
+#if SYM_CONF_MAX_LUN > 64
+#error "more than 64 logical units per target not allowed."
+#endif
+
+/*
+ * Asynchronous pre-scaler (ns). Shall be 40 for
+ * the SCSI timings to be compliant.
+ */
+#define SYM_CONF_MIN_ASYNC (40)
+
+/*
+ * Number of entries in the START and DONE queues.
+ *
+ * We limit to 1 PAGE in order to succeed allocation of
+ * these queues. Each entry is 8 bytes long (2 DWORDS).
+ */
+#ifdef SYM_CONF_MAX_START
+#define SYM_CONF_MAX_QUEUE (SYM_CONF_MAX_START+2)
+#else
+#define SYM_CONF_MAX_QUEUE (7*SYM_CONF_MAX_TASK+2)
+#define SYM_CONF_MAX_START (SYM_CONF_MAX_QUEUE-2)
+#endif
+
+#if SYM_CONF_MAX_QUEUE > SYM_MEM_CLUSTER_SIZE/8
+#undef SYM_CONF_MAX_QUEUE
+#define SYM_CONF_MAX_QUEUE (SYM_MEM_CLUSTER_SIZE/8)
+#undef SYM_CONF_MAX_START
+#define SYM_CONF_MAX_START (SYM_CONF_MAX_QUEUE-2)
+#endif
+
+/*
+ * For this one, we want a short name :-)
+ */
+#define MAX_QUEUE SYM_CONF_MAX_QUEUE
+
+/*
+ * Union of supported NVRAM formats.
+ */
+struct sym_nvram {
+ int type;
+#define SYM_SYMBIOS_NVRAM (1)
+#define SYM_TEKRAM_NVRAM (2)
+#if SYM_CONF_NVRAM_SUPPORT
+ union {
+ Symbios_nvram Symbios;
+ Tekram_nvram Tekram;
+ } data;
+#endif
+};
+
+/*
+ * Common definitions for both bus space based and legacy IO methods.
+ */
+#define INB(r) INB_OFF(offsetof(struct sym_reg,r))
+#define INW(r) INW_OFF(offsetof(struct sym_reg,r))
+#define INL(r) INL_OFF(offsetof(struct sym_reg,r))
+
+#define OUTB(r, v) OUTB_OFF(offsetof(struct sym_reg,r), (v))
+#define OUTW(r, v) OUTW_OFF(offsetof(struct sym_reg,r), (v))
+#define OUTL(r, v) OUTL_OFF(offsetof(struct sym_reg,r), (v))
+
+#define OUTONB(r, m) OUTB(r, INB(r) | (m))
+#define OUTOFFB(r, m) OUTB(r, INB(r) & ~(m))
+#define OUTONW(r, m) OUTW(r, INW(r) | (m))
+#define OUTOFFW(r, m) OUTW(r, INW(r) & ~(m))
+#define OUTONL(r, m) OUTL(r, INL(r) | (m))
+#define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m))
+
+/*
+ * We normally want the chip to have a consistent view
+ * of driver internal data structures when we restart it.
+ * Thus these macros.
+ */
+#define OUTL_DSP(v) \
+ do { \
+ MEMORY_WRITE_BARRIER(); \
+ OUTL (nc_dsp, (v)); \
+ } while (0)
+
+#define OUTONB_STD() \
+ do { \
+ MEMORY_WRITE_BARRIER(); \
+ OUTONB (nc_dcntl, (STD|NOCOM)); \
+ } while (0)
+
+/*
+ * Command control block states.
+ */
+#define HS_IDLE (0)
+#define HS_BUSY (1)
+#define HS_NEGOTIATE (2) /* sync/wide data transfer*/
+#define HS_DISCONNECT (3) /* Disconnected by target */
+#define HS_WAIT (4) /* waiting for resource */
+
+#define HS_DONEMASK (0x80)
+#define HS_COMPLETE (4|HS_DONEMASK)
+#define HS_SEL_TIMEOUT (5|HS_DONEMASK) /* Selection timeout */
+#define HS_UNEXPECTED (6|HS_DONEMASK) /* Unexpected disconnect */
+#define HS_COMP_ERR (7|HS_DONEMASK) /* Completed with error */
+
+/*
+ * Software Interrupt Codes
+ */
+#define SIR_BAD_SCSI_STATUS (1)
+#define SIR_SEL_ATN_NO_MSG_OUT (2)
+#define SIR_MSG_RECEIVED (3)
+#define SIR_MSG_WEIRD (4)
+#define SIR_NEGO_FAILED (5)
+#define SIR_NEGO_PROTO (6)
+#define SIR_SCRIPT_STOPPED (7)
+#define SIR_REJECT_TO_SEND (8)
+#define SIR_SWIDE_OVERRUN (9)
+#define SIR_SODL_UNDERRUN (10)
+#define SIR_RESEL_NO_MSG_IN (11)
+#define SIR_RESEL_NO_IDENTIFY (12)
+#define SIR_RESEL_BAD_LUN (13)
+#define SIR_TARGET_SELECTED (14)
+#define SIR_RESEL_BAD_I_T_L (15)
+#define SIR_RESEL_BAD_I_T_L_Q (16)
+#define SIR_ABORT_SENT (17)
+#define SIR_RESEL_ABORTED (18)
+#define SIR_MSG_OUT_DONE (19)
+#define SIR_COMPLETE_ERROR (20)
+#define SIR_DATA_OVERRUN (21)
+#define SIR_BAD_PHASE (22)
+#if SYM_CONF_DMA_ADDRESSING_MODE == 2
+#define SIR_DMAP_DIRTY (23)
+#define SIR_MAX (23)
+#else
+#define SIR_MAX (22)
+#endif
+
+/*
+ * Extended error bit codes.
+ * xerr_status field of struct sym_ccb.
+ */
+#define XE_EXTRA_DATA (1) /* unexpected data phase */
+#define XE_BAD_PHASE (1<<1) /* illegal phase (4/5) */
+#define XE_PARITY_ERR (1<<2) /* unrecovered SCSI parity error */
+#define XE_SODL_UNRUN (1<<3) /* ODD transfer in DATA OUT phase */
+#define XE_SWIDE_OVRUN (1<<4) /* ODD transfer in DATA IN phase */
+
+/*
+ * Negotiation status.
+ * nego_status field of struct sym_ccb.
+ */
+#define NS_SYNC (1)
+#define NS_WIDE (2)
+#define NS_PPR (3)
+
+/*
+ * A CCB hashed table is used to retrieve CCB address
+ * from DSA value.
+ */
+#define CCB_HASH_SHIFT 8
+#define CCB_HASH_SIZE (1UL << CCB_HASH_SHIFT)
+#define CCB_HASH_MASK (CCB_HASH_SIZE-1)
+#if 1
+#define CCB_HASH_CODE(dsa) \
+ (((dsa) >> (_LGRU16_(sizeof(struct sym_ccb)))) & CCB_HASH_MASK)
+#else
+#define CCB_HASH_CODE(dsa) (((dsa) >> 9) & CCB_HASH_MASK)
+#endif


+
+#if SYM_CONF_DMA_ADDRESSING_MODE == 2
+/*

+ * We may want to use segment registers for 64 bit DMA.
+ * 16 segments registers -> up to 64 GB addressable.
+ */
+#define SYM_DMAP_SHIFT (4)
+#define SYM_DMAP_SIZE (1u<<SYM_DMAP_SHIFT)
+#define SYM_DMAP_MASK (SYM_DMAP_SIZE-1)
+#endif
+
+/*
+ * Device flags.
+ */
+#define SYM_DISC_ENABLED (1)
+#define SYM_TAGS_ENABLED (1<<1)
+#define SYM_SCAN_BOOT_DISABLED (1<<2)
+#define SYM_SCAN_LUNS_DISABLED (1<<3)
+
+/*
+ * Host adapter miscellaneous flags.
+ */
+#define SYM_AVOID_BUS_RESET (1)
+#define SYM_SCAN_TARGETS_HILO (1<<1)
+
+/*
+ * Misc.
+ */
+#define SYM_SNOOP_TIMEOUT (10000000)
+#define BUS_8_BIT 0
+#define BUS_16_BIT 1
+
+/*
+ * Gather negotiable parameters value
+ */
+struct sym_trans {
+ u8 scsi_version;
+ u8 spi_version;
+ u8 period;
+ u8 offset;
+ u8 width;
+ u8 options; /* PPR options */
+};
+
+struct sym_tinfo {
+ struct sym_trans curr;
+ struct sym_trans goal;
+ struct sym_trans user;
+#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
+ struct sym_trans prev;
+#endif
+};
+
+/*
+ * Global TCB HEADER.
+ *
+ * Due to lack of indirect addressing on earlier NCR chips,
+ * this substructure is copied from the TCB to a global
+ * address after selection.
+ * For SYMBIOS chips that support LOAD/STORE this copy is
+ * not needed and thus not performed.
+ */
+struct sym_tcbh {
+ /*
+ * Scripts bus addresses of LUN table accessed from scripts.
+ * LUN #0 is a special case, since multi-lun devices are rare,
+ * and we we want to speed-up the general case and not waste
+ * resources.
+ */
+ u32 luntbl_sa; /* bus address of this table */
+ u32 lun0_sa; /* bus address of LCB #0 */
+ /*
+ * Actual SYNC/WIDE IO registers value for this target.
+ * 'sval', 'wval' and 'uval' are read from SCRIPTS and
+ * so have alignment constraints.
+ */
+/*0*/ u_char uval; /* -> SCNTL4 register */
+/*1*/ u_char sval; /* -> SXFER io register */
+/*2*/ u_char filler1;
+/*3*/ u_char wval; /* -> SCNTL3 io register */
+};
+
+/*
+ * Target Control Block
+ */
+struct sym_tcb {
+ /*
+ * TCB header.
+ * Assumed at offset 0.
+ */
+/*0*/ struct sym_tcbh head;
+
+ /*
+ * LUN table used by the SCRIPTS processor.
+ * An array of bus addresses is used on reselection.
+ */
+ u32 *luntbl; /* LCBs bus address table */
+
+ /*
+ * LUN table used by the C code.
+ */
+ lcb_p lun0p; /* LCB of LUN #0 (usual case) */
+#if SYM_CONF_MAX_LUN > 1
+ lcb_p *lunmp; /* Other LCBs [1..MAX_LUN] */
+#endif
+
+ /*
+ * Bitmap that tells about LUNs that succeeded at least
+ * 1 IO and therefore assumed to be a real device.
+ * Avoid useless allocation of the LCB structure.
+ */
+ u32 lun_map[(SYM_CONF_MAX_LUN+31)/32];
+
+ /*
+ * Bitmap that tells about LUNs that haven't yet an LCB
+ * allocated (not discovered or LCB allocation failed).
+ */
+ u32 busy0_map[(SYM_CONF_MAX_LUN+31)/32];
+
+#ifdef SYM_HAVE_STCB
+ /*
+ * O/S specific data structure.
+ */
+ struct sym_stcb s;
+#endif
+
+ /*
+ * Transfer capabilities (SIP)
+ */
+ struct sym_tinfo tinfo;
+
+ /*
+ * Keep track of the CCB used for the negotiation in order
+ * to ensure that only 1 negotiation is queued at a time.
+ */
+ ccb_p nego_cp; /* CCB used for the nego */
+
+ /*
+ * Set when we want to reset the device.
+ */
+ u_char to_reset;
+
+ /*
+ * Other user settable limits and options.
+ * These limits are read from the NVRAM if present.
+ */
+ u_char usrflags;
+ u_short usrtags;
+
+#ifdef SYM_OPT_SNIFF_INQUIRY
+ /*
+ * Some minimal information from INQUIRY response.
+ */
+ u32 cmdq_map[(SYM_CONF_MAX_LUN+31)/32];
+ u_char inq_version;
+ u_char inq_byte7;
+ u_char inq_byte56;
+ u_char inq_byte7_valid;
+#endif
+
+};
+
+/*
+ * Global LCB HEADER.
+ *
+ * Due to lack of indirect addressing on earlier NCR chips,
+ * this substructure is copied from the LCB to a global
+ * address after selection.
+ * For SYMBIOS chips that support LOAD/STORE this copy is
+ * not needed and thus not performed.
+ */
+struct sym_lcbh {
+ /*
+ * SCRIPTS address jumped by SCRIPTS on reselection.
+ * For not probed logical units, this address points to
+ * SCRIPTS that deal with bad LU handling (must be at
+ * offset zero of the LCB for that reason).
+ */
+/*0*/ u32 resel_sa;
+
+ /*
+ * Task (bus address of a CCB) read from SCRIPTS that points
+ * to the unique ITL nexus allowed to be disconnected.
+ */
+ u32 itl_task_sa;
+
+ /*
+ * Task table bus address (read from SCRIPTS).
+ */
+ u32 itlq_tbl_sa;
+};
+
+/*
+ * Logical Unit Control Block
+ */
+struct sym_lcb {
+ /*
+ * TCB header.
+ * Assumed at offset 0.
+ */
+/*0*/ struct sym_lcbh head;
+
+ /*
+ * Task table read from SCRIPTS that contains pointers to
+ * ITLQ nexuses. The bus address read from SCRIPTS is
+ * inside the header.
+ */
+ u32 *itlq_tbl; /* Kernel virtual address */
+
+ /*
+ * Busy CCBs management.
+ */
+ u_short busy_itlq; /* Number of busy tagged CCBs */
+ u_short busy_itl; /* Number of busy untagged CCBs */
+
+ /*
+ * Circular tag allocation buffer.
+ */
+ u_short ia_tag; /* Tag allocation index */
+ u_short if_tag; /* Tag release index */
+ u_char *cb_tags; /* Circular tags buffer */
+
+ /*
+ * O/S specific data structure.
+ */
+#ifdef SYM_HAVE_SLCB
+ struct sym_slcb s;
+#endif
+
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ /*
+ * Optionnaly the driver can handle device queueing,
+ * and requeues internally command to redo.
+ */
+ SYM_QUEHEAD
+ waiting_ccbq;
+ SYM_QUEHEAD
+ started_ccbq;
+ int num_sgood;
+ u_short started_tags;
+ u_short started_no_tag;
+ u_short started_max;
+ u_short started_limit;
+#endif


+
+#ifdef SYM_OPT_LIMIT_COMMAND_REORDERING
+ /*

+ * Optionnaly the driver can try to prevent SCSI
+ * IOs from being too much reordering.
+ */
+ u_char tags_si; /* Current index to tags sum */
+ u_short tags_sum[2]; /* Tags sum counters */
+ u_short tags_since; /* # of tags since last switch */
+#endif
+
+ /*
+ * Set when we want to clear all tasks.
+ */
+ u_char to_clear;
+
+ /*
+ * Capabilities.
+ */
+ u_char user_flags;
+ u_char curr_flags;
+};
+
+/*
+ * Action from SCRIPTS on a task.
+ * Is part of the CCB, but is also used separately to plug
+ * error handling action to perform from SCRIPTS.
+ */
+struct sym_actscr {
+ u32 start; /* Jumped by SCRIPTS after selection */
+ u32 restart; /* Jumped by SCRIPTS on relection */
+};
+
+/*
+ * Phase mismatch context.
+ *
+ * It is part of the CCB and is used as parameters for the
+ * DATA pointer. We need two contexts to handle correctly the
+ * SAVED DATA POINTER.
+ */
+struct sym_pmc {
+ struct sym_tblmove sg; /* Updated interrupted SG block */
+ u32 ret; /* SCRIPT return address */
+};
+
+/*
+ * LUN control block lookup.
+ * We use a direct pointer for LUN #0, and a table of
+ * pointers which is only allocated for devices that support
+ * LUN(s) > 0.
+ */
+#if SYM_CONF_MAX_LUN <= 1
+#define sym_lp(np, tp, lun) (!lun) ? (tp)->lun0p : 0
+#else
+#define sym_lp(np, tp, lun) \
+ (!lun) ? (tp)->lun0p : (tp)->lunmp ? (tp)->lunmp[(lun)] : 0
+#endif
+
+/*
+ * Status are used by the host and the script processor.
+ *
+ * The last four bytes (status[4]) are copied to the
+ * scratchb register (declared as scr0..scr3) just after the
+ * select/reselect, and copied back just after disconnecting.
+ * Inside the script the XX_REG are used.
+ */
+
+/*
+ * Last four bytes (script)
+ */
+#define HX_REG scr0
+#define HX_PRT nc_scr0
+#define HS_REG scr1
+#define HS_PRT nc_scr1
+#define SS_REG scr2
+#define SS_PRT nc_scr2
+#define HF_REG scr3
+#define HF_PRT nc_scr3
+
+/*
+ * Last four bytes (host)
+ */
+#define host_xflags phys.head.status[0]
+#define host_status phys.head.status[1]
+#define ssss_status phys.head.status[2]
+#define host_flags phys.head.status[3]
+
+/*
+ * Host flags
+ */
+#define HF_IN_PM0 1u
+#define HF_IN_PM1 (1u<<1)
+#define HF_ACT_PM (1u<<2)
+#define HF_DP_SAVED (1u<<3)
+#define HF_SENSE (1u<<4)
+#define HF_EXT_ERR (1u<<5)
+#define HF_DATA_IN (1u<<6)
+#ifdef SYM_CONF_IARB_SUPPORT
+#define HF_HINT_IARB (1u<<7)
+#endif
+
+/*
+ * More host flags
+ */
+#if SYM_CONF_DMA_ADDRESSING_MODE == 2
+#define HX_DMAP_DIRTY (1u<<7)
+#endif
+
+/*
+ * Global CCB HEADER.
+ *
+ * Due to lack of indirect addressing on earlier NCR chips,
+ * this substructure is copied from the ccb to a global
+ * address after selection (or reselection) and copied back
+ * before disconnect.
+ * For SYMBIOS chips that support LOAD/STORE this copy is
+ * not needed and thus not performed.
+ */
+
+struct sym_ccbh {
+ /*
+ * Start and restart SCRIPTS addresses (must be at 0).
+ */
+/*0*/ struct sym_actscr go;
+
+ /*
+ * SCRIPTS jump address that deal with data pointers.
+ * 'savep' points to the position in the script responsible
+ * for the actual transfer of data.
+ * It's written on reception of a SAVE_DATA_POINTER message.
+ */
+ u32 savep; /* Jump address to saved data pointer */
+ u32 lastp; /* SCRIPTS address at end of data */
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+ u32 wlastp;
+#endif
+
+ /*
+ * Status fields.
+ */
+ u8 status[4];
+};
+
+/*
+ * GET/SET the value of the data pointer used by SCRIPTS.
+ *
+ * We must distinguish between the LOAD/STORE-based SCRIPTS
+ * that use directly the header in the CCB, and the NCR-GENERIC
+ * SCRIPTS that use the copy of the header in the HCB.
+ */
+#if SYM_CONF_GENERIC_SUPPORT
+#define sym_set_script_dp(np, cp, dp) \
+ do { \
+ if (np->features & FE_LDSTR) \
+ cp->phys.head.lastp = cpu_to_scr(dp); \
+ else \
+ np->ccb_head.lastp = cpu_to_scr(dp); \
+ } while (0)
+#define sym_get_script_dp(np, cp) \
+ scr_to_cpu((np->features & FE_LDSTR) ? \
+ cp->phys.head.lastp : np->ccb_head.lastp)
+#else
+#define sym_set_script_dp(np, cp, dp) \
+ do { \
+ cp->phys.head.lastp = cpu_to_scr(dp); \
+ } while (0)
+
+#define sym_get_script_dp(np, cp) (cp->phys.head.lastp)
+#endif
+
+/*
+ * Data Structure Block
+ *
+ * During execution of a ccb by the script processor, the
+ * DSA (data structure address) register points to this
+ * substructure of the ccb.
+ */
+struct sym_dsb {
+ /*
+ * CCB header.
+ * Also assumed at offset 0 of the sym_ccb structure.
+ */
+/*0*/ struct sym_ccbh head;
+
+ /*
+ * Phase mismatch contexts.
+ * We need two to handle correctly the SAVED DATA POINTER.
+ * MUST BOTH BE AT OFFSET < 256, due to using 8 bit arithmetic
+ * for address calculation from SCRIPTS.
+ */
+ struct sym_pmc pm0;
+ struct sym_pmc pm1;
+
+ /*
+ * Table data for Script
+ */
+ struct sym_tblsel select;
+ struct sym_tblmove smsg;
+ struct sym_tblmove smsg_ext;
+ struct sym_tblmove cmd;
+ struct sym_tblmove sense;
+ struct sym_tblmove wresid;
+ struct sym_tblmove data [SYM_CONF_MAX_SG];
+};
+
+/*
+ * Our Command Control Block
+ */
+struct sym_ccb {
+ /*
+ * This is the data structure which is pointed by the DSA
+ * register when it is executed by the script processor.
+ * It must be the first entry.
+ */
+ struct sym_dsb phys;
+
+ /*
+ * Pointer to CAM ccb and related stuff.
+ */
+ cam_ccb_p cam_ccb; /* CAM scsiio ccb */
+ u8 cdb_buf[16]; /* Copy of CDB */
+ u8 *sns_bbuf; /* Bounce buffer for sense data */
+#ifndef SYM_SNS_BBUF_LEN
+#define SYM_SNS_BBUF_LEN (32)
+#endif
+ int data_len; /* Total data length */
+ int segments; /* Number of SG segments */
+
+ u8 order; /* Tag type (if tagged command) */
+
+ /*
+ * Miscellaneous status'.
+ */
+ u_char nego_status; /* Negotiation status */
+ u_char xerr_status; /* Extended error flags */
+ u32 extra_bytes; /* Extraneous bytes transferred */
+
+ /*
+ * Message areas.
+ * We prepare a message to be sent after selection.
+ * We may use a second one if the command is rescheduled
+ * due to CHECK_CONDITION or COMMAND TERMINATED.
+ * Contents are IDENTIFY and SIMPLE_TAG.
+ * While negotiating sync or wide transfer,
+ * a SDTR or WDTR message is appended.
+ */
+ u_char scsi_smsg [12];
+ u_char scsi_smsg2[12];
+
+ /*
+ * Auto request sense related fields.
+ */
+ u_char sensecmd[6]; /* Request Sense command */
+ u_char sv_scsi_status; /* Saved SCSI status */
+ u_char sv_xerr_status; /* Saved extended status */
+ int sv_resid; /* Saved residual */
+
+ /*
+ * O/S specific data structure.
+ */
+#ifdef SYM_HAVE_SCCB
+ struct sym_sccb s;
+#endif
+ /*
+ * Other fields.
+ */
+#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
+ SYM_QUEHEAD tmo_linkq; /* Optional timeout handling */
+ u_int tmo_clock; /* (link and dealine value) */
+#endif
+ u32 ccb_ba; /* BUS address of this CCB */
+ u_short tag; /* Tag for this transfer */
+ /* NO_TAG means no tag */
+ u_char target;
+ u_char lun;
+ ccb_p link_ccbh; /* Host adapter CCB hash chain */
+ SYM_QUEHEAD
+ link_ccbq; /* Link to free/busy CCB queue */
+ u32 startp; /* Initial data pointer */
+ u32 goalp; /* Expected last data pointer */
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+ u32 wgoalp;
+#endif
+ int ext_sg; /* Extreme data pointer, used */
+ int ext_ofs; /* to calculate the residual. */
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ SYM_QUEHEAD
+ link2_ccbq; /* Link for device queueing */
+ u_char started; /* CCB queued to the squeue */
+#endif
+ u_char to_abort; /* Want this IO to be aborted */
+#ifdef SYM_OPT_LIMIT_COMMAND_REORDERING
+ u_char tags_si; /* Lun tags sum index (0,1) */
+#endif
+};
+
+#define CCB_BA(cp,lbl) (cp->ccb_ba + offsetof(struct sym_ccb, lbl))
+
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+#define sym_goalp(cp) ((cp->host_flags & HF_DATA_IN) ? cp->goalp : cp->wgoalp)
+#else
+#define sym_goalp(cp) (cp->goalp)
+#endif
+
+/*
+ * Host Control Block
+ */
+struct sym_hcb {
+ /*
+ * Global headers.
+ * Due to poorness of addressing capabilities, earlier
+ * chips (810, 815, 825) copy part of the data structures
+ * (CCB, TCB and LCB) in fixed areas.
+ */
+#if SYM_CONF_GENERIC_SUPPORT
+ struct sym_ccbh ccb_head;
+ struct sym_tcbh tcb_head;
+ struct sym_lcbh lcb_head;
+#endif
+ /*
+ * Idle task and invalid task actions and
+ * their bus addresses.
+ */
+ struct sym_actscr idletask, notask, bad_itl, bad_itlq;
+ u32 idletask_ba, notask_ba, bad_itl_ba, bad_itlq_ba;
+
+ /*
+ * Dummy lun table to protect us against target
+ * returning bad lun number on reselection.
+ */
+ u32 *badluntbl; /* Table physical address */
+ u32 badlun_sa; /* SCRIPT handler BUS address */
+
+ /*
+ * Bus address of this host control block.
+ */
+ u32 hcb_ba;
+
+ /*
+ * Bit 32-63 of the on-chip RAM bus address in LE format.
+ * The START_RAM64 script loads the MMRS and MMWS from this
+ * field.
+ */
+ u32 scr_ram_seg;
+
+ /*
+ * Initial value of some IO register bits.
+ * These values are assumed to have been set by BIOS, and may
+ * be used to probe adapter implementation differences.
+ */
+ u_char sv_scntl0, sv_scntl3, sv_dmode, sv_dcntl, sv_ctest3, sv_ctest4,
+ sv_ctest5, sv_gpcntl, sv_stest2, sv_stest4, sv_scntl4,
+ sv_stest1;
+
+ /*
+ * Actual initial value of IO register bits used by the
+ * driver. They are loaded at initialisation according to
+ * features that are to be enabled/disabled.
+ */
+ u_char rv_scntl0, rv_scntl3, rv_dmode, rv_dcntl, rv_ctest3, rv_ctest4,
+ rv_ctest5, rv_stest2, rv_ccntl0, rv_ccntl1, rv_scntl4;
+
+ /*
+ * Target data.
+ */
+ struct sym_tcb target[SYM_CONF_MAX_TARGET];
+
+ /*
+ * Target control block bus address array used by the SCRIPT
+ * on reselection.
+ */
+ u32 *targtbl;
+ u32 targtbl_ba;
+
+ /*
+ * DMA pool handle for this HBA.
+ */
+#ifdef SYM_OPT_BUS_DMA_ABSTRACTION
+ m_pool_ident_t bus_dmat;
+#endif
+
+ /*
+ * O/S specific data structure
+ */
+ struct sym_shcb s;
+
+ /*
+ * Physical bus addresses of the chip.
+ */
+ u32 mmio_ba; /* MMIO 32 bit BUS address */
+ int mmio_ws; /* MMIO Window size */
+
+ u32 ram_ba; /* RAM 32 bit BUS address */
+ int ram_ws; /* RAM window size */
+
+ /*
+ * SCRIPTS virtual and physical bus addresses.
+ * 'script' is loaded in the on-chip RAM if present.
+ * 'scripth' stays in main memory for all chips except the
+ * 53C895A, 53C896 and 53C1010 that provide 8K on-chip RAM.
+ */
+ u_char *scripta0; /* Copy of scripts A, B, Z */
+ u_char *scriptb0;
+ u_char *scriptz0;
+ u32 scripta_ba; /* Actual scripts A, B, Z */
+ u32 scriptb_ba; /* 32 bit bus addresses. */
+ u32 scriptz_ba;
+ u_short scripta_sz; /* Actual size of script A, B, Z*/
+ u_short scriptb_sz;
+ u_short scriptz_sz;
+
+ /*
+ * Bus addresses, setup and patch methods for
+ * the selected firmware.
+ */
+ struct sym_fwa_ba fwa_bas; /* Useful SCRIPTA bus addresses */
+ struct sym_fwb_ba fwb_bas; /* Useful SCRIPTB bus addresses */
+ struct sym_fwz_ba fwz_bas; /* Useful SCRIPTZ bus addresses */
+ void (*fw_setup)(hcb_p np, struct sym_fw *fw);
+ void (*fw_patch)(hcb_p np);
+ char *fw_name;
+
+ /*
+ * General controller parameters and configuration.
+ */


+ u_short device_id; /* PCI device id */

+ u_char revision_id; /* PCI device revision id */
+ u_int features; /* Chip features map */
+ u_char myaddr; /* SCSI id of the adapter */
+ u_char maxburst; /* log base 2 of dwords burst */
+ u_char maxwide; /* Maximum transfer width */
+ u_char minsync; /* Min sync period factor (ST) */
+ u_char maxsync; /* Max sync period factor (ST) */
+ u_char maxoffs; /* Max scsi offset (ST) */
+ u_char minsync_dt; /* Min sync period factor (DT) */
+ u_char maxsync_dt; /* Max sync period factor (DT) */
+ u_char maxoffs_dt; /* Max scsi offset (DT) */
+ u_char multiplier; /* Clock multiplier (1,2,4) */
+ u_char clock_divn; /* Number of clock divisors */
+ u32 clock_khz; /* SCSI clock frequency in KHz */
+ u32 pciclk_khz; /* Estimated PCI clock in KHz */
+ /*
+ * Start queue management.
+ * It is filled up by the host processor and accessed by the
+ * SCRIPTS processor in order to start SCSI commands.
+ */
+ volatile /* Prevent code optimizations */
+ u32 *squeue; /* Start queue virtual address */
+ u32 squeue_ba; /* Start queue BUS address */
+ u_short squeueput; /* Next free slot of the queue */
+ u_short actccbs; /* Number of allocated CCBs */
+
+ /*
+ * Command completion queue.
+ * It is the same size as the start queue to avoid overflow.
+ */
+ u_short dqueueget; /* Next position to scan */
+ volatile /* Prevent code optimizations */
+ u32 *dqueue; /* Completion (done) queue */
+ u32 dqueue_ba; /* Done queue BUS address */
+
+ /*
+ * Miscellaneous buffers accessed by the scripts-processor.
+ * They shall be DWORD aligned, because they may be read or
+ * written with a script command.
+ */
+ u_char msgout[8]; /* Buffer for MESSAGE OUT */
+ u_char msgin [8]; /* Buffer for MESSAGE IN */
+ u32 lastmsg; /* Last SCSI message sent */
+ u32 scratch; /* Scratch for SCSI receive */
+ /* Also used for cache test */
+ /*
+ * Miscellaneous configuration and status parameters.
+ */
+ u_char usrflags; /* Miscellaneous user flags */
+ u_char scsi_mode; /* Current SCSI BUS mode */
+ u_char verbose; /* Verbosity for this controller*/
+
+ /*
+ * CCB lists and queue.
+ */
+ ccb_p ccbh[CCB_HASH_SIZE]; /* CCB hashed by DSA value */
+ SYM_QUEHEAD free_ccbq; /* Queue of available CCBs */
+ SYM_QUEHEAD busy_ccbq; /* Queue of busy CCBs */
+
+ /*
+ * During error handling and/or recovery,
+ * active CCBs that are to be completed with
+ * error or requeued are moved from the busy_ccbq
+ * to the comp_ccbq prior to completion.
+ */
+ SYM_QUEHEAD comp_ccbq;
+
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ SYM_QUEHEAD dummy_ccbq;
+#endif
+ /*
+ * Optional handling of IO timeouts.
+ */
+#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
+ SYM_QUEHEAD tmo0_ccbq;
+ SYM_QUEHEAD *tmo_ccbq; /* [2*SYM_TIMEOUT_ORDER_MAX] */
+ u_int tmo_clock;
+ u_int tmo_actq;
+#endif
+
+ /*
+ * IMMEDIATE ARBITRATION (IARB) control.
+ *
+ * We keep track in 'last_cp' of the last CCB that has been
+ * queued to the SCRIPTS processor and clear 'last_cp' when
+ * this CCB completes. If last_cp is not zero at the moment
+ * we queue a new CCB, we set a flag in 'last_cp' that is
+ * used by the SCRIPTS as a hint for setting IARB.
+ * We donnot set more than 'iarb_max' consecutive hints for
+ * IARB in order to leave devices a chance to reselect.
+ * By the way, any non zero value of 'iarb_max' is unfair. :)
+ */
+#ifdef SYM_CONF_IARB_SUPPORT
+ u_short iarb_max; /* Max. # consecutive IARB hints*/
+ u_short iarb_count; /* Actual # of these hints */
+ ccb_p last_cp;
+#endif
+
+ /*
+ * Command abort handling.
+ * We need to synchronize tightly with the SCRIPTS
+ * processor in order to handle things correctly.
+ */
+ u_char abrt_msg[4]; /* Message to send buffer */
+ struct sym_tblmove abrt_tbl; /* Table for the MOV of it */
+ struct sym_tblsel abrt_sel; /* Sync params for selection */
+ u_char istat_sem; /* Tells the chip to stop (SEM) */
+
+ /*
+ * 64 bit DMA handling.
+ */
+#if SYM_CONF_DMA_ADDRESSING_MODE != 0
+ u_char use_dac; /* Use PCI DAC cycles */
+#if SYM_CONF_DMA_ADDRESSING_MODE == 2
+ u_char dmap_dirty; /* Dma segments registers dirty */
+ u32 dmap_bah[SYM_DMAP_SIZE];/* Segment registers map */
+#endif
+#endif
+};
+
+#define HCB_BA(np, lbl) (np->hcb_ba + offsetof(struct sym_hcb, lbl))
+
+/*
+ * NVRAM reading (sym_nvram.c).
+ */
+void sym_nvram_setup_host (hcb_p np, struct sym_nvram *nvram);
+void sym_nvram_setup_target (hcb_p np, int target, struct sym_nvram *nvp);
+int sym_read_nvram (sdev_p np, struct sym_nvram *nvp);
+
+/*
+ * FIRMWARES (sym_fw.c)
+ */
+struct sym_fw * sym_find_firmware(struct sym_pci_chip *chip);
+void sym_fw_bind_script (hcb_p np, u32 *start, int len);
+
+/*
+ * Driver methods called from O/S specific code.
+ */
+char *sym_driver_name(void);
+void sym_print_xerr(ccb_p cp, int x_status);
+int sym_reset_scsi_bus(hcb_p np, int enab_int);
+struct sym_pci_chip *
+sym_lookup_pci_chip_table (u_short device_id, u_char revision);
+void sym_put_start_queue(hcb_p np, ccb_p cp);
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn);
+#endif
+void sym_start_up (hcb_p np, int reason);
+void sym_interrupt (hcb_p np);
+void sym_flush_comp_queue(hcb_p np, int cam_status);
+int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task);
+ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order);
+void sym_free_ccb (hcb_p np, ccb_p cp);
+lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln);
+int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp);
+int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out);
+int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
+int sym_reset_scsi_target(hcb_p np, int target);
+void sym_hcb_free(hcb_p np);
+
+#ifdef SYM_OPT_NVRAM_PRE_READ
+int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram);
+#else
+int sym_hcb_attach(hcb_p np, struct sym_fw *fw);
+#endif
+
+/*
+ * Optionnaly, the driver may handle IO timeouts.
+ */
+#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
+int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
+void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks);
+static void __inline sym_untimeout_ccb(hcb_p np, ccb_p cp)
+{
+ sym_remque(&cp->tmo_linkq);


+ sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
+}

+void sym_clock(hcb_p np);
+#endif /* SYM_OPT_HANDLE_IO_TIMEOUT */
+
+/*
+ * Optionnaly, the driver may provide a function
+ * to announce transfer rate changes.
+ */
+#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
+void sym_announce_transfer_rate(hcb_p np, int target);
+#endif
+
+/*
+ * Optionnaly, the driver may sniff inquiry data.
+ */
+#ifdef SYM_OPT_SNIFF_INQUIRY
+#define INQ7_CMDQ (0x02)
+#define INQ7_SYNC (0x10)
+#define INQ7_WIDE16 (0x20)
+
+#define INQ56_CLOCKING (3<<2)
+#define INQ56_ST_ONLY (0<<2)
+#define INQ56_DT_ONLY (1<<2)
+#define INQ56_ST_DT (3<<2)
+
+void sym_update_trans_settings(hcb_p np, tcb_p tp);
+int
+__sym_sniff_inquiry(hcb_p np, u_char tn, u_char ln,
+ u_char *inq_data, int inq_len);
+#endif
+
+
+/*
+ * Build a scatter/gather entry.
+ *
+ * For 64 bit systems, we use the 8 upper bits of the size field
+ * to provide bus address bits 32-39 to the SCRIPTS processor.
+ * This allows the 895A, 896, 1010 to address up to 1 TB of memory.
+ */
+
+#if SYM_CONF_DMA_ADDRESSING_MODE == 0
+#define sym_build_sge(np, data, badd, len) \
+do { \
+ (data)->addr = cpu_to_scr(badd); \
+ (data)->size = cpu_to_scr(len); \
+} while (0)
+#elif SYM_CONF_DMA_ADDRESSING_MODE == 1
+#define sym_build_sge(np, data, badd, len) \
+do { \
+ (data)->addr = cpu_to_scr(badd); \
+ (data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len); \
+} while (0)
+#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
+int sym_lookup_dmap(hcb_p np, u32 h, int s);
+static __inline void
+sym_build_sge(hcb_p np, struct sym_tblmove *data, u64 badd, int len)
+{
+ u32 h = (badd>>32);
+ int s = (h&SYM_DMAP_MASK);
+
+ if (h != np->dmap_bah[s])
+ goto bad;
+good:
+ (data)->addr = cpu_to_scr(badd);
+ (data)->size = cpu_to_scr((s<<24) + len);
+ return;
+bad:
+ s = sym_lookup_dmap(np, h, s);
+ goto good;
+}
+#else
+#error "Unsupported DMA addressing mode"
+#endif
+
+/*
+ * Set up data pointers used by SCRIPTS.
+ * Called from O/S specific code.
+ */
+static void __inline
+sym_setup_data_pointers(hcb_p np, ccb_p cp, int dir)
+{
+ u32 lastp, goalp;
+
+ /*
+ * No segments means no data.
+ */
+ if (!cp->segments)
+ dir = CAM_DIR_NONE;
+
+ /*
+ * Set the data pointer.
+ */
+ switch(dir) {
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+ case CAM_DIR_UNKNOWN:
+#endif
+ case CAM_DIR_OUT:
+ goalp = SCRIPTA_BA (np, data_out2) + 8;
+ lastp = goalp - 8 - (cp->segments * (2*4));
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+ cp->wgoalp = cpu_to_scr(goalp);
+ if (dir != CAM_DIR_UNKNOWN)
+ break;
+ cp->phys.head.wlastp = cpu_to_scr(lastp);


+ /* fall through */

+#else
+ break;
+#endif
+ case CAM_DIR_IN:
+ cp->host_flags |= HF_DATA_IN;
+ goalp = SCRIPTA_BA (np, data_in2) + 8;
+ lastp = goalp - 8 - (cp->segments * (2*4));
+ break;
+ case CAM_DIR_NONE:
+ default:
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+ cp->host_flags |= HF_DATA_IN;
+#endif
+ lastp = goalp = SCRIPTB_BA (np, no_data);


+ break;
+ }
+
+ /*

+ * Set all pointers values needed by SCRIPTS.
+ */
+ cp->phys.head.lastp = cpu_to_scr(lastp);
+ cp->phys.head.savep = cpu_to_scr(lastp);
+ cp->startp = cp->phys.head.savep;
+ cp->goalp = cpu_to_scr(goalp);
+
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+ /*
+ * If direction is unknown, start at data_io.
+ */
+ if (dir == CAM_DIR_UNKNOWN)
+ cp->phys.head.savep = cpu_to_scr(SCRIPTB_BA (np, data_io));
+#endif
+}
+
+/*
+ * MEMORY ALLOCATOR.
+ */
+
+/*
+ * Shortest memory chunk is (1<<SYM_MEM_SHIFT), currently 16.
+ * Actual allocations happen as SYM_MEM_CLUSTER_SIZE sized.
+ * (1 PAGE at a time is just fine).
+ */
+#define SYM_MEM_SHIFT 4
+#define SYM_MEM_CLUSTER_SIZE (1UL << SYM_MEM_CLUSTER_SHIFT)
+#define SYM_MEM_CLUSTER_MASK (SYM_MEM_CLUSTER_SIZE-1)
+
+/*
+ * Link between free memory chunks of a given size.
+ */
+typedef struct sym_m_link {
+ struct sym_m_link *next;
+} *m_link_p;
+
+/*
+ * Virtual to bus physical translation for a given cluster.
+ * Such a structure is only useful with DMA abstraction.
+ */
+#ifdef SYM_OPT_BUS_DMA_ABSTRACTION
+typedef struct sym_m_vtob { /* Virtual to Bus address translation */
+ struct sym_m_vtob *next;
+#ifdef SYM_HAVE_M_SVTOB
+ struct sym_m_svtob s; /* OS specific data structure */
+#endif
+ m_addr_t vaddr; /* Virtual address */
+ m_addr_t baddr; /* Bus physical address */
+} *m_vtob_p;
+
+/* Hash this stuff a bit to speed up translations */
+#define VTOB_HASH_SHIFT 5
+#define VTOB_HASH_SIZE (1UL << VTOB_HASH_SHIFT)
+#define VTOB_HASH_MASK (VTOB_HASH_SIZE-1)
+#define VTOB_HASH_CODE(m) \
+ ((((m_addr_t) (m)) >> SYM_MEM_CLUSTER_SHIFT) & VTOB_HASH_MASK)
+#endif /* SYM_OPT_BUS_DMA_ABSTRACTION */
+
+/*
+ * Memory pool of a given kind.
+ * Ideally, we want to use:
+ * 1) 1 pool for memory we donnot need to involve in DMA.
+ * 2) The same pool for controllers that require same DMA
+ * constraints and features.
+ * The OS specific m_pool_id_t thing and the sym_m_pool_match()
+ * method are expected to tell the driver about.
+ */
+typedef struct sym_m_pool {
+#ifdef SYM_OPT_BUS_DMA_ABSTRACTION
+ m_pool_ident_t dev_dmat; /* Identifies the pool (see above) */
+ m_addr_t (*get_mem_cluster)(struct sym_m_pool *);
+#ifdef SYM_MEM_FREE_UNUSED
+ void (*free_mem_cluster)(struct sym_m_pool *, m_addr_t);
+#endif
+#define M_GET_MEM_CLUSTER() mp->get_mem_cluster(mp)
+#define M_FREE_MEM_CLUSTER(p) mp->free_mem_cluster(mp, p)
+#ifdef SYM_HAVE_M_SPOOL
+ struct sym_m_spool s; /* OS specific data structure */
+#endif
+ int nump;
+ m_vtob_p vtob[VTOB_HASH_SIZE];
+ struct sym_m_pool *next;
+#else
+#define M_GET_MEM_CLUSTER() sym_get_mem_cluster()
+#define M_FREE_MEM_CLUSTER(p) sym_free_mem_cluster(p)
+#endif /* SYM_OPT_BUS_DMA_ABSTRACTION */
+ struct sym_m_link h[SYM_MEM_CLUSTER_SHIFT - SYM_MEM_SHIFT + 1];
+} *m_pool_p;
+
+/*
+ * Alloc and free non DMAable memory.
+ */
+void sym_mfree_unlocked(void *ptr, int size, char *name);
+void *sym_calloc_unlocked(int size, char *name);
+
+/*
+ * Alloc, free and translate addresses to bus physical
+ * for DMAable memory.
+ */
+#ifdef SYM_OPT_BUS_DMA_ABSTRACTION
+void *__sym_calloc_dma_unlocked(m_pool_ident_t dev_dmat, int size, char *name);
+void
+__sym_mfree_dma_unlocked(m_pool_ident_t dev_dmat, void *m,int size, char *name);
+u32 __vtobus_unlocked(m_pool_ident_t dev_dmat, void *m);
+#endif
+
+/*
+ * Verbs used by the driver code for DMAable memory handling.
+ * The _uvptv_ macro avoids a nasty warning about pointer to volatile
+ * being discarded.
+ */
+#define _uvptv_(p) ((void *)((u_long)(p)))
+
+#define _sym_calloc_dma(np, l, n) __sym_calloc_dma(np->bus_dmat, l, n)
+#define _sym_mfree_dma(np, p, l, n) \
+ __sym_mfree_dma(np->bus_dmat, _uvptv_(p), l, n)
+#define sym_calloc_dma(l, n) _sym_calloc_dma(np, l, n)
+#define sym_mfree_dma(p, l, n) _sym_mfree_dma(np, p, l, n)
+#define _vtobus(np, p) __vtobus(np->bus_dmat, _uvptv_(p))
+#define vtobus(p) _vtobus(np, p)
+
+/*
+ * Override some function names.
+ */
+#define PRINT_ADDR sym_print_addr
+#define PRINT_TARGET sym_print_target
+#define PRINT_LUN sym_print_lun


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

echo 'End of part 067'
echo 'File patch-2.4.15 is continued in part 068'
echo "068" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:38 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part062

#!/bin/sh -x
# this is part 062 of a 115 - part archive


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

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

+ u32 start [ 14];
+ u32 getjob_begin [ 4];
+ u32 getjob_end [ 4];
+#ifdef SYM_CONF_TARGET_ROLE_SUPPORT
+ u32 select [ 6];
+#else
+ u32 select [ 4];
+#endif
+#if SYM_CONF_DMA_ADDRESSING_MODE == 2
+ u32 is_dmap_dirty [ 4];
+#endif
+ u32 wf_sel_done [ 2];
+ u32 sel_done [ 2];


+ u32 send_ident [ 2];
+#ifdef SYM_CONF_IARB_SUPPORT
+ u32 select2 [ 8];
+#else
+ u32 select2 [ 2];
+#endif
+ u32 command [ 2];
+ u32 dispatch [ 28];
+ u32 sel_no_cmd [ 10];
+ u32 init [ 6];
+ u32 clrack [ 4];

+ u32 datai_done [ 10];
+ u32 datai_done_wsr [ 20];
+ u32 datao_done [ 10];
+ u32 datao_done_wss [ 6];
+ u32 datai_phase [ 4];
+ u32 datao_phase [ 6];


+ u32 msg_in [ 2];
+ u32 msg_in2 [ 10];
+#ifdef SYM_CONF_IARB_SUPPORT
+ u32 status [ 14];
+#else
+ u32 status [ 10];
+#endif
+ u32 complete [ 6];

+ u32 complete2 [ 12];
+ u32 done [ 14];
+ u32 done_end [ 2];
+ u32 complete_error [ 4];
+ u32 save_dp [ 12];
+ u32 restore_dp [ 8];
+ u32 disconnect [ 12];


+#ifdef SYM_CONF_IARB_SUPPORT
+ u32 idle [ 4];
+#else
+ u32 idle [ 2];
+#endif
+#ifdef SYM_CONF_IARB_SUPPORT

+ u32 ungetjob [ 6];
+#else
+ u32 ungetjob [ 4];


+#endif
+#ifdef SYM_CONF_TARGET_ROLE_SUPPORT
+ u32 reselect [ 4];
+#else
+ u32 reselect [ 2];
+#endif

+ u32 reselected [ 22];
+ u32 resel_scntl4 [ 20];
+ u32 resel_lun0 [ 6];
+#if SYM_CONF_MAX_TASK*4 > 512
+ u32 resel_tag [ 26];
+#elif SYM_CONF_MAX_TASK*4 > 256
+ u32 resel_tag [ 20];
+#else
+ u32 resel_tag [ 16];
+#endif


+ u32 resel_dsa [ 2];
+ u32 resel_dsa1 [ 4];

+ u32 resel_no_tag [ 6];


+ u32 data_in [SYM_CONF_MAX_SG * 2];
+ u32 data_in2 [ 4];
+ u32 data_out [SYM_CONF_MAX_SG * 2];
+ u32 data_out2 [ 4];
+ u32 pm0_data [ 12];
+ u32 pm0_data_out [ 6];

+ u32 pm0_data_end [ 6];


+ u32 pm1_data [ 12];
+ u32 pm1_data_out [ 6];

+ u32 pm1_data_end [ 6];


+};
+
+/*
+ * Script fragments which stay in main memory for all chips
+ * except for chips that support 8K on-chip RAM.
+ */
+struct SYM_FWB_SCR {

+ u32 start64 [ 2];


+ u32 no_data [ 2];
+#ifdef SYM_CONF_TARGET_ROLE_SUPPORT
+ u32 sel_for_abort [ 18];
+#else
+ u32 sel_for_abort [ 16];
+#endif
+ u32 sel_for_abort_1 [ 2];
+ u32 msg_in_etc [ 12];

+ u32 msg_received [ 4];
+ u32 msg_weird_seen [ 4];
+ u32 msg_extended [ 20];


+ u32 msg_bad [ 6];
+ u32 msg_weird [ 4];
+ u32 msg_weird1 [ 8];
+
+ u32 wdtr_resp [ 6];
+ u32 send_wdtr [ 4];
+ u32 sdtr_resp [ 6];
+ u32 send_sdtr [ 4];
+ u32 ppr_resp [ 6];
+ u32 send_ppr [ 4];
+ u32 nego_bad_phase [ 4];
+ u32 msg_out [ 4];
+ u32 msg_out_done [ 4];

+ u32 data_ovrun [ 2];


+ u32 data_ovrun1 [ 22];
+ u32 data_ovrun2 [ 8];
+ u32 abort_resel [ 16];
+ u32 resend_ident [ 4];
+ u32 ident_break [ 4];
+ u32 ident_break_atn [ 4];
+ u32 sdata_in [ 6];
+ u32 resel_bad_lun [ 4];
+ u32 bad_i_t_l [ 4];
+ u32 bad_i_t_l_q [ 4];

+ u32 bad_status [ 6];
+ u32 pm_handle [ 20];
+ u32 pm_handle1 [ 4];
+ u32 pm_save [ 4];
+ u32 pm0_save [ 12];
+ u32 pm_save_end [ 4];
+ u32 pm1_save [ 14];
+
+ /* WSR handling */
+ u32 pm_wsr_handle [ 38];


+ u32 wsr_ma_helper [ 4];
+
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+ /* Unknown direction handling */
+ u32 data_io [ 2];

+ u32 data_io_in [ 2];
+ u32 data_io_com [ 6];
+ u32 data_io_out [ 8];


+#endif
+ /* Data area */
+ u32 zero [ 1];
+ u32 scratch [ 1];

+ u32 pm0_data_addr [ 1];
+ u32 pm1_data_addr [ 1];
+ u32 done_pos [ 1];


+ u32 startpos [ 1];
+ u32 targtbl [ 1];
+};
+
+/*
+ * Script fragments used at initialisations.
+ * Only runs out of main memory.
+ */
+struct SYM_FWZ_SCR {

+ u32 snooptest [ 6];


+ u32 snoopend [ 2];
+#ifdef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ u32 start_ram [ 1];
+ u32 scripta0_ba [ 4];

+ u32 start_ram64 [ 3];
+ u32 scripta0_ba64 [ 3];
+ u32 scriptb0_ba64 [ 6];
+ u32 ram_seg64 [ 1];

+ SCR_LOAD_ABS (scratcha, 4),
+ PADDR_B (startpos),


+ SCR_INT ^ IFTRUE (MASK (SEM, SEM)),
+ SIR_SCRIPT_STOPPED,
+ /*
+ * Start the next job.
+ *
+ * @DSA = start point for this job.
+ * SCRATCHA = address of this job in the start queue.
+ *
+ * We will restore startpos with SCRATCHA if we fails the
+ * arbitration or if it is the idle job.
+ *
+ * The below GETJOB_BEGIN to GETJOB_END section of SCRIPTS
+ * is a critical path. If it is partially executed, it then
+ * may happen that the job address is not yet in the DSA
+ * and the the next queue position points to the next JOB.
+ */

+ SCR_LOAD_ABS (dsa, 4),
+ PADDR_B (startpos),
+ SCR_LOAD_REL (temp, 4),
+ 4,
+}/*-------------------------< GETJOB_BEGIN >---------------------*/,{
+ SCR_STORE_ABS (temp, 4),
+ PADDR_B (startpos),
+ SCR_LOAD_REL (dsa, 4),
+ 0,
+}/*-------------------------< GETJOB_END >-----------------------*/,{
+ SCR_LOAD_REL (temp, 4),
+ 0,

+ /*
+ * Initialize the status registers
+ */
+ SCR_LOAD_REL (scr0, 4),
+ offsetof (struct sym_ccb, phys.head.status),
+ /*
+ * We may need help from CPU if the DMA segment
+ * registers aren't up-to-date for this IO.
+ * Patched with NOOP for chips that donnot
+ * support DAC addressing.


+ */
+#if SYM_CONF_DMA_ADDRESSING_MODE == 2

+}/*-------------------------< IS_DMAP_DIRTY >--------------------*/,{
+ SCR_FROM_REG (HX_REG),
+ 0,
+ SCR_INT ^ IFTRUE (MASK (HX_DMAP_DIRTY, HX_DMAP_DIRTY)),
+ SIR_DMAP_DIRTY,
+#endif


+}/*-------------------------< WF_SEL_DONE >----------------------*/,{
+ SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+ SIR_SEL_ATN_NO_MSG_OUT,

+}/*-------------------------< SEL_DONE >-------------------------*/,{
+ /*
+ * C1010-33 errata work-around.
+ * Due to a race, the SCSI core may not have
+ * loaded SCNTL3 on SEL_TBL instruction.
+ * We reload it once phase is stable.
+ * Patched with a NOOP for other chips.
+ */
+ SCR_LOAD_REL (scntl3, 1),
+ offsetof(struct sym_dsb, select.sel_scntl3),

+ SCR_STORE_REL (temp, 4),
+ offsetof (struct sym_ccb, phys.head.lastp),

+ SCR_STORE_REL (temp, 4),
+ offsetof (struct sym_ccb, phys.head.lastp),

+ SCR_LOAD_REL (temp, 4),
+ offsetof (struct sym_ccb, phys.head.lastp),


+ SCR_RETURN,
+ 0,
+}/*-------------------------< DATAO_PHASE >----------------------*/,{
+ /*

+ * C1010-66 errata work-around.
+ * Extra clocks of data hold must be inserted
+ * in DATA OUT phase on 33 MHz PCI BUS.
+ * Patched with a NOOP for other chips.
+ */
+ SCR_REG_REG (scntl4, SCR_OR, (XCLKH_DT|XCLKH_ST)),
+ 0,
+ /*


+ * Jump to current pointer.
+ */

+ SCR_LOAD_REL (temp, 4),
+ offsetof (struct sym_ccb, phys.head.lastp),

+ SCR_STORE_REL (scr0, 4),
+ offsetof (struct sym_ccb, phys.head.status),


+ /*
+ * Some bridges may reorder DMA writes to memory.
+ * We donnot want the CPU to deal with completions
+ * without all the posted write having been flushed
+ * to memory. This DUMMY READ should flush posted
+ * buffers prior to the CPU having to deal with
+ * completions.
+ */

+ SCR_LOAD_REL (scr0, 4), /* DUMMY READ */
+ offsetof (struct sym_ccb, phys.head.status),
+
+ /*


+ * If command resulted in not GOOD status,
+ * call the C code if needed.
+ */
+ SCR_FROM_REG (SS_REG),
+ 0,
+ SCR_CALL ^ IFFALSE (DATA (S_GOOD)),
+ PADDR_B (bad_status),
+ /*
+ * If we performed an auto-sense, call
+ * the C code to synchronyze task aborts
+ * with UNIT ATTENTION conditions.
+ */
+ SCR_FROM_REG (HF_REG),
+ 0,
+ SCR_JUMP ^ IFFALSE (MASK (0 ,(HF_SENSE|HF_EXT_ERR))),
+ PADDR_A (complete_error),
+}/*-------------------------< DONE >-----------------------------*/,{
+ /*
+ * Copy the DSA to the DONE QUEUE and
+ * signal completion to the host.
+ * If we are interrupted between DONE
+ * and DONE_END, we must reset, otherwise
+ * the completed CCB may be lost.
+ */

+ SCR_STORE_ABS (dsa, 4),
+ PADDR_B (scratch),
+ SCR_LOAD_ABS (dsa, 4),
+ PADDR_B (done_pos),
+ SCR_LOAD_ABS (scratcha, 4),
+ PADDR_B (scratch),
+ SCR_STORE_REL (scratcha, 4),
+ 0,
+ /*


+ * The instruction below reads the DONE QUEUE next
+ * free position from memory.
+ * In addition it ensures that all PCI posted writes
+ * are flushed and so the DSA value of the done
+ * CCB is visible by the CPU before INTFLY is raised.
+ */

+ SCR_LOAD_REL (scratcha, 4),
+ 4,
+ SCR_INT_FLY,
+ 0,
+ SCR_STORE_ABS (scratcha, 4),
+ PADDR_B (done_pos),
+}/*-------------------------< DONE_END >-------------------------*/,{


+ SCR_JUMP,
+ PADDR_A (start),
+}/*-------------------------< COMPLETE_ERROR >-------------------*/,{

+ SCR_LOAD_ABS (scratcha, 4),
+ PADDR_B (startpos),


+ SCR_INT,
+ SIR_COMPLETE_ERROR,
+}/*-------------------------< SAVE_DP >--------------------------*/,{
+ /*
+ * Clear ACK immediately.
+ * No need to delay it.
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+ /*
+ * Keep track we received a SAVE DP, so
+ * we will switch to the other PM context
+ * on the next PM since the DP may point
+ * to the current PM context.
+ */
+ SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED),
+ 0,
+ /*
+ * SAVE_DP message:
+ * Copy LASTP to SAVEP.
+ */

+ SCR_LOAD_REL (scratcha, 4),
+ offsetof (struct sym_ccb, phys.head.lastp),
+ SCR_STORE_REL (scratcha, 4),
+ offsetof (struct sym_ccb, phys.head.savep),


+ /*
+ * Anticipate the MESSAGE PHASE for
+ * the DISCONNECT message.
+ */
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
+ PADDR_A (msg_in),
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< RESTORE_DP >-----------------------*/,{
+ /*
+ * Clear ACK immediately.
+ * No need to delay it.
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+ /*
+ * Copy SAVEP to LASTP.
+ */

+ SCR_LOAD_REL (scratcha, 4),
+ offsetof (struct sym_ccb, phys.head.savep),
+ SCR_STORE_REL (scratcha, 4),
+ offsetof (struct sym_ccb, phys.head.lastp),

+ SCR_STORE_REL (scr0, 4),
+ offsetof (struct sym_ccb, phys.head.status),

+ SCR_STORE_ABS (scratcha, 4),

+ SCR_LOAD_ABS (dsa, 4),
+ PADDR_B (targtbl),


+ SCR_SFBR_REG (dsa, SCR_SHL, 0),
+ 0,
+ SCR_REG_REG (dsa, SCR_SHL, 0),
+ 0,
+ SCR_REG_REG (dsa, SCR_AND, 0x3c),
+ 0,

+ SCR_LOAD_REL (dsa, 4),
+ 0,
+ /*


+ * We expect MESSAGE IN phase.
+ * If not, get help from the C code.
+ */
+ SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)),
+ SIR_RESEL_NO_MSG_IN,

+ /*
+ * Load the legacy synchronous transfer registers.
+ */
+ SCR_LOAD_REL (scntl3, 1),
+ offsetof(struct sym_tcb, head.wval),
+ SCR_LOAD_REL (sxfer, 1),
+ offsetof(struct sym_tcb, head.sval),
+}/*-------------------------< RESEL_SCNTL4 >---------------------*/,{
+ /*
+ * The C1010 uses a new synchronous timing scheme.
+ * Will be patched with a NO_OP if not a C1010.
+ */
+ SCR_LOAD_REL (scntl4, 1),
+ offsetof(struct sym_tcb, head.uval),


+ /*
+ * Get the IDENTIFY message.
+ */
+ SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
+ HADDR_1 (msgin),
+ /*
+ * If IDENTIFY LUN #0, use a faster path
+ * to find the LCB structure.
+ */
+ SCR_JUMP ^ IFTRUE (MASK (0x80, 0xbf)),
+ PADDR_A (resel_lun0),
+ /*
+ * If message isn't an IDENTIFY,
+ * tell the C code about.
+ */
+ SCR_INT ^ IFFALSE (MASK (0x80, 0x80)),
+ SIR_RESEL_NO_IDENTIFY,
+ /*
+ * It is an IDENTIFY message,
+ * Load the LUN control block address.
+ */

+ SCR_LOAD_REL (dsa, 4),
+ offsetof(struct sym_tcb, head.luntbl_sa),


+ SCR_SFBR_REG (dsa, SCR_SHL, 0),
+ 0,
+ SCR_REG_REG (dsa, SCR_SHL, 0),
+ 0,
+ SCR_REG_REG (dsa, SCR_AND, 0xfc),
+ 0,

+ SCR_LOAD_REL (dsa, 4),
+ 0,
+ SCR_JUMPR,
+ 8,


+}/*-------------------------< RESEL_LUN0 >-----------------------*/,{
+ /*
+ * LUN 0 special case (but usual one :))
+ */

+ SCR_LOAD_REL (dsa, 4),
+ offsetof(struct sym_tcb, head.lun0_sa),


+ /*
+ * Jump indirectly to the reselect action for this LUN.

+ */
+ SCR_LOAD_REL (temp, 4),
+ offsetof(struct sym_lcb, head.resel_sa),


+ SCR_RETURN,
+ 0,
+ /* In normal situations, we jump to RESEL_TAG or RESEL_NO_TAG */
+}/*-------------------------< RESEL_TAG >------------------------*/,{
+ /*
+ * ACK the IDENTIFY previously received.
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+ /*
+ * It shall be a tagged command.
+ * Read SIMPLE+TAG.
+ * The C code will deal with errors.
+ * Agressive optimization, is'nt it? :)
+ */
+ SCR_MOVE_ABS (2) ^ SCR_MSG_IN,
+ HADDR_1 (msgin),
+ /*

+ * Load the pointer to the tagged task
+ * table for this LUN.
+ */

+ SCR_LOAD_REL (dsa, 4),
+ offsetof(struct sym_lcb, head.itlq_tbl_sa),

+ SCR_LOAD_REL (dsa, 4),
+ 0,
+ SCR_LOAD_REL (temp, 4),
+ offsetof(struct sym_ccb, phys.head.go.restart),


+ SCR_RETURN,
+ 0,
+ /* In normal situations we branch to RESEL_DSA */
+}/*-------------------------< RESEL_DSA >------------------------*/,{
+ /*
+ * ACK the IDENTIFY or TAG previously received.
+ */
+ SCR_CLR (SCR_ACK),
+ 0,
+}/*-------------------------< RESEL_DSA1 >-----------------------*/,{
+ /*

+ * Initialize the status registers
+ */
+ SCR_LOAD_REL (scr0, 4),
+ offsetof (struct sym_ccb, phys.head.status),


+ /*
+ * Jump to dispatcher.
+ */
+ SCR_JUMP,
+ PADDR_A (dispatch),
+}/*-------------------------< RESEL_NO_TAG >---------------------*/,{
+ /*

+ * Load the DSA with the unique ITL task.
+ */

+ SCR_LOAD_REL (dsa, 4),
+ offsetof(struct sym_lcb, head.itl_task_sa),
+ /*


+ * JUMP indirectly to the restart point of the CCB.
+ */

+ SCR_LOAD_REL (temp, 4),
+ offsetof(struct sym_ccb, phys.head.go.restart),


+ SCR_RETURN,
+ 0,
+ /* In normal situations we branch to RESEL_DSA */

+ SCR_LOAD_REL (temp, 4),
+ offsetof (struct sym_ccb, phys.pm0.ret),

+ SCR_LOAD_REL (temp, 4),
+ offsetof (struct sym_ccb, phys.pm1.ret),
+ SCR_RETURN,
+ 0,
+}/*-------------------------<>-----------------------------------*/


+};
+
+static struct SYM_FWB_SCR SYM_FWB_SCR = {

+/*--------------------------< START64 >--------------------------*/ {
+ /*
+ * SCRIPT entry point for the 895A, 896 and 1010.
+ * For now, there is no specific stuff for those
+ * chips at this point, but this may come.
+ */
+ SCR_JUMP,
+ PADDR_A (init),
+}/*-------------------------< NO_DATA >--------------------------*/,{


+ SCR_JUMP,
+ PADDR_B (data_ovrun),
+}/*-------------------------< SEL_FOR_ABORT >--------------------*/,{
+ /*
+ * We are jumped here by the C code, if we have
+ * some target to reset or some disconnected
+ * job to abort. Since error recovery is a serious
+ * busyness, we will really reset the SCSI BUS, if
+ * case of a SCSI interrupt occuring in this path.
+ */

+ SCR_LOAD_REL (scratcha, 4), /* DUMMY READ */
+ 0,


+ SCR_INT,
+ SIR_MSG_RECEIVED,
+}/*-------------------------< MSG_WEIRD_SEEN >-------------------*/,{

+ SCR_LOAD_REL (scratcha, 4), /* DUMMY READ */
+ 0,

+ SCR_STORE_REL (scratcha, 1),
+ offsetof (struct sym_dsb, smsg_ext.size),


+ SCR_CLR (SCR_ACK),
+ 0,

+ SCR_MOVE_TBL ^ SCR_MSG_IN,
+ offsetof (struct sym_dsb, smsg_ext),

+ * Use scratcha to count the extra bytes.
+ */
+ SCR_LOAD_ABS (scratcha, 4),
+ PADDR_B (zero),

+ SCR_LOAD_ABS (scratcha, 4),
+ PADDR_B (startpos),


+ SCR_INT ^ IFFALSE (DATA (S_COND_MET)),
+ SIR_BAD_SCSI_STATUS,
+ SCR_RETURN,
+ 0,

+}/*-------------------------< PM_HANDLE >------------------------*/,{
+ /*
+ * Phase mismatch handling.
+ *
+ * Since we have to deal with 2 SCSI data pointers
+ * (current and saved), we need at least 2 contexts.
+ * Each context (pm0 and pm1) has a saved area, a
+ * SAVE mini-script and a DATA phase mini-script.
+ */
+ /*
+ * Get the PM handling flags.


+ */
+ SCR_FROM_REG (HF_REG),
+ 0,
+ /*

+ * If no flags (1rst PM for example), avoid
+ * all the below heavy flags testing.
+ * This makes the normal case a bit faster.
+ */
+ SCR_JUMP ^ IFTRUE (MASK (0, (HF_IN_PM0 | HF_IN_PM1 | HF_DP_SAVED))),
+ PADDR_B (pm_handle1),
+ /*
+ * If we received a SAVE DP, switch to the
+ * other PM context since the savep may point

+ * to the current PM context.
+ */

+ SCR_JUMPR ^ IFFALSE (MASK (HF_DP_SAVED, HF_DP_SAVED)),
+ 8,
+ SCR_REG_REG (sfbr, SCR_XOR, HF_ACT_PM),
+ 0,
+ /*
+ * If we have been interrupt in a PM DATA mini-script,
+ * we take the return address from the corresponding
+ * saved area.
+ * This ensure the return address always points to the
+ * main DATA script for this transfer.
+ */
+ SCR_JUMP ^ IFTRUE (MASK (0, (HF_IN_PM0 | HF_IN_PM1))),
+ PADDR_B (pm_handle1),
+ SCR_JUMPR ^ IFFALSE (MASK (HF_IN_PM0, HF_IN_PM0)),
+ 16,
+ SCR_LOAD_REL (ia, 4),
+ offsetof(struct sym_ccb, phys.pm0.ret),
+ SCR_JUMP,
+ PADDR_B (pm_save),
+ SCR_LOAD_REL (ia, 4),
+ offsetof(struct sym_ccb, phys.pm1.ret),
+ SCR_JUMP,
+ PADDR_B (pm_save),
+}/*-------------------------< PM_HANDLE1 >-----------------------*/,{
+ /*
+ * Normal case.
+ * Update the return address so that it
+ * will point after the interrupted MOVE.
+ */
+ SCR_REG_REG (ia, SCR_ADD, 8),
+ 0,
+ SCR_REG_REG (ia1, SCR_ADDC, 0),
+ 0,
+}/*-------------------------< PM_SAVE >--------------------------*/,{
+ /*
+ * Clear all the flags that told us if we were
+ * interrupted in a PM DATA mini-script and/or
+ * we received a SAVE DP.
+ */
+ SCR_SFBR_REG (HF_REG, SCR_AND, (~(HF_IN_PM0|HF_IN_PM1|HF_DP_SAVED))),
+ 0,
+ /*
+ * Choose the current PM context.
+ */
+ SCR_JUMP ^ IFTRUE (MASK (HF_ACT_PM, HF_ACT_PM)),
+ PADDR_B (pm1_save),
+}/*-------------------------< PM0_SAVE >-------------------------*/,{
+ SCR_STORE_REL (ia, 4),
+ offsetof(struct sym_ccb, phys.pm0.ret),
+ /*
+ * If WSR bit is set, either UA and RBC may
+ * have to be changed whether the device wants
+ * to ignore this residue or not.


+ */
+ SCR_FROM_REG (scntl2),
+ 0,

+ SCR_CALL ^ IFTRUE (MASK (WSR, WSR)),
+ PADDR_B (pm_wsr_handle),
+ /*
+ * Save the remaining byte count, the updated
+ * address and the return address.
+ */
+ SCR_STORE_REL (rbc, 4),
+ offsetof(struct sym_ccb, phys.pm0.sg.size),
+ SCR_STORE_REL (ua, 4),
+ offsetof(struct sym_ccb, phys.pm0.sg.addr),
+ /*
+ * Set the current pointer at the PM0 DATA mini-script.
+ */
+ SCR_LOAD_ABS (ia, 4),
+ PADDR_B (pm0_data_addr),
+}/*-------------------------< PM_SAVE_END >----------------------*/,{
+ SCR_STORE_REL (ia, 4),
+ offsetof(struct sym_ccb, phys.head.lastp),


+ SCR_JUMP,
+ PADDR_A (dispatch),

+}/*-------------------------< PM1_SAVE >-------------------------*/,{
+ SCR_STORE_REL (ia, 4),
+ offsetof(struct sym_ccb, phys.pm1.ret),
+ /*
+ * If WSR bit is set, either UA and RBC may
+ * have to be changed whether the device wants
+ * to ignore this residue or not.


+ */
+ SCR_FROM_REG (scntl2),
+ 0,

+ SCR_CALL ^ IFTRUE (MASK (WSR, WSR)),
+ PADDR_B (pm_wsr_handle),
+ /*
+ * Save the remaining byte count, the updated
+ * address and the return address.
+ */
+ SCR_STORE_REL (rbc, 4),
+ offsetof(struct sym_ccb, phys.pm1.sg.size),
+ SCR_STORE_REL (ua, 4),
+ offsetof(struct sym_ccb, phys.pm1.sg.addr),
+ /*
+ * Set the current pointer at the PM1 DATA mini-script.
+ */
+ SCR_LOAD_ABS (ia, 4),
+ PADDR_B (pm1_data_addr),
+ SCR_JUMP,
+ PADDR_B (pm_save_end),
+}/*-------------------------< PM_WSR_HANDLE >--------------------*/,{
+ /*
+ * Phase mismatch handling from SCRIPT with WSR set.
+ * Such a condition can occur if the chip wants to
+ * execute a CHMOV(size > 1) when the WSR bit is
+ * set and the target changes PHASE.
+ *
+ * We must move the residual byte to memory.
+ *
+ * UA contains bit 0..31 of the address to
+ * move the residual byte.
+ * Move it to the table indirect.
+ */
+ SCR_STORE_REL (ua, 4),
+ offsetof (struct sym_ccb, phys.wresid.addr),
+ /*
+ * Increment UA (move address to next position).
+ */
+ SCR_REG_REG (ua, SCR_ADD, 1),
+ 0,
+ SCR_REG_REG (ua1, SCR_ADDC, 0),
+ 0,
+ SCR_REG_REG (ua2, SCR_ADDC, 0),
+ 0,
+ SCR_REG_REG (ua3, SCR_ADDC, 0),
+ 0,
+ /*
+ * Compute SCRATCHA as:
+ * - size to transfer = 1 byte.
+ * - bit 24..31 = high address bit [32...39].
+ */
+ SCR_LOAD_ABS (scratcha, 4),
+ PADDR_B (zero),
+ SCR_REG_REG (scratcha, SCR_OR, 1),
+ 0,
+ SCR_FROM_REG (rbc3),
+ 0,
+ SCR_TO_REG (scratcha3),
+ 0,
+ /*
+ * Move this value to the table indirect.
+ */
+ SCR_STORE_REL (scratcha, 4),
+ offsetof (struct sym_ccb, phys.wresid.size),
+ /*
+ * Wait for a valid phase.
+ * While testing with bogus QUANTUM drives, the C1010
+ * sometimes raised a spurious phase mismatch with
+ * WSR and the CHMOV(1) triggered another PM.
+ * Waiting explicitely for the PHASE seemed to avoid
+ * the nested phase mismatch. Btw, this didn't happen
+ * using my IBM drives.
+ */
+ SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_IN)),
+ 0,
+ /*


+ * Perform the move of the residual byte.
+ */
+ SCR_CHMOV_TBL ^ SCR_DATA_IN,
+ offsetof (struct sym_ccb, phys.wresid),

+ /*
+ * We can now handle the phase mismatch with UA fixed.
+ * RBC[0..23]=0 is a special case that does not require
+ * a PM context. The C code also checks against this.
+ */
+ SCR_FROM_REG (rbc),
+ 0,
+ SCR_RETURN ^ IFFALSE (DATA (0)),
+ 0,
+ SCR_FROM_REG (rbc1),
+ 0,
+ SCR_RETURN ^ IFFALSE (DATA (0)),
+ 0,
+ SCR_FROM_REG (rbc2),
+ 0,
+ SCR_RETURN ^ IFFALSE (DATA (0)),
+ 0,
+ /*
+ * RBC[0..23]=0.
+ * Not only we donnot need a PM context, but this would
+ * lead to a bogus CHMOV(0). This condition means that
+ * the residual was the last byte to move from this CHMOV.
+ * So, we just have to move the current data script pointer
+ * (i.e. TEMP) to the SCRIPTS address following the
+ * interrupted CHMOV and jump to dispatcher.
+ * IA contains the data pointer to save.
+ */
+ SCR_JUMP,
+ PADDR_B (pm_save_end),


+}/*-------------------------< WSR_MA_HELPER >--------------------*/,{
+ /*
+ * Helper for the C code when WSR bit is set.
+ * Perform the move of the residual byte.
+ */
+ SCR_CHMOV_TBL ^ SCR_DATA_IN,
+ offsetof (struct sym_ccb, phys.wresid),
+ SCR_JUMP,
+ PADDR_A (dispatch),
+
+#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
+}/*-------------------------< DATA_IO >--------------------------*/,{
+ /*
+ * We jump here if the data direction was unknown at the
+ * time we had to queue the command to the scripts processor.
+ * Pointers had been set as follow in this situation:
+ * savep --> DATA_IO
+ * lastp --> start pointer when DATA_IN
+ * wlastp --> start pointer when DATA_OUT
+ * This script sets savep and lastp according to the
+ * direction chosen by the target.
+ */
+ SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_OUT)),
+ PADDR_B (data_io_out),

+}/*-------------------------< DATA_IO_IN >-----------------------*/,{
+ /*


+ * Direction is DATA IN.
+ */

+ SCR_LOAD_REL (scratcha, 4),
+ offsetof (struct sym_ccb, phys.head.lastp),
+}/*-------------------------< DATA_IO_COM >----------------------*/,{
+ SCR_STORE_REL (scratcha, 4),
+ offsetof (struct sym_ccb, phys.head.savep),
+
+ /*


+ * Jump to the SCRIPTS according to actual direction.
+ */

+ SCR_LOAD_REL (temp, 4),
+ offsetof (struct sym_ccb, phys.head.savep),


+ SCR_RETURN,
+ 0,
+}/*-------------------------< DATA_IO_OUT >----------------------*/,{
+ /*
+ * Direction is DATA OUT.
+ */
+ SCR_REG_REG (HF_REG, SCR_AND, (~HF_DATA_IN)),
+ 0,

+ SCR_LOAD_REL (scratcha, 4),
+ offsetof (struct sym_ccb, phys.head.wlastp),
+ SCR_STORE_REL (scratcha, 4),
+ offsetof (struct sym_ccb, phys.head.lastp),


+ SCR_JUMP,
+ PADDR_B(data_io_com),
+#endif /* SYM_OPT_HANDLE_DIR_UNKNOWN */
+
+}/*-------------------------< ZERO >-----------------------------*/,{
+ SCR_DATA_ZERO,
+}/*-------------------------< SCRATCH >--------------------------*/,{
+ SCR_DATA_ZERO,

+}/*-------------------------< PM0_DATA_ADDR >--------------------*/,{
+ SCR_DATA_ZERO,
+}/*-------------------------< PM1_DATA_ADDR >--------------------*/,{
+ SCR_DATA_ZERO,


+}/*-------------------------< DONE_POS >-------------------------*/,{
+ SCR_DATA_ZERO,

+}/*-------------------------< STARTPOS >-------------------------*/,{
+ SCR_DATA_ZERO,
+}/*-------------------------< TARGTBL >--------------------------*/,{
+ SCR_DATA_ZERO,

+}/*-------------------------<>-----------------------------------*/
+};
+

+static struct SYM_FWZ_SCR SYM_FWZ_SCR = {
+ /*-------------------------< SNOOPTEST >------------------------*/{
+ /*

+ * Read the variable from memory.
+ */
+ SCR_LOAD_REL (scratcha, 4),
+ offsetof(struct sym_hcb, scratch),
+ /*
+ * Write the variable to memory.
+ */
+ SCR_STORE_REL (temp, 4),
+ offsetof(struct sym_hcb, scratch),
+ /*
+ * Read back the variable from memory.
+ */
+ SCR_LOAD_REL (temp, 4),
+ offsetof(struct sym_hcb, scratch),


+}/*-------------------------< SNOOPEND >-------------------------*/,{
+ /*
+ * And stop.
+ */
+ SCR_INT,
+ 99,
+#ifdef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ /*
+ * We may use MEMORY MOVE instructions to load the on chip-RAM,
+ * if it happens that mapping PCI memory is not possible.
+ * But writing the RAM from the CPU is the preferred method,
+ * since PCI 2.2 seems to disallow PCI self-mastering.
+ */
+}/*-------------------------< START_RAM >------------------------*/,{
+ /*
+ * Load the script into on-chip RAM,
+ * and jump to start point.
+ */
+ SCR_COPY (sizeof(struct SYM_FWA_SCR)),
+}/*-------------------------< SCRIPTA0_BA >----------------------*/,{
+ 0,
+ PADDR_A (start),
+ SCR_JUMP,
+ PADDR_A (init),

+}/*-------------------------< START_RAM64 >----------------------*/,{
+ /*
+ * Load the RAM and start for 64 bit PCI (895A,896).
+ * Both scripts (script and scripth) are loaded into
+ * the RAM which is 8K (4K for 825A/875/895).
+ * We also need to load some 32-63 bit segments
+ * address of the SCRIPTS processor.
+ * LOAD/STORE ABSOLUTE always refers to on-chip RAM
+ * in our implementation. The main memory is
+ * accessed using LOAD/STORE DSA RELATIVE.
+ */
+ SCR_LOAD_REL (mmws, 4),
+ offsetof (struct sym_hcb, scr_ram_seg),
+ SCR_COPY (sizeof(struct SYM_FWA_SCR)),
+}/*-------------------------< SCRIPTA0_BA64 >--------------------*/,{


+ 0,
+ PADDR_A (start),

+ SCR_COPY (sizeof(struct SYM_FWB_SCR)),
+}/*-------------------------< SCRIPTB0_BA64 >--------------------*/,{
+ 0,
+ PADDR_B (start64),
+ SCR_LOAD_REL (mmrs, 4),
+ offsetof (struct sym_hcb, scr_ram_seg),
+ SCR_JUMP64,
+ PADDR_B (start64),
+}/*-------------------------< RAM_SEG64 >------------------------*/,{
+ 0,


+#endif /* SYM_OPT_NO_BUS_MEMORY_MAPPING */
+}/*-------------------------<>-----------------------------------*/
+};

diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_glue.c linux/drivers/scsi/sym53c8xx_2/sym_glue.c
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_glue.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym_glue.c Fri Nov 9 15:22:54 2001
@@ -0,0 +1,3012 @@

+#define SYM_GLUE_C
+
+#include <linux/module.h>


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

echo 'End of part 062'
echo 'File patch-2.4.15 is continued in part 063'
echo "063" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:50 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part074

#!/bin/sh -x
# this is part 074 of a 115 - part archive


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

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

+} SiS310_LCDACRT1DataStruct;
+SiS310_LCDACRT1DataStruct SiS310_LCDACRT1800x600_1[] = {
+ {{0x65, 0x4f, 0x89, 0x56, 0x83, 0xaf, 0x1f,
+ 0x90, 0x85, 0x8f, 0xab, 0x30, 0x00, 0x05,
+ 0x00}},
+ {{0x65, 0x4f, 0x89, 0x56, 0x83, 0x83, 0x1f,
+ 0x5e, 0x83, 0x5d, 0x79, 0x10, 0x00, 0x05,
+ 0x00}},
+ {{0x65, 0x4f, 0x89, 0x56, 0x83, 0xaf, 0x1f,
+ 0x90, 0x85, 0x8f, 0xab, 0x30, 0x00, 0x05,
+ 0x00}},
+ {{0x65, 0x4f, 0x89, 0x56, 0x83, 0x83, 0x1f,
+ 0x5e, 0x83, 0x5d, 0x79, 0x10, 0x00, 0x05,
+ 0x00}},
+ {{0x65, 0x4f, 0x89, 0x56, 0x83, 0x04, 0x3e,
+ 0xe0, 0x85, 0xdf, 0xfb, 0x10, 0x00, 0x05,
+ 0x00}},
+ {{0x7f, 0x63, 0x83, 0x6c, 0x1c, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x73, 0x20, 0x00, 0x06,
+ 0x01}}
+};
+
+SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_1[] = {
+ {{0x73, 0x4f, 0x4f, 0x97, 0x55, 0x86, 0xc4, 0x1f,
+ 0x92, 0x89, 0x8f, 0x8f, 0xb5, 0x30, 0x00, 0x05,
+ 0x00}},
+ {{0x73, 0x4f, 0x4f, 0x97, 0x55, 0x86, 0x97, 0x1f,
+ 0x60, 0x87, 0x5d, 0x5d, 0x83, 0x10, 0x00, 0x05,
+ 0x00}},
+ {{0x73, 0x4f, 0x4f, 0x97, 0x55, 0x86, 0xc4, 0x1f,
+ 0x92, 0x89, 0x8f, 0x8f, 0xb5, 0x30, 0x00, 0x05,
+ 0x00}},
+ {{0x73, 0x4f, 0x4f, 0x97, 0x55, 0x86, 0x97, 0x1f,
+ 0x60, 0x87, 0x5d, 0x5d, 0x83, 0x10, 0x00, 0x05,
+ 0x00}},
+ {{0x73, 0x4f, 0x4f, 0x97, 0x55, 0x86, 0x04, 0x3e,
+ 0xE2, 0x89, 0xDf, 0xDf, 0x05, 0x00, 0x00, 0x05,
+ 0x00}},
+ {{0x87, 0x63, 0x63, 0x8B, 0x69, 0x1A, 0x7c, 0xf0,
+ 0x5A, 0x8F, 0x57, 0x57, 0x7D, 0x20, 0x00, 0x26,
+ 0x01}},
+ {{0xA3, 0x7f, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xFf, 0xFf, 0x25, 0x10, 0x00, 0x02,
+ 0x01}}
+};
+
+SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_1[] = {
+ {{0x63, 0x4f, 0x87, 0x54, 0x9f, 0xb4, 0x1f,
+ 0x92, 0x89, 0x8f, 0xb5, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x63, 0x4f, 0x87, 0x54, 0x9f, 0x82, 0x1f,
+ 0x60, 0x87, 0x5d, 0x83, 0x10, 0x00, 0x01,
+ 0x00}},
+ {{0x63, 0x4f, 0x87, 0x54, 0x9f, 0xb4, 0x1f,
+ 0x92, 0x89, 0x8f, 0xb5, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x63, 0x4f, 0x87, 0x54, 0x9f, 0x82, 0x1f,
+ 0x60, 0x87, 0x5d, 0x83, 0x10, 0x00, 0x01,
+ 0x00}},
+ {{0x63, 0x4f, 0x87, 0x54, 0x9f, 0x04, 0x3e,
+ 0xe2, 0x89, 0xdf, 0x05, 0x00, 0x00, 0x01,
+ 0x00}},
+ {{0x7e, 0x63, 0x82, 0x68, 0x15, 0x7c, 0xf0,
+ 0x5a, 0x8f, 0x57, 0x7d, 0x20, 0x00, 0x26,
+ 0x01}},
+ {{0xa3, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0x25, 0x10, 0x00, 0x02,
+ 0x01}}
+};
+
+SiS310_LCDACRT1DataStruct SiS310_LCDACRT1800x600_1_H[] = {
+ {{0x30, 0x27, 0x94, 0x2c, 0x92, 0xaf, 0x1f,
+ 0x90, 0x85, 0x8f, 0xab, 0x30, 0x00, 0x04,
+ 0x00}},
+ {{0x30, 0x27, 0x94, 0x2c, 0x92, 0x83, 0x1f,
+ 0x5e, 0x83, 0x5d, 0x79, 0x10, 0x00, 0x04,
+ 0x00}},
+ {{0x30, 0x27, 0x94, 0x2c, 0x92, 0xaf, 0x1f,
+ 0x90, 0x85, 0x8f, 0xab, 0x30, 0x00, 0x04,
+ 0x00}},
+ {{0x30, 0x27, 0x94, 0x2c, 0x92, 0x83, 0x1f,
+ 0x5e, 0x83, 0x5d, 0x79, 0x10, 0x00, 0x04,
+ 0x00}},
+ {{0x30, 0x27, 0x94, 0x2c, 0x92, 0x04, 0x3e,
+ 0xe0, 0x85, 0xdf, 0xfb, 0x10, 0x00, 0x04,
+ 0x00}},
+ {{0x3d, 0x31, 0x81, 0x37, 0x1f, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x73, 0x20, 0x00, 0x05,
+ 0x01}}
+};
+
+SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_1_H[] = {
+ {{0x37, 0x27, 0x27, 0x9B, 0x2b, 0x94, 0xc4, 0x1f,
+ 0x92, 0x89, 0x8f, 0x8f, 0xb5, 0x30, 0x00, 0x44,
+ 0x00}},
+ {{0x37, 0x27, 0x27, 0x9B, 0x2b, 0x94, 0x97, 0x1f,
+ 0x60, 0x87, 0x5D, 0x5D, 0x83, 0x01, 0x00, 0x44,
+ 0x00}},
+ {{0x37, 0x27, 0x27, 0x9B, 0x2b, 0x94, 0xc4, 0x1f,
+ 0x92, 0x89, 0x8f, 0x8f, 0xb5, 0x30, 0x00, 0x44,
+ 0x00}},
+ {{0x37, 0x27, 0x27, 0x9B, 0x2b, 0x94, 0x97, 0x1f,
+ 0x60, 0x87, 0x5D, 0x5D, 0x83, 0x01, 0x00, 0x44,
+ 0x00}},
+ {{0x37, 0x27, 0x27, 0x9B, 0x2b, 0x94, 0x04, 0x3e,
+ 0xE2, 0x89, 0xDf, 0xDf, 0x05, 0x00, 0x00, 0x44,
+ 0x00}},
+ {{0x41, 0x31, 0x31, 0x85, 0x35, 0x1d, 0x7c, 0xf0,
+ 0x5A, 0x8F, 0x57, 0x57, 0x7D, 0x20, 0x00, 0x55,
+ 0x01}},
+ {{0x4f, 0x3F, 0x3F, 0x93, 0x45, 0x0D, 0x24, 0xf5,
+ 0x02, 0x88, 0xFf, 0xFf, 0x25, 0x10, 0x00, 0x01,
+ 0x01}}
+};
+
+SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_1_H[] = {
+ {{0x2f, 0x27, 0x93, 0x2b, 0x90, 0xb4, 0x1f,
+ 0x92, 0x89, 0x8f, 0xb5, 0x30, 0x00, 0x04,
+ 0x00}},
+ {{0x2f, 0x27, 0x93, 0x2b, 0x90, 0x82, 0x1f,
+ 0x60, 0x87, 0x5d, 0x83, 0x10, 0x00, 0x04,
+ 0x00}},
+ {{0x2f, 0x27, 0x93, 0x2b, 0x90, 0xb4, 0x1f,
+ 0x92, 0x89, 0x8f, 0xb5, 0x30, 0x00, 0x04,
+ 0x00}},
+ {{0x2f, 0x27, 0x93, 0x2b, 0x90, 0x82, 0x1f,
+ 0x60, 0x87, 0x5d, 0x83, 0x10, 0x00, 0x04,
+ 0x00}},
+ {{0x2f, 0x27, 0x93, 0x2b, 0x90, 0x04, 0x3e,
+ 0xe2, 0x89, 0xdf, 0x05, 0x00, 0x00, 0x04,
+ 0x00}},
+ {{0x3c, 0x31, 0x80, 0x35, 0x1c, 0x7c, 0xf0,
+ 0x5a, 0x8f, 0x57, 0x7d, 0x20, 0x00, 0x55,
+ 0x01}},
+ {{0x4f, 0x3f, 0x93, 0x45, 0x0d, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0x25, 0x10, 0x00, 0x01,
+ 0x01}}
+};
+
+SiS310_LCDACRT1DataStruct SiS310_LCDACRT1800x600_2[] = {
+ {{0x7f, 0x4f, 0x83, 0x62, 0x12, 0x72, 0x3e,
+ 0xf4, 0x88, 0x8f, 0x73, 0x20, 0x00, 0x06,
+ 0x00}},
+ {{0x7f, 0x4f, 0x83, 0x62, 0x12, 0x72, 0x3e,
+ 0xdb, 0x8f, 0x5d, 0x73, 0x20, 0x00, 0x06,
+ 0x00}},
+ {{0x7f, 0x4f, 0x83, 0x62, 0x12, 0x72, 0x3e,
+ 0xf4, 0x88, 0x8f, 0x73, 0x20, 0x00, 0x06,
+ 0x00}},
+ {{0x7f, 0x4f, 0x83, 0x62, 0x12, 0x72, 0x3e,
+ 0xdb, 0x8f, 0x5d, 0x73, 0x20, 0x00, 0x06,
+ 0x00}},
+ {{0x7f, 0x4f, 0x83, 0x62, 0x12, 0x72, 0xba,
+ 0x1c, 0x80, 0xdf, 0x73, 0x00, 0x00, 0x06,
+ 0x00}},
+ {{0x7f, 0x63, 0x83, 0x6c, 0x1c, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x73, 0x20, 0x00, 0x06,
+ 0x01}}
+};
+
+SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_2[] = {
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x72, 0x88, 0xdf, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x63, 0x87, 0x78, 0x89, 0x24, 0xf1,
+ 0xae, 0x84, 0x57, 0x25, 0x30, 0x00, 0x02,
+ 0x01}},
+ {{0xa3, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0x25, 0x10, 0x00, 0x02,
+ 0x01}}
+};
+
+SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_2[] = {
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x72, 0x88, 0xdf, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x63, 0x87, 0x78, 0x89, 0x24, 0xf1,
+ 0xae, 0x84, 0x57, 0x25, 0x30, 0x00, 0x02,
+ 0x01}},
+ {{0xa3, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0x25, 0x10, 0x00, 0x02,
+ 0x01}}
+};
+
+SiS310_LCDACRT1DataStruct SiS310_LCDACRT1800x600_2_H[] = {
+ {{0x3d, 0x27, 0x81, 0x32, 0x1a, 0x72, 0x3e,
+ 0xf4, 0x88, 0x8f, 0x73, 0x20, 0x00, 0x05,
+ 0x00}},
+ {{0x3d, 0x27, 0x81, 0x32, 0x1a, 0x72, 0x3e,
+ 0xdb, 0x8f, 0x5d, 0x73, 0x20, 0x00, 0x05,
+ 0x00}},
+ {{0x3d, 0x27, 0x81, 0x32, 0x1a, 0x72, 0x3e,
+ 0xf4, 0x88, 0x8f, 0x73, 0x20, 0x00, 0x05,
+ 0x00}},
+ {{0x3d, 0x27, 0x81, 0x3a, 0x1a, 0x72, 0x3e,
+ 0xdb, 0x8f, 0x5d, 0x73, 0x20, 0x00, 0x05,
+ 0x00}},
+ {{0x3d, 0x27, 0x81, 0x32, 0x1a, 0x72, 0xba,
+ 0x1c, 0x80, 0xdf, 0x73, 0x00, 0x00, 0x05,
+ 0x00}},
+ {{0x3d, 0x31, 0x81, 0x37, 0x1f, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x73, 0x20, 0x00, 0x05,
+ 0x01}}
+};
+
+SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_2_H[] = {
+ {{0x4f, 0x27, 0x93, 0x39, 0x01, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x01, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x01, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x01, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x01, 0x24, 0xbb,
+ 0x72, 0x88, 0xdf, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x31, 0x93, 0x3e, 0x06, 0x24, 0xf1,
+ 0xae, 0x84, 0x57, 0x25, 0x30, 0x00, 0x01,
+ 0x01}},
+ {{0x4f, 0x3f, 0x93, 0x45, 0x0d, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0x25, 0x10, 0x00, 0x01,
+ 0x01}}
+};
+
+SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_2_H[] = {
+ {{0x4f, 0x27, 0x93, 0x39, 0x81, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x81, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x81, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x81, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x81, 0x24, 0xbb,
+ 0x72, 0x88, 0xdf, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x31, 0x93, 0x3e, 0x86, 0x24, 0xf1,
+ 0xae, 0x84, 0x57, 0x25, 0x30, 0x00, 0x01,
+ 0x01}},
+ {{0x4f, 0x3f, 0x93, 0x45, 0x0d, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0x25, 0x10, 0x00, 0x01,
+ 0x01}}
+};
+
+typedef struct _SiS310_LVDSCRT1DataStruct {
+ UCHAR CR[15];
+} SiS310_LVDSCRT1DataStruct;
+SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1[] = {
+ {{0x65, 0x4f, 0x89, 0x56, 0x83, 0xaf, 0x1f,
+ 0x90, 0x85, 0x8f, 0xab, 0x30, 0x00, 0x05,
+ 0x00}},
+ {{0x65, 0x4f, 0x89, 0x56, 0x83, 0x83, 0x1f,
+ 0x5e, 0x83, 0x5d, 0x79, 0x10, 0x00, 0x05,
+ 0x00}},
+ {{0x65, 0x4f, 0x89, 0x56, 0x83, 0xaf, 0x1f,
+ 0x90, 0x85, 0x8f, 0xab, 0x30, 0x00, 0x05,
+ 0x00}},
+ {{0x65, 0x4f, 0x89, 0x56, 0x83, 0x83, 0x1f,
+ 0x5e, 0x83, 0x5d, 0x79, 0x10, 0x00, 0x05,
+ 0x00}},
+ {{0x65, 0x4f, 0x89, 0x56, 0x83, 0x04, 0x3e,
+ 0xe0, 0x85, 0xdf, 0xfb, 0x10, 0x00, 0x05,
+ 0x00}},
+ {{0x7f, 0x63, 0x83, 0x6c, 0x1c, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x73, 0x20, 0x00, 0x06,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1[] = {
+ {{0x73, 0x4f, 0x97, 0x55, 0x86, 0xc4, 0x1f,
+ 0x92, 0x89, 0x8f, 0xb5, 0x30, 0x00, 0x05,
+ 0x00}},
+ {{0x73, 0x4f, 0x97, 0x55, 0x86, 0x97, 0x1f,
+ 0x60, 0x87, 0x5d, 0x83, 0x10, 0x00, 0x05,
+ 0x00}},
+ {{0x73, 0x4f, 0x97, 0x55, 0x86, 0xc4, 0x1f,
+ 0x92, 0x89, 0x8f, 0xb5, 0x30, 0x00, 0x05,
+ 0x00}},
+ {{0x73, 0x4f, 0x97, 0x55, 0x86, 0x97, 0x1f,
+ 0x60, 0x87, 0x5d, 0x83, 0x10, 0x00, 0x05,
+ 0x00}},
+ {{0x73, 0x4f, 0x97, 0x55, 0x86, 0x04, 0x3e,
+ 0xE2, 0x89, 0xDf, 0x05, 0x00, 0x00, 0x05,
+ 0x00}},
+ {{0x87, 0x63, 0x8B, 0x69, 0x1A, 0x7c, 0xf0,
+ 0x5A, 0x8F, 0x57, 0x7D, 0x20, 0x00, 0x26,
+ 0x01}},
+ {{0xA3, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xFf, 0x25, 0x10, 0x00, 0x02,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_1[] = {
+ {{0x63, 0x4f, 0x87, 0x54, 0x9f, 0xb4, 0x1f,
+ 0x92, 0x89, 0x8f, 0xb5, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x63, 0x4f, 0x87, 0x54, 0x9f, 0x82, 0x1f,
+ 0x60, 0x87, 0x5d, 0x83, 0x10, 0x00, 0x01,
+ 0x00}},
+ {{0x63, 0x4f, 0x87, 0x54, 0x9f, 0xb4, 0x1f,
+ 0x92, 0x89, 0x8f, 0xb5, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x63, 0x4f, 0x87, 0x54, 0x9f, 0x82, 0x1f,
+ 0x60, 0x87, 0x5d, 0x83, 0x10, 0x00, 0x01,
+ 0x00}},
+ {{0x63, 0x4f, 0x87, 0x54, 0x9f, 0x04, 0x3e,
+ 0xe2, 0x89, 0xdf, 0x05, 0x00, 0x00, 0x01,
+ 0x00}},
+ {{0x7e, 0x63, 0x82, 0x68, 0x15, 0x7c, 0xf0,
+ 0x5a, 0x8f, 0x57, 0x7d, 0x20, 0x00, 0x26,
+ 0x01}},
+ {{0xa3, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0x25, 0x10, 0x00, 0x02,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1_H[] = {
+ {{0x30, 0x27, 0x94, 0x2c, 0x92, 0xaf, 0x1f,
+ 0x90, 0x85, 0x8f, 0xab, 0x30, 0x00, 0x04,
+ 0x00}},
+ {{0x30, 0x27, 0x94, 0x2c, 0x92, 0x83, 0x1f,
+ 0x5e, 0x83, 0x5d, 0x79, 0x10, 0x00, 0x04,
+ 0x00}},
+ {{0x30, 0x27, 0x94, 0x2c, 0x92, 0xaf, 0x1f,
+ 0x90, 0x85, 0x8f, 0xab, 0x30, 0x00, 0x04,
+ 0x00}},
+ {{0x30, 0x27, 0x94, 0x2c, 0x92, 0x83, 0x1f,
+ 0x5e, 0x83, 0x5d, 0x79, 0x10, 0x00, 0x04,
+ 0x00}},
+ {{0x30, 0x27, 0x94, 0x2c, 0x92, 0x04, 0x3e,
+ 0xe0, 0x85, 0xdf, 0xfb, 0x10, 0x00, 0x04,
+ 0x00}},
+ {{0x3d, 0x31, 0x81, 0x37, 0x1f, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x73, 0x20, 0x00, 0x05,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1_H[] = {
+ {{0x37, 0x27, 0x9B, 0x2b, 0x94, 0xc4, 0x1f,
+ 0x92, 0x89, 0x8f, 0xb5, 0x30, 0x00, 0x44,
+ 0x00}},
+ {{0x37, 0x27, 0x9B, 0x2b, 0x94, 0x97, 0x1f,
+ 0x60, 0x87, 0x5D, 0x83, 0x01, 0x00, 0x44,
+ 0x00}},
+ {{0x37, 0x27, 0x9B, 0x2b, 0x94, 0xc4, 0x1f,
+ 0x92, 0x89, 0x8f, 0xb5, 0x30, 0x00, 0x44,
+ 0x00}},
+ {{0x37, 0x27, 0x9B, 0x2b, 0x94, 0x97, 0x1f,
+ 0x60, 0x87, 0x5D, 0x83, 0x01, 0x00, 0x44,
+ 0x00}},
+ {{0x37, 0x27, 0x9B, 0x2b, 0x94, 0x04, 0x3e,
+ 0xE2, 0x89, 0xDf, 0x05, 0x00, 0x00, 0x44,
+ 0x00}},
+ {{0x41, 0x31, 0x85, 0x35, 0x1d, 0x7c, 0xf0,
+ 0x5A, 0x8F, 0x57, 0x7D, 0x20, 0x00, 0x55,
+ 0x01}},
+ {{0x4f, 0x3F, 0x93, 0x45, 0x0D, 0x24, 0xf5,
+ 0x02, 0x88, 0xFf, 0x25, 0x10, 0x00, 0x01,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_1_H[] = {
+ {{0x2f, 0x27, 0x93, 0x2b, 0x90, 0xb4, 0x1f,
+ 0x92, 0x89, 0x8f, 0xb5, 0x30, 0x00, 0x04,
+ 0x00}},
+ {{0x2f, 0x27, 0x93, 0x2b, 0x90, 0x82, 0x1f,
+ 0x60, 0x87, 0x5d, 0x83, 0x10, 0x00, 0x04,
+ 0x00}},
+ {{0x2f, 0x27, 0x93, 0x2b, 0x90, 0xb4, 0x1f,
+ 0x92, 0x89, 0x8f, 0xb5, 0x30, 0x00, 0x04,
+ 0x00}},
+ {{0x2f, 0x27, 0x93, 0x2b, 0x90, 0x82, 0x1f,
+ 0x60, 0x87, 0x5d, 0x83, 0x10, 0x00, 0x04,
+ 0x00}},
+ {{0x2f, 0x27, 0x93, 0x2b, 0x90, 0x04, 0x3e,
+ 0xe2, 0x89, 0xdf, 0x05, 0x00, 0x00, 0x04,
+ 0x00}},
+ {{0x3c, 0x31, 0x80, 0x35, 0x1c, 0x7c, 0xf0,
+ 0x5a, 0x8f, 0x57, 0x7d, 0x20, 0x00, 0x55,
+ 0x01}},
+ {{0x4f, 0x3f, 0x93, 0x45, 0x0d, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0x25, 0x10, 0x00, 0x01,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_2[] = {
+ {{0x7f, 0x4f, 0x83, 0x62, 0x12, 0x72, 0x3e,
+ 0xf4, 0x88, 0x8f, 0x73, 0x20, 0x00, 0x06,
+ 0x00}},
+ {{0x7f, 0x4f, 0x83, 0x62, 0x12, 0x72, 0x3e,
+ 0xdb, 0x8f, 0x5d, 0x73, 0x20, 0x00, 0x06,
+ 0x00}},
+ {{0x7f, 0x4f, 0x83, 0x62, 0x12, 0x72, 0x3e,
+ 0xf4, 0x88, 0x8f, 0x73, 0x20, 0x00, 0x06,
+ 0x00}},
+ {{0x7f, 0x4f, 0x83, 0x62, 0x12, 0x72, 0x3e,
+ 0xdb, 0x8f, 0x5d, 0x73, 0x20, 0x00, 0x06,
+ 0x00}},
+ {{0x7f, 0x4f, 0x83, 0x62, 0x12, 0x72, 0xba,
+ 0x1c, 0x80, 0xdf, 0x73, 0x00, 0x00, 0x06,
+ 0x00}},
+ {{0x7f, 0x63, 0x83, 0x6c, 0x1c, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x73, 0x20, 0x00, 0x06,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_2[] = {
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x72, 0x88, 0xdf, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x63, 0x87, 0x78, 0x89, 0x24, 0xf1,
+ 0xae, 0x84, 0x57, 0x25, 0x30, 0x00, 0x02,
+ 0x01}},
+ {{0xa3, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0x25, 0x10, 0x00, 0x02,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_2[] = {
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x4f, 0x87, 0x6e, 0x9f, 0x24, 0xbb,
+ 0x72, 0x88, 0xdf, 0x25, 0x30, 0x00, 0x06,
+ 0x00}},
+ {{0xa3, 0x63, 0x87, 0x78, 0x89, 0x24, 0xf1,
+ 0xae, 0x84, 0x57, 0x25, 0x30, 0x00, 0x02,
+ 0x01}},
+ {{0xa3, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0x25, 0x10, 0x00, 0x02,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_2_H[] = {
+ {{0x3d, 0x27, 0x81, 0x32, 0x1a, 0x72, 0x3e,
+ 0xf4, 0x88, 0x8f, 0x73, 0x20, 0x00, 0x05,
+ 0x00}},
+ {{0x3d, 0x27, 0x81, 0x32, 0x1a, 0x72, 0x3e,
+ 0xdb, 0x8f, 0x5d, 0x73, 0x20, 0x00, 0x05,
+ 0x00}},
+ {{0x3d, 0x27, 0x81, 0x32, 0x1a, 0x72, 0x3e,
+ 0xf4, 0x88, 0x8f, 0x73, 0x20, 0x00, 0x05,
+ 0x00}},
+ {{0x3d, 0x27, 0x81, 0x3a, 0x1a, 0x72, 0x3e,
+ 0xdb, 0x8f, 0x5d, 0x73, 0x20, 0x00, 0x05,
+ 0x00}},
+ {{0x3d, 0x27, 0x81, 0x32, 0x1a, 0x72, 0xba,
+ 0x1c, 0x80, 0xdf, 0x73, 0x00, 0x00, 0x05,
+ 0x00}},
+ {{0x3d, 0x31, 0x81, 0x37, 0x1f, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x73, 0x20, 0x00, 0x05,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_2_H[] = {
+ {{0x4f, 0x27, 0x93, 0x39, 0x01, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x01, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x01, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x01, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x01, 0x24, 0xbb,
+ 0x72, 0x88, 0xdf, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x31, 0x93, 0x3e, 0x06, 0x24, 0xf1,
+ 0xae, 0x84, 0x57, 0x25, 0x30, 0x00, 0x01,
+ 0x01}},
+ {{0x4f, 0x3f, 0x93, 0x45, 0x0d, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0x25, 0x10, 0x00, 0x01,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_2_H[] = {
+ {{0x4f, 0x27, 0x93, 0x39, 0x81, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x81, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x81, 0x24, 0xbb,
+ 0x4a, 0x80, 0x8f, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x81, 0x24, 0xbb,
+ 0x31, 0x87, 0x5d, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x27, 0x93, 0x39, 0x81, 0x24, 0xbb,
+ 0x72, 0x88, 0xdf, 0x25, 0x30, 0x00, 0x01,
+ 0x00}},
+ {{0x4f, 0x31, 0x93, 0x3e, 0x86, 0x24, 0xf1,
+ 0xae, 0x84, 0x57, 0x25, 0x30, 0x00, 0x01,
+ 0x01}},
+ {{0x4f, 0x3f, 0x93, 0x45, 0x0d, 0x24, 0xf5,
+ 0x02, 0x88, 0xff, 0x25, 0x10, 0x00, 0x01,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1UNTSC[] = {
+ {{0x64, 0x4f, 0x88, 0x56, 0x9f, 0x56, 0x3e,
+ 0xe8, 0x84, 0x8f, 0x57, 0x20, 0x00, 0x01,
+ 0x00}},
+ {{0x64, 0x4f, 0x88, 0x56, 0x9f, 0x56, 0x3e,
+ 0xd0, 0x82, 0x5d, 0x57, 0x00, 0x00, 0x01,
+ 0x00}},
+ {{0x64, 0x4f, 0x88, 0x56, 0x9f, 0x56, 0x3e,
+ 0xe8, 0x84, 0x8f, 0x57, 0x20, 0x00, 0x01,
+ 0x00}},
+ {{0x64, 0x4f, 0x88, 0x56, 0x9f, 0x56, 0x3e,
+ 0xd0, 0x82, 0x5d, 0x57, 0x00, 0x00, 0x01,
+ 0x00}},
+ {{0x5d, 0x4f, 0x81, 0x53, 0x9c, 0x56, 0xba,
+ 0x18, 0x84, 0xdf, 0x57, 0x00, 0x00, 0x01,
+ 0x00}},
+ {{0x80, 0x63, 0x84, 0x6c, 0x17, 0xec, 0xf0,
+ 0x90, 0x8c, 0x57, 0xed, 0x20, 0x00, 0x06,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1ONTSC[] = {
+ {{0x64, 0x4f, 0x88, 0x5a, 0x9f, 0x0b, 0x3e,
+ 0xc0, 0x84, 0x8f, 0x0c, 0x20, 0x00, 0x01,
+ 0x00}},
+ {{0x64, 0x4f, 0x88, 0x5a, 0x9f, 0x0b, 0x3e,
+ 0xb0, 0x8d, 0x5d, 0x0c, 0x00, 0x00, 0x01,
+ 0x00}},
+ {{0x64, 0x4f, 0x88, 0x5a, 0x9f, 0x0b, 0x3e,
+ 0xc0, 0x84, 0x8f, 0x0c, 0x20, 0x00, 0x01,
+ 0x00}},
+ {{0x64, 0x4f, 0x88, 0x5a, 0x9f, 0x0b, 0x3e,
+ 0xb0, 0x8d, 0x5d, 0x0c, 0x00, 0x00, 0x01,
+ 0x00}},
+ {{0x5d, 0x4f, 0x81, 0x56, 0x9c, 0x0b, 0x3e,
+ 0xe8, 0x84, 0xdf, 0x0c, 0x00, 0x00, 0x01,
+ 0x00}},
+ {{0x7d, 0x63, 0x81, 0x6a, 0x16, 0xba, 0xf0,
+ 0x7f, 0x86, 0x57, 0xbb, 0x00, 0x00, 0x06,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1UPAL[] = {
+ {{0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
+ 0xf8, 0x83, 0x8f, 0x70, 0x20, 0x00, 0x05,
+ 0x00}},
+ {{0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
+ 0xde, 0x81, 0x5d, 0x70, 0x00, 0x00, 0x05,
+ 0x00}},
+ {{0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
+ 0xf8, 0x83, 0x8f, 0x70, 0x20, 0x00, 0x05,
+ 0x00}},
+ {{0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
+ 0xde, 0x81, 0x5d, 0x70, 0x00, 0x00, 0x05,
+ 0x00}},
+ {{0x64, 0x4f, 0x88, 0x55, 0x80, 0xec, 0xba,
+ 0x50, 0x84, 0xdf, 0xed, 0x00, 0x00, 0x05,
+ 0x00}},
+ {{0x70, 0x63, 0x94, 0x68, 0x8d, 0x42, 0xf1,
+ 0xc8, 0x8c, 0x57, 0xe9, 0x20, 0x00, 0x05,
+ 0x01}}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1OPAL[] = {
+ {{0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
+ 0xf0, 0x83, 0x8f, 0x70, 0x20, 0x00, 0x05,
+ 0x00}},
+ {{0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
+ 0xde, 0x81, 0x5d, 0x70, 0x00, 0x00, 0x05,
+ 0x00}},
+ {{0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
+ 0xf0, 0x83, 0x8f, 0x70, 0x20, 0x00, 0x05,
+ 0x00}},
+ {{0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e,
+ 0xde, 0x81, 0x5d, 0x70, 0x00, 0x00, 0x05,
+ 0x00}},
+ {{0x64, 0x4f, 0x88, 0x55, 0x80, 0x6f, 0xba,
+ 0x20, 0x83, 0xdf, 0x70, 0x00, 0x00, 0x05,
+ 0x00}},
+ {{0x73, 0x63, 0x97, 0x69, 0x8e, 0xec, 0xf0,
+ 0x90, 0x8c, 0x57, 0xed, 0x20, 0x00, 0x05,
+ 0x01}}
+};
+
+typedef struct _SiS310_CHTVRegDataStruct {
+ UCHAR Reg[5];
+} SiS310_CHTVRegDataStruct;
+SiS310_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] = {
+ {{0x00}}
+};
+
+SiS310_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] = {
+ {{0x00}}
+};
+
+SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] = {
+ {{0x00}}
+};
+
+SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] = {
+ {{0x00}}
+};
+
+UCHAR SiS310_CHTVVCLKUNTSC[] = { 0x00 };
+
+UCHAR SiS310_CHTVVCLKONTSC[] = { 0x00 };
+
+UCHAR SiS310_CHTVVCLKUPAL[] = { 0x00 };
+
+UCHAR SiS310_CHTVVCLKOPAL[] = { 0x00 };
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/325vtbl.h linux/drivers/video/sis/325vtbl.h
--- v2.4.14/linux/drivers/video/sis/325vtbl.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/sis/325vtbl.h Fri Nov 9 14:11:14 2001
@@ -0,0 +1,2318 @@


+typedef struct _SiS310_StStruct {
+ UCHAR St_ModeID;
+ USHORT St_ModeFlag;
+ UCHAR St_StTableIndex;
+ UCHAR St_CRT2CRTC;
+ UCHAR St_ResInfo;
+ UCHAR VB_StTVFlickerIndex;
+ UCHAR VB_StTVEdgeIndex;
+ UCHAR VB_StTVYFilterIndex;
+} SiS310_StStruct;

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

echo 'End of part 074'
echo 'File patch-2.4.15 is continued in part 075'
echo "075" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:41 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part065

#!/bin/sh -x
# this is part 065 of a 115 - part archive


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

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

+#elif SYM_CONF_DMA_ADDRESSING_MODE == 2


+ if (!np->use_dac)
+ np->rv_ccntl1 |= (DDAC);
+ else

+ np->rv_ccntl1 |= (0 | EXTIBMV);
+#endif
+ }
+
+ /*
+ * Phase mismatch handled by SCRIPTS (895A/896/1010) ?
+ */
+ if (np->features & FE_NOPM)
+ np->rv_ccntl0 |= (ENPMJ);
+
+ /*
+ * C1010-33 Errata: Part Number:609-039638 (rev. 1) is fixed.
+ * In dual channel mode, contention occurs if internal cycles
+ * are used. Disable internal cycles.
+ */
+ if (np->device_id == PCI_ID_LSI53C1010 &&
+ np->revision_id < 0x1)
+ np->rv_ccntl0 |= DILS;
+
+ /*
+ * Select burst length (dwords)
+ */
+ burst_max = SYM_SETUP_BURST_ORDER;
+ if (burst_max == 255)
+ burst_max = burst_code(np->sv_dmode, np->sv_ctest4,
+ np->sv_ctest5);
+ if (burst_max > 7)
+ burst_max = 7;
+ if (burst_max > np->maxburst)
+ burst_max = np->maxburst;
+
+ /*
+ * DEL 352 - 53C810 Rev x11 - Part Number 609-0392140 - ITEM 2.
+ * This chip and the 860 Rev 1 may wrongly use PCI cache line
+ * based transactions on LOAD/STORE instructions. So we have
+ * to prevent these chips from using such PCI transactions in
+ * this driver. The generic ncr driver that does not use
+ * LOAD/STORE instructions does not need this work-around.
+ */
+ if ((np->device_id == PCI_ID_SYM53C810 &&
+ np->revision_id >= 0x10 && np->revision_id <= 0x11) ||
+ (np->device_id == PCI_ID_SYM53C860 &&
+ np->revision_id <= 0x1))
+ np->features &= ~(FE_WRIE|FE_ERL|FE_ERMP);
+
+ /*
+ * Select all supported special features.
+ * If we are using on-board RAM for scripts, prefetch (PFEN)
+ * does not help, but burst op fetch (BOF) does.
+ * Disabling PFEN makes sure BOF will be used.
+ */
+ if (np->features & FE_ERL)
+ np->rv_dmode |= ERL; /* Enable Read Line */
+ if (np->features & FE_BOF)
+ np->rv_dmode |= BOF; /* Burst Opcode Fetch */
+ if (np->features & FE_ERMP)
+ np->rv_dmode |= ERMP; /* Enable Read Multiple */
+#if 1
+ if ((np->features & FE_PFEN) && !np->ram_ba)
+#else
+ if (np->features & FE_PFEN)
+#endif
+ np->rv_dcntl |= PFEN; /* Prefetch Enable */
+ if (np->features & FE_CLSE)
+ np->rv_dcntl |= CLSE; /* Cache Line Size Enable */
+ if (np->features & FE_WRIE)
+ np->rv_ctest3 |= WRIE; /* Write and Invalidate */
+ if (np->features & FE_DFS)
+ np->rv_ctest5 |= DFS; /* Dma Fifo Size */
+
+ /*
+ * Select some other
+ */
+ if (SYM_SETUP_PCI_PARITY)
+ np->rv_ctest4 |= MPEE; /* Master parity checking */
+ if (SYM_SETUP_SCSI_PARITY)
+ np->rv_scntl0 |= 0x0a; /* full arb., ena parity, par->ATN */
+
+ /*
+ * Get parity checking, host ID and verbose mode from NVRAM
+ */
+ np->myaddr = 255;
+ sym_nvram_setup_host (np, nvram);
+
+ /*
+ * Get SCSI addr of host adapter (set by bios?).
+ */
+ if (np->myaddr == 255) {
+ np->myaddr = INB(nc_scid) & 0x07;
+ if (!np->myaddr)
+ np->myaddr = SYM_SETUP_HOST_ID;
+ }
+
+ /*
+ * Prepare initial io register bits for burst length
+ */
+ sym_init_burst(np, burst_max);
+
+ /*
+ * Set SCSI BUS mode.
+ * - LVD capable chips (895/895A/896/1010) report the
+ * current BUS mode through the STEST4 IO register.
+ * - For previous generation chips (825/825A/875),
+ * user has to tell us how to check against HVD,
+ * since a 100% safe algorithm is not possible.
+ */
+ np->scsi_mode = SMODE_SE;
+ if (np->features & (FE_ULTRA2|FE_ULTRA3))
+ np->scsi_mode = (np->sv_stest4 & SMODE);
+ else if (np->features & FE_DIFF) {
+ if (SYM_SETUP_SCSI_DIFF == 1) {
+ if (np->sv_scntl3) {
+ if (np->sv_stest2 & 0x20)
+ np->scsi_mode = SMODE_HVD;
+ }
+ else if (nvram->type == SYM_SYMBIOS_NVRAM) {
+ if (!(INB(nc_gpreg) & 0x08))
+ np->scsi_mode = SMODE_HVD;
+ }
+ }
+ else if (SYM_SETUP_SCSI_DIFF == 2)
+ np->scsi_mode = SMODE_HVD;
+ }
+ if (np->scsi_mode == SMODE_HVD)
+ np->rv_stest2 |= 0x20;
+
+ /*
+ * Set LED support from SCRIPTS.
+ * Ignore this feature for boards known to use a
+ * specific GPIO wiring and for the 895A, 896
+ * and 1010 that drive the LED directly.
+ */
+ if ((SYM_SETUP_SCSI_LED ||
+ (nvram->type == SYM_SYMBIOS_NVRAM ||
+ (nvram->type == SYM_TEKRAM_NVRAM &&
+ np->device_id == PCI_ID_SYM53C895))) &&
+ !(np->features & FE_LEDC) && !(np->sv_gpcntl & 0x01))
+ np->features |= FE_LED0;
+
+ /*
+ * Set irq mode.
+ */
+ switch(SYM_SETUP_IRQ_MODE & 3) {
+ case 2:
+ np->rv_dcntl |= IRQM;


+ break;
+ case 1:

+ np->rv_dcntl |= (np->sv_dcntl & IRQM);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Configure targets according to driver setup.
+ * If NVRAM present get targets setup from NVRAM.
+ */
+ for (i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {
+ tcb_p tp = &np->target[i];
+
+ tp->tinfo.user.scsi_version = tp->tinfo.curr.scsi_version= 2;
+ tp->tinfo.user.spi_version = tp->tinfo.curr.spi_version = 2;
+ tp->tinfo.user.period = np->minsync;
+ tp->tinfo.user.offset = np->maxoffs;
+ tp->tinfo.user.width = np->maxwide ? BUS_16_BIT : BUS_8_BIT;
+ tp->usrflags |= (SYM_DISC_ENABLED | SYM_TAGS_ENABLED);
+ tp->usrtags = SYM_SETUP_MAX_TAG;
+
+ sym_nvram_setup_target (np, i, nvram);
+
+ /*
+ * For now, guess PPR/DT support from the period
+ * and BUS width.
+ */
+ if (np->features & FE_ULTRA3) {
+ if (tp->tinfo.user.period <= 9 &&
+ tp->tinfo.user.width == BUS_16_BIT) {
+ tp->tinfo.user.options |= PPR_OPT_DT;
+ tp->tinfo.user.offset = np->maxoffs_dt;
+ tp->tinfo.user.spi_version = 3;
+ }
+ }
+
+ if (!tp->usrtags)
+ tp->usrflags &= ~SYM_TAGS_ENABLED;
+ }
+
+ /*
+ * Let user know about the settings.
+ */
+ i = nvram->type;
+ printf("%s: %s NVRAM, ID %d, Fast-%d, %s, %s\n", sym_name(np),
+ i == SYM_SYMBIOS_NVRAM ? "Symbios" :
+ (i == SYM_TEKRAM_NVRAM ? "Tekram" : "No"),
+ np->myaddr,
+ (np->features & FE_ULTRA3) ? 80 :
+ (np->features & FE_ULTRA2) ? 40 :
+ (np->features & FE_ULTRA) ? 20 : 10,
+ sym_scsi_bus_mode(np->scsi_mode),
+ (np->rv_scntl0 & 0xa) ? "parity checking" : "NO parity");
+ /*
+ * Tell him more on demand.
+ */
+ if (sym_verbose) {
+ printf("%s: %s IRQ line driver%s\n",
+ sym_name(np),
+ np->rv_dcntl & IRQM ? "totem pole" : "open drain",
+ np->ram_ba ? ", using on-chip SRAM" : "");
+ printf("%s: using %s firmware.\n", sym_name(np), np->fw_name);
+ if (np->features & FE_NOPM)
+ printf("%s: handling phase mismatch from SCRIPTS.\n",
+ sym_name(np));
+ }
+ /*
+ * And still more.
+ */


+ if (sym_verbose >= 2) {

+ printf ("%s: initial SCNTL3/DMODE/DCNTL/CTEST3/4/5 = "
+ "(hex) %02x/%02x/%02x/%02x/%02x/%02x\n",
+ sym_name(np), np->sv_scntl3, np->sv_dmode, np->sv_dcntl,
+ np->sv_ctest3, np->sv_ctest4, np->sv_ctest5);
+
+ printf ("%s: final SCNTL3/DMODE/DCNTL/CTEST3/4/5 = "
+ "(hex) %02x/%02x/%02x/%02x/%02x/%02x\n",
+ sym_name(np), np->rv_scntl3, np->rv_dmode, np->rv_dcntl,
+ np->rv_ctest3, np->rv_ctest4, np->rv_ctest5);
+ }
+ /*
+ * Let user be aware of targets that have some disable flags set.
+ */
+ sym_print_targets_flag(np, SYM_SCAN_BOOT_DISABLED, "SCAN AT BOOT");
+ if (sym_verbose)
+ sym_print_targets_flag(np, SYM_SCAN_LUNS_DISABLED,
+ "SCAN FOR LUNS");


+
+ return 0;
+}
+
+/*

+ * Test the pci bus snoop logic :-(
+ *
+ * Has to be called with interrupts disabled.
+ */
+#ifndef SYM_CONF_IOMAPPED
+static int sym_regtest (hcb_p np)
+{
+ register volatile u32 data;
+ /*
+ * chip registers may NOT be cached.
+ * write 0xffffffff to a read only register area,
+ * and try to read it back.
+ */
+ data = 0xffffffff;
+ OUTL_OFF(offsetof(struct sym_reg, nc_dstat), data);
+ data = INL_OFF(offsetof(struct sym_reg, nc_dstat));
+#if 1
+ if (data == 0xffffffff) {
+#else
+ if ((data & 0xe2f0fffd) != 0x02000080) {
+#endif
+ printf ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n",
+ (unsigned) data);
+ return (0x10);
+ };
+ return (0);
+}
+#endif
+
+static int sym_snooptest (hcb_p np)
+{
+ u32 sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat;
+ int i, err=0;
+#ifndef SYM_CONF_IOMAPPED
+ err |= sym_regtest (np);
+ if (err) return (err);
+#endif
+restart_test:
+ /*
+ * Enable Master Parity Checking as we intend
+ * to enable it for normal operations.
+ */
+ OUTB (nc_ctest4, (np->rv_ctest4 & MPEE));
+ /*
+ * init
+ */
+ pc = SCRIPTZ_BA (np, snooptest);
+ host_wr = 1;
+ sym_wr = 2;
+ /*
+ * Set memory and register.
+ */
+ np->scratch = cpu_to_scr(host_wr);
+ OUTL (nc_temp, sym_wr);
+ /*
+ * Start script (exchange values)
+ */
+ OUTL (nc_dsa, np->hcb_ba);
+ OUTL_DSP (pc);
+ /*
+ * Wait 'til done (with timeout)
+ */
+ for (i=0; i<SYM_SNOOP_TIMEOUT; i++)


+ if (INB(nc_istat) & (INTF|SIP|DIP))

+ break;
+ if (i>=SYM_SNOOP_TIMEOUT) {
+ printf ("CACHE TEST FAILED: timeout.\n");
+ return (0x20);
+ };
+ /*
+ * Check for fatal DMA errors.
+ */
+ dstat = INB (nc_dstat);
+#if 1 /* Band aiding for broken hardwares that fail PCI parity */
+ if ((dstat & MDPE) && (np->rv_ctest4 & MPEE)) {
+ printf ("%s: PCI DATA PARITY ERROR DETECTED - "
+ "DISABLING MASTER DATA PARITY CHECKING.\n",
+ sym_name(np));
+ np->rv_ctest4 &= ~MPEE;
+ goto restart_test;
+ }
+#endif
+ if (dstat & (MDPE|BF|IID)) {
+ printf ("CACHE TEST FAILED: DMA error (dstat=0x%02x).", dstat);
+ return (0x80);
+ }
+ /*
+ * Save termination position.
+ */
+ pc = INL (nc_dsp);
+ /*
+ * Read memory and register.
+ */
+ host_rd = scr_to_cpu(np->scratch);
+ sym_rd = INL (nc_scratcha);
+ sym_bk = INL (nc_temp);
+ /*
+ * Check termination position.
+ */
+ if (pc != SCRIPTZ_BA (np, snoopend)+8) {
+ printf ("CACHE TEST FAILED: script execution failed.\n");
+ printf ("start=%08lx, pc=%08lx, end=%08lx\n",
+ (u_long) SCRIPTZ_BA (np, snooptest), (u_long) pc,
+ (u_long) SCRIPTZ_BA (np, snoopend) +8);
+ return (0x40);
+ };
+ /*
+ * Show results.
+ */
+ if (host_wr != sym_rd) {
+ printf ("CACHE TEST FAILED: host wrote %d, chip read %d.\n",
+ (int) host_wr, (int) sym_rd);
+ err |= 1;
+ };
+ if (host_rd != sym_wr) {
+ printf ("CACHE TEST FAILED: chip wrote %d, host read %d.\n",
+ (int) sym_wr, (int) host_rd);
+ err |= 2;
+ };
+ if (sym_bk != sym_wr) {
+ printf ("CACHE TEST FAILED: chip wrote %d, read back %d.\n",
+ (int) sym_wr, (int) sym_bk);
+ err |= 4;
+ };
+
+ return (err);
+}
+
+/*
+ * log message for real hard errors
+ *
+ * sym0 targ 0?: ERROR (ds:si) (so-si-sd) (sx/s3/s4) @ name (dsp:dbc).
+ * reg: r0 r1 r2 r3 r4 r5 r6 ..... rf.
+ *
+ * exception register:
+ * ds: dstat
+ * si: sist
+ *
+ * SCSI bus lines:
+ * so: control lines as driven by chip.
+ * si: control lines as seen by chip.
+ * sd: scsi data lines as seen by chip.
+ *
+ * wide/fastmode:
+ * sx: sxfer (see the manual)
+ * s3: scntl3 (see the manual)
+ * s4: scntl4 (see the manual)
+ *
+ * current script command:
+ * dsp: script adress (relative to start of script).
+ * dbc: first word of script command.
+ *
+ * First 24 register of the chip:
+ * r0..rf
+ */
+static void sym_log_hard_error(hcb_p np, u_short sist, u_char dstat)
+{
+ u32 dsp;
+ int script_ofs;
+ int script_size;
+ char *script_name;
+ u_char *script_base;
+ int i;
+
+ dsp = INL (nc_dsp);
+
+ if (dsp > np->scripta_ba &&
+ dsp <= np->scripta_ba + np->scripta_sz) {
+ script_ofs = dsp - np->scripta_ba;
+ script_size = np->scripta_sz;
+ script_base = (u_char *) np->scripta0;
+ script_name = "scripta";
+ }
+ else if (np->scriptb_ba < dsp &&
+ dsp <= np->scriptb_ba + np->scriptb_sz) {
+ script_ofs = dsp - np->scriptb_ba;
+ script_size = np->scriptb_sz;
+ script_base = (u_char *) np->scriptb0;
+ script_name = "scriptb";
+ } else {
+ script_ofs = dsp;
+ script_size = 0;
+ script_base = 0;
+ script_name = "mem";
+ }
+
+ printf ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x/%x) @ (%s %x:%08x).\n",
+ sym_name (np), (unsigned)INB (nc_sdid)&0x0f, dstat, sist,
+ (unsigned)INB (nc_socl), (unsigned)INB (nc_sbcl),
+ (unsigned)INB (nc_sbdl), (unsigned)INB (nc_sxfer),
+ (unsigned)INB (nc_scntl3),
+ (np->features & FE_C10) ? (unsigned)INB (nc_scntl4) : 0,
+ script_name, script_ofs, (unsigned)INL (nc_dbc));
+
+ if (((script_ofs & 3) == 0) &&
+ (unsigned)script_ofs < script_size) {
+ printf ("%s: script cmd = %08x\n", sym_name(np),
+ scr_to_cpu((int) *(u32 *)(script_base + script_ofs)));
+ }
+
+ printf ("%s: regdump:", sym_name(np));
+ for (i=0; i<24;i++)
+ printf (" %02x", (unsigned)INB_OFF(i));


+ printf (".\n");
+

+ /*
+ * PCI BUS error.
+ */
+ if (dstat & (MDPE|BF))
+ sym_log_bus_error(np);
+}
+
+static struct sym_pci_chip sym_pci_dev_table[] = {
+ {PCI_ID_SYM53C810, 0x0f, "810", 4, 8, 4, 64,
+ FE_ERL}
+ ,
+#ifdef SYM_DEBUG_GENERIC_SUPPORT
+ {PCI_ID_SYM53C810, 0xff, "810a", 4, 8, 4, 1,
+ FE_BOF}
+ ,
+#else
+ {PCI_ID_SYM53C810, 0xff, "810a", 4, 8, 4, 1,
+ FE_CACHE_SET|FE_LDSTR|FE_PFEN|FE_BOF}
+ ,
+#endif
+ {PCI_ID_SYM53C815, 0xff, "815", 4, 8, 4, 64,
+ FE_BOF|FE_ERL}
+ ,
+ {PCI_ID_SYM53C825, 0x0f, "825", 6, 8, 4, 64,
+ FE_WIDE|FE_BOF|FE_ERL|FE_DIFF}
+ ,
+ {PCI_ID_SYM53C825, 0xff, "825a", 6, 8, 4, 2,
+ FE_WIDE|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM|FE_DIFF}
+ ,
+ {PCI_ID_SYM53C860, 0xff, "860", 4, 8, 5, 1,
+ FE_ULTRA|FE_CACHE_SET|FE_BOF|FE_LDSTR|FE_PFEN}
+ ,
+ {PCI_ID_SYM53C875, 0x01, "875", 6, 16, 5, 2,
+ FE_WIDE|FE_ULTRA|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
+ FE_RAM|FE_DIFF|FE_VARCLK}
+ ,
+ {PCI_ID_SYM53C875, 0xff, "875", 6, 16, 5, 2,
+ FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
+ FE_RAM|FE_DIFF|FE_VARCLK}
+ ,
+ {PCI_ID_SYM53C875_2, 0xff, "875", 6, 16, 5, 2,
+ FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
+ FE_RAM|FE_DIFF|FE_VARCLK}
+ ,
+ {PCI_ID_SYM53C885, 0xff, "885", 6, 16, 5, 2,
+ FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
+ FE_RAM|FE_DIFF|FE_VARCLK}
+ ,
+#ifdef SYM_DEBUG_GENERIC_SUPPORT
+ {PCI_ID_SYM53C895, 0xff, "895", 6, 31, 7, 2,
+ FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|
+ FE_RAM|FE_LCKFRQ}
+ ,
+#else
+ {PCI_ID_SYM53C895, 0xff, "895", 6, 31, 7, 2,
+ FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
+ FE_RAM|FE_LCKFRQ}
+ ,
+#endif
+ {PCI_ID_SYM53C896, 0xff, "896", 6, 31, 7, 4,
+ FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
+ FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ}
+ ,
+ {PCI_ID_SYM53C895A, 0xff, "895a", 6, 31, 7, 4,
+ FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
+ FE_RAM|FE_RAM8K|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ}
+ ,
+ {PCI_ID_SYM53C875A, 0xff, "875a", 6, 31, 7, 4,
+ FE_WIDE|FE_ULTRA|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
+ FE_RAM|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ}
+ ,
+ {PCI_ID_LSI53C1010, 0x00, "1010-33", 6, 31, 7, 8,
+ FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
+ FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC|
+ FE_C10}
+ ,
+ {PCI_ID_LSI53C1010, 0xff, "1010-33", 6, 31, 7, 8,
+ FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
+ FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC|
+ FE_C10|FE_U3EN}
+ ,
+ {PCI_ID_LSI53C1010_2, 0xff, "1010-66", 6, 31, 7, 8,
+ FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
+ FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_66MHZ|FE_CRC|
+ FE_C10|FE_U3EN}
+ ,
+ {PCI_ID_LSI53C1510D, 0xff, "1510d", 6, 31, 7, 4,
+ FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
+ FE_RAM|FE_IO256|FE_LEDC}
+};
+
+#define sym_pci_num_devs \
+ (sizeof(sym_pci_dev_table) / sizeof(sym_pci_dev_table[0]))
+
+/*
+ * Look up the chip table.
+ *
+ * Return a pointer to the chip entry if found,
+ * zero otherwise.
+ */


+struct sym_pci_chip *
+sym_lookup_pci_chip_table (u_short device_id, u_char revision)

+{
+ struct sym_pci_chip *chip;
+ int i;
+
+ for (i = 0; i < sym_pci_num_devs; i++) {
+ chip = &sym_pci_dev_table[i];
+ if (device_id != chip->device_id)
+ continue;
+ if (revision > chip->revision_id)
+ continue;
+ return chip;
+ }


+
+ return 0;
+}
+

+#if SYM_CONF_DMA_ADDRESSING_MODE == 2
+/*

+ * Lookup the 64 bit DMA segments map.
+ * This is only used if the direct mapping
+ * has been unsuccessful.
+ */


+int sym_lookup_dmap(hcb_p np, u32 h, int s)

+{
+ int i;
+
+ if (!np->use_dac)
+ goto weird;
+
+ /* Look up existing mappings */
+ for (i = SYM_DMAP_SIZE-1; i > 0; i--) {
+ if (h == np->dmap_bah[i])
+ return i;
+ }
+ /* If direct mapping is free, get it */
+ if (!np->dmap_bah[s])
+ goto new;
+ /* Collision -> lookup free mappings */
+ for (s = SYM_DMAP_SIZE-1; s > 0; s--) {
+ if (!np->dmap_bah[s])
+ goto new;
+ }
+weird:
+ panic("sym: ran out of 64 bit DMA segment registers");
+ return -1;
+new:
+ np->dmap_bah[s] = h;
+ np->dmap_dirty = 1;
+ return s;
+}
+
+/*
+ * Update IO registers scratch C..R so they will be
+ * in sync. with queued CCB expectations.
+ */
+static void sym_update_dmap_regs(hcb_p np)
+{
+ int o, i;
+
+ if (!np->dmap_dirty)
+ return;
+ o = offsetof(struct sym_reg, nc_scrx[0]);
+ for (i = 0; i < SYM_DMAP_SIZE; i++) {
+ OUTL_OFF(o, np->dmap_bah[i]);
+ o += 4;
+ }
+ np->dmap_dirty = 0;
+}
+#endif
+
+/*
+ * Prepare the next negotiation message if needed.
+ *
+ * Fill in the part of message buffer that contains the
+ * negotiation and the nego_status field of the CCB.
+ * Returns the size of the message in bytes.
+ */
+static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
+{
+ tcb_p tp = &np->target[cp->target];
+ int msglen = 0;
+
+ /*
+ * Early C1010 chips need a work-around for DT
+ * data transfer to work.
+ */
+ if (!(np->features & FE_U3EN))


+ tp->tinfo.goal.options = 0;

+ /*
+ * negotiate using PPR ?
+ */
+ if (tp->tinfo.goal.options & PPR_OPT_MASK)
+ nego = NS_PPR;
+ /*
+ * negotiate wide transfers ?
+ */
+ else if (tp->tinfo.curr.width != tp->tinfo.goal.width)
+ nego = NS_WIDE;
+ /*
+ * negotiate synchronous transfers?
+ */
+ else if (tp->tinfo.curr.period != tp->tinfo.goal.period ||
+ tp->tinfo.curr.offset != tp->tinfo.goal.offset)


+ nego = NS_SYNC;
+

+ switch (nego) {
+ case NS_SYNC:
+ msgptr[msglen++] = M_EXTENDED;
+ msgptr[msglen++] = 3;
+ msgptr[msglen++] = M_X_SYNC_REQ;
+ msgptr[msglen++] = tp->tinfo.goal.period;
+ msgptr[msglen++] = tp->tinfo.goal.offset;


+ break;
+ case NS_WIDE:

+ msgptr[msglen++] = M_EXTENDED;
+ msgptr[msglen++] = 2;
+ msgptr[msglen++] = M_X_WIDE_REQ;
+ msgptr[msglen++] = tp->tinfo.goal.width;
+ break;
+ case NS_PPR:
+ msgptr[msglen++] = M_EXTENDED;
+ msgptr[msglen++] = 6;
+ msgptr[msglen++] = M_X_PPR_REQ;
+ msgptr[msglen++] = tp->tinfo.goal.period;
+ msgptr[msglen++] = 0;
+ msgptr[msglen++] = tp->tinfo.goal.offset;
+ msgptr[msglen++] = tp->tinfo.goal.width;
+ msgptr[msglen++] = tp->tinfo.goal.options & PPR_OPT_DT;
+ break;
+ };
+
+ cp->nego_status = nego;
+
+ if (nego) {
+ tp->nego_cp = cp; /* Keep track a nego will be performed */


+ if (DEBUG_FLAGS & DEBUG_NEGO) {
+ sym_print_nego_msg(np, cp->target,

+ nego == NS_SYNC ? "sync msgout" :
+ nego == NS_WIDE ? "wide msgout" :
+ "ppr msgout", msgptr);
+ };
+ };
+
+ return msglen;
+}
+
+/*
+ * Insert a job into the start queue.
+ */


+void sym_put_start_queue(hcb_p np, ccb_p cp)

+{
+ u_short qidx;
+
+#ifdef SYM_CONF_IARB_SUPPORT
+ /*
+ * If the previously queued CCB is not yet done,
+ * set the IARB hint. The SCRIPTS will go with IARB
+ * for this job when starting the previous one.
+ * We leave devices a chance to win arbitration by
+ * not using more than 'iarb_max' consecutive
+ * immediate arbitrations.
+ */
+ if (np->last_cp && np->iarb_count < np->iarb_max) {
+ np->last_cp->host_flags |= HF_HINT_IARB;
+ ++np->iarb_count;
+ }
+ else
+ np->iarb_count = 0;
+ np->last_cp = cp;
+#endif
+
+#if SYM_CONF_DMA_ADDRESSING_MODE == 2
+ /*
+ * Make SCRIPTS aware of the 64 bit DMA
+ * segment registers not being up-to-date.
+ */
+ if (np->dmap_dirty)
+ cp->host_xflags |= HX_DMAP_DIRTY;
+#endif
+
+ /*
+ * Optionnaly, set the IO timeout condition.
+ */
+#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
+ sym_timeout_ccb(np, cp, sym_cam_timeout(cp->cam_ccb));
+#endif
+
+ /*
+ * Insert first the idle task and then our job.
+ * The MBs should ensure proper ordering.
+ */
+ qidx = np->squeueput + 2;
+ if (qidx >= MAX_QUEUE*2) qidx = 0;
+
+ np->squeue [qidx] = cpu_to_scr(np->idletask_ba);
+ MEMORY_WRITE_BARRIER();
+ np->squeue [np->squeueput] = cpu_to_scr(cp->ccb_ba);
+
+ np->squeueput = qidx;
+
+ if (DEBUG_FLAGS & DEBUG_QUEUE)
+ printf ("%s: queuepos=%d.\n", sym_name (np), np->squeueput);
+
+ /*
+ * Script processor may be waiting for reselect.
+ * Wake it up.
+ */
+ MEMORY_WRITE_BARRIER();
+ OUTB (nc_istat, SIGP|np->istat_sem);
+}
+
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+/*
+ * Start next ready-to-start CCBs.
+ */


+void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn)

+{
+ SYM_QUEHEAD *qp;
+ ccb_p cp;

+
+ /*
+ * Paranoia, as usual. :-)
+ */
+ assert(!lp->started_tags || !lp->started_no_tag);
+
+ /*
+ * Try to start as many commands as asked by caller.
+ * Prevent from having both tagged and untagged
+ * commands queued to the device at the same time.
+ */
+ while (maxn--) {
+ qp = sym_remque_head(&lp->waiting_ccbq);
+ if (!qp)
+ break;
+ cp = sym_que_entry(qp, struct sym_ccb, link2_ccbq);


+ if (cp->tag != NO_TAG) {

+ if (lp->started_no_tag ||
+ lp->started_tags >= lp->started_max) {
+ sym_insque_head(qp, &lp->waiting_ccbq);
+ break;
+ }
+ lp->itlq_tbl[cp->tag] = cpu_to_scr(cp->ccb_ba);


+ lp->head.resel_sa =
+ cpu_to_scr(SCRIPTA_BA (np, resel_tag));

+ ++lp->started_tags;
+ } else {
+ if (lp->started_no_tag || lp->started_tags) {
+ sym_insque_head(qp, &lp->waiting_ccbq);
+ break;
+ }


+ lp->head.itl_task_sa = cpu_to_scr(cp->ccb_ba);
+ lp->head.resel_sa =
+ cpu_to_scr(SCRIPTA_BA (np, resel_no_tag));

+ ++lp->started_no_tag;
+ }
+ cp->started = 1;
+ sym_insque_tail(qp, &lp->started_ccbq);


+ sym_put_start_queue(np, cp);
+ }
+}

+#endif /* SYM_OPT_HANDLE_DEVICE_QUEUEING */
+
+/*
+ * The chip may have completed jobs. Look at the DONE QUEUE.
+ *
+ * On paper, memory read barriers may be needed here to
+ * prevent out of order LOADs by the CPU from having
+ * prefetched stale data prior to DMA having occurred.
+ */
+static int sym_wakeup_done (hcb_p np)
+{
+ ccb_p cp;
+ int i, n;
+ u32 dsa;
+
+ n = 0;
+ i = np->dqueueget;
+
+ /* MEMORY_READ_BARRIER(); */
+ while (1) {
+ dsa = scr_to_cpu(np->dqueue[i]);
+ if (!dsa)
+ break;
+ np->dqueue[i] = 0;
+ if ((i = i+2) >= MAX_QUEUE*2)


+ i = 0;
+

+ cp = sym_ccb_from_dsa(np, dsa);
+ if (cp) {
+ MEMORY_READ_BARRIER();
+ sym_complete_ok (np, cp);
+ ++n;
+ }
+ else
+ printf ("%s: bad DSA (%x) in done queue.\n",
+ sym_name(np), (u_int) dsa);
+ }
+ np->dqueueget = i;
+
+ return n;
+}
+
+/*
+ * Complete all active CCBs with error.
+ * Used on CHIP/SCSI RESET.
+ */
+static void sym_flush_busy_queue (hcb_p np, int cam_status)
+{
+ /*
+ * Move all active CCBs to the COMP queue
+ * and flush this queue.
+ */
+ sym_que_splice(&np->busy_ccbq, &np->comp_ccbq);
+ sym_que_init(&np->busy_ccbq);
+ sym_flush_comp_queue(np, cam_status);
+}
+
+/*
+ * Start chip.
+ *
+ * 'reason' means:
+ * 0: initialisation.
+ * 1: SCSI BUS RESET delivered or received.
+ * 2: SCSI BUS MODE changed.
+ */


+void sym_start_up (hcb_p np, int reason)

+{
+ int i;
+ u32 phys;
+
+ /*
+ * Reset chip if asked, otherwise just clear fifos.
+ */
+ if (reason == 1)
+ sym_soft_reset(np);
+ else {
+ OUTB (nc_stest3, TE|CSF);
+ OUTONB (nc_ctest3, CLF);
+ }
+
+ /*
+ * Clear Start Queue
+ */
+ phys = np->squeue_ba;
+ for (i = 0; i < MAX_QUEUE*2; i += 2) {
+ np->squeue[i] = cpu_to_scr(np->idletask_ba);
+ np->squeue[i+1] = cpu_to_scr(phys + (i+2)*4);
+ }
+ np->squeue[MAX_QUEUE*2-1] = cpu_to_scr(phys);
+
+ /*
+ * Start at first entry.
+ */
+ np->squeueput = 0;
+
+ /*
+ * Clear Done Queue
+ */
+ phys = np->dqueue_ba;
+ for (i = 0; i < MAX_QUEUE*2; i += 2) {
+ np->dqueue[i] = 0;
+ np->dqueue[i+1] = cpu_to_scr(phys + (i+2)*4);
+ }
+ np->dqueue[MAX_QUEUE*2-1] = cpu_to_scr(phys);
+
+ /*
+ * Start at first entry.
+ */
+ np->dqueueget = 0;
+
+ /*
+ * Install patches in scripts.
+ * This also let point to first position the start
+ * and done queue pointers used from SCRIPTS.
+ */
+ np->fw_patch(np);
+
+ /*
+ * Wakeup all pending jobs.
+ */
+ sym_flush_busy_queue(np, CAM_SCSI_BUS_RESET);
+
+ /*
+ * Init chip.
+ */
+ OUTB (nc_istat, 0x00 ); /* Remove Reset, abort */
+ UDELAY (2000); /* The 895 needs time for the bus mode to settle */
+
+ OUTB (nc_scntl0, np->rv_scntl0 | 0xc0);
+ /* full arb., ena parity, par->ATN */
+ OUTB (nc_scntl1, 0x00); /* odd parity, and remove CRST!! */
+
+ sym_selectclock(np, np->rv_scntl3); /* Select SCSI clock */
+
+ OUTB (nc_scid , RRE|np->myaddr); /* Adapter SCSI address */
+ OUTW (nc_respid, 1ul<<np->myaddr); /* Id to respond to */
+ OUTB (nc_istat , SIGP ); /* Signal Process */
+ OUTB (nc_dmode , np->rv_dmode); /* Burst length, dma mode */
+ OUTB (nc_ctest5, np->rv_ctest5); /* Large fifo + large burst */
+
+ OUTB (nc_dcntl , NOCOM|np->rv_dcntl); /* Protect SFBR */
+ OUTB (nc_ctest3, np->rv_ctest3); /* Write and invalidate */
+ OUTB (nc_ctest4, np->rv_ctest4); /* Master parity checking */
+
+ /* Extended Sreq/Sack filtering not supported on the C10 */


+ if (np->features & FE_C10)

+ OUTB (nc_stest2, np->rv_stest2);
+ else
+ OUTB (nc_stest2, EXT|np->rv_stest2);
+
+ OUTB (nc_stest3, TE); /* TolerANT enable */
+ OUTB (nc_stime0, 0x0c); /* HTH disabled STO 0.25 sec */
+
+ /*
+ * For now, disable AIP generation on C1010-66.
+ */
+ if (np->device_id == PCI_ID_LSI53C1010_2)
+ OUTB (nc_aipcntl1, DISAIP);
+
+ /*
+ * C10101 rev. 0 errata.
+ * Errant SGE's when in narrow. Write bits 4 & 5 of
+ * STEST1 register to disable SGE. We probably should do
+ * that from SCRIPTS for each selection/reselection, but
+ * I just don't want. :)
+ */
+ if (np->device_id == PCI_ID_LSI53C1010 &&
+ np->revision_id < 1)
+ OUTB (nc_stest1, INB(nc_stest1) | 0x30);
+
+ /*
+ * DEL 441 - 53C876 Rev 5 - Part Number 609-0392787/2788 - ITEM 2.
+ * Disable overlapped arbitration for some dual function devices,
+ * regardless revision id (kind of post-chip-design feature. ;-))
+ */
+ if (np->device_id == PCI_ID_SYM53C875)
+ OUTB (nc_ctest0, (1<<5));
+ else if (np->device_id == PCI_ID_SYM53C896)
+ np->rv_ccntl0 |= DPR;
+
+ /*
+ * Write CCNTL0/CCNTL1 for chips capable of 64 bit addressing
+ * and/or hardware phase mismatch, since only such chips
+ * seem to support those IO registers.
+ */
+ if (np->features & (FE_DAC|FE_NOPM)) {
+ OUTB (nc_ccntl0, np->rv_ccntl0);
+ OUTB (nc_ccntl1, np->rv_ccntl1);
+ }
+
+#if SYM_CONF_DMA_ADDRESSING_MODE == 2
+ /*
+ * Set up scratch C and DRS IO registers to map the 32 bit
+ * DMA address range our data structures are located in.
+ */
+ if (np->use_dac) {
+ np->dmap_bah[0] = 0; /* ??? */
+ OUTL (nc_scrx[0], np->dmap_bah[0]);
+ OUTL (nc_drs, np->dmap_bah[0]);


+ }
+#endif
+
+ /*

+ * If phase mismatch handled by scripts (895A/896/1010),
+ * set PM jump addresses.
+ */
+ if (np->features & FE_NOPM) {
+ OUTL (nc_pmjad1, SCRIPTB_BA (np, pm_handle));
+ OUTL (nc_pmjad2, SCRIPTB_BA (np, pm_handle));
+ }
+
+ /*
+ * Enable GPIO0 pin for writing if LED support from SCRIPTS.
+ * Also set GPIO5 and clear GPIO6 if hardware LED control.
+ */
+ if (np->features & FE_LED0)
+ OUTB(nc_gpcntl, INB(nc_gpcntl) & ~0x01);
+ else if (np->features & FE_LEDC)
+ OUTB(nc_gpcntl, (INB(nc_gpcntl) & ~0x41) | 0x20);
+
+ /*
+ * enable ints
+ */
+ OUTW (nc_sien , STO|HTH|MA|SGE|UDC|RST|PAR);
+ OUTB (nc_dien , MDPE|BF|SSI|SIR|IID);
+
+ /*
+ * For 895/6 enable SBMC interrupt and save current SCSI bus mode.
+ * Try to eat the spurious SBMC interrupt that may occur when
+ * we reset the chip but not the SCSI BUS (at initialization).
+ */
+ if (np->features & (FE_ULTRA2|FE_ULTRA3)) {
+ OUTONW (nc_sien, SBMC);
+ if (reason == 0) {
+ MDELAY(100);
+ INW (nc_sist);
+ }
+ np->scsi_mode = INB (nc_stest4) & SMODE;
+ }
+
+ /*
+ * Fill in target structure.
+ * Reinitialize usrsync.
+ * Reinitialize usrwide.
+ * Prepare sync negotiation according to actual SCSI bus mode.
+ */
+ for (i=0;i<SYM_CONF_MAX_TARGET;i++) {
+ tcb_p tp = &np->target[i];
+


+ tp->to_reset = 0;

+ tp->head.sval = 0;

+ tp->head.wval = np->rv_scntl3;
+ tp->head.uval = 0;
+


+ tp->tinfo.curr.period = 0;
+ tp->tinfo.curr.offset = 0;
+ tp->tinfo.curr.width = BUS_8_BIT;
+ tp->tinfo.curr.options = 0;

+ }
+
+ /*
+ * Download SCSI SCRIPTS to on-chip RAM if present,
+ * and start script processor.
+ * We do the download preferently from the CPU.
+ * For platforms that may not support PCI memory mapping,
+ * we use simple SCRIPTS that performs MEMORY MOVEs.
+ */
+ if (np->ram_ba) {


+ if (sym_verbose >= 2)

+ printf ("%s: Downloading SCSI SCRIPTS.\n",
+ sym_name(np));
+#ifdef SYM_OPT_NO_BUS_MEMORY_MAPPING
+ np->fw_patch(np);
+ if (np->ram_ws == 8192)
+ phys = SCRIPTZ_BA (np, start_ram64);
+ else
+ phys = SCRIPTZ_BA (np, start_ram);
+#else
+ if (np->ram_ws == 8192) {
+ OUTRAM_OFF(4096, np->scriptb0, np->scriptb_sz);
+ phys = scr_to_cpu(np->scr_ram_seg);
+ OUTL (nc_mmws, phys);
+ OUTL (nc_mmrs, phys);
+ OUTL (nc_sfs, phys);
+ phys = SCRIPTB_BA (np, start64);
+ }
+ else
+ phys = SCRIPTA_BA (np, init);
+ OUTRAM_OFF(0, np->scripta0, np->scripta_sz);
+#endif
+ }
+ else
+ phys = SCRIPTA_BA (np, init);
+
+ np->istat_sem = 0;
+
+ OUTL (nc_dsa, np->hcb_ba);
+ OUTL_DSP (phys);
+
+ /*
+ * Notify the XPT about the RESET condition.
+ */
+ if (reason != 0)
+ sym_xpt_async_bus_reset(np);
+}
+
+/*
+ * Switch trans mode for current job and it's target.
+ */
+static void sym_settrans(hcb_p np, int target, u_char dt, u_char ofs,
+ u_char per, u_char wide, u_char div, u_char fak)
+{
+ SYM_QUEHEAD *qp;
+ u_char sval, wval, uval;
+ tcb_p tp = &np->target[target];
+
+ assert(target == (INB (nc_sdid) & 0x0f));
+
+ sval = tp->head.sval;
+ wval = tp->head.wval;
+ uval = tp->head.uval;
+
+#if 0
+ printf("XXXX sval=%x wval=%x uval=%x (%x)\n",
+ sval, wval, uval, np->rv_scntl3);
+#endif
+ /*
+ * Set the offset.
+ */
+ if (!(np->features & FE_C10))
+ sval = (sval & ~0x1f) | ofs;
+ else
+ sval = (sval & ~0x3f) | ofs;
+
+ /*
+ * Set the sync divisor and extra clock factor.
+ */
+ if (ofs != 0) {
+ wval = (wval & ~0x70) | ((div+1) << 4);
+ if (!(np->features & FE_C10))
+ sval = (sval & ~0xe0) | (fak << 5);
+ else {
+ uval = uval & ~(XCLKH_ST|XCLKH_DT|XCLKS_ST|XCLKS_DT);
+ if (fak >= 1) uval |= (XCLKH_ST|XCLKH_DT);
+ if (fak >= 2) uval |= (XCLKS_ST|XCLKS_DT);


+ }
+ }
+
+ /*

+ * Set the bus width.
+ */
+ wval = wval & ~EWS;
+ if (wide != 0)
+ wval |= EWS;
+
+ /*
+ * Set misc. ultra enable bits.


+ */
+ if (np->features & FE_C10) {

+ uval = uval & ~(U3EN|AIPCKEN);
+ if (dt) {
+ assert(np->features & FE_U3EN);
+ uval |= U3EN;
+ }
+ }
+ else {
+ wval = wval & ~ULTRA;
+ if (per <= 12) wval |= ULTRA;
+ }
+
+ /*
+ * Stop there if sync parameters are unchanged.
+ */
+ if (tp->head.sval == sval &&
+ tp->head.wval == wval &&
+ tp->head.uval == uval)
+ return;
+ tp->head.sval = sval;
+ tp->head.wval = wval;
+ tp->head.uval = uval;
+
+ /*
+ * Disable extended Sreq/Sack filtering if per < 50.
+ * Not supported on the C1010.
+ */
+ if (per < 50 && !(np->features & FE_C10))
+ OUTOFFB (nc_stest2, EXT);
+
+ /*
+ * set actual value and sync_status
+ */
+ OUTB (nc_sxfer, tp->head.sval);
+ OUTB (nc_scntl3, tp->head.wval);
+


+ if (np->features & FE_C10) {

+ OUTB (nc_scntl4, tp->head.uval);
+ }
+
+ /*
+ * patch ALL busy ccbs of this target.
+ */
+ FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
+ ccb_p cp;


+ cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);

+ if (cp->target != target)
+ continue;

+ cp->phys.select.sel_scntl3 = tp->head.wval;
+ cp->phys.select.sel_sxfer = tp->head.sval;

+ if (np->features & FE_C10) {

+ cp->phys.select.sel_scntl4 = tp->head.uval;

+ }
+ }
+}
+
+/*

+ * We received a WDTR.
+ * Let everything be aware of the changes.
+ */
+static void sym_setwide(hcb_p np, int target, u_char wide)
+{
+ tcb_p tp = &np->target[target];
+
+ sym_settrans(np, target, 0, 0, 0, wide, 0, 0);
+
+ tp->tinfo.goal.width = tp->tinfo.curr.width = wide;


+ tp->tinfo.curr.offset = 0;
+ tp->tinfo.curr.period = 0;

+ tp->tinfo.curr.options = 0;
+

+ sym_xpt_async_nego_wide(np, target);
+}
+
+/*
+ * We received a SDTR.
+ * Let everything be aware of the changes.
+ */
+static void
+sym_setsync(hcb_p np, int target,
+ u_char ofs, u_char per, u_char div, u_char fak)
+{
+ tcb_p tp = &np->target[target];
+ u_char wide = (tp->head.wval & EWS) ? BUS_16_BIT : BUS_8_BIT;
+
+ sym_settrans(np, target, 0, ofs, per, wide, div, fak);
+
+ tp->tinfo.goal.period = tp->tinfo.curr.period = per;
+ tp->tinfo.goal.offset = tp->tinfo.curr.offset = ofs;
+ tp->tinfo.goal.options = tp->tinfo.curr.options = 0;
+
+ sym_xpt_async_nego_sync(np, target);
+}
+
+/*
+ * We received a PPR.
+ * Let everything be aware of the changes.
+ */
+static void
+sym_setpprot(hcb_p np, int target, u_char dt, u_char ofs,
+ u_char per, u_char wide, u_char div, u_char fak)
+{
+ tcb_p tp = &np->target[target];
+
+ sym_settrans(np, target, dt, ofs, per, wide, div, fak);
+
+ tp->tinfo.goal.width = tp->tinfo.curr.width = wide;
+ tp->tinfo.goal.period = tp->tinfo.curr.period = per;
+ tp->tinfo.goal.offset = tp->tinfo.curr.offset = ofs;
+ tp->tinfo.goal.options = tp->tinfo.curr.options = dt;
+
+ sym_xpt_async_nego_ppr(np, target);
+}
+
+/*
+ * generic recovery from scsi interrupt
+ *
+ * The doc says that when the chip gets an SCSI interrupt,
+ * it tries to stop in an orderly fashion, by completing
+ * an instruction fetch that had started or by flushing
+ * the DMA fifo for a write to memory that was executing.
+ * Such a fashion is not enough to know if the instruction
+ * that was just before the current DSP value has been
+ * executed or not.
+ *
+ * There are some small SCRIPTS sections that deal with
+ * the start queue and the done queue that may break any
+ * assomption from the C code if we are interrupted
+ * inside, so we reset if this happens. Btw, since these
+ * SCRIPTS sections are executed while the SCRIPTS hasn't
+ * started SCSI operations, it is very unlikely to happen.
+ *
+ * All the driver data structures are supposed to be
+ * allocated from the same 4 GB memory window, so there
+ * is a 1 to 1 relationship between DSA and driver data
+ * structures. Since we are careful :) to invalidate the
+ * DSA when we complete a command or when the SCRIPTS
+ * pushes a DSA into a queue, we can trust it when it
+ * points to a CCB.
+ */
+static void sym_recover_scsi_int (hcb_p np, u_char hsts)
+{
+ u32 dsp = INL (nc_dsp);


+ u32 dsa = INL (nc_dsa);
+ ccb_p cp = sym_ccb_from_dsa(np, dsa);

+
+ /*
+ * If we haven't been interrupted inside the SCRIPTS
+ * critical pathes, we can safely restart the SCRIPTS
+ * and trust the DSA value if it matches a CCB.
+ */
+ if ((!(dsp > SCRIPTA_BA (np, getjob_begin) &&
+ dsp < SCRIPTA_BA (np, getjob_end) + 1)) &&
+ (!(dsp > SCRIPTA_BA (np, ungetjob) &&
+ dsp < SCRIPTA_BA (np, reselect) + 1)) &&
+ (!(dsp > SCRIPTB_BA (np, sel_for_abort) &&
+ dsp < SCRIPTB_BA (np, sel_for_abort_1) + 1)) &&
+ (!(dsp > SCRIPTA_BA (np, done) &&
+ dsp < SCRIPTA_BA (np, done_end) + 1))) {
+ OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */
+ OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */
+ /*
+ * If we have a CCB, let the SCRIPTS call us back for
+ * the handling of the error with SCRATCHA filled with
+ * STARTPOS. This way, we will be able to freeze the
+ * device queue and requeue awaiting IOs.
+ */
+ if (cp) {
+ cp->host_status = hsts;
+ OUTL_DSP (SCRIPTA_BA (np, complete_error));
+ }
+ /*
+ * Otherwise just restart the SCRIPTS.
+ */
+ else {
+ OUTL (nc_dsa, 0xffffff);


+ OUTL_DSP (SCRIPTA_BA (np, start));
+ }

+ }
+ else
+ goto reset_all;
+
+ return;
+
+reset_all:
+ sym_start_reset(np);
+}
+
+/*
+ * chip exception handler for selection timeout
+ */
+static void sym_int_sto (hcb_p np)
+{
+ u32 dsp = INL (nc_dsp);
+
+ if (DEBUG_FLAGS & DEBUG_TINY) printf ("T");
+
+ if (dsp == SCRIPTA_BA (np, wf_sel_done) + 8)
+ sym_recover_scsi_int(np, HS_SEL_TIMEOUT);
+ else
+ sym_start_reset(np);
+}
+
+/*
+ * chip exception handler for unexpected disconnect
+ */
+static void sym_int_udc (hcb_p np)
+{
+ printf ("%s: unexpected disconnect\n", sym_name(np));
+ sym_recover_scsi_int(np, HS_UNEXPECTED);
+}
+
+/*
+ * chip exception handler for SCSI bus mode change
+ *
+ * spi2-r12 11.2.3 says a transceiver mode change must
+ * generate a reset event and a device that detects a reset
+ * event shall initiate a hard reset. It says also that a
+ * device that detects a mode change shall set data transfer
+ * mode to eight bit asynchronous, etc...
+ * So, just reinitializing all except chip should be enough.
+ */
+static void sym_int_sbmc (hcb_p np)
+{
+ u_char scsi_mode = INB (nc_stest4) & SMODE;
+
+ /*
+ * Notify user.
+ */
+ printf("%s: SCSI BUS mode change from %s to %s.\n", sym_name(np),
+ sym_scsi_bus_mode(np->scsi_mode), sym_scsi_bus_mode(scsi_mode));
+
+ /*
+ * Should suspend command processing for a few seconds and
+ * reinitialize all except the chip.
+ */
+ sym_start_up (np, 2);
+}
+
+/*
+ * chip exception handler for SCSI parity error.
+ *
+ * When the chip detects a SCSI parity error and is
+ * currently executing a (CH)MOV instruction, it does
+ * not interrupt immediately, but tries to finish the
+ * transfer of the current scatter entry before
+ * interrupting. The following situations may occur:
+ *
+ * - The complete scatter entry has been transferred
+ * without the device having changed phase.
+ * The chip will then interrupt with the DSP pointing
+ * to the instruction that follows the MOV.
+ *
+ * - A phase mismatch occurs before the MOV finished
+ * and phase errors are to be handled by the C code.
+ * The chip will then interrupt with both PAR and MA
+ * conditions set.
+ *
+ * - A phase mismatch occurs before the MOV finished and
+ * phase errors are to be handled by SCRIPTS.
+ * The chip will load the DSP with the phase mismatch
+ * JUMP address and interrupt the host processor.
+ */
+static void sym_int_par (hcb_p np, u_short sist)
+{
+ u_char hsts = INB (HS_PRT);
+ u32 dsp = INL (nc_dsp);
+ u32 dbc = INL (nc_dbc);


+ u32 dsa = INL (nc_dsa);

+ u_char sbcl = INB (nc_sbcl);
+ u_char cmd = dbc >> 24;
+ int phase = cmd & 7;


+ ccb_p cp = sym_ccb_from_dsa(np, dsa);
+

+ printf("%s: SCSI parity error detected: SCR1=%d DBC=%x SBCL=%x\n",
+ sym_name(np), hsts, dbc, sbcl);
+
+ /*
+ * Check that the chip is connected to the SCSI BUS.
+ */
+ if (!(INB (nc_scntl1) & ISCON)) {
+ sym_recover_scsi_int(np, HS_UNEXPECTED);
+ return;
+ }
+
+ /*
+ * If the nexus is not clearly identified, reset the bus.
+ * We will try to do better later.
+ */
+ if (!cp)
+ goto reset_all;
+
+ /*
+ * Check instruction was a MOV, direction was INPUT and
+ * ATN is asserted.
+ */
+ if ((cmd & 0xc0) || !(phase & 1) || !(sbcl & 0x8))
+ goto reset_all;
+
+ /*
+ * Keep track of the parity error.
+ */
+ OUTONB (HF_PRT, HF_EXT_ERR);
+ cp->xerr_status |= XE_PARITY_ERR;
+
+ /*
+ * Prepare the message to send to the device.
+ */
+ np->msgout[0] = (phase == 7) ? M_PARITY : M_ID_ERROR;
+
+ /*
+ * If the old phase was DATA IN phase, we have to deal with
+ * the 3 situations described above.
+ * For other input phases (MSG IN and STATUS), the device
+ * must resend the whole thing that failed parity checking
+ * or signal error. So, jumping to dispatcher should be OK.
+ */
+ if (phase == 1 || phase == 5) {
+ /* Phase mismatch handled by SCRIPTS */
+ if (dsp == SCRIPTB_BA (np, pm_handle))
+ OUTL_DSP (dsp);
+ /* Phase mismatch handled by the C code */
+ else if (sist & MA)
+ sym_int_ma (np);
+ /* No phase mismatch occurred */
+ else {
+ sym_set_script_dp (np, cp, dsp);
+ OUTL_DSP (SCRIPTA_BA (np, dispatch));
+ }
+ }
+ else if (phase == 7) /* We definitely cannot handle parity errors */
+#if 1 /* in message-in phase due to the relection */
+ goto reset_all; /* path and various message anticipations. */
+#else


+ OUTL_DSP (SCRIPTA_BA (np, clrack));

+#endif
+ else
+ OUTL_DSP (SCRIPTA_BA (np, dispatch));
+ return;
+
+reset_all:
+ sym_start_reset(np);
+ return;
+}
+
+/*
+ * chip exception handler for phase errors.
+ *
+ * We have to construct a new transfer descriptor,
+ * to transfer the rest of the current block.


+ */
+static void sym_int_ma (hcb_p np)

+{
+ u32 dbc;
+ u32 rest;
+ u32 dsp;
+ u32 dsa;
+ u32 nxtdsp;
+ u32 *vdsp;
+ u32 oadr, olen;
+ u32 *tblp;
+ u32 newcmd;
+ u_int delta;
+ u_char cmd;
+ u_char hflags, hflags0;
+ struct sym_pmc *pm;
+ ccb_p cp;
+
+ dsp = INL (nc_dsp);
+ dbc = INL (nc_dbc);
+ dsa = INL (nc_dsa);
+
+ cmd = dbc >> 24;
+ rest = dbc & 0xffffff;
+ delta = 0;
+
+ /*
+ * locate matching cp if any.
+ */
+ cp = sym_ccb_from_dsa(np, dsa);
+
+ /*
+ * Donnot take into account dma fifo and various buffers in
+ * INPUT phase since the chip flushes everything before
+ * raising the MA interrupt for interrupted INPUT phases.
+ * For DATA IN phase, we will check for the SWIDE later.
+ */
+ if ((cmd & 7) != 1 && (cmd & 7) != 5) {
+ u_char ss0, ss2;
+
+ if (np->features & FE_DFBC)
+ delta = INW (nc_dfbc);
+ else {
+ u32 dfifo;
+
+ /*
+ * Read DFIFO, CTEST[4-6] using 1 PCI bus ownership.
+ */
+ dfifo = INL(nc_dfifo);
+
+ /*
+ * Calculate remaining bytes in DMA fifo.
+ * (CTEST5 = dfifo >> 16)
+ */
+ if (dfifo & (DFS << 16))
+ delta = ((((dfifo >> 8) & 0x300) |
+ (dfifo & 0xff)) - rest) & 0x3ff;
+ else
+ delta = ((dfifo & 0xff) - rest) & 0x7f;
+ }
+
+ /*
+ * The data in the dma fifo has not been transfered to
+ * the target -> add the amount to the rest
+ * and clear the data.
+ * Check the sstat2 register in case of wide transfer.
+ */
+ rest += delta;
+ ss0 = INB (nc_sstat0);
+ if (ss0 & OLF) rest++;
+ if (!(np->features & FE_C10))
+ if (ss0 & ORF) rest++;
+ if (cp && (cp->phys.select.sel_scntl3 & EWS)) {
+ ss2 = INB (nc_sstat2);
+ if (ss2 & OLF1) rest++;
+ if (!(np->features & FE_C10))
+ if (ss2 & ORF1) rest++;
+ };
+
+ /*
+ * Clear fifos.
+ */
+ OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* dma fifo */
+ OUTB (nc_stest3, TE|CSF); /* scsi fifo */
+ }
+
+ /*
+ * log the information
+ */
+ if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_PHASE))
+ printf ("P%x%x RL=%d D=%d ", cmd&7, INB(nc_sbcl)&7,
+ (unsigned) rest, (unsigned) delta);
+
+ /*
+ * try to find the interrupted script command,
+ * and the address at which to continue.
+ */
+ vdsp = 0;
+ nxtdsp = 0;
+ if (dsp > np->scripta_ba &&
+ dsp <= np->scripta_ba + np->scripta_sz) {
+ vdsp = (u32 *)((char*)np->scripta0 + (dsp-np->scripta_ba-8));
+ nxtdsp = dsp;
+ }
+ else if (dsp > np->scriptb_ba &&
+ dsp <= np->scriptb_ba + np->scriptb_sz) {
+ vdsp = (u32 *)((char*)np->scriptb0 + (dsp-np->scriptb_ba-8));
+ nxtdsp = dsp;
+ }
+
+ /*
+ * log the information
+ */
+ if (DEBUG_FLAGS & DEBUG_PHASE) {
+ printf ("\nCP=%p DSP=%x NXT=%x VDSP=%p CMD=%x ",
+ cp, (unsigned)dsp, (unsigned)nxtdsp, vdsp, cmd);
+ };
+
+ if (!vdsp) {
+ printf ("%s: interrupted SCRIPT address not found.\n",
+ sym_name (np));
+ goto reset_all;
+ }
+
+ if (!cp) {
+ printf ("%s: SCSI phase error fixup: CCB already dequeued.\n",
+ sym_name (np));
+ goto reset_all;
+ }
+
+ /*
+ * get old startaddress and old length.
+ */
+ oadr = scr_to_cpu(vdsp[1]);
+
+ if (cmd & 0x10) { /* Table indirect */
+ tblp = (u32 *) ((char*) &cp->phys + oadr);
+ olen = scr_to_cpu(tblp[0]);
+ oadr = scr_to_cpu(tblp[1]);
+ } else {
+ tblp = (u32 *) 0;
+ olen = scr_to_cpu(vdsp[0]) & 0xffffff;
+ };
+
+ if (DEBUG_FLAGS & DEBUG_PHASE) {
+ printf ("OCMD=%x\nTBLP=%p OLEN=%x OADR=%x\n",
+ (unsigned) (scr_to_cpu(vdsp[0]) >> 24),
+ tblp,
+ (unsigned) olen,
+ (unsigned) oadr);
+ };
+
+ /*
+ * check cmd against assumed interrupted script command.
+ * If dt data phase, the MOVE instruction hasn't bit 4 of
+ * the phase.
+ */
+ if (((cmd & 2) ? cmd : (cmd & ~4)) != (scr_to_cpu(vdsp[0]) >> 24)) {
+ PRINT_ADDR(cp);
+ printf ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n",
+ (unsigned)cmd, (unsigned)scr_to_cpu(vdsp[0]) >> 24);
+
+ goto reset_all;
+ };
+
+ /*
+ * if old phase not dataphase, leave here.
+ */
+ if (cmd & 2) {
+ PRINT_ADDR(cp);
+ printf ("phase change %x-%x %d@%08x resid=%d.\n",
+ cmd&7, INB(nc_sbcl)&7, (unsigned)olen,
+ (unsigned)oadr, (unsigned)rest);
+ goto unexpected_phase;
+ };
+
+ /*
+ * Choose the correct PM save area.
+ *
+ * Look at the PM_SAVE SCRIPT if you want to understand
+ * this stuff. The equivalent code is implemented in
+ * SCRIPTS for the 895A, 896 and 1010 that are able to
+ * handle PM from the SCRIPTS processor.
+ */
+ hflags0 = INB (HF_PRT);
+ hflags = hflags0;
+
+ if (hflags & (HF_IN_PM0 | HF_IN_PM1 | HF_DP_SAVED)) {
+ if (hflags & HF_IN_PM0)
+ nxtdsp = scr_to_cpu(cp->phys.pm0.ret);
+ else if (hflags & HF_IN_PM1)
+ nxtdsp = scr_to_cpu(cp->phys.pm1.ret);


+
+ if (hflags & HF_DP_SAVED)
+ hflags ^= HF_ACT_PM;
+ }
+
+ if (!(hflags & HF_ACT_PM)) {
+ pm = &cp->phys.pm0;

+ newcmd = SCRIPTA_BA (np, pm0_data);


+ }
+ else {
+ pm = &cp->phys.pm1;

+ newcmd = SCRIPTA_BA (np, pm1_data);
+ }
+
+ hflags &= ~(HF_IN_PM0 | HF_IN_PM1 | HF_DP_SAVED);
+ if (hflags != hflags0)
+ OUTB (HF_PRT, hflags);
+
+ /*
+ * fillin the phase mismatch context
+ */
+ pm->sg.addr = cpu_to_scr(oadr + olen - rest);
+ pm->sg.size = cpu_to_scr(rest);
+ pm->ret = cpu_to_scr(nxtdsp);
+
+ /*
+ * If we have a SWIDE,
+ * - prepare the address to write the SWIDE from SCRIPTS,
+ * - compute the SCRIPTS address to restart from,
+ * - move current data pointer context by one byte.
+ */
+ nxtdsp = SCRIPTA_BA (np, dispatch);
+ if ((cmd & 7) == 1 && cp && (cp->phys.select.sel_scntl3 & EWS) &&
+ (INB (nc_scntl2) & WSR)) {
+ u32 tmp;
+
+ /*
+ * Set up the table indirect for the MOVE
+ * of the residual byte and adjust the data
+ * pointer context.
+ */
+ tmp = scr_to_cpu(pm->sg.addr);
+ cp->phys.wresid.addr = cpu_to_scr(tmp);
+ pm->sg.addr = cpu_to_scr(tmp + 1);
+ tmp = scr_to_cpu(pm->sg.size);
+ cp->phys.wresid.size = cpu_to_scr((tmp&0xff000000) | 1);
+ pm->sg.size = cpu_to_scr(tmp - 1);
+
+ /*
+ * If only the residual byte is to be moved,
+ * no PM context is needed.
+ */
+ if ((tmp&0xffffff) == 1)
+ newcmd = pm->ret;
+
+ /*
+ * Prepare the address of SCRIPTS that will
+ * move the residual byte to memory.
+ */
+ nxtdsp = SCRIPTB_BA (np, wsr_ma_helper);
+ }
+
+ if (DEBUG_FLAGS & DEBUG_PHASE) {
+ PRINT_ADDR(cp);
+ printf ("PM %x %x %x / %x %x %x.\n",
+ hflags0, hflags, newcmd,
+ (unsigned)scr_to_cpu(pm->sg.addr),
+ (unsigned)scr_to_cpu(pm->sg.size),
+ (unsigned)scr_to_cpu(pm->ret));
+ }
+
+ /*


+ * Restart the SCRIPTS processor.
+ */

+ sym_set_script_dp (np, cp, newcmd);
+ OUTL_DSP (nxtdsp);
+ return;
+
+ /*
+ * Unexpected phase changes that occurs when the current phase
+ * is not a DATA IN or DATA OUT phase are due to error conditions.
+ * Such event may only happen when the SCRIPTS is using a
+ * multibyte SCSI MOVE.
+ *
+ * Phase change Some possible cause
+ *
+ * COMMAND --> MSG IN SCSI parity error detected by target.
+ * COMMAND --> STATUS Bad command or refused by target.
+ * MSG OUT --> MSG IN Message rejected by target.
+ * MSG OUT --> COMMAND Bogus target that discards extended
+ * negotiation messages.
+ *
+ * The code below does not care of the new phase and so
+ * trusts the target. Why to annoy it ?
+ * If the interrupted phase is COMMAND phase, we restart at
+ * dispatcher.
+ * If a target does not get all the messages after selection,
+ * the code assumes blindly that the target discards extended
+ * messages and clears the negotiation status.
+ * If the target does not want all our response to negotiation,
+ * we force a SIR_NEGO_PROTO interrupt (it is a hack that avoids
+ * bloat for such a should_not_happen situation).
+ * In all other situation, we reset the BUS.
+ * Are these assumptions reasonnable ? (Wait and see ...)
+ */
+unexpected_phase:
+ dsp -= 8;
+ nxtdsp = 0;
+
+ switch (cmd & 7) {
+ case 2: /* COMMAND phase */
+ nxtdsp = SCRIPTA_BA (np, dispatch);
+ break;
+#if 0
+ case 3: /* STATUS phase */
+ nxtdsp = SCRIPTA_BA (np, dispatch);
+ break;
+#endif
+ case 6: /* MSG OUT phase */
+ /*
+ * If the device may want to use untagged when we want
+ * tagged, we prepare an IDENTIFY without disc. granted,
+ * since we will not be able to handle reselect.
+ * Otherwise, we just don't care.
+ */
+ if (dsp == SCRIPTA_BA (np, send_ident)) {
+ if (cp->tag != NO_TAG && olen - rest <= 3) {


+ cp->host_status = HS_BUSY;

+ np->msgout[0] = M_IDENTIFY | cp->lun;
+ nxtdsp = SCRIPTB_BA (np, ident_break_atn);
+ }
+ else
+ nxtdsp = SCRIPTB_BA (np, ident_break);
+ }
+ else if (dsp == SCRIPTB_BA (np, send_wdtr) ||
+ dsp == SCRIPTB_BA (np, send_sdtr) ||
+ dsp == SCRIPTB_BA (np, send_ppr)) {
+ nxtdsp = SCRIPTB_BA (np, nego_bad_phase);
+ }
+ break;
+#if 0
+ case 7: /* MSG IN phase */
+ nxtdsp = SCRIPTA_BA (np, clrack);
+ break;
+#endif
+ }
+
+ if (nxtdsp) {
+ OUTL_DSP (nxtdsp);
+ return;
+ }
+
+reset_all:
+ sym_start_reset(np);
+}
+
+/*
+ * chip interrupt handler
+ *
+ * In normal situations, interrupt conditions occur one at
+ * a time. But when something bad happens on the SCSI BUS,
+ * the chip may raise several interrupt flags before
+ * stopping and interrupting the CPU. The additionnal
+ * interrupt flags are stacked in some extra registers
+ * after the SIP and/or DIP flag has been raised in the
+ * ISTAT. After the CPU has read the interrupt condition
+ * flag from SIST or DSTAT, the chip unstacks the other
+ * interrupt flags and sets the corresponding bits in
+ * SIST or DSTAT. Since the chip starts stacking once the
+ * SIP or DIP flag is set, there is a small window of time
+ * where the stacking does not occur.
+ *
+ * Typically, multiple interrupt conditions may happen in
+ * the following situations:
+ *
+ * - SCSI parity error + Phase mismatch (PAR|MA)
+ * When an parity error is detected in input phase
+ * and the device switches to msg-in phase inside a
+ * block MOV.
+ * - SCSI parity error + Unexpected disconnect (PAR|UDC)
+ * When a stupid device does not want to handle the
+ * recovery of an SCSI parity error.
+ * - Some combinations of STO, PAR, UDC, ...
+ * When using non compliant SCSI stuff, when user is
+ * doing non compliant hot tampering on the BUS, when
+ * something really bad happens to a device, etc ...
+ *
+ * The heuristic suggested by SYMBIOS to handle
+ * multiple interrupts is to try unstacking all
+ * interrupts conditions and to handle them on some
+ * priority based on error severity.
+ * This will work when the unstacking has been
+ * successful, but we cannot be 100 % sure of that,
+ * since the CPU may have been faster to unstack than
+ * the chip is able to stack. Hmmm ... But it seems that
+ * such a situation is very unlikely to happen.
+ *
+ * If this happen, for example STO caught by the CPU
+ * then UDC happenning before the CPU have restarted
+ * the SCRIPTS, the driver may wrongly complete the
+ * same command on UDC, since the SCRIPTS didn't restart
+ * and the DSA still points to the same command.
+ * We avoid this situation by setting the DSA to an
+ * invalid value when the CCB is completed and before
+ * restarting the SCRIPTS.
+ *
+ * Another issue is that we need some section of our
+ * recovery procedures to be somehow uninterruptible but
+ * the SCRIPTS processor does not provides such a
+ * feature. For this reason, we handle recovery preferently
+ * from the C code and check against some SCRIPTS critical
+ * sections from the C code.
+ *
+ * Hopefully, the interrupt handling of the driver is now
+ * able to resist to weird BUS error conditions, but donnot
+ * ask me for any guarantee that it will never fail. :-)
+ * Use at your own decision and risk.
+ */
+
+void sym_interrupt (hcb_p np)
+{
+ u_char istat, istatc;
+ u_char dstat;
+ u_short sist;
+
+ /*
+ * interrupt on the fly ?
+ * (SCRIPTS may still be running)
+ *
+ * A `dummy read' is needed to ensure that the
+ * clear of the INTF flag reaches the device
+ * and that posted writes are flushed to memory
+ * before the scanning of the DONE queue.
+ * Note that SCRIPTS also (dummy) read to memory
+ * prior to deliver the INTF interrupt condition.
+ */


+ istat = INB (nc_istat);

+ if (istat & INTF) {
+ OUTB (nc_istat, (istat & SIGP) | INTF | np->istat_sem);
+ istat = INB (nc_istat); /* DUMMY READ */
+ if (DEBUG_FLAGS & DEBUG_TINY) printf ("F ");
+ (void)sym_wakeup_done (np);
+ };
+
+ if (!(istat & (SIP|DIP)))
+ return;
+
+#if 0 /* We should never get this one */
+ if (istat & CABRT)
+ OUTB (nc_istat, CABRT);
+#endif
+
+ /*
+ * PAR and MA interrupts may occur at the same time,
+ * and we need to know of both in order to handle
+ * this situation properly. We try to unstack SCSI
+ * interrupts for that reason. BTW, I dislike a LOT
+ * such a loop inside the interrupt routine.
+ * Even if DMA interrupt stacking is very unlikely to
+ * happen, we also try unstacking these ones, since
+ * this has no performance impact.
+ */
+ sist = 0;
+ dstat = 0;
+ istatc = istat;
+ do {
+ if (istatc & SIP)
+ sist |= INW (nc_sist);
+ if (istatc & DIP)
+ dstat |= INB (nc_dstat);
+ istatc = INB (nc_istat);
+ istat |= istatc;
+ } while (istatc & (SIP|DIP));
+
+ if (DEBUG_FLAGS & DEBUG_TINY)
+ printf ("<%d|%x:%x|%x:%x>",
+ (int)INB(nc_scr0),
+ dstat,sist,
+ (unsigned)INL(nc_dsp),
+ (unsigned)INL(nc_dbc));
+ /*
+ * On paper, a memory read barrier may be needed here to
+ * prevent out of order LOADs by the CPU from having
+ * prefetched stale data prior to DMA having occurred.
+ * And since we are paranoid ... :)
+ */
+ MEMORY_READ_BARRIER();
+
+ /*
+ * First, interrupts we want to service cleanly.
+ *
+ * Phase mismatch (MA) is the most frequent interrupt
+ * for chip earlier than the 896 and so we have to service
+ * it as quickly as possible.
+ * A SCSI parity error (PAR) may be combined with a phase
+ * mismatch condition (MA).
+ * Programmed interrupts (SIR) are used to call the C code
+ * from SCRIPTS.
+ * The single step interrupt (SSI) is not used in this
+ * driver.
+ */
+ if (!(sist & (STO|GEN|HTH|SGE|UDC|SBMC|RST)) &&
+ !(dstat & (MDPE|BF|ABRT|IID))) {
+ if (sist & PAR) sym_int_par (np, sist);
+ else if (sist & MA) sym_int_ma (np);
+ else if (dstat & SIR) sym_int_sir (np);
+ else if (dstat & SSI) OUTONB_STD ();
+ else goto unknown_int;
+ return;
+ };
+
+ /*
+ * Now, interrupts that donnot happen in normal
+ * situations and that we may need to recover from.
+ *
+ * On SCSI RESET (RST), we reset everything.
+ * On SCSI BUS MODE CHANGE (SBMC), we complete all
+ * active CCBs with RESET status, prepare all devices
+ * for negotiating again and restart the SCRIPTS.
+ * On STO and UDC, we complete the CCB with the corres-
+ * ponding status and restart the SCRIPTS.
+ */
+ if (sist & RST) {
+ printf("%s: SCSI BUS reset detected.\n", sym_name(np));
+ sym_start_up (np, 1);
+ return;
+ };
+
+ OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */
+ OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */
+
+ if (!(sist & (GEN|HTH|SGE)) &&
+ !(dstat & (MDPE|BF|ABRT|IID))) {
+ if (sist & SBMC) sym_int_sbmc (np);
+ else if (sist & STO) sym_int_sto (np);
+ else if (sist & UDC) sym_int_udc (np);
+ else goto unknown_int;
+ return;
+ };
+
+ /*
+ * Now, interrupts we are not able to recover cleanly.
+ *
+ * Log message for hard errors.
+ * Reset everything.
+ */
+
+ sym_log_hard_error(np, sist, dstat);
+
+ if ((sist & (GEN|HTH|SGE)) ||
+ (dstat & (MDPE|BF|ABRT|IID))) {
+ sym_start_reset(np);
+ return;
+ };
+
+unknown_int:
+ /*
+ * We just miss the cause of the interrupt. :(
+ * Print a message. The timeout will do the real work.
+ */
+ printf( "%s: unknown interrupt(s) ignored, "
+ "ISTAT=0x%x DSTAT=0x%x SIST=0x%x\n",
+ sym_name(np), istat, dstat, sist);
+}
+
+/*
+ * Dequeue from the START queue all CCBs that match
+ * a given target/lun/task condition (-1 means all),
+ * and move them from the BUSY queue to the COMP queue
+ * with CAM_REQUEUE_REQ status condition.
+ * This function is used during error handling/recovery.
+ * It is called with SCRIPTS not running.
+ */
+static int
+sym_dequeue_from_squeue(hcb_p np, int i, int target, int lun, int task)
+{
+ int j;
+ ccb_p cp;
+
+ /*
+ * Make sure the starting index is within range.
+ */
+ assert((i >= 0) && (i < 2*MAX_QUEUE));
+
+ /*
+ * Walk until end of START queue and dequeue every job
+ * that matches the target/lun/task condition.
+ */
+ j = i;
+ while (i != np->squeueput) {
+ cp = sym_ccb_from_dsa(np, scr_to_cpu(np->squeue[i]));
+ assert(cp);
+#ifdef SYM_CONF_IARB_SUPPORT
+ /* Forget hints for IARB, they may be no longer relevant */
+ cp->host_flags &= ~HF_HINT_IARB;
+#endif
+ if ((target == -1 || cp->target == target) &&
+ (lun == -1 || cp->lun == lun) &&
+ (task == -1 || cp->tag == task)) {
+ sym_set_cam_status(cp->cam_ccb, CAM_REQUEUE_REQ);
+ sym_remque(&cp->link_ccbq);
+ sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);
+ }
+ else {


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

echo 'End of part 065'
echo 'File patch-2.4.15 is continued in part 066'
echo "066" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:44 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part068

#!/bin/sh -x
# this is part 068 of a 115 - part archive


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

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

+#define MDELAY sym_mdelay
+#define UDELAY sym_udelay
+
+#endif /* SYM_HIPD_H */
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_malloc.c linux/drivers/scsi/sym53c8xx_2/sym_malloc.c
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_malloc.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym_malloc.c Fri Nov 9 15:22:54 2001
@@ -0,0 +1,418 @@

+#ifdef __FreeBSD__
+#include <dev/sym/sym_glue.h>
+#else
+#include "sym_glue.h"

+#endif
+
+/*
+ * Simple power of two buddy-like generic allocator.
+ * Provides naturally aligned memory chunks.
+ *
+ * This simple code is not intended to be fast, but to
+ * provide power of 2 aligned memory allocations.
+ * Since the SCRIPTS processor only supplies 8 bit arithmetic,
+ * this allocator allows simple and fast address calculations
+ * from the SCRIPTS code. In addition, cache line alignment
+ * is guaranteed for power of 2 cache line size.
+ *
+ * This allocator has been developped for the Linux sym53c8xx
+ * driver, since this O/S does not provide naturally aligned
+ * allocations.
+ * It has the advantage of allowing the driver to use private
+ * pages of memory that will be useful if we ever need to deal
+ * with IO MMUs for PCI.
+ */
+static void *___sym_malloc(m_pool_p mp, int size)
+{


+ int i = 0;

+ int s = (1 << SYM_MEM_SHIFT);
+ int j;
+ m_addr_t a;
+ m_link_p h = mp->h;
+
+ if (size > SYM_MEM_CLUSTER_SIZE)
+ return 0;
+
+ while (size > s) {
+ s <<= 1;
+ ++i;
+ }
+
+ j = i;
+ while (!h[j].next) {
+ if (s == SYM_MEM_CLUSTER_SIZE) {
+ h[j].next = (m_link_p) M_GET_MEM_CLUSTER();
+ if (h[j].next)
+ h[j].next->next = 0;
+ break;
+ }
+ ++j;
+ s <<= 1;
+ }
+ a = (m_addr_t) h[j].next;
+ if (a) {
+ h[j].next = h[j].next->next;
+ while (j > i) {
+ j -= 1;
+ s >>= 1;
+ h[j].next = (m_link_p) (a+s);
+ h[j].next->next = 0;
+ }
+ }
+#ifdef DEBUG
+ printf("___sym_malloc(%d) = %p\n", size, (void *) a);
+#endif
+ return (void *) a;
+}
+
+/*
+ * Counter-part of the generic allocator.
+ */
+static void ___sym_mfree(m_pool_p mp, void *ptr, int size)
+{


+ int i = 0;

+ int s = (1 << SYM_MEM_SHIFT);
+ m_link_p q;
+ m_addr_t a, b;
+ m_link_p h = mp->h;
+
+#ifdef DEBUG
+ printf("___sym_mfree(%p, %d)\n", ptr, size);
+#endif
+
+ if (size > SYM_MEM_CLUSTER_SIZE)
+ return;
+
+ while (size > s) {
+ s <<= 1;
+ ++i;
+ }
+
+ a = (m_addr_t) ptr;
+
+ while (1) {
+#ifdef SYM_MEM_FREE_UNUSED
+ if (s == SYM_MEM_CLUSTER_SIZE) {
+ M_FREE_MEM_CLUSTER(a);
+ break;
+ }
+#endif
+ b = a ^ s;
+ q = &h[i];
+ while (q->next && q->next != (m_link_p) b) {
+ q = q->next;
+ }
+ if (!q->next) {
+ ((m_link_p) a)->next = h[i].next;
+ h[i].next = (m_link_p) a;
+ break;
+ }
+ q->next = q->next->next;
+ a = a & b;
+ s <<= 1;
+ ++i;
+ }
+}
+
+/*
+ * Verbose and zeroing allocator that wrapps to the generic allocator.
+ */
+static void *__sym_calloc2(m_pool_p mp, int size, char *name, int uflags)
+{
+ void *p;
+
+ p = ___sym_malloc(mp, size);
+
+ if (DEBUG_FLAGS & DEBUG_ALLOC) {
+ printf ("new %-10s[%4d] @%p.\n", name, size, p);
+ }
+
+ if (p)
+ bzero(p, size);
+ else if (uflags & SYM_MEM_WARN)
+ printf ("__sym_calloc2: failed to allocate %s[%d]\n", name, size);
+ return p;
+}
+#define __sym_calloc(mp, s, n) __sym_calloc2(mp, s, n, SYM_MEM_WARN)
+
+/*
+ * Its counter-part.
+ */
+static void __sym_mfree(m_pool_p mp, void *ptr, int size, char *name)
+{
+ if (DEBUG_FLAGS & DEBUG_ALLOC)
+ printf ("freeing %-10s[%4d] @%p.\n", name, size, ptr);
+
+ ___sym_mfree(mp, ptr, size);
+}
+
+/*
+ * Default memory pool we donnot need to involve in DMA.
+ *
+ * If DMA abtraction is not needed, the generic allocator
+ * calls directly some kernel allocator.
+ *
+ * With DMA abstraction, we use functions (methods), to
+ * distinguish between non DMAable memory and DMAable memory.
+ */
+#ifndef SYM_OPT_BUS_DMA_ABSTRACTION
+
+static struct sym_m_pool mp0;
+
+#else
+
+static m_addr_t ___mp0_get_mem_cluster(m_pool_p mp)
+{
+ m_addr_t m = (m_addr_t) sym_get_mem_cluster();
+ if (m)
+ ++mp->nump;


+ return m;
+}
+

+#ifdef SYM_MEM_FREE_UNUSED
+static void ___mp0_free_mem_cluster(m_pool_p mp, m_addr_t m)
+{
+ sym_free_mem_cluster(m);
+ --mp->nump;
+}
+#endif
+
+#ifdef SYM_MEM_FREE_UNUSED
+static struct sym_m_pool mp0 =
+ {0, ___mp0_get_mem_cluster, ___mp0_free_mem_cluster};
+#else
+static struct sym_m_pool mp0 =
+ {0, ___mp0_get_mem_cluster};
+#endif
+


+#endif /* SYM_OPT_BUS_DMA_ABSTRACTION */
+
+/*

+ * Actual memory allocation routine for non-DMAed memory.
+ */


+void *sym_calloc_unlocked(int size, char *name)

+{
+ void *m;
+ m = __sym_calloc(&mp0, size, name);
+ return m;
+}
+
+/*
+ * Its counter-part.


+ */
+void sym_mfree_unlocked(void *ptr, int size, char *name)

+{
+ __sym_mfree(&mp0, ptr, size, name);
+}
+
+#ifdef SYM_OPT_BUS_DMA_ABSTRACTION
+/*
+ * Methods that maintains DMAable pools according to user allocations.
+ * New pools are created on the fly when a new pool id is provided.
+ * They are deleted on the fly when they get emptied.
+ */
+/* Get a memory cluster that matches the DMA contraints of a given pool */
+static m_addr_t ___get_dma_mem_cluster(m_pool_p mp)
+{
+ m_vtob_p vbp;
+ m_addr_t vaddr;
+
+ vbp = __sym_calloc(&mp0, sizeof(*vbp), "VTOB");
+ if (!vbp)
+ goto out_err;
+
+ vaddr = sym_m_get_dma_mem_cluster(mp, vbp);
+ if (vaddr) {
+ int hc = VTOB_HASH_CODE(vaddr);
+ vbp->next = mp->vtob[hc];
+ mp->vtob[hc] = vbp;
+ ++mp->nump;


+ return (m_addr_t) vaddr;
+ }

+ return vaddr;
+out_err:


+ return 0;
+}
+

+#ifdef SYM_MEM_FREE_UNUSED
+/* Free a memory cluster and associated resources for DMA */
+static void ___free_dma_mem_cluster(m_pool_p mp, m_addr_t m)
+{
+ m_vtob_p *vbpp, vbp;
+ int hc = VTOB_HASH_CODE(m);
+
+ vbpp = &mp->vtob[hc];
+ while (*vbpp && (*vbpp)->vaddr != m)
+ vbpp = &(*vbpp)->next;
+ if (*vbpp) {
+ vbp = *vbpp;
+ *vbpp = (*vbpp)->next;
+ sym_m_free_dma_mem_cluster(mp, vbp);
+ __sym_mfree(&mp0, vbp, sizeof(*vbp), "VTOB");
+ --mp->nump;
+ }
+}
+#endif
+
+/* Fetch the memory pool for a given pool id (i.e. DMA constraints) */
+static __inline m_pool_p ___get_dma_pool(m_pool_ident_t dev_dmat)
+{
+ m_pool_p mp;
+ for (mp = mp0.next;
+ mp && !sym_m_pool_match(mp->dev_dmat, dev_dmat);
+ mp = mp->next);
+ return mp;
+}
+
+/* Create a new memory DMAable pool (when fetch failed) */
+static m_pool_p ___cre_dma_pool(m_pool_ident_t dev_dmat)
+{
+ m_pool_p mp = 0;
+
+ mp = __sym_calloc(&mp0, sizeof(*mp), "MPOOL");
+ if (mp) {
+ mp->dev_dmat = dev_dmat;
+ if (!sym_m_create_dma_mem_tag(mp)) {
+ mp->get_mem_cluster = ___get_dma_mem_cluster;
+#ifdef SYM_MEM_FREE_UNUSED
+ mp->free_mem_cluster = ___free_dma_mem_cluster;
+#endif
+ mp->next = mp0.next;
+ mp0.next = mp;
+ return mp;
+ }
+ }
+ if (mp)
+ __sym_mfree(&mp0, mp, sizeof(*mp), "MPOOL");


+ return 0;
+}
+

+#ifdef SYM_MEM_FREE_UNUSED
+/* Destroy a DMAable memory pool (when got emptied) */
+static void ___del_dma_pool(m_pool_p p)
+{
+ m_pool_p *pp = &mp0.next;
+
+ while (*pp && *pp != p)
+ pp = &(*pp)->next;
+ if (*pp) {
+ *pp = (*pp)->next;
+ sym_m_delete_dma_mem_tag(p);
+ __sym_mfree(&mp0, p, sizeof(*p), "MPOOL");


+ }
+}
+#endif
+
+/*

+ * Actual allocator for DMAable memory.
+ */


+void *__sym_calloc_dma_unlocked(m_pool_ident_t dev_dmat, int size, char *name)

+{
+ m_pool_p mp;
+ void *m = 0;
+
+ mp = ___get_dma_pool(dev_dmat);
+ if (!mp)
+ mp = ___cre_dma_pool(dev_dmat);
+ if (mp)
+ m = __sym_calloc(mp, size, name);
+#ifdef SYM_MEM_FREE_UNUSED
+ if (mp && !mp->nump)
+ ___del_dma_pool(mp);
+#endif
+
+ return m;
+}
+
+/*
+ * Its counter-part.
+ */
+void
+__sym_mfree_dma_unlocked(m_pool_ident_t dev_dmat, void *m, int size, char *name)
+{
+ m_pool_p mp;
+
+ mp = ___get_dma_pool(dev_dmat);
+ if (mp)
+ __sym_mfree(mp, m, size, name);
+#ifdef SYM_MEM_FREE_UNUSED
+ if (mp && !mp->nump)
+ ___del_dma_pool(mp);
+#endif
+}
+
+/*
+ * Actual virtual to bus physical address translator
+ * for 32 bit addressable DMAable memory.
+ */


+u32 __vtobus_unlocked(m_pool_ident_t dev_dmat, void *m)

+{
+ m_pool_p mp;
+ int hc = VTOB_HASH_CODE(m);
+ m_vtob_p vp = 0;
+ m_addr_t a = ((m_addr_t) m) & ~SYM_MEM_CLUSTER_MASK;
+
+ mp = ___get_dma_pool(dev_dmat);
+ if (mp) {
+ vp = mp->vtob[hc];
+ while (vp && (m_addr_t) vp->vaddr != a)
+ vp = vp->next;
+ }
+ if (!vp)
+ panic("sym: VTOBUS FAILED!\n");
+ return (u32)(vp ? vp->baddr + (((m_addr_t) m) - a) : 0);
+}
+
+#endif /* SYM_OPT_BUS_DMA_ABSTRACTION */
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_misc.c linux/drivers/scsi/sym53c8xx_2/sym_misc.c
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_misc.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym_misc.c Fri Nov 9 15:22:54 2001
@@ -0,0 +1,336 @@

+#ifdef __FreeBSD__
+#include <dev/sym/sym_glue.h>
+#else
+#include "sym_glue.h"
+#endif
+

+#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
+/*
+ * Optional CCB timeout handling.
+ *
+ * This code is useful for O/Ses that allow or expect
+ * SIMs (low-level drivers) to handle SCSI IO timeouts.
+ * It uses a power-of-two based algorithm of my own:)
+ * that avoids scanning of lists, provided that:
+ *
+ * - The IO does complete in less than half the associated
+ * timeout value.
+ * - The greatest delay between the queuing of the IO and
+ * its completion is less than
+ * (1<<(SYM_CONF_TIMEOUT_ORDER_MAX-1))/2 ticks.
+ *
+ * For example, if tick is 1 second and the max order is 8,
+ * any IO that is completed within less than 64 seconds will
+ * just be put into some list at queuing and be removed
+ * at completion without any additionnal overhead.
+ */
+
+/*
+ * Set a timeout condition on a CCB.
+ */

+void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks)

+{
+ sym_remque(&cp->tmo_linkq);
+ cp->tmo_clock = np->tmo_clock + ticks;
+ if (!ticks) {


+ sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
+ }

+ else {
+ int i = SYM_CONF_TIMEOUT_ORDER_MAX - 1;
+ while (i > 0) {
+ if (ticks >= (1<<(i+1)))
+ break;
+ --i;
+ }
+ if (!(np->tmo_actq & (1<<i)))
+ i += SYM_CONF_TIMEOUT_ORDER_MAX;
+ sym_insque_head(&cp->tmo_linkq, &np->tmo_ccbq[i]);
+ }
+}
+
+/*
+ * Walk a list of CCB and handle timeout conditions.
+ * Should never be called in normal situations.
+ */
+static void sym_walk_ccb_tmo_list(hcb_p np, SYM_QUEHEAD *tmoq)
+{
+ SYM_QUEHEAD qtmp, *qp;
+ ccb_p cp;
+
+ sym_que_move(tmoq, &qtmp);


+ while ((qp = sym_remque_head(&qtmp)) != 0) {

+ sym_insque_head(qp, &np->tmo0_ccbq);
+ cp = sym_que_entry(qp, struct sym_ccb, tmo_linkq);
+ if (cp->tmo_clock != np->tmo_clock &&
+ cp->tmo_clock + 1 != np->tmo_clock)
+ sym_timeout_ccb(np, cp, cp->tmo_clock - np->tmo_clock);
+ else
+ sym_abort_ccb(np, cp, 1);
+ }
+}
+
+/*
+ * Our clock handler called from the O/S specific side.
+ */
+void sym_clock(hcb_p np)
+{
+ int i, j;
+ u_int tmp;
+
+ tmp = np->tmo_clock;
+ tmp ^= (++np->tmo_clock);
+
+ for (i = 0; i < SYM_CONF_TIMEOUT_ORDER_MAX; i++, tmp >>= 1) {
+ if (!(tmp & 1))
+ continue;
+ j = i;
+ if (np->tmo_actq & (1<<i))
+ j += SYM_CONF_TIMEOUT_ORDER_MAX;
+
+ if (!sym_que_empty(&np->tmo_ccbq[j])) {
+ sym_walk_ccb_tmo_list(np, &np->tmo_ccbq[j]);
+ }
+ np->tmo_actq ^= (1<<i);
+ }
+}


+#endif /* SYM_OPT_HANDLE_IO_TIMEOUT */
+
+

+#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
+/*
+ * Announce transfer rate if anything changed since last announcement.
+ */


+void sym_announce_transfer_rate(hcb_p np, int target)

+{
+ tcb_p tp = &np->target[target];
+
+#define __tprev tp->tinfo.prev
+#define __tcurr tp->tinfo.curr
+
+ if (__tprev.options == __tcurr.options &&
+ __tprev.width == __tcurr.width &&
+ __tprev.offset == __tcurr.offset &&
+ !(__tprev.offset && __tprev.period != __tcurr.period))
+ return;
+
+ __tprev.options = __tcurr.options;
+ __tprev.width = __tcurr.width;
+ __tprev.offset = __tcurr.offset;
+ __tprev.period = __tcurr.period;
+
+ if (__tcurr.offset && __tcurr.period) {
+ u_int period, f10, mb10;
+ char *scsi;
+
+ period = f10 = mb10 = 0;
+ scsi = "FAST-5";
+
+ if (__tcurr.period <= 9) {
+ scsi = "FAST-80";
+ period = 125;
+ mb10 = 1600;
+ }
+ else {
+ if (__tcurr.period <= 11) {
+ scsi = "FAST-40";
+ period = 250;
+ if (__tcurr.period == 11)
+ period = 303;
+ }
+ else if (__tcurr.period < 25) {
+ scsi = "FAST-20";
+ if (__tcurr.period == 12)
+ period = 500;
+ }
+ else if (__tcurr.period <= 50) {
+ scsi = "FAST-10";
+ }
+ if (!period)
+ period = 40 * __tcurr.period;
+ f10 = 100000 << (__tcurr.width ? 1 : 0);
+ mb10 = (f10 + period/2) / period;
+ }
+ printf_info (
+ "%s:%d: %s %sSCSI %d.%d MB/s %s (%d.%d ns, offset %d)\n",
+ sym_name(np), target, scsi, __tcurr.width? "WIDE " : "",
+ mb10/10, mb10%10,
+ (__tcurr.options & PPR_OPT_DT) ? "DT" : "ST",
+ period/10, period%10, __tcurr.offset);
+ }
+ else
+ printf_info ("%s:%d: %sasynchronous.\n",
+ sym_name(np), target, __tcurr.width? "wide " : "");
+}
+#undef __tprev
+#undef __tcurr
+#endif /* SYM_OPT_ANNOUNCE_TRANSFER_RATE */
+
+
+#ifdef SYM_OPT_SNIFF_INQUIRY
+/*
+ * Update transfer settings according to user settings
+ * and bits sniffed out from INQUIRY response.
+ */


+void sym_update_trans_settings(hcb_p np, tcb_p tp)

+{
+ bcopy(&tp->tinfo.user, &tp->tinfo.goal, sizeof(tp->tinfo.goal));
+
+ if (tp->inq_version >= 4) {
+ switch(tp->inq_byte56 & INQ56_CLOCKING) {
+ case INQ56_ST_ONLY:


+ tp->tinfo.goal.options = 0;

+ break;
+ case INQ56_DT_ONLY:
+ case INQ56_ST_DT:
+ default:


+ break;
+ }
+ }
+

+ if (!((tp->inq_byte7 & tp->inq_byte7_valid) & INQ7_WIDE16)) {
+ tp->tinfo.goal.width = 0;


+ tp->tinfo.goal.options = 0;
+ }

+
+ if (!((tp->inq_byte7 & tp->inq_byte7_valid) & INQ7_SYNC)) {


+ tp->tinfo.goal.offset = 0;

+ tp->tinfo.goal.options = 0;
+ }

+
+ if (tp->tinfo.goal.options & PPR_OPT_DT) {
+ if (tp->tinfo.goal.offset > np->maxoffs_dt)


+ tp->tinfo.goal.offset = np->maxoffs_dt;

+ }
+ else {
+ if (tp->tinfo.goal.offset > np->maxoffs)


+ tp->tinfo.goal.offset = np->maxoffs;

+ }
+}
+
+/*
+ * Snoop target capabilities from INQUIRY response.
+ * We only believe device versions >= SCSI-2 that use
+ * appropriate response data format (2). But it seems
+ * that some CCS devices also support SYNC (?).
+ */


+int
+__sym_sniff_inquiry(hcb_p np, u_char tn, u_char ln,
+ u_char *inq_data, int inq_len)

+{
+ tcb_p tp = &np->target[tn];


+ u_char inq_version;
+ u_char inq_byte7;
+ u_char inq_byte56;
+

+ if (!inq_data || inq_len < 2)


+ return -1;
+
+ /*

+ * Check device type and qualifier.
+ */
+ if ((inq_data[0] & 0xe0) == 0x60)


+ return -1;
+
+ /*

+ * Get SPC version.
+ */
+ if (inq_len <= 2)
+ return -1;
+ inq_version = inq_data[2] & 0x7;
+
+ /*
+ * Get SYNC/WIDE16 capabilities.
+ */
+ inq_byte7 = tp->inq_byte7;
+ if (inq_version >= 2 && (inq_data[3] & 0xf) == 2) {
+ if (inq_len > 7)
+ inq_byte7 = inq_data[7];
+ }
+ else if (inq_version == 1 && (inq_data[3] & 0xf) == 1)
+ inq_byte7 = INQ7_SYNC;
+
+ /*
+ * Get Tagged Command Queuing capability.
+ */
+ if (inq_byte7 & INQ7_CMDQ)
+ sym_set_bit(tp->cmdq_map, ln);
+ else
+ sym_clr_bit(tp->cmdq_map, ln);
+ inq_byte7 &= ~INQ7_CMDQ;
+
+ /*
+ * Get CLOCKING capability.
+ */
+ inq_byte56 = tp->inq_byte56;
+ if (inq_version >= 4 && inq_len > 56)
+ tp->inq_byte56 = inq_data[56];
+#if 0
+printf("XXXXXX [%d] inq_version=%x inq_byte7=%x inq_byte56=%x XXXXX\n",
+ inq_len, inq_version, inq_byte7, inq_byte56);
+#endif
+ /*
+ * Trigger a negotiation if needed.
+ */
+ if (tp->inq_version != inq_version ||
+ tp->inq_byte7 != inq_byte7 ||
+ tp->inq_byte56 != inq_byte56) {
+ tp->inq_version = inq_version;
+ tp->inq_byte7 = inq_byte7;
+ tp->inq_byte56 = inq_byte56;
+ return 1;


+ }
+ return 0;
+}

+#endif /* SYM_OPT_SNIFF_INQUIRY */
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_misc.h linux/drivers/scsi/sym53c8xx_2/sym_misc.h
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_misc.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym_misc.h Fri Nov 9 15:22:54 2001
@@ -0,0 +1,311 @@

+#ifndef SYM_MISC_H
+#define SYM_MISC_H
+
+/*
+ * A 'read barrier' flushes any data that have been prefetched
+ * by the processor due to out of order execution. Such a barrier
+ * must notably be inserted prior to looking at data that have
+ * been DMAed, assuming that program does memory READs in proper
+ * order and that the device ensured proper ordering of WRITEs.
+ *
+ * A 'write barrier' prevents any previous WRITEs to pass further
+ * WRITEs. Such barriers must be inserted each time another agent
+ * relies on ordering of WRITEs.
+ *
+ * Note that, due to posting of PCI memory writes, we also must
+ * insert dummy PCI read transactions when some ordering involving
+ * both directions over the PCI does matter. PCI transactions are
+ * fully ordered in each direction.
+ *
+ * IA32 processors insert implicit barriers when the processor
+ * accesses unchacheable either for reading or writing, and
+ * donnot reorder WRITEs. As a result, some 'read barriers' can
+ * be avoided (following access to uncacheable), and 'write
+ * barriers' should be useless (preventing compiler optimizations
+ * should be enough).
+ */
+
+#if defined __i386__
+#define __READ_BARRIER() \
+ __asm__ volatile("lock; addl $0,0(%%esp)": : :"memory")
+#define __WRITE_BARRIER() __asm__ volatile ("": : :"memory")
+#elif defined __powerpc__
+#define __READ_BARRIER() __asm__ volatile("eieio; sync" : : : "memory")
+#define __WRITE_BARRIER() __asm__ volatile("eieio; sync" : : : "memory")
+#elif defined __ia64__
+#define __READ_BARRIER() __asm__ volatile("mf.a; mf" : : : "memory")
+#define __WRITE_BARRIER() __asm__ volatile("mf.a; mf" : : : "memory")
+#elif defined __alpha__
+#define __READ_BARRIER() __asm__ volatile("mb": : :"memory")
+#define __WRITE_BARRIER() __asm__ volatile("mb": : :"memory")
+#else
+#define __READ_BARRIER() mb()
+#define __WRITE_BARRIER() mb()
+#endif
+
+#ifndef MEMORY_READ_BARRIER
+#define MEMORY_READ_BARRIER() __READ_BARRIER()
+#endif
+#ifndef MEMORY_WRITE_BARRIER
+#define MEMORY_WRITE_BARRIER() __WRITE_BARRIER()
+#endif
+
+
+/*
+ * A la VMS/CAM-3 queue management.
+ */
+typedef struct sym_quehead {
+ struct sym_quehead *flink; /* Forward pointer */
+ struct sym_quehead *blink; /* Backward pointer */
+} SYM_QUEHEAD;
+
+#define sym_que_init(ptr) do { \
+ (ptr)->flink = (ptr); (ptr)->blink = (ptr); \
+} while (0)
+
+static __inline struct sym_quehead *sym_que_first(struct sym_quehead *head)
+{
+ return (head->flink == head) ? 0 : head->flink;
+}
+
+static __inline struct sym_quehead *sym_que_last(struct sym_quehead *head)
+{
+ return (head->blink == head) ? 0 : head->blink;
+}
+
+static __inline void __sym_que_add(struct sym_quehead * new,
+ struct sym_quehead * blink,
+ struct sym_quehead * flink)
+{
+ flink->blink = new;
+ new->flink = flink;
+ new->blink = blink;
+ blink->flink = new;
+}
+
+static __inline void __sym_que_del(struct sym_quehead * blink,
+ struct sym_quehead * flink)
+{
+ flink->blink = blink;
+ blink->flink = flink;
+}
+
+static __inline int sym_que_empty(struct sym_quehead *head)
+{
+ return head->flink == head;
+}
+
+static __inline void sym_que_splice(struct sym_quehead *list,
+ struct sym_quehead *head)
+{
+ struct sym_quehead *first = list->flink;
+
+ if (first != list) {
+ struct sym_quehead *last = list->blink;
+ struct sym_quehead *at = head->flink;
+
+ first->blink = head;
+ head->flink = first;
+
+ last->flink = at;
+ at->blink = last;
+ }
+}
+
+static __inline void sym_que_move(struct sym_quehead *orig,
+ struct sym_quehead *dest)
+{
+ struct sym_quehead *first, *last;
+
+ first = orig->flink;
+ if (first != orig) {
+ first->blink = dest;
+ dest->flink = first;
+ last = orig->blink;
+ last->flink = dest;
+ dest->blink = last;
+ orig->flink = orig;
+ orig->blink = orig;
+ } else {
+ dest->flink = dest;
+ dest->blink = dest;
+ }
+}
+
+#define sym_que_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned int)(&((type *)0)->member)))
+
+
+#define sym_insque(new, pos) __sym_que_add(new, pos, (pos)->flink)
+
+#define sym_remque(el) __sym_que_del((el)->blink, (el)->flink)
+
+#define sym_insque_head(new, head) __sym_que_add(new, head, (head)->flink)
+
+static __inline struct sym_quehead *sym_remque_head(struct sym_quehead *head)
+{
+ struct sym_quehead *elem = head->flink;
+
+ if (elem != head)
+ __sym_que_del(head, elem->flink);
+ else
+ elem = 0;
+ return elem;
+}
+
+#define sym_insque_tail(new, head) __sym_que_add(new, (head)->blink, head)
+
+static __inline struct sym_quehead *sym_remque_tail(struct sym_quehead *head)
+{
+ struct sym_quehead *elem = head->blink;
+
+ if (elem != head)
+ __sym_que_del(elem->blink, head);
+ else
+ elem = 0;
+ return elem;
+}
+
+/*
+ * This one may be useful.
+ */
+#define FOR_EACH_QUEUED_ELEMENT(head, qp) \
+ for (qp = (head)->flink; qp != (head); qp = qp->flink)
+/*
+ * FreeBSD does not offer our kind of queue in the CAM CCB.
+ * So, we have to cast.
+ */
+#define sym_qptr(p) ((struct sym_quehead *) (p))
+
+/*
+ * Simple bitmap operations.
+ */
+#define sym_set_bit(p, n) (((u32 *)(p))[(n)>>5] |= (1<<((n)&0x1f)))
+#define sym_clr_bit(p, n) (((u32 *)(p))[(n)>>5] &= ~(1<<((n)&0x1f)))
+#define sym_is_bit(p, n) (((u32 *)(p))[(n)>>5] & (1<<((n)&0x1f)))
+
+/*
+ * Portable but silly implemented byte order primitives.
+ */
+#if BYTE_ORDER == BIG_ENDIAN
+
+#define __revb16(x) ( (((u16)(x) & (u16)0x00ffU) << 8) | \
+ (((u16)(x) & (u16)0xff00U) >> 8) )
+#define __revb32(x) ( (((u32)(x) & 0x000000ffU) << 24) | \
+ (((u32)(x) & 0x0000ff00U) << 8) | \
+ (((u32)(x) & 0x00ff0000U) >> 8) | \
+ (((u32)(x) & 0xff000000U) >> 24) )
+
+#define __htole16(v) __revb16(v)
+#define __htole32(v) __revb32(v)
+#define __le16toh(v) __htole16(v)
+#define __le32toh(v) __htole32(v)
+
+static __inline u16 _htole16(u16 v) { return __htole16(v); }
+static __inline u32 _htole32(u32 v) { return __htole32(v); }
+#define _le16toh _htole16
+#define _le32toh _htole32
+
+#else /* LITTLE ENDIAN */
+
+#define __htole16(v) (v)
+#define __htole32(v) (v)
+#define __le16toh(v) (v)
+#define __le32toh(v) (v)
+
+#define _htole16(v) (v)
+#define _htole32(v) (v)
+#define _le16toh(v) (v)
+#define _le32toh(v) (v)
+
+#endif /* BYTE_ORDER */
+
+/*
+ * The below round up/down macros are to be used with a constant
+ * as argument (sizeof(...) for example), for the compiler to
+ * optimize the whole thing.
+ */
+#define _U_(a,m) (a)<=(1<<m)?m:
+#define _D_(a,m) (a)<(1<<(m+1))?m:
+
+/*
+ * Round up logarithm to base 2 of a 16 bit constant.
+ */
+#define _LGRU16_(a) \
+( \
+ _U_(a, 0)_U_(a, 1)_U_(a, 2)_U_(a, 3)_U_(a, 4)_U_(a, 5)_U_(a, 6)_U_(a, 7) \
+ _U_(a, 8)_U_(a, 9)_U_(a,10)_U_(a,11)_U_(a,12)_U_(a,13)_U_(a,14)_U_(a,15) \
+ 16)
+
+/*
+ * Round down logarithm to base 2 of a 16 bit constant.
+ */
+#define _LGRD16_(a) \
+( \
+ _D_(a, 0)_D_(a, 1)_D_(a, 2)_D_(a, 3)_D_(a, 4)_D_(a, 5)_D_(a, 6)_D_(a, 7) \
+ _D_(a, 8)_D_(a, 9)_D_(a,10)_D_(a,11)_D_(a,12)_D_(a,13)_D_(a,14)_D_(a,15) \
+ 16)
+
+/*
+ * Round up a 16 bit constant to the nearest power of 2.
+ */
+#define _SZRU16_(a) ((a)==0?0:(1<<_LGRU16_(a)))
+
+/*
+ * Round down a 16 bit constant to the nearest power of 2.
+ */
+#define _SZRD16_(a) ((a)==0?0:(1<<_LGRD16_(a)))
+
+#endif /* SYM_MISC_H */
diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_nvram.c linux/drivers/scsi/sym53c8xx_2/sym_nvram.c
--- v2.4.14/linux/drivers/scsi/sym53c8xx_2/sym_nvram.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sym53c8xx_2/sym_nvram.c Fri Nov 9 15:22:54 2001
@@ -0,0 +1,730 @@

+#ifdef __FreeBSD__
+#include <dev/sym/sym_glue.h>
+#else
+#include "sym_glue.h"

+#endif
+
+/*
+ * Some poor and bogus sync table that refers to Tekram NVRAM layout.
+ */
+#if SYM_CONF_NVRAM_SUPPORT
+static u_char Tekram_sync[16] =
+ {25,31,37,43, 50,62,75,125, 12,15,18,21, 6,7,9,10};
+#ifdef SYM_CONF_DEBUG_NVRAM
+static u_char Tekram_boot_delay[7] = {3, 5, 10, 20, 30, 60, 120};
+#endif
+#endif
+
+/*
+ * Get host setup from NVRAM.


+ */
+void sym_nvram_setup_host (hcb_p np, struct sym_nvram *nvram)

+{
+#if SYM_CONF_NVRAM_SUPPORT
+ /*
+ * Get parity checking, host ID, verbose mode
+ * and miscellaneous host flags from NVRAM.
+ */
+ switch(nvram->type) {
+ case SYM_SYMBIOS_NVRAM:
+ if (!(nvram->data.Symbios.flags & SYMBIOS_PARITY_ENABLE))
+ np->rv_scntl0 &= ~0x0a;
+ np->myaddr = nvram->data.Symbios.host_id & 0x0f;
+ if (nvram->data.Symbios.flags & SYMBIOS_VERBOSE_MSGS)
+ np->verbose += 1;
+ if (nvram->data.Symbios.flags1 & SYMBIOS_SCAN_HI_LO)
+ np->usrflags |= SYM_SCAN_TARGETS_HILO;
+ if (nvram->data.Symbios.flags2 & SYMBIOS_AVOID_BUS_RESET)
+ np->usrflags |= SYM_AVOID_BUS_RESET;


+ break;
+ case SYM_TEKRAM_NVRAM:

+ np->myaddr = nvram->data.Tekram.host_id & 0x0f;


+ break;
+ default:
+ break;
+ }

+#endif
+}
+
+/*
+ * Get target setup from NVRAM.
+ */
+#if SYM_CONF_NVRAM_SUPPORT
+static void sym_Symbios_setup_target(hcb_p np,int target, Symbios_nvram *nvram);
+static void sym_Tekram_setup_target(hcb_p np,int target, Tekram_nvram *nvram);
+#endif
+


+void sym_nvram_setup_target (hcb_p np, int target, struct sym_nvram *nvp)

+{
+#if SYM_CONF_NVRAM_SUPPORT


+ switch(nvp->type) {
+ case SYM_SYMBIOS_NVRAM:

+ sym_Symbios_setup_target (np, target, &nvp->data.Symbios);


+ break;
+ case SYM_TEKRAM_NVRAM:

+ sym_Tekram_setup_target (np, target, &nvp->data.Tekram);


+ break;
+ default:
+ break;
+ }

+#endif
+}
+
+#if SYM_CONF_NVRAM_SUPPORT
+/*
+ * Get target set-up from Symbios format NVRAM.
+ */
+static void
+sym_Symbios_setup_target(hcb_p np, int target, Symbios_nvram *nvram)
+{
+ tcb_p tp = &np->target[target];
+ Symbios_target *tn = &nvram->target[target];
+
+ tp->tinfo.user.period = tn->sync_period ? (tn->sync_period + 3) / 4 : 0;
+ tp->tinfo.user.width = tn->bus_width == 0x10 ? BUS_16_BIT : BUS_8_BIT;
+ tp->usrtags =
+ (tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? SYM_SETUP_MAX_TAG : 0;
+
+ if (!(tn->flags & SYMBIOS_DISCONNECT_ENABLE))
+ tp->usrflags &= ~SYM_DISC_ENABLED;
+ if (!(tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME))
+ tp->usrflags |= SYM_SCAN_BOOT_DISABLED;
+ if (!(tn->flags & SYMBIOS_SCAN_LUNS))
+ tp->usrflags |= SYM_SCAN_LUNS_DISABLED;
+}
+
+/*
+ * Get target set-up from Tekram format NVRAM.
+ */
+static void
+sym_Tekram_setup_target(hcb_p np, int target, Tekram_nvram *nvram)
+{
+ tcb_p tp = &np->target[target];
+ struct Tekram_target *tn = &nvram->target[target];
+ int i;
+
+ if (tn->flags & TEKRAM_SYNC_NEGO) {
+ i = tn->sync_index & 0xf;
+ tp->tinfo.user.period = Tekram_sync[i];
+ }
+
+ tp->tinfo.user.width =
+ (tn->flags & TEKRAM_WIDE_NEGO) ? BUS_16_BIT : BUS_8_BIT;
+
+ if (tn->flags & TEKRAM_TAGGED_COMMANDS) {
+ tp->usrtags = 2 << nvram->max_tags_index;
+ }
+
+ if (tn->flags & TEKRAM_DISCONNECT_ENABLE)
+ tp->usrflags |= SYM_DISC_ENABLED;
+
+ /* If any device does not support parity, we will not use this option */
+ if (!(tn->flags & TEKRAM_PARITY_CHECK))
+ np->rv_scntl0 &= ~0x0a; /* SCSI parity checking disabled */
+}
+
+#ifdef SYM_CONF_DEBUG_NVRAM
+/*
+ * Dump Symbios format NVRAM for debugging purpose.
+ */
+static void sym_display_Symbios_nvram(sdev_p np, Symbios_nvram *nvram)
+{
+ int i;
+
+ /* display Symbios nvram host data */
+ printf("%s: HOST ID=%d%s%s%s%s%s%s\n",
+ sym_name(np), nvram->host_id & 0x0f,
+ (nvram->flags & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"",
+ (nvram->flags & SYMBIOS_PARITY_ENABLE) ? " PARITY" :"",
+ (nvram->flags & SYMBIOS_VERBOSE_MSGS) ? " VERBOSE" :"",
+ (nvram->flags & SYMBIOS_CHS_MAPPING) ? " CHS_ALT" :"",
+ (nvram->flags2 & SYMBIOS_AVOID_BUS_RESET)?" NO_RESET" :"",
+ (nvram->flags1 & SYMBIOS_SCAN_HI_LO) ? " HI_LO" :"");
+
+ /* display Symbios nvram drive data */
+ for (i = 0 ; i < 15 ; i++) {
+ struct Symbios_target *tn = &nvram->target[i];
+ printf("%s-%d:%s%s%s%s WIDTH=%d SYNC=%d TMO=%d\n",
+ sym_name(np), i,
+ (tn->flags & SYMBIOS_DISCONNECT_ENABLE) ? " DISC" : "",
+ (tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME) ? " SCAN_BOOT" : "",
+ (tn->flags & SYMBIOS_SCAN_LUNS) ? " SCAN_LUNS" : "",
+ (tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? " TCQ" : "",
+ tn->bus_width,
+ tn->sync_period / 4,
+ tn->timeout);
+ }
+}
+
+/*
+ * Dump TEKRAM format NVRAM for debugging purpose.
+ */
+static void sym_display_Tekram_nvram(sdev_p np, Tekram_nvram *nvram)
+{
+ int i, tags, boot_delay;
+ char *rem;
+
+ /* display Tekram nvram host data */
+ tags = 2 << nvram->max_tags_index;
+ boot_delay = 0;
+ if (nvram->boot_delay_index < 6)
+ boot_delay = Tekram_boot_delay[nvram->boot_delay_index];
+ switch((nvram->flags & TEKRAM_REMOVABLE_FLAGS) >> 6) {
+ default:
+ case 0: rem = ""; break;
+ case 1: rem = " REMOVABLE=boot device"; break;
+ case 2: rem = " REMOVABLE=all"; break;
+ }
+
+ printf("%s: HOST ID=%d%s%s%s%s%s%s%s%s%s BOOT DELAY=%d tags=%d\n",
+ sym_name(np), nvram->host_id & 0x0f,
+ (nvram->flags1 & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"",
+ (nvram->flags & TEKRAM_MORE_THAN_2_DRIVES) ? " >2DRIVES":"",
+ (nvram->flags & TEKRAM_DRIVES_SUP_1GB) ? " >1GB" :"",
+ (nvram->flags & TEKRAM_RESET_ON_POWER_ON) ? " RESET" :"",
+ (nvram->flags & TEKRAM_ACTIVE_NEGATION) ? " ACT_NEG" :"",
+ (nvram->flags & TEKRAM_IMMEDIATE_SEEK) ? " IMM_SEEK" :"",
+ (nvram->flags & TEKRAM_SCAN_LUNS) ? " SCAN_LUNS" :"",
+ (nvram->flags1 & TEKRAM_F2_F6_ENABLED) ? " F2_F6" :"",
+ rem, boot_delay, tags);
+
+ /* display Tekram nvram drive data */
+ for (i = 0; i <= 15; i++) {
+ int sync, j;
+ struct Tekram_target *tn = &nvram->target[i];
+ j = tn->sync_index & 0xf;
+ sync = Tekram_sync[j];
+ printf("%s-%d:%s%s%s%s%s%s PERIOD=%d\n",
+ sym_name(np), i,
+ (tn->flags & TEKRAM_PARITY_CHECK) ? " PARITY" : "",
+ (tn->flags & TEKRAM_SYNC_NEGO) ? " SYNC" : "",
+ (tn->flags & TEKRAM_DISCONNECT_ENABLE) ? " DISC" : "",
+ (tn->flags & TEKRAM_START_CMD) ? " START" : "",
+ (tn->flags & TEKRAM_TAGGED_COMMANDS) ? " TCQ" : "",
+ (tn->flags & TEKRAM_WIDE_NEGO) ? " WIDE" : "",
+ sync);
+ }
+}
+#endif /* SYM_CONF_DEBUG_NVRAM */
+#endif /* SYM_CONF_NVRAM_SUPPORT */
+
+
+/*
+ * Try reading Symbios or Tekram NVRAM
+ */
+#if SYM_CONF_NVRAM_SUPPORT
+static int sym_read_Symbios_nvram (sdev_p np, Symbios_nvram *nvram);
+static int sym_read_Tekram_nvram (sdev_p np, Tekram_nvram *nvram);
+#endif
+


+int sym_read_nvram (sdev_p np, struct sym_nvram *nvp)

+{
+#if SYM_CONF_NVRAM_SUPPORT
+ /*
+ * Try to read SYMBIOS nvram.
+ * Try to read TEKRAM nvram if Symbios nvram not found.
+ */
+ if (SYM_SETUP_SYMBIOS_NVRAM &&
+ !sym_read_Symbios_nvram (np, &nvp->data.Symbios)) {
+ nvp->type = SYM_SYMBIOS_NVRAM;
+#ifdef SYM_CONF_DEBUG_NVRAM
+ sym_display_Symbios_nvram(np, &nvp->data.Symbios);
+#endif
+ }
+ else if (SYM_SETUP_TEKRAM_NVRAM &&
+ !sym_read_Tekram_nvram (np, &nvp->data.Tekram)) {
+ nvp->type = SYM_TEKRAM_NVRAM;
+#ifdef SYM_CONF_DEBUG_NVRAM
+ sym_display_Tekram_nvram(np, &nvp->data.Tekram);
+#endif
+ }
+ else
+ nvp->type = 0;
+#else


+ nvp->type = 0;

+#endif
+ return nvp->type;
+}
+
+
+#if SYM_CONF_NVRAM_SUPPORT
+/*
+ * 24C16 EEPROM reading.
+ *
+ * GPOI0 - data in/data out
+ * GPIO1 - clock
+ * Symbios NVRAM wiring now also used by Tekram.
+ */
+
+#define SET_BIT 0
+#define CLR_BIT 1
+#define SET_CLK 2
+#define CLR_CLK 3
+
+/*
+ * Set/clear data/clock bit in GPIO0
+ */
+static void S24C16_set_bit(sdev_p np, u_char write_bit, u_char *gpreg,
+ int bit_mode)
+{
+ UDELAY (5);
+ switch (bit_mode){
+ case SET_BIT:
+ *gpreg |= write_bit;
+ break;
+ case CLR_BIT:
+ *gpreg &= 0xfe;
+ break;
+ case SET_CLK:
+ *gpreg |= 0x02;
+ break;
+ case CLR_CLK:
+ *gpreg &= 0xfd;
+ break;
+
+ }
+ OUTB (nc_gpreg, *gpreg);
+ UDELAY (5);
+}
+
+/*
+ * Send START condition to NVRAM to wake it up.
+ */
+static void S24C16_start(sdev_p np, u_char *gpreg)
+{
+ S24C16_set_bit(np, 1, gpreg, SET_BIT);
+ S24C16_set_bit(np, 0, gpreg, SET_CLK);
+ S24C16_set_bit(np, 0, gpreg, CLR_BIT);
+ S24C16_set_bit(np, 0, gpreg, CLR_CLK);
+}
+
+/*
+ * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZzzzz!!
+ */
+static void S24C16_stop(sdev_p np, u_char *gpreg)
+{
+ S24C16_set_bit(np, 0, gpreg, SET_CLK);
+ S24C16_set_bit(np, 1, gpreg, SET_BIT);
+}
+
+/*
+ * Read or write a bit to the NVRAM,
+ * read if GPIO0 input else write if GPIO0 output
+ */
+static void S24C16_do_bit(sdev_p np, u_char *read_bit, u_char write_bit,
+ u_char *gpreg)
+{
+ S24C16_set_bit(np, write_bit, gpreg, SET_BIT);
+ S24C16_set_bit(np, 0, gpreg, SET_CLK);
+ if (read_bit)
+ *read_bit = INB (nc_gpreg);
+ S24C16_set_bit(np, 0, gpreg, CLR_CLK);
+ S24C16_set_bit(np, 0, gpreg, CLR_BIT);
+}
+
+/*
+ * Output an ACK to the NVRAM after reading,
+ * change GPIO0 to output and when done back to an input
+ */
+static void S24C16_write_ack(sdev_p np, u_char write_bit, u_char *gpreg,
+ u_char *gpcntl)
+{
+ OUTB (nc_gpcntl, *gpcntl & 0xfe);
+ S24C16_do_bit(np, 0, write_bit, gpreg);
+ OUTB (nc_gpcntl, *gpcntl);
+}
+
+/*
+ * Input an ACK from NVRAM after writing,
+ * change GPIO0 to input and when done back to an output
+ */
+static void S24C16_read_ack(sdev_p np, u_char *read_bit, u_char *gpreg,
+ u_char *gpcntl)
+{
+ OUTB (nc_gpcntl, *gpcntl | 0x01);
+ S24C16_do_bit(np, read_bit, 1, gpreg);
+ OUTB (nc_gpcntl, *gpcntl);
+}
+
+/*
+ * WRITE a byte to the NVRAM and then get an ACK to see it was accepted OK,
+ * GPIO0 must already be set as an output
+ */
+static void S24C16_write_byte(sdev_p np, u_char *ack_data, u_char write_data,
+ u_char *gpreg, u_char *gpcntl)
+{
+ int x;
+
+ for (x = 0; x < 8; x++)
+ S24C16_do_bit(np, 0, (write_data >> (7 - x)) & 0x01, gpreg);
+
+ S24C16_read_ack(np, ack_data, gpreg, gpcntl);
+}
+
+/*
+ * READ a byte from the NVRAM and then send an ACK to say we have got it,
+ * GPIO0 must already be set as an input
+ */
+static void S24C16_read_byte(sdev_p np, u_char *read_data, u_char ack_data,
+ u_char *gpreg, u_char *gpcntl)
+{
+ int x;
+ u_char read_bit;
+
+ *read_data = 0;
+ for (x = 0; x < 8; x++) {
+ S24C16_do_bit(np, &read_bit, 1, gpreg);
+ *read_data |= ((read_bit & 0x01) << (7 - x));
+ }
+
+ S24C16_write_ack(np, ack_data, gpreg, gpcntl);
+}
+
+/*
+ * Read 'len' bytes starting at 'offset'.
+ */
+static int sym_read_S24C16_nvram (sdev_p np, int offset, u_char *data, int len)
+{
+ u_char gpcntl, gpreg;
+ u_char old_gpcntl, old_gpreg;
+ u_char ack_data;
+ int retv = 1;
+ int x;
+
+ /* save current state of GPCNTL and GPREG */
+ old_gpreg = INB (nc_gpreg);
+ old_gpcntl = INB (nc_gpcntl);
+ gpcntl = old_gpcntl & 0x1c;
+
+ /* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */
+ OUTB (nc_gpreg, old_gpreg);
+ OUTB (nc_gpcntl, gpcntl);
+
+ /* this is to set NVRAM into a known state with GPIO0/1 both low */
+ gpreg = old_gpreg;
+ S24C16_set_bit(np, 0, &gpreg, CLR_CLK);
+ S24C16_set_bit(np, 0, &gpreg, CLR_BIT);
+
+ /* now set NVRAM inactive with GPIO0/1 both high */
+ S24C16_stop(np, &gpreg);
+
+ /* activate NVRAM */
+ S24C16_start(np, &gpreg);
+
+ /* write device code and random address MSB */
+ S24C16_write_byte(np, &ack_data,
+ 0xa0 | ((offset >> 7) & 0x0e), &gpreg, &gpcntl);
+ if (ack_data & 0x01)
+ goto out;
+
+ /* write random address LSB */
+ S24C16_write_byte(np, &ack_data,
+ offset & 0xff, &gpreg, &gpcntl);
+ if (ack_data & 0x01)
+ goto out;
+
+ /* regenerate START state to set up for reading */
+ S24C16_start(np, &gpreg);
+
+ /* rewrite device code and address MSB with read bit set (lsb = 0x01) */
+ S24C16_write_byte(np, &ack_data,
+ 0xa1 | ((offset >> 7) & 0x0e), &gpreg, &gpcntl);
+ if (ack_data & 0x01)
+ goto out;
+
+ /* now set up GPIO0 for inputting data */
+ gpcntl |= 0x01;
+ OUTB (nc_gpcntl, gpcntl);
+
+ /* input all requested data - only part of total NVRAM */
+ for (x = 0; x < len; x++)
+ S24C16_read_byte(np, &data[x], (x == (len-1)), &gpreg, &gpcntl);
+
+ /* finally put NVRAM back in inactive mode */
+ gpcntl &= 0xfe;
+ OUTB (nc_gpcntl, gpcntl);
+ S24C16_stop(np, &gpreg);
+ retv = 0;
+out:
+ /* return GPIO0/1 to original states after having accessed NVRAM */
+ OUTB (nc_gpcntl, old_gpcntl);
+ OUTB (nc_gpreg, old_gpreg);
+


+ return retv;
+}
+

+#undef SET_BIT 0
+#undef CLR_BIT 1
+#undef SET_CLK 2
+#undef CLR_CLK 3
+
+/*
+ * Try reading Symbios NVRAM.
+ * Return 0 if OK.
+ */
+static int sym_read_Symbios_nvram (sdev_p np, Symbios_nvram *nvram)
+{
+ static u_char Symbios_trailer[6] = {0xfe, 0xfe, 0, 0, 0, 0};
+ u_char *data = (u_char *) nvram;
+ int len = sizeof(*nvram);
+ u_short csum;
+ int x;
+
+ /* probe the 24c16 and read the SYMBIOS 24c16 area */
+ if (sym_read_S24C16_nvram (np, SYMBIOS_NVRAM_ADDRESS, data, len))
+ return 1;
+
+ /* check valid NVRAM signature, verify byte count and checksum */
+ if (nvram->type != 0 ||
+ bcmp(nvram->trailer, Symbios_trailer, 6) ||
+ nvram->byte_count != len - 12)
+ return 1;
+
+ /* verify checksum */
+ for (x = 6, csum = 0; x < len - 6; x++)
+ csum += data[x];
+ if (csum != nvram->checksum)
+ return 1;


+
+ return 0;
+}
+
+/*

+ * 93C46 EEPROM reading.
+ *
+ * GPOI0 - data in
+ * GPIO1 - data out
+ * GPIO2 - clock
+ * GPIO4 - chip select
+ *
+ * Used by Tekram.
+ */
+
+/*
+ * Pulse clock bit in GPIO0
+ */
+static void T93C46_Clk(sdev_p np, u_char *gpreg)
+{
+ OUTB (nc_gpreg, *gpreg | 0x04);
+ UDELAY (2);
+ OUTB (nc_gpreg, *gpreg);
+}
+
+/*
+ * Read bit from NVRAM
+ */
+static void T93C46_Read_Bit(sdev_p np, u_char *read_bit, u_char *gpreg)
+{
+ UDELAY (2);
+ T93C46_Clk(np, gpreg);
+ *read_bit = INB (nc_gpreg);
+}
+
+/*
+ * Write bit to GPIO0
+ */
+static void T93C46_Write_Bit(sdev_p np, u_char write_bit, u_char *gpreg)
+{
+ if (write_bit & 0x01)
+ *gpreg |= 0x02;
+ else
+ *gpreg &= 0xfd;
+
+ *gpreg |= 0x10;
+
+ OUTB (nc_gpreg, *gpreg);
+ UDELAY (2);
+
+ T93C46_Clk(np, gpreg);
+}
+
+/*
+ * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZZzzz!!
+ */
+static void T93C46_Stop(sdev_p np, u_char *gpreg)
+{
+ *gpreg &= 0xef;
+ OUTB (nc_gpreg, *gpreg);
+ UDELAY (2);
+
+ T93C46_Clk(np, gpreg);
+}
+
+/*
+ * Send read command and address to NVRAM
+ */
+static void T93C46_Send_Command(sdev_p np, u_short write_data,
+ u_char *read_bit, u_char *gpreg)
+{
+ int x;
+
+ /* send 9 bits, start bit (1), command (2), address (6) */
+ for (x = 0; x < 9; x++)
+ T93C46_Write_Bit(np, (u_char) (write_data >> (8 - x)), gpreg);
+
+ *read_bit = INB (nc_gpreg);
+}
+
+/*
+ * READ 2 bytes from the NVRAM
+ */
+static void T93C46_Read_Word(sdev_p np, u_short *nvram_data, u_char *gpreg)
+{
+ int x;
+ u_char read_bit;
+
+ *nvram_data = 0;
+ for (x = 0; x < 16; x++) {
+ T93C46_Read_Bit(np, &read_bit, gpreg);
+
+ if (read_bit & 0x01)
+ *nvram_data |= (0x01 << (15 - x));
+ else
+ *nvram_data &= ~(0x01 << (15 - x));
+ }
+}
+
+/*
+ * Read Tekram NvRAM data.
+ */
+static int T93C46_Read_Data(sdev_p np, u_short *data,int len,u_char *gpreg)
+{
+ u_char read_bit;
+ int x;
+
+ for (x = 0; x < len; x++) {
+
+ /* output read command and address */
+ T93C46_Send_Command(np, 0x180 | x, &read_bit, gpreg);
+ if (read_bit & 0x01)
+ return 1; /* Bad */
+ T93C46_Read_Word(np, &data[x], gpreg);
+ T93C46_Stop(np, gpreg);
+ }


+
+ return 0;
+}
+
+/*

+ * Try reading 93C46 Tekram NVRAM.
+ */
+static int sym_read_T93C46_nvram (sdev_p np, Tekram_nvram *nvram)
+{
+ u_char gpcntl, gpreg;
+ u_char old_gpcntl, old_gpreg;
+ int retv = 1;
+
+ /* save current state of GPCNTL and GPREG */
+ old_gpreg = INB (nc_gpreg);
+ old_gpcntl = INB (nc_gpcntl);
+
+ /* set up GPREG & GPCNTL to set GPIO0/1/2/4 in to known state, 0 in,
+ 1/2/4 out */
+ gpreg = old_gpreg & 0xe9;
+ OUTB (nc_gpreg, gpreg);
+ gpcntl = (old_gpcntl & 0xe9) | 0x09;
+ OUTB (nc_gpcntl, gpcntl);
+
+ /* input all of NVRAM, 64 words */
+ retv = T93C46_Read_Data(np, (u_short *) nvram,
+ sizeof(*nvram) / sizeof(short), &gpreg);
+
+ /* return GPIO0/1/2/4 to original states after having accessed NVRAM */
+ OUTB (nc_gpcntl, old_gpcntl);
+ OUTB (nc_gpreg, old_gpreg);
+
+ return retv;
+}
+
+/*
+ * Try reading Tekram NVRAM.
+ * Return 0 if OK.
+ */
+static int sym_read_Tekram_nvram (sdev_p np, Tekram_nvram *nvram)
+{
+ u_char *data = (u_char *) nvram;
+ int len = sizeof(*nvram);
+ u_short csum;
+ int x;
+
+ switch (np->device_id) {
+ case PCI_ID_SYM53C885:
+ case PCI_ID_SYM53C895:
+ case PCI_ID_SYM53C896:
+ x = sym_read_S24C16_nvram(np, TEKRAM_24C16_NVRAM_ADDRESS,
+ data, len);
+ break;
+ case PCI_ID_SYM53C875:
+ x = sym_read_S24C16_nvram(np, TEKRAM_24C16_NVRAM_ADDRESS,
+ data, len);
+ if (!x)
+ break;
+ default:
+ x = sym_read_T93C46_nvram(np, nvram);
+ break;
+ }
+ if (x)
+ return 1;
+
+ /* verify checksum */
+ for (x = 0, csum = 0; x < len - 1; x += 2)
+ csum += data[x] + (data[x+1] << 8);
+ if (csum != 0x1234)
+ return 1;


+
+ return 0;
+}
+

+#endif /* SYM_CONF_NVRAM_SUPPORT */
diff -u --recursive --new-file v2.4.14/linux/drivers/sound/ac97_codec.c linux/drivers/sound/ac97_codec.c
--- v2.4.14/linux/drivers/sound/ac97_codec.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/sound/ac97_codec.c Mon Nov 12 10:02:54 2001
@@ -130,7 +130,7 @@
X {0x54524103, "TriTech TR28023", &null_ops},
X {0x54524106, "TriTech TR28026", &null_ops},
X {0x54524108, "TriTech TR28028", &tritech_ops},
- {0x54524123, "TriTech TR?????", &null_ops},
+ {0x54524123, "TriTech TR A5", &null_ops},
X {0x574D4C00, "Wolfson WM9704", &wolfson_ops},
X {0x574D4C03, "Wolfson WM9703/9704", &wolfson_ops},
X {0x574D4C04, "Wolfson WM9704 (quad)", &wolfson_ops},
@@ -143,7 +143,6 @@
X {0x83847656, "SigmaTel STAC9756/57", &sigmatel_9744_ops},
X {0x83847684, "SigmaTel STAC9783/84?", &null_ops},
X {0x57454301, "Winbond 83971D", &null_ops},
- {0,}
X };
X
X static const char *ac97_stereo_enhancements[] =
@@ -1020,4 +1019,31 @@
X }
X
X EXPORT_SYMBOL(ac97_set_adc_rate);
+
+int ac97_save_state(struct ac97_codec *codec)


+{
+ return 0;
+}
+

+EXPORT_SYMBOL(ac97_save_state);
+
+int ac97_restore_state(struct ac97_codec *codec)
+{
+ int i;
+ unsigned int left, right, val;
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (!supported_mixer(codec, i))
+ continue;
+
+ val = codec->mixer_state[i];
+ right = val >> 8;
+ left = val & 0xff;
+ codec->write_mixer(codec, i, left, right);


+ }
+ return 0;
+}
+

+EXPORT_SYMBOL(ac97_restore_state);
+
X MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/sound/aci.c linux/drivers/sound/aci.c
--- v2.4.14/linux/drivers/sound/aci.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/sound/aci.c Fri Nov 9 14:07:41 2001
@@ -47,6 +47,8 @@
X * changed param aci_reset to reset, new params: ide, wss.
X * 2001-04-20 Robert Siemer
X * even more cleanups...
+ * 2001-10-08 Arnaldo Carvalho de Melo <ac...@conectiva.com.br>
+ * Get rid of check_region, .bss optimizations, use set_current_state
X */
X
X #include <linux/kernel.h>
@@ -70,9 +72,9 @@
X #include "aci.h"
X
X
-static int aci_solo=0; /* status bit of the card that can't be *
+static int aci_solo; /* status bit of the card that can't be *
X * checked with ACI versions prior to 0xb0 */
-static int aci_amp=0; /* status bit for power-amp/line-out level
+static int aci_amp; /* status bit for power-amp/line-out level
X but I have no docs about what is what... */
X static int aci_micpreamp=3; /* microphone preamp-level that can't be *
X * checked with ACI versions prior to 0xb0 */
@@ -81,7 +83,7 @@
X static struct semaphore aci_sem;
X
X #ifdef MODULE
-static int reset = 0;
+static int reset;
X MODULE_PARM(reset,"i");
X MODULE_PARM_DESC(reset,"When set to 1, reset aci mixer.");
X #else
@@ -146,7 +148,7 @@
X case 20 ... 30:
X out /= 10;
X default:
- current->state=TASK_UNINTERRUPTIBLE;
+ set_current_state(TASK_UNINTERRUPTIBLE);
X schedule_timeout(out);
X break;
X }
@@ -209,28 +211,25 @@
X int aci_rw_cmd(int write1, int write2, int write3)
X {
X int write[] = {write1, write2, write3};
- int read, i;
+ int read = -EINTR, i;
X
X if (down_interruptible(&aci_sem))
- return -EINTR;
+ goto out;
X
X for (i=0; i<3; i++) {
X if (write[i]< 0 || write[i] > 255)
X break;
- else
- if (aci_rawwrite(write[i])<0) {
- up(&aci_sem);
- return -EBUSY;
- }
+ else {
+ read = aci_rawwrite(write[i]);
+ if (read < 0)
+ goto out_up;
+ }
+
X }
X
- if ((read=aci_rawread())<0) {
- up(&aci_sem);
- return -EBUSY;
- }
-
- up(&aci_sem);
- return read;
+ read = aci_rawread();
+out_up: up(&aci_sem);
+out: return read;
X }
X
X EXPORT_SYMBOL(aci_rw_cmd);
@@ -602,7 +601,7 @@
X static int __init attach_aci(void)
X {
X char *boardname;
- int i;
+ int i, rc = -EBUSY;
X
X init_MUTEX(&aci_sem);
X
@@ -610,27 +609,32 @@
X aci_port = (inb(0xf90) & 0x10) ?
X 0x344: 0x354; /* Get aci_port from MC4_PORT */
X
- if (check_region(aci_port, 3)) {
- printk(KERN_NOTICE "aci: I/O area 0x%03x-0x%03x already used.\n",
+ if (!request_region(aci_port, 3, "sound mixer (ACI)")) {
+ printk(KERN_NOTICE
+ "aci: I/O area 0x%03x-0x%03x already used.\n",
X aci_port, aci_port+2);
- return -EBUSY;


+ goto out;
X }
X

X /* force ACI into a known state */
+ rc = -EFAULT;
X for (i=0; i<3; i++)
X if (aci_rw_cmd(ACI_ERROR_OP, -1, -1)<0)
- return -EFAULT;
+ goto out_release_region;
X
X /* official this is one aci read call: */
+ rc = -EFAULT;
X if ((aci_idcode[0]=aci_rw_cmd(ACI_READ_IDCODE, -1, -1))<0 ||
X (aci_idcode[1]=aci_rw_cmd(ACI_READ_IDCODE, -1, -1))<0) {
- printk(KERN_ERR "aci: Failed to read idcode on 0x%03x.\n", aci_port);
- return -EFAULT;
+ printk(KERN_ERR "aci: Failed to read idcode on 0x%03x.\n",
+ aci_port);
+ goto out_release_region;
X }
X
X if ((aci_version=aci_rw_cmd(ACI_READ_VERSION, -1, -1))<0) {
- printk(KERN_ERR "aci: Failed to read version on 0x%03x.\n", aci_port);
- return -EFAULT;
+ printk(KERN_ERR "aci: Failed to read version on 0x%03x.\n",
+ aci_port);
+ goto out_release_region;
X }
X
X if (aci_idcode[0] == 'm') {
@@ -660,42 +664,40 @@
X aci_idcode[0], aci_idcode[1],
X boardname, aci_port);
X
+ rc = -EBUSY;
X if (reset) {
X /* first write()s after reset fail with my PCM20 */
X if (aci_rw_cmd(ACI_INIT, -1, -1)<0 ||
X aci_rw_cmd(ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP)<0 ||
X aci_rw_cmd(ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP)<0)
- return -EBUSY;
+ goto out_release_region;
X }
X
X /* the PCM20 is muted after reset (and reboot) */
X if (aci_rw_cmd(ACI_SET_MUTE, 0x00, -1)<0)
- return -EBUSY;
+ goto out_release_region;
X
X if (ide>=0)
X if (aci_rw_cmd(ACI_SET_IDE, !ide, -1)<0)
- return -EBUSY;
+ goto out_release_region;
X
X if (wss>=0 && aci_idcode[1]=='A')
X if (aci_rw_cmd(ACI_SET_WSS, !!wss, -1)<0)
- return -EBUSY;
-
- if (!request_region(aci_port, 3, "sound mixer (ACI)"))
- return -ENOMEM;
+ goto out_release_region;
X
- if ((mixer_device = sound_install_mixer(MIXER_DRIVER_VERSION,
- boardname,
- &aci_mixer_operations,
- sizeof(aci_mixer_operations),
- NULL)) >= 0) {
- /* Maybe initialize the CS4231A mixer here... */
- } else {
+ mixer_device = sound_install_mixer(MIXER_DRIVER_VERSION, boardname,
+ &aci_mixer_operations,
+ sizeof(aci_mixer_operations), NULL);
+ rc = 0;
+ if (mixer_device < 0) {
X printk(KERN_ERR "aci: Failed to install mixer.\n");
- release_region(aci_port, 3);
- return mixer_device;
- }
-
- return 0;
+ rc = mixer_device;
+ goto out_release_region;
+ } /* else Maybe initialize the CS4231A mixer here... */
+out: return rc;
+out_release_region:
+ release_region(aci_port, 3);


+ goto out;
X }
X

X static void __exit unload_aci(void)
diff -u --recursive --new-file v2.4.14/linux/drivers/sound/ad1816.c linux/drivers/sound/ad1816.c
--- v2.4.14/linux/drivers/sound/ad1816.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/sound/ad1816.c Fri Nov 9 15:22:54 2001


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

echo 'End of part 068'
echo 'File patch-2.4.15 is continued in part 069'
echo "069" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:51 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part075

#!/bin/sh -x
# this is part 075 of a 115 - part archive


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

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

+ {0x41, 0x22, 157}, /* 0x20 */
+ {0x70, 0x24, 162}, /* 0x21 */
+ {0x30, 0x21, 175}, /* 0x22 */
+ {0x4e, 0x22, 189}, /* 0x23 */
+ {0xde, 0x26, 194}, /* 0x24 */

+ {0x70, 0x07, 202}, /* 0x25 */

+UCHAR SiS310_OutputSelect = 0;

+ {143, 120, 1056, 643, 1288, 440, 0, 128, 0, 0xf4, 0x10, 0x1c, 0x00},


+ {2, 1, 858, 503, 1270, 480, 0, 128, 0, 0xee, 0x0c, 0x22, 0x08},
+ {65, 64, 1056, 791, 1270, 480, 638, 0, 0, 0xEE, 0x0C, 0x22, 0x08} /*301b */
+};
+

+SiS310_TVDataStruct SiS310_St1HiTVData[] = {
+ 0x00
+};
+
+SiS310_TVDataStruct SiS310_St2HiTVData[] = {
+ 0x00
+};
+
+SiS310_TVDataStruct SiS310_ExtHiTVData[] = {
+ 0x00
+};
+

+SiS310_PanelDelayTblStruct SiS310_PanelDelayTbl[] = { {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}
+};
+

+ {1059, 626},
+ {1059, 624},
+ {1059, 626},
+ {1059, 624},
+ {1059, 624},
+ {0, 627},
+ {0, 627},
+ {0, 0},
+ {0, 0}
+};
+

+SiS310_LVDSDesStruct SiS310_PanelType01_1[] = {
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+ {0, 805},
+ {0, 794},
+ {0, 0}
+};
+
+SiS310_LVDSDesStruct SiS310_PanelType02_1[] = {

+};
+
+typedef struct _SiS310_LVDSCRT1DataStruct {

+ UCHAR CR[17];


+} SiS310_LVDSCRT1DataStruct;
+SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1[] =
+ { {0x65, 0x4f, 0x89, 0x56, 0x83, 0xaf, 0x1f,
+ 0x90, 0x85, 0x8f, 0xab, 0x30, 0x00, 0x05,
+ 0x00},
+{0x65, 0x4f, 0x89, 0x56, 0x83, 0x83, 0x1f,
+ 0x5e, 0x83, 0x5d, 0x79, 0x10, 0x00, 0x05,
+ 0x00},
+{0x65, 0x4f, 0x89, 0x56, 0x83, 0xaf, 0x1f,
+ 0x90, 0x85, 0x8f, 0xab, 0x30, 0x00, 0x05,
+ 0x00},
+{0x65, 0x4f, 0x89, 0x56, 0x83, 0x83, 0x1f,
+ 0x5e, 0x83, 0x5d, 0x79, 0x10, 0x00, 0x05,
+ 0x00},
+{0x65, 0x4f, 0x89, 0x56, 0x83, 0x04, 0x3e,
+ 0xe0, 0x85, 0xdf, 0xfb, 0x10, 0x00, 0x05,
+ 0x00},
+{0x7f, 0x63, 0x83, 0x6c, 0x1c, 0x72, 0xf0,
+ 0x58, 0x8c, 0x57, 0x73, 0x20, 0x00, 0x06,
+ 0x01}
+};
+
+SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1[] =

+ { {0x73, 0x4f, 0x4f, 0x97, 0x55, 0x86, 0xc4, 0x1f,


+ 0x92, 0x89, 0x8f, 0x8f, 0xb5, 0x30, 0x00, 0x05,
+ 0x00},
+{0x73, 0x4f, 0x4f, 0x97, 0x55, 0x86, 0x97, 0x1f,
+ 0x60, 0x87, 0x5d, 0x5d, 0x83, 0x10, 0x00, 0x05,
+ 0x00},
+{0x73, 0x4f, 0x4f, 0x97, 0x55, 0x86, 0xc4, 0x1f,
+ 0x92, 0x89, 0x8f, 0x8f, 0xb5, 0x30, 0x00, 0x05,
+ 0x00},
+{0x73, 0x4f, 0x4f, 0x97, 0x55, 0x86, 0x97, 0x1f,
+ 0x60, 0x87, 0x5d, 0x5d, 0x83, 0x10, 0x00, 0x05,
+ 0x00},
+{0x73, 0x4f, 0x4f, 0x97, 0x55, 0x86, 0x04, 0x3e,
+ 0xE2, 0x89, 0xDf, 0xDf, 0x05, 0x00, 0x00, 0x05,
+ 0x00},
+{0x87, 0x63, 0x63, 0x8B, 0x69, 0x1A, 0x7c, 0xf0,
+ 0x5A, 0x8F, 0x57, 0x57, 0x7D, 0x20, 0x00, 0x26,
+ 0x01},
+{0xA3, 0x7f, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5,
+ 0x02, 0x88, 0xFf, 0xFf, 0x25, 0x10, 0x00, 0x02,
+ 0x01}
+};
+

+ { {0x37, 0x27, 0x27, 0x9B, 0x2b, 0x94, 0xc4, 0x1f,


+ 0x92, 0x89, 0x8f, 0x8f, 0xb5, 0x30, 0x00, 0x44,
+ 0x00},
+{0x37, 0x27, 0x27, 0x9B, 0x2b, 0x94, 0x97, 0x1f,
+ 0x60, 0x87, 0x5D, 0x5D, 0x83, 0x01, 0x00, 0x44,
+ 0x00},
+{0x37, 0x27, 0x27, 0x9B, 0x2b, 0x94, 0xc4, 0x1f,
+ 0x92, 0x89, 0x8f, 0x8f, 0xb5, 0x30, 0x00, 0x44,
+ 0x00},
+{0x37, 0x27, 0x27, 0x9B, 0x2b, 0x94, 0x97, 0x1f,
+ 0x60, 0x87, 0x5D, 0x5D, 0x83, 0x01, 0x00, 0x44,
+ 0x00},
+{0x37, 0x27, 0x27, 0x9B, 0x2b, 0x94, 0x04, 0x3e,
+ 0xE2, 0x89, 0xDf, 0xDf, 0x05, 0x00, 0x00, 0x44,
+ 0x00},
+{0x41, 0x31, 0x31, 0x85, 0x35, 0x1d, 0x7c, 0xf0,
+ 0x5A, 0x8F, 0x57, 0x57, 0x7D, 0x20, 0x00, 0x55,
+ 0x01},
+{0x4f, 0x3F, 0x3F, 0x93, 0x45, 0x0D, 0x24, 0xf5,
+ 0x02, 0x88, 0xFf, 0xFf, 0x25, 0x10, 0x00, 0x01,
+ 0x01}
+};
+

diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/Makefile linux/drivers/video/sis/Makefile
--- v2.4.14/linux/drivers/video/sis/Makefile Tue Oct 9 17:06:53 2001
+++ linux/drivers/video/sis/Makefile Fri Nov 9 14:11:14 2001
@@ -6,7 +6,7 @@
X
X export-objs := sis_main.o
X
-obj-y := sis_main.o sis_300.o sis_301.o
+obj-y := sis_main.o init.o init301.o
X obj-m := $(O_TARGET)
X
X include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/init.c linux/drivers/video/sis/init.c
--- v2.4.14/linux/drivers/video/sis/init.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/sis/init.c Fri Nov 9 14:11:14 2001
@@ -0,0 +1,3784 @@
+/* Function: Support NT X.0 MM function */
+/* Version : V 0.80 [ynlai] 04/12/98 */
+
+#include "init.h"
+#ifdef CONFIG_FB_SIS_300
+#include "300vtbl.h"
+#endif
+#ifdef CONFIG_FB_SIS_315
+#include "310vtbl.h"
+#endif
+
+BOOLEAN SiSInit (PSIS_HW_DEVICE_INFO HwDeviceExtension);
+BOOLEAN SiSSetMode (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT ModeNo);
+
+#if defined(ALLOC_PRAGMA)
+#pragma alloc_text(PAGE,SiSSetMode)
+#pragma alloc_text(PAGE,SiSInit)
+#endif
+
+void SiS_SetReg1 (USHORT, USHORT, USHORT);
+void SiS_SetReg2 (USHORT, USHORT, USHORT);
+void SiS_SetReg3 (USHORT, USHORT);
+void SiS_SetReg4 (USHORT, ULONG);
+UCHAR SiS_GetReg1 (USHORT, USHORT);
+UCHAR SiS_GetReg2 (USHORT);
+ULONG SiS_GetReg3 (USHORT);
+void SiS_ClearDAC (ULONG);
+
+#ifdef CONFIG_FB_SIS_300
+void
+InitTo300Pointer (void)
+{
+ SiS_SModeIDTable = (SiS_StStruct *) SiS300_SModeIDTable;
+ SiS_VBModeIDTable = (SiS_VBModeStruct *) SiS300_VBModeIDTable; /*add for 300 oem util */
+ SiS_StandTable = (SiS_StandTableStruct *) SiS300_StandTable;
+ SiS_EModeIDTable = (SiS_ExtStruct *) SiS300_EModeIDTable;
+ SiS_RefIndex = (SiS_Ext2Struct *) SiS300_RefIndex;
+ SiS_CRT1Table = (SiS_CRT1TableStruct *) SiS300_CRT1Table;
+ SiS_MCLKData = (SiS_MCLKDataStruct *) SiS300_MCLKData;
+ SiS_ECLKData = (SiS_ECLKDataStruct *) SiS300_ECLKData;
+ SiS_VCLKData = (SiS_VCLKDataStruct *) SiS300_VCLKData;
+ SiS_VBVCLKData = (SiS_VBVCLKDataStruct *) SiS300_VCLKData;
+ SiS_ScreenOffset = SiS300_ScreenOffset;
+ SiS_StResInfo = (SiS_StResInfoStruct *) SiS300_StResInfo;
+ SiS_ModeResInfo = (SiS_ModeResInfoStruct *) SiS300_ModeResInfo;
+
+ pSiS_OutputSelect = &SiS300_OutputSelect;
+ pSiS_SoftSetting = &SiS300_SoftSetting;
+ pSiS_SR07 = &SiS300_SR07;
+ SiS_SR15 = SiS300_SR15;
+ SiS_CR40 = SiS300_CR40;
+ SiS_CR49 = SiS300_CR49;
+ pSiS_SR1F = &SiS300_SR1F;
+ pSiS_SR21 = &SiS300_SR21;
+ pSiS_SR22 = &SiS300_SR22;
+ pSiS_SR23 = &SiS300_SR23;
+ pSiS_SR24 = &SiS300_SR24;
+ SiS_SR25 = SiS300_SR25;
+ pSiS_SR31 = &SiS300_SR31;
+ pSiS_SR32 = &SiS300_SR32;
+ pSiS_SR33 = &SiS300_SR33;
+ pSiS_CRT2Data_1_2 = &SiS300_CRT2Data_1_2;
+ pSiS_CRT2Data_4_D = &SiS300_CRT2Data_4_D;
+ pSiS_CRT2Data_4_E = &SiS300_CRT2Data_4_E;
+ pSiS_CRT2Data_4_10 = &SiS300_CRT2Data_4_10;
+ pSiS_RGBSenseData = &SiS300_RGBSenseData;
+ pSiS_VideoSenseData = &SiS300_VideoSenseData;
+ pSiS_YCSenseData = &SiS300_YCSenseData;
+ pSiS_RGBSenseData2 = &SiS300_RGBSenseData2;
+ pSiS_VideoSenseData2 = &SiS300_VideoSenseData2;
+ pSiS_YCSenseData2 = &SiS300_YCSenseData2;
+
+ SiS_NTSCPhase = SiS300_NTSCPhase;
+ SiS_PALPhase = SiS300_PALPhase;
+ SiS_NTSCPhase2 = SiS300_NTSCPhase2;
+ SiS_PALPhase2 = SiS300_PALPhase2;
+ SiS_PALMPhase = SiS300_PALMPhase; /*add for PALMN */
+ SiS_PALNPhase = SiS300_PALNPhase;
+
+ SiS_StLCD1024x768Data = (SiS_LCDDataStruct *) SiS300_StLCD1024x768Data;
+ SiS_ExtLCD1024x768Data =
+ (SiS_LCDDataStruct *) SiS300_ExtLCD1024x768Data;
+ SiS_St2LCD1024x768Data =
+ (SiS_LCDDataStruct *) SiS300_St2LCD1024x768Data;
+ SiS_StLCD1280x1024Data =
+ (SiS_LCDDataStruct *) SiS300_StLCD1280x1024Data;
+ SiS_ExtLCD1280x1024Data =
+ (SiS_LCDDataStruct *) SiS300_ExtLCD1280x1024Data;
+ SiS_St2LCD1280x1024Data =
+ (SiS_LCDDataStruct *) SiS300_St2LCD1280x1024Data;
+ SiS_NoScaleData = (SiS_LCDDataStruct *) SiS300_NoScaleData;
+ SiS_LCD1280x960Data = (SiS_LCDDataStruct *) SiS300_LCD1280x960Data;
+ SiS_StPALData = (SiS_TVDataStruct *) SiS300_StPALData;
+ SiS_ExtPALData = (SiS_TVDataStruct *) SiS300_ExtPALData;
+ SiS_StNTSCData = (SiS_TVDataStruct *) SiS300_StNTSCData;
+ SiS_ExtNTSCData = (SiS_TVDataStruct *) SiS300_ExtNTSCData;
+ SiS_St1HiTVData = (SiS_TVDataStruct *) SiS300_St1HiTVData;
+ SiS_St2HiTVData = (SiS_TVDataStruct *) SiS300_St2HiTVData;
+ SiS_ExtHiTVData = (SiS_TVDataStruct *) SiS300_ExtHiTVData;
+ SiS_NTSCTiming = SiS300_NTSCTiming;
+ SiS_PALTiming = SiS300_PALTiming;
+ SiS_HiTVSt1Timing = SiS300_HiTVSt1Timing;
+ SiS_HiTVSt2Timing = SiS300_HiTVSt2Timing;
+ SiS_HiTVTextTiming = SiS300_HiTVTextTiming;
+ SiS_HiTVGroup3Data = SiS300_HiTVGroup3Data;
+ SiS_HiTVGroup3Simu = SiS300_HiTVGroup3Simu;
+ SiS_HiTVGroup3Text = SiS300_HiTVGroup3Text;
+
+ SiS_PanelDelayTbl = (SiS_PanelDelayTblStruct *) SiS300_PanelDelayTbl;
+ SiS_LVDS800x600Data_1 = (SiS_LVDSDataStruct *) SiS300_LVDS800x600Data_1;
+ SiS_LVDS800x600Data_2 = (SiS_LVDSDataStruct *) SiS300_LVDS800x600Data_2;
+ SiS_LVDS1024x768Data_1 =
+ (SiS_LVDSDataStruct *) SiS300_LVDS1024x768Data_1;
+ SiS_LVDS1024x768Data_2 =
+ (SiS_LVDSDataStruct *) SiS300_LVDS1024x768Data_2;
+ SiS_LVDS1280x1024Data_1 =
+ (SiS_LVDSDataStruct *) SiS300_LVDS1280x1024Data_1;
+ SiS_LVDS1280x1024Data_2 =
+ (SiS_LVDSDataStruct *) SiS300_LVDS1280x1024Data_2;
+ SiS_LVDS640x480Data_1 = (SiS_LVDSDataStruct *) SiS300_LVDS640x480Data_1;
+ SiS_CHTVUNTSCData = (SiS_LVDSDataStruct *) SiS300_CHTVUNTSCData;
+ SiS_CHTVONTSCData = (SiS_LVDSDataStruct *) SiS300_CHTVONTSCData;
+ SiS_CHTVUPALData = (SiS_LVDSDataStruct *) SiS300_CHTVUPALData;
+ SiS_CHTVOPALData = (SiS_LVDSDataStruct *) SiS300_CHTVOPALData;
+ SiS_PanelType00_1 = (SiS_LVDSDesStruct *) SiS300_PanelType00_1;
+ SiS_PanelType01_1 = (SiS_LVDSDesStruct *) SiS300_PanelType01_1;
+ SiS_PanelType02_1 = (SiS_LVDSDesStruct *) SiS300_PanelType02_1;
+ SiS_PanelType03_1 = (SiS_LVDSDesStruct *) SiS300_PanelType03_1;
+ SiS_PanelType04_1 = (SiS_LVDSDesStruct *) SiS300_PanelType04_1;
+ SiS_PanelType05_1 = (SiS_LVDSDesStruct *) SiS300_PanelType05_1;
+ SiS_PanelType06_1 = (SiS_LVDSDesStruct *) SiS300_PanelType06_1;
+ SiS_PanelType07_1 = (SiS_LVDSDesStruct *) SiS300_PanelType07_1;
+ SiS_PanelType08_1 = (SiS_LVDSDesStruct *) SiS300_PanelType08_1;
+ SiS_PanelType09_1 = (SiS_LVDSDesStruct *) SiS300_PanelType09_1;
+ SiS_PanelType0a_1 = (SiS_LVDSDesStruct *) SiS300_PanelType0a_1;
+ SiS_PanelType0b_1 = (SiS_LVDSDesStruct *) SiS300_PanelType0b_1;
+ SiS_PanelType0c_1 = (SiS_LVDSDesStruct *) SiS300_PanelType0c_1;
+ SiS_PanelType0d_1 = (SiS_LVDSDesStruct *) SiS300_PanelType0d_1;
+ SiS_PanelType0e_1 = (SiS_LVDSDesStruct *) SiS300_PanelType0e_1;
+ SiS_PanelType0f_1 = (SiS_LVDSDesStruct *) SiS300_PanelType0f_1;
+ SiS_PanelType00_2 = (SiS_LVDSDesStruct *) SiS300_PanelType00_2;
+ SiS_PanelType01_2 = (SiS_LVDSDesStruct *) SiS300_PanelType01_2;
+ SiS_PanelType02_2 = (SiS_LVDSDesStruct *) SiS300_PanelType02_2;
+ SiS_PanelType03_2 = (SiS_LVDSDesStruct *) SiS300_PanelType03_2;
+ SiS_PanelType04_2 = (SiS_LVDSDesStruct *) SiS300_PanelType04_2;
+ SiS_PanelType05_2 = (SiS_LVDSDesStruct *) SiS300_PanelType05_2;
+ SiS_PanelType06_2 = (SiS_LVDSDesStruct *) SiS300_PanelType06_2;
+ SiS_PanelType07_2 = (SiS_LVDSDesStruct *) SiS300_PanelType07_2;
+ SiS_PanelType08_2 = (SiS_LVDSDesStruct *) SiS300_PanelType08_2;
+ SiS_PanelType09_2 = (SiS_LVDSDesStruct *) SiS300_PanelType09_2;
+ SiS_PanelType0a_2 = (SiS_LVDSDesStruct *) SiS300_PanelType0a_2;
+ SiS_PanelType0b_2 = (SiS_LVDSDesStruct *) SiS300_PanelType0b_2;
+ SiS_PanelType0c_2 = (SiS_LVDSDesStruct *) SiS300_PanelType0c_2;
+ SiS_PanelType0d_2 = (SiS_LVDSDesStruct *) SiS300_PanelType0d_2;
+ SiS_PanelType0e_2 = (SiS_LVDSDesStruct *) SiS300_PanelType0e_2;
+ SiS_PanelType0f_2 = (SiS_LVDSDesStruct *) SiS300_PanelType0f_2;
+ SiS_CHTVUNTSCDesData = (SiS_LVDSDesStruct *) SiS300_CHTVUNTSCDesData;
+ SiS_CHTVONTSCDesData = (SiS_LVDSDesStruct *) SiS300_CHTVONTSCDesData;
+ SiS_CHTVUPALDesData = (SiS_LVDSDesStruct *) SiS300_CHTVUPALDesData;
+ SiS_CHTVOPALDesData = (SiS_LVDSDesStruct *) SiS300_CHTVOPALDesData;
+ SiS_LVDSCRT1800x600_1 =
+ (SiS_LVDSCRT1DataStruct *) SiS300_LVDSCRT1800x600_1;
+ SiS_LVDSCRT11024x768_1 =
+ (SiS_LVDSCRT1DataStruct *) SiS300_LVDSCRT11024x768_1;
+ SiS_LVDSCRT11280x1024_1 =
+ (SiS_LVDSCRT1DataStruct *) SiS300_LVDSCRT11280x1024_1;
+ SiS_LVDSCRT1800x600_1_H =
+ (SiS_LVDSCRT1DataStruct *) SiS300_LVDSCRT1800x600_1_H;
+ SiS_LVDSCRT11024x768_1_H =
+ (SiS_LVDSCRT1DataStruct *) SiS300_LVDSCRT11024x768_1_H;
+ SiS_LVDSCRT11280x1024_1_H =
+ (SiS_LVDSCRT1DataStruct *) SiS300_LVDSCRT11280x1024_1_H;
+ SiS_LVDSCRT1800x600_2 =
+ (SiS_LVDSCRT1DataStruct *) SiS300_LVDSCRT1800x600_2;
+ SiS_LVDSCRT11024x768_2 =
+ (SiS_LVDSCRT1DataStruct *) SiS300_LVDSCRT11024x768_2;
+ SiS_LVDSCRT11280x1024_2 =
+ (SiS_LVDSCRT1DataStruct *) SiS300_LVDSCRT11280x1024_2;
+ SiS_LVDSCRT1800x600_2_H =
+ (SiS_LVDSCRT1DataStruct *) SiS300_LVDSCRT1800x600_2_H;
+ SiS_LVDSCRT11024x768_2_H =
+ (SiS_LVDSCRT1DataStruct *) SiS300_LVDSCRT11024x768_2_H;
+ SiS_LVDSCRT11280x1024_2_H =
+ (SiS_LVDSCRT1DataStruct *) SiS300_LVDSCRT11280x1024_2_H;
+ SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *) SiS300_CHTVCRT1UNTSC;
+ SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *) SiS300_CHTVCRT1ONTSC;
+ SiS_CHTVCRT1UPAL = (SiS_LVDSCRT1DataStruct *) SiS300_CHTVCRT1UPAL;
+ SiS_CHTVCRT1OPAL = (SiS_LVDSCRT1DataStruct *) SiS300_CHTVCRT1OPAL;
+ SiS_CHTVReg_UNTSC = (SiS_CHTVRegDataStruct *) SiS300_CHTVReg_UNTSC;
+ SiS_CHTVReg_ONTSC = (SiS_CHTVRegDataStruct *) SiS300_CHTVReg_ONTSC;
+ SiS_CHTVReg_UPAL = (SiS_CHTVRegDataStruct *) SiS300_CHTVReg_UPAL;
+ SiS_CHTVReg_OPAL = (SiS_CHTVRegDataStruct *) SiS300_CHTVReg_OPAL;
+ SiS_CHTVVCLKUNTSC = SiS300_CHTVVCLKUNTSC;
+ SiS_CHTVVCLKONTSC = SiS300_CHTVVCLKONTSC;
+ SiS_CHTVVCLKUPAL = SiS300_CHTVVCLKUPAL;
+ SiS_CHTVVCLKOPAL = SiS300_CHTVVCLKOPAL;
+ /* 300 customization related */
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+void
+InitTo310Pointer (void)
+{
+ SiS_SModeIDTable = (SiS_StStruct *) SiS310_SModeIDTable;
+ SiS_StandTable = (SiS_StandTableStruct *) SiS310_StandTable;
+ SiS_EModeIDTable = (SiS_ExtStruct *) SiS310_EModeIDTable;
+ SiS_RefIndex = (SiS_Ext2Struct *) SiS310_RefIndex;
+ SiS_CRT1Table = (SiS_CRT1TableStruct *) SiS310_CRT1Table;
+ SiS_MCLKData = (SiS_MCLKDataStruct *) SiS310_MCLKData;
+ SiS_ECLKData = (SiS_ECLKDataStruct *) SiS310_ECLKData;
+ SiS_VCLKData = (SiS_VCLKDataStruct *) SiS310_VCLKData;
+ SiS_VBVCLKData = (SiS_VBVCLKDataStruct *) SiS310_VBVCLKData;
+ SiS_ScreenOffset = SiS310_ScreenOffset;
+ SiS_StResInfo = (SiS_StResInfoStruct *) SiS310_StResInfo;
+ SiS_ModeResInfo = (SiS_ModeResInfoStruct *) SiS310_ModeResInfo;
+
+ pSiS_OutputSelect = &SiS310_OutputSelect;
+ pSiS_SoftSetting = &SiS310_SoftSetting;
+ pSiS_SR07 = &SiS310_SR07;
+ SiS_SR15 = SiS310_SR15;
+ SiS_CR40 = SiS310_CR40;
+ SiS_CR49 = SiS310_CR49;
+ pSiS_SR1F = &SiS310_SR1F;
+ pSiS_SR21 = &SiS310_SR21;
+ pSiS_SR22 = &SiS310_SR22;
+ pSiS_SR23 = &SiS310_SR23;
+ pSiS_SR24 = &SiS310_SR24;
+ SiS_SR25 = SiS310_SR25;
+ pSiS_SR31 = &SiS310_SR31;
+ pSiS_SR32 = &SiS310_SR32;
+ pSiS_SR33 = &SiS310_SR33;
+ pSiS_CRT2Data_1_2 = &SiS310_CRT2Data_1_2;
+ pSiS_CRT2Data_4_D = &SiS310_CRT2Data_4_D;
+ pSiS_CRT2Data_4_E = &SiS310_CRT2Data_4_E;
+ pSiS_CRT2Data_4_10 = &SiS310_CRT2Data_4_10;
+ pSiS_RGBSenseData = &SiS310_RGBSenseData;
+ pSiS_VideoSenseData = &SiS310_VideoSenseData;
+ pSiS_YCSenseData = &SiS310_YCSenseData;
+ pSiS_RGBSenseData2 = &SiS310_RGBSenseData2;
+ pSiS_VideoSenseData2 = &SiS310_VideoSenseData2;
+ pSiS_YCSenseData2 = &SiS310_YCSenseData2;
+ SiS_NTSCPhase = SiS310_NTSCPhase;
+ SiS_PALPhase = SiS310_PALPhase;
+ SiS_NTSCPhase2 = SiS310_NTSCPhase2;
+ SiS_PALPhase2 = SiS310_PALPhase2;
+ SiS_PALMPhase = SiS310_PALMPhase; /*add for PALMN */
+ SiS_PALNPhase = SiS310_PALNPhase;
+
+ SiS_StLCD1024x768Data = (SiS_LCDDataStruct *) SiS310_StLCD1024x768Data;
+ SiS_ExtLCD1024x768Data =
+ (SiS_LCDDataStruct *) SiS310_ExtLCD1024x768Data;
+ SiS_St2LCD1024x768Data =
+ (SiS_LCDDataStruct *) SiS310_St2LCD1024x768Data;
+ SiS_StLCD1280x1024Data =
+ (SiS_LCDDataStruct *) SiS310_StLCD1280x1024Data;
+ SiS_ExtLCD1280x1024Data =
+ (SiS_LCDDataStruct *) SiS310_ExtLCD1280x1024Data;
+ SiS_St2LCD1280x1024Data =
+ (SiS_LCDDataStruct *) SiS310_St2LCD1280x1024Data;
+ SiS_NoScaleData = (SiS_LCDDataStruct *) SiS310_NoScaleData;
+ SiS_LCD1280x960Data = (SiS_LCDDataStruct *) SiS310_LCD1280x960Data;
+ SiS_StPALData = (SiS_TVDataStruct *) SiS310_StPALData;
+ SiS_ExtPALData = (SiS_TVDataStruct *) SiS310_ExtPALData;
+ SiS_StNTSCData = (SiS_TVDataStruct *) SiS310_StNTSCData;
+ SiS_ExtNTSCData = (SiS_TVDataStruct *) SiS310_ExtNTSCData;
+ SiS_St1HiTVData = (SiS_TVDataStruct *) SiS310_St1HiTVData;
+ SiS_St2HiTVData = (SiS_TVDataStruct *) SiS310_St2HiTVData;
+ SiS_ExtHiTVData = (SiS_TVDataStruct *) SiS310_ExtHiTVData;
+ SiS_NTSCTiming = SiS310_NTSCTiming;
+ SiS_PALTiming = SiS310_PALTiming;
+ SiS_HiTVSt1Timing = SiS310_HiTVSt1Timing;
+ SiS_HiTVSt2Timing = SiS310_HiTVSt2Timing;
+ SiS_HiTVTextTiming = SiS310_HiTVTextTiming;
+ SiS_HiTVGroup3Data = SiS310_HiTVGroup3Data;
+ SiS_HiTVGroup3Simu = SiS310_HiTVGroup3Simu;
+ SiS_HiTVGroup3Text = SiS310_HiTVGroup3Text;
+
+ SiS_PanelDelayTbl = (SiS_PanelDelayTblStruct *) SiS310_PanelDelayTbl;
+ SiS_LVDS800x600Data_1 = (SiS_LVDSDataStruct *) SiS310_LVDS800x600Data_1;
+ SiS_LVDS800x600Data_2 = (SiS_LVDSDataStruct *) SiS310_LVDS800x600Data_2;
+ SiS_LVDS1024x768Data_1 =
+ (SiS_LVDSDataStruct *) SiS310_LVDS1024x768Data_1;
+ SiS_LVDS1024x768Data_2 =
+ (SiS_LVDSDataStruct *) SiS310_LVDS1024x768Data_2;
+ SiS_LVDS1280x1024Data_1 =
+ (SiS_LVDSDataStruct *) SiS310_LVDS1280x1024Data_1;
+ SiS_LVDS1280x1024Data_2 =
+ (SiS_LVDSDataStruct *) SiS310_LVDS1280x1024Data_2;
+ SiS_LVDS640x480Data_1 = (SiS_LVDSDataStruct *) SiS310_LVDS640x480Data_1;
+ SiS_CHTVUNTSCData = (SiS_LVDSDataStruct *) SiS310_CHTVUNTSCData;
+ SiS_CHTVONTSCData = (SiS_LVDSDataStruct *) SiS310_CHTVONTSCData;
+ SiS_CHTVUPALData = (SiS_LVDSDataStruct *) SiS310_CHTVUPALData;
+ SiS_CHTVOPALData = (SiS_LVDSDataStruct *) SiS310_CHTVOPALData;
+ SiS_PanelType00_1 = (SiS_LVDSDesStruct *) SiS310_PanelType00_1;
+ SiS_PanelType01_1 = (SiS_LVDSDesStruct *) SiS310_PanelType01_1;
+ SiS_PanelType02_1 = (SiS_LVDSDesStruct *) SiS310_PanelType02_1;
+ SiS_PanelType03_1 = (SiS_LVDSDesStruct *) SiS310_PanelType03_1;
+ SiS_PanelType04_1 = (SiS_LVDSDesStruct *) SiS310_PanelType04_1;
+ SiS_PanelType05_1 = (SiS_LVDSDesStruct *) SiS310_PanelType05_1;
+ SiS_PanelType06_1 = (SiS_LVDSDesStruct *) SiS310_PanelType06_1;
+ SiS_PanelType07_1 = (SiS_LVDSDesStruct *) SiS310_PanelType07_1;
+ SiS_PanelType08_1 = (SiS_LVDSDesStruct *) SiS310_PanelType08_1;
+ SiS_PanelType09_1 = (SiS_LVDSDesStruct *) SiS310_PanelType09_1;
+ SiS_PanelType0a_1 = (SiS_LVDSDesStruct *) SiS310_PanelType0a_1;
+ SiS_PanelType0b_1 = (SiS_LVDSDesStruct *) SiS310_PanelType0b_1;
+ SiS_PanelType0c_1 = (SiS_LVDSDesStruct *) SiS310_PanelType0c_1;
+ SiS_PanelType0d_1 = (SiS_LVDSDesStruct *) SiS310_PanelType0d_1;
+ SiS_PanelType0e_1 = (SiS_LVDSDesStruct *) SiS310_PanelType0e_1;
+ SiS_PanelType0f_1 = (SiS_LVDSDesStruct *) SiS310_PanelType0f_1;
+ SiS_PanelType00_2 = (SiS_LVDSDesStruct *) SiS310_PanelType00_2;
+ SiS_PanelType01_2 = (SiS_LVDSDesStruct *) SiS310_PanelType01_2;
+ SiS_PanelType02_2 = (SiS_LVDSDesStruct *) SiS310_PanelType02_2;
+ SiS_PanelType03_2 = (SiS_LVDSDesStruct *) SiS310_PanelType03_2;
+ SiS_PanelType04_2 = (SiS_LVDSDesStruct *) SiS310_PanelType04_2;
+ SiS_PanelType05_2 = (SiS_LVDSDesStruct *) SiS310_PanelType05_2;
+ SiS_PanelType06_2 = (SiS_LVDSDesStruct *) SiS310_PanelType06_2;
+ SiS_PanelType07_2 = (SiS_LVDSDesStruct *) SiS310_PanelType07_2;
+ SiS_PanelType08_2 = (SiS_LVDSDesStruct *) SiS310_PanelType08_2;
+ SiS_PanelType09_2 = (SiS_LVDSDesStruct *) SiS310_PanelType09_2;
+ SiS_PanelType0a_2 = (SiS_LVDSDesStruct *) SiS310_PanelType0a_2;
+ SiS_PanelType0b_2 = (SiS_LVDSDesStruct *) SiS310_PanelType0b_2;
+ SiS_PanelType0c_2 = (SiS_LVDSDesStruct *) SiS310_PanelType0c_2;
+ SiS_PanelType0d_2 = (SiS_LVDSDesStruct *) SiS310_PanelType0d_2;
+ SiS_PanelType0e_2 = (SiS_LVDSDesStruct *) SiS310_PanelType0e_2;
+ SiS_PanelType0f_2 = (SiS_LVDSDesStruct *) SiS310_PanelType0f_2;
+ /*301b */
+ LVDS1024x768Des_1 = (SiS_LVDSDesStruct *) SiS310_PanelType1076_1;
+ LVDS1280x1024Des_1 = (SiS_LVDSDesStruct *) SiS310_PanelType1210_1;
+ LVDS1280x960Des_1 = (SiS_LVDSDesStruct *) SiS310_PanelType1296_1;
+ LVDS1024x768Des_2 = (SiS_LVDSDesStruct *) SiS310_PanelType1076_2;
+ LVDS1280x1024Des_2 = (SiS_LVDSDesStruct *) SiS310_PanelType1210_2;
+ LVDS1280x960Des_2 = (SiS_LVDSDesStruct *) SiS310_PanelType1296_2;
+ /*end 301b */
+
+ SiS_CHTVUNTSCDesData = (SiS_LVDSDesStruct *) SiS310_CHTVUNTSCDesData;
+ SiS_CHTVONTSCDesData = (SiS_LVDSDesStruct *) SiS310_CHTVONTSCDesData;
+ SiS_CHTVUPALDesData = (SiS_LVDSDesStruct *) SiS310_CHTVUPALDesData;
+ SiS_CHTVOPALDesData = (SiS_LVDSDesStruct *) SiS310_CHTVOPALDesData;
+ SiS_LVDSCRT1800x600_1 =
+ (SiS_LVDSCRT1DataStruct *) SiS310_LVDSCRT1800x600_1;
+ SiS_LVDSCRT11024x768_1 =
+ (SiS_LVDSCRT1DataStruct *) SiS310_LVDSCRT11024x768_1;
+ SiS_LVDSCRT11280x1024_1 =
+ (SiS_LVDSCRT1DataStruct *) SiS310_LVDSCRT11280x1024_1;
+ SiS_LVDSCRT1800x600_1_H =
+ (SiS_LVDSCRT1DataStruct *) SiS310_LVDSCRT1800x600_1_H;
+ SiS_LVDSCRT11024x768_1_H =
+ (SiS_LVDSCRT1DataStruct *) SiS310_LVDSCRT11024x768_1_H;
+ SiS_LVDSCRT11280x1024_1_H =
+ (SiS_LVDSCRT1DataStruct *) SiS310_LVDSCRT11280x1024_1_H;
+ SiS_LVDSCRT1800x600_2 =
+ (SiS_LVDSCRT1DataStruct *) SiS310_LVDSCRT1800x600_2;
+ SiS_LVDSCRT11024x768_2 =
+ (SiS_LVDSCRT1DataStruct *) SiS310_LVDSCRT11024x768_2;
+ SiS_LVDSCRT11280x1024_2 =
+ (SiS_LVDSCRT1DataStruct *) SiS310_LVDSCRT11280x1024_2;
+ SiS_LVDSCRT1800x600_2_H =
+ (SiS_LVDSCRT1DataStruct *) SiS310_LVDSCRT1800x600_2_H;
+ SiS_LVDSCRT11024x768_2_H =
+ (SiS_LVDSCRT1DataStruct *) SiS310_LVDSCRT11024x768_2_H;
+ SiS_LVDSCRT11280x1024_2_H =
+ (SiS_LVDSCRT1DataStruct *) SiS310_LVDSCRT11280x1024_2_H;
+ SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *) SiS310_CHTVCRT1UNTSC;
+ SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *) SiS310_CHTVCRT1ONTSC;
+ SiS_CHTVCRT1UPAL = (SiS_LVDSCRT1DataStruct *) SiS310_CHTVCRT1UPAL;
+ SiS_CHTVCRT1OPAL = (SiS_LVDSCRT1DataStruct *) SiS310_CHTVCRT1OPAL;
+ SiS_CHTVReg_UNTSC = (SiS_CHTVRegDataStruct *) SiS310_CHTVReg_UNTSC;
+ SiS_CHTVReg_ONTSC = (SiS_CHTVRegDataStruct *) SiS310_CHTVReg_ONTSC;
+ SiS_CHTVReg_UPAL = (SiS_CHTVRegDataStruct *) SiS310_CHTVReg_UPAL;
+ SiS_CHTVReg_OPAL = (SiS_CHTVRegDataStruct *) SiS310_CHTVReg_OPAL;
+ /*add for LCDA */
+ SiS_LCDACRT1800x600_1 =
+ (SiS_LCDACRT1DataStruct *) SiS310_LCDACRT1800x600_1;
+ SiS_LCDACRT11024x768_1 =
+ (SiS_LCDACRT1DataStruct *) SiS310_LCDACRT11024x768_1;
+ SiS_LCDACRT11280x1024_1 =
+ (SiS_LCDACRT1DataStruct *) SiS310_LCDACRT11280x1024_1;
+ SiS_LCDACRT1800x600_1_H =
+ (SiS_LCDACRT1DataStruct *) SiS310_LCDACRT1800x600_1_H;
+ SiS_LCDACRT11024x768_1_H =
+ (SiS_LCDACRT1DataStruct *) SiS310_LCDACRT11024x768_1_H;
+ SiS_LCDACRT11280x1024_1_H =
+ (SiS_LCDACRT1DataStruct *) SiS310_LCDACRT11280x1024_1_H;
+ SiS_LCDACRT1800x600_2 =
+ (SiS_LCDACRT1DataStruct *) SiS310_LCDACRT1800x600_2;
+ SiS_LCDACRT11024x768_2 =
+ (SiS_LCDACRT1DataStruct *) SiS310_LCDACRT11024x768_2;
+ SiS_LCDACRT11280x1024_2 =
+ (SiS_LCDACRT1DataStruct *) SiS310_LCDACRT11280x1024_2;
+ SiS_LCDACRT1800x600_2_H =
+ (SiS_LCDACRT1DataStruct *) SiS310_LCDACRT1800x600_2_H;
+ SiS_LCDACRT11024x768_2_H =
+ (SiS_LCDACRT1DataStruct *) SiS310_LCDACRT11024x768_2_H;
+ SiS_LCDACRT11280x1024_2_H =
+ (SiS_LCDACRT1DataStruct *) SiS310_LCDACRT11280x1024_2_H;
+ /*end for 301b */
+
+ SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC;
+ SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC;
+ SiS_CHTVVCLKUPAL = SiS310_CHTVVCLKUPAL;
+ SiS_CHTVVCLKOPAL = SiS310_CHTVVCLKOPAL;
+ /* 310 customization related */
+
+}
+#endif
+
+BOOLEAN
+SiSInit (PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+ ULONG ROMAddr = (ULONG) HwDeviceExtension->pjVirtualRomBase;
+ ULONG FBAddr = (ULONG) HwDeviceExtension->pjVideoMemoryAddress;
+ USHORT BaseAddr = (USHORT) HwDeviceExtension->ulIOAddress;
+ UCHAR i, temp = 0;
+ UCHAR SR11, temp1;
+ ULONG base;
+ UCHAR SR12 = 0, SR13 = 0, SR14 = 0, SR16 = 0, SR17 = 0, SR18 = 0, SR19 =
+ 0, SR1A = 0;
+#ifdef CONFIG_FB_SIS_315
+ /* ULONG j, k; */
+ UCHAR CR39 = 0, CR3A = 0, CR3B = 0, CR3C = 0, CR3D = 0, CR3E = 0, CR3F =
+ 0;
+ UCHAR CR79 = 0, CR7A = 0, CR7B = 0, CR7C = 0;
+ PSIS_DSReg pSR;
+ ULONG Temp;
+#endif
+ UCHAR VBIOSVersion[5];
+
+/* if(ROMAddr==0) return (FALSE);*/
+ if (FBAddr == 0)
+ return (FALSE);
+ if (BaseAddr == 0)
+ return (FALSE);
+
+ SiS_SetReg3 ((USHORT) (BaseAddr + 0x12), 0x67); /* 3c2 <- 67 ,ynlai */
+#ifdef CONFIG_FB_SIS_315
+ /*if(HwDeviceExtension->jChipType > SIS_315H) */
+ if (HwDeviceExtension->jChipType > SIS_315PRO) {
+ if (!HwDeviceExtension->bIntegratedMMEnabled)
+ return (FALSE); /* alan */
+ }
+#endif
+
+ SiS_MemoryCopy (VBIOSVersion, HwDeviceExtension->szVBIOSVer, 4);
+
+ VBIOSVersion[4] = 0x0;
+ /* 09/07/99 modify by domao */
+
+#ifdef CONFIG_FB_SIS_315
+ if ((HwDeviceExtension->jChipType == SIS_315H) ||
+ (HwDeviceExtension->jChipType == SIS_315PRO) ||
+ (HwDeviceExtension->jChipType == SIS_550) || /* 05/02/01 ynlai for 550 */
+ (HwDeviceExtension->jChipType == SIS_640) || /* 08/20/01 chiawen for 640/740 */
+ (HwDeviceExtension->jChipType == SIS_740)) /* 09/03/01 chiawen for 650 */
+ InitTo310Pointer ();
+#endif
+
+#ifdef CONFIG_FB_SIS_300
+ if ((HwDeviceExtension->jChipType == SIS_540) ||
+ (HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_730) ||
+ (HwDeviceExtension->jChipType == SIS_300))
+ InitTo300Pointer ();
+#endif
+
+ SiS_P3c4 = BaseAddr + 0x14;
+ SiS_P3d4 = BaseAddr + 0x24;
+ SiS_P3c0 = BaseAddr + 0x10;
+ SiS_P3ce = BaseAddr + 0x1e;
+ SiS_P3c2 = BaseAddr + 0x12;
+ SiS_P3ca = BaseAddr + 0x1a;
+ SiS_P3c6 = BaseAddr + 0x16;
+ SiS_P3c7 = BaseAddr + 0x17;
+ SiS_P3c8 = BaseAddr + 0x18;
+ SiS_P3c9 = BaseAddr + 0x19;
+ SiS_P3da = BaseAddr + 0x2A;
+ SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
+ SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;
+ SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;
+ SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;
+ SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;
+ SiS_Set_LVDS_TRUMPION (HwDeviceExtension); /*2/29/00 by Mars Wen for LVDS and Trumpion */
+
+ SiS_SetReg1 (SiS_P3c4, 0x05, 0x86); /* 1.Openkey */
+
+#ifdef LINUX_KERNEL
+#ifdef CONFIG_FB_SIS_300 /* add to set SR14 */
+ if ((HwDeviceExtension->jChipType == SIS_540) ||
+ (HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_730)) {
+ base = 0x80000060;
+ OutPortLong (base, 0xcf8);
+ temp1 = InPortLong (0xcfc);
+ temp1 = temp1 >> (16 + 8 + 4);
+ temp1 = temp1 & (0x07);
+ temp1 = temp1 + 1;
+ temp1 = 1 << temp1;
+ SR14 = temp1 - 1;
+ base = 0x80000064;
+ OutPortLong (base, 0xcf8);
+ temp1 = InPortLong (0xcfc);
+ temp1 = temp1 & (0x00000020);
+ if (temp1)
+ SR14 = (0x10000000) | SR14;
+ else
+ SR14 = (0x01000000) | SR14;
+ }
+#endif
+
+#ifdef CONFIG_FB_SIS_315 /* add to set SR14 */
+ if ((HwDeviceExtension->jChipType == SIS_550)) {
+ base = 0x80000060;
+ OutPortLong (base, 0xcf8);
+ temp1 = InPortLong (0xcfc);
+ temp1 = temp1 >> (16 + 8 + 4);
+ temp1 = temp1 & (0x07);
+ temp1 = temp1 + 1;
+ temp1 = 1 << temp1;
+ SR14 = temp1 - 1;
+ base = 0x80000064;
+ OutPortLong (base, 0xcf8);
+ temp1 = InPortLong (0xcfc);
+ temp1 = temp1 & (0x00000020);
+ if (temp1)
+ SR14 = (0x10000000) | SR14;
+ else
+ SR14 = (0x01000000) | SR14;
+ }
+
+ if ((HwDeviceExtension->jChipType == SIS_640)
+ || (HwDeviceExtension->jChipType == SIS_740)) {
+ base = 0x80000064;
+ OutPortLong (base, 0xcf8);
+ temp1 = InPortLong (0xcfc);
+ temp1 = temp >> 4;
+ temp1 = temp1 & (0x07);
+ if (temp1 > 2) {
+ temp = temp1;
+ switch (temp) {
+ case 3:
+ temp1 = 0x07;
+ break;
+ case 4:
+ temp1 = 0x0F;
+ break;
+ case 5:
+ temp1 = 0x1F;
+ break;
+ case 6:
+ temp1 = 0x05;
+ break;
+ case 7:
+ temp1 = 0x17;
+ break;
+ case 8:
+ break;
+ case 9:
+ break;
+ }
+ }
+ SR14 = temp1;
+ base = 0x8000007C;
+ OutPortLong (base, 0xcf8);
+ temp1 = InPortLong (0xcfc);
+ temp1 = temp1 & (0x00000020);
+ if (temp1)
+ SR14 = (0x10000000) | SR14;


+ }
+#endif
+
+#endif
+

+#ifdef CONFIG_FB_SIS_300
+ if ((HwDeviceExtension->jChipType == SIS_540) ||
+ (HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_730)) {
+ SR12 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x12);
+ SR13 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x13);
+ SR14 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x14);
+ SR16 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x16);
+ SR17 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x17);
+ SR18 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x18);
+ SR19 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x19);
+ SR1A = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x1A);
+ } else {
+ SR13 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x13);
+ SR14 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x14);
+ }
+#endif
+#ifdef CONFIG_FB_SIS_315
+ if ((HwDeviceExtension->jChipType == SIS_550)) {
+ CR39 = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x39);
+ CR3A = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x3A);
+ CR3B = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x3B);
+ CR3C = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x3C);
+ CR3D = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x3D);
+ CR3E = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x3E);
+ CR3F = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x3F);
+ CR79 = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x79);
+ CR7A = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x7A);
+ CR7B = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x7B);
+ CR7C = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x7C);
+ } else if ((HwDeviceExtension->jChipType == SIS_640) || /* 08/20/01 chiawen for 640/740 */
+ (HwDeviceExtension->jChipType == SIS_740)) {
+ SR12 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x12);
+ SR13 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x13);
+ SR14 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x14);
+ SR16 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x16);


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

echo 'End of part 075'
echo 'File patch-2.4.15 is continued in part 076'
echo "076" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:45 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part069

#!/bin/sh -x
# this is part 069 of a 115 - part archive


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

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

@@ -28,6 +28,8 @@
X * Christoph Hellwig: Adapted to module_init/module_exit. 2000/03/03
X *
X * Christoph Hellwig: Added isapnp support 2000/03/15
+ *
+ * Arnaldo Carvalho de Melo: get rid of check_region 2001/10/07
X */
X
X #include <linux/config.h>
@@ -48,7 +50,7 @@
X timeout--; \
X } \
X if (timeout==0) {\
- printk("ad1816: Check for power failed in %s line: %d\n",__FILE__,__LINE__); \
+ printk(KERN_WARNING "ad1816: Check for power failed in %s line: %d\n",__FILE__,__LINE__); \
X } \
X }
X
@@ -78,9 +80,9 @@
X
X } ad1816_info;
X
-static int nr_ad1816_devs = 0;
-static int ad1816_clockfreq=33000;
-static int options=0;
+static int nr_ad1816_devs;
+static int ad1816_clockfreq = 33000;
+static int options;
X
X /* for backward mapping of irq to sound device */
X
@@ -558,14 +560,15 @@
X
X
X if (irq < 0 || irq > 15) {
- printk ("ad1816: Got bogus interrupt %d\n", irq);
+ printk(KERN_WARNING "ad1816: Got bogus interrupt %d\n", irq);
X return;
X }
X
X dev = irq2dev[irq];
X
X if (dev < 0 || dev >= num_audiodevs) {
- printk ("ad1816: IRQ2AD1816-mapping failed for irq %d device %d\n", irq,dev);
+ printk(KERN_WARNING "ad1816: IRQ2AD1816-mapping failed for "
+ "irq %d device %d\n", irq,dev);
X return;
X }
X
@@ -1000,8 +1003,10 @@
X int *osp=hw_config->osp;
X int tmp;
X
- printk("ad1816: AD1816 sounddriver Copyright (C) 1998 by Thorsten Knabe\n");
- printk("ad1816: io=0x%x, irq=%d, dma=%d, dma2=%d, clockfreq=%d, options=%d isadmabug=%d\n",
+ printk(KERN_INFO "ad1816: AD1816 sounddriver "
+ "Copyright (C) 1998 by Thorsten Knabe\n");
+ printk(KERN_INFO "ad1816: io=0x%x, irq=%d, dma=%d, dma2=%d, "
+ "clockfreq=%d, options=%d isadmabug=%d\n",
X hw_config->io_base,
X hw_config->irq,
X hw_config->dma,
@@ -1010,16 +1015,17 @@
X options,
X isa_dma_bridge_buggy);
X
- if (check_region (io_base, 16)) {
- printk ("ad1816: I/O port 0x%03x not free\n", io_base);
- return 0;
+ if (!request_region(io_base, 16, "AD1816 Sound")) {
+ printk(KERN_WARNING "ad1816: I/O port 0x%03x not free\n",
+ io_base);
+ goto err;
X }
X
X DEBUGLOG(printk ("ad1816: detect(%x)\n", io_base));
X
X if (nr_ad1816_devs >= MAX_AUDIO_DEV) {
- printk ("ad1816: detect error - step 0\n");
- return 0;
+ printk(KERN_WARNING "ad1816: detect error - step 0\n");


+ goto out_release_region;
X }
X

X devc->base = io_base;
@@ -1032,7 +1038,7 @@
X tmp=inb(devc->base);
X if ( (tmp&0x80)==0 || tmp==255 ) {
X DEBUGLOG (printk ("ad1816: Chip is not an AD1816 or chip is not active (Test 0)\n"));
- return(0);


+ goto out_release_region;
X }
X
X

@@ -1040,14 +1046,14 @@
X ad_write(devc,8,12345);
X if (ad_read(devc,9)!=12345) {
X DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 1)\n"));
- return(0);


+ goto out_release_region;
X }
X

X /* writes to ireg 8 are copied to ireg 9 */
X ad_write(devc,8,54321);
X if (ad_read(devc,9)!=54321) {
X DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 2)\n"));
- return(0);


+ goto out_release_region;
X }
X
X

@@ -1055,14 +1061,14 @@
X ad_write(devc,10,54321);
X if (ad_read(devc,11)!=54321) {
X DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 3)\n"));
- return(0);


+ goto out_release_region;
X }
X

X /* writes to ireg 10 are copied to ireg 11 */
X ad_write(devc,10,12345);
X if (ad_read(devc,11)!=12345) {
X DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 4)\n"));
- return(0);


+ goto out_release_region;
X }
X

X /* bit in base +1 cannot be set to 1 */
@@ -1070,15 +1076,19 @@
X outb(0xff,devc->base+1);
X if (inb(devc->base+1)!=tmp) {
X DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 5)\n"));
- return(0);


+ goto out_release_region;
X }
X
X

X DEBUGLOG (printk ("ad1816: detect() - Detected OK\n"));
X DEBUGLOG (printk ("ad1816: AD1816 Version: %d\n",ad_read(devc,45)));
X
- /* detection was successful */
+ /* detection was successful */
X return 1;
+out_release_region:
+ release_region(io_base, 16);
+ /* detection was NOT successful */
+err: return 0;
X }
X
X
@@ -1092,10 +1102,7 @@
X int my_dev;
X char dev_name[100];
X ad1816_info *devc = &dev_info[nr_ad1816_devs];
-
X
- /* allocate i/o ports */
- request_region (hw_config->io_base, 16, "AD1816 Sound");
X devc->base = hw_config->io_base;
X
X /* disable all interrupts */
@@ -1105,35 +1112,29 @@
X outb (0, devc->base+1);
X
X /* allocate irq */
- if (hw_config->irq < 0 || hw_config->irq > 15) {
- release_region(hw_config->io_base, 16);
- return;
- }
+ if (hw_config->irq < 0 || hw_config->irq > 15)
+ goto out_release_region;
X if (request_irq(hw_config->irq, ad1816_interrupt,0,
- "SoundPort",
- hw_config->osp) < 0) {
- printk ("ad1816: IRQ in use\n");
- release_region(hw_config->io_base, 16);
- return;
+ "SoundPort", hw_config->osp) < 0) {
+ printk(KERN_WARNING "ad1816: IRQ in use\n");
+ goto out_release_region;
X }
X devc->irq=hw_config->irq;
X
X /* DMA stuff */
X if (sound_alloc_dma (hw_config->dma, "Sound System")) {
- printk ("ad1816: Can't allocate DMA%d\n", hw_config->dma);
- free_irq(hw_config->irq,hw_config->osp);
- release_region(hw_config->io_base, 16);
- return;
+ printk(KERN_WARNING "ad1816: Can't allocate DMA%d\n",
+ hw_config->dma);
+ goto out_free_irq;
X }
X devc->dma_playback=hw_config->dma;
X
X if ( hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma) {
- if (sound_alloc_dma (hw_config->dma2, "Sound System (capture)")) {
- printk ("ad1816: Can't allocate DMA%d\n", hw_config->dma2);
- sound_free_dma(hw_config->dma);
- free_irq(hw_config->irq,hw_config->osp);
- release_region(hw_config->io_base, 16);
- return;
+ if (sound_alloc_dma(hw_config->dma2,
+ "Sound System (capture)")) {
+ printk(KERN_WARNING "ad1816: Can't allocate DMA%d\n",
+ hw_config->dma2);
+ goto out_free_dma;
X }
X devc->dma_capture=hw_config->dma2;
X devc->audio_mode=DMA_AUTOMODE|DMA_DUPLEX;
@@ -1157,15 +1158,8 @@
X devc,
X hw_config->dma,
X hw_config->dma2)) < 0) {
- printk ("ad1816: Can't install sound driver\n");
- if (devc->dma_capture>=0) {
- sound_free_dma(hw_config->dma2);
- }
- sound_free_dma(hw_config->dma);
- free_irq(hw_config->irq,hw_config->osp);
- release_region(hw_config->io_base, 16);
- return;
-
+ printk(KERN_WARNING "ad1816: Can't install sound driver\n");
+ goto out_free_dma_2;
X }
X
X /* fill rest of structure with reasonable default values */
@@ -1211,6 +1205,17 @@
X devc)) >= 0) {
X audio_devs[my_dev]->min_fragment = 0;
X }
+out: return;
+out_free_dma_2:
+ if (devc->dma_capture >= 0)
+ sound_free_dma(hw_config->dma2);
+out_free_dma:
+ sound_free_dma(hw_config->dma);
+out_free_irq:
+ free_irq(hw_config->irq,hw_config->osp);
+out_release_region:
+ release_region(hw_config->io_base, 16);


+ goto out;
X }
X

X static void __exit unload_card(ad1816_info *devc)
@@ -1242,9 +1247,8 @@
X
X DEBUGLOG (printk("ad1816: Unloading card at base=%x was successful\n",devc->base));
X
- } else {
- printk ("ad1816: no device/card specified\n");
- }
+ } else
+ printk(KERN_WARNING "ad1816: no device/card specified\n");
X }
X
X static struct address_info cfg;
diff -u --recursive --new-file v2.4.14/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c
--- v2.4.14/linux/drivers/sound/cmpci.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/sound/cmpci.c Fri Nov 9 14:07:41 2001
@@ -884,9 +884,9 @@
X
X spin_unlock_irqrestore(&s->lock, flags);
X ret = prog_dmabuf(s, 1);
+ if (ret) return ret;
X spin_lock_irqsave(&s->lock, flags);
X
- if (ret) return ret;
X // copy the hw state
X fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_DACSHIFT);
X fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_ADCSHIFT);
@@ -2846,6 +2846,17 @@
X MODULE_PARM_DESC(use_line_as_rear, "(1/0) Use line-in jack as rear-out");
X MODULE_PARM_DESC(use_line_as_bass, "(1/0) Use line-in jack as bass/center");
X MODULE_PARM_DESC(joystick, "(1/0) Enable joystick interface, still need joystick driver");
+
+static struct pci_device_id cmpci_pci_tbl[] = {
+ { PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, cmpci_pci_tbl);
X
X void initialize_chip(struct pci_dev *pcidev)
X {
diff -u --recursive --new-file v2.4.14/linux/drivers/sound/i810_audio.c linux/drivers/sound/i810_audio.c
--- v2.4.14/linux/drivers/sound/i810_audio.c Mon Nov 5 15:55:32 2001
+++ linux/drivers/sound/i810_audio.c Fri Nov 9 14:07:41 2001
@@ -2478,6 +2478,10 @@
X
X for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
X
+ /* Assume codec isn't available until we go through the
+ * gauntlet below */
+ card->ac97_codec[num_ac97] = NULL;
+
X /* The ICH programmer's reference says you should */
X /* check the ready status before probing. So we chk */
X /* What do we do if it's not ready? Wait and try */
@@ -2485,7 +2489,6 @@
X if (!i810_ac97_exists(card,num_ac97)) {
X if(num_ac97 == 0)
X printk(KERN_ERR "i810_audio: Primary codec not ready.\n");
- card->ac97_codec[num_ac97] = 0;
X break; /* I think this works, if not ready stop */
X }
X
@@ -2503,6 +2506,7 @@
X
X if(!i810_ac97_probe_and_powerup(card,codec)) {
X printk("i810_audio: timed out waiting for codec %d analog ready", num_ac97);
+ kfree(codec);
X break; /* it didn't work */
X }
X /* Store state information about S/PDIF transmitter */
@@ -2750,7 +2754,7 @@
X kfree(card);
X return -ENODEV;
X }
- pci_dev->driver_data = card;
+ pci_set_drvdata(pci_dev, card);
X
X if(clocking == 48000) {
X i810_configure_clocking();
@@ -2778,7 +2782,7 @@
X static void __exit i810_remove(struct pci_dev *pci_dev)
X {
X int i;
- struct i810_card *card = pci_dev->driver_data;
+ struct i810_card *card = pci_get_drvdata(pci_dev);
X /* free hardware resources */
X free_irq(card->irq, devs);
X release_region(card->iobase, 64);
@@ -2797,7 +2801,7 @@
X #ifdef CONFIG_PM
X static int i810_pm_suspend(struct pci_dev *dev, u32 pm_state)
X {
- struct i810_card *card = dev->driver_data;
+ struct i810_card *card = pci_get_drvdata(dev);
X struct i810_state *state;
X unsigned long flags;
X struct dmabuf *dmabuf;
@@ -2856,7 +2860,7 @@
X static int i810_pm_resume(struct pci_dev *dev)
X {
X int num_ac97,i=0;
- struct i810_card *card=(struct i810_card *)dev->driver_data;
+ struct i810_card *card=pci_get_drvdata(dev);
X pci_enable_device(dev);
X pci_restore_state (dev,card->pm_save_state);
X
@@ -2870,7 +2874,7 @@
X struct ac97_codec *codec = card->ac97_codec[num_ac97];
X /* check they haven't stolen the hardware while we were
X away */
- if(!i810_ac97_exists(card,num_ac97)) {
+ if(!codec || !i810_ac97_exists(card,num_ac97)) {
X if(num_ac97) continue;
X else BUG();
X }
diff -u --recursive --new-file v2.4.14/linux/drivers/sound/maestro3.c linux/drivers/sound/maestro3.c
--- v2.4.14/linux/drivers/sound/maestro3.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/sound/maestro3.c Fri Nov 9 13:41:42 2001
@@ -2693,7 +2693,7 @@


X goto out;
X }
X

- pci_dev->driver_data = card;
+ pci_set_drvdata(pci_dev, card);
X
X m3_enable_ints(card);
X m3_assp_continue(card);
@@ -2773,7 +2773,7 @@
X {
X unsigned long flags;
X int i;
- struct m3_card *card = pci_dev->driver_data;
+ struct m3_card *card = pci_get_drvdata(pci_dev);
X
X /* must be a better way.. */
X save_flags(flags);
@@ -2825,7 +2825,7 @@
X unsigned long flags;
X int index;
X int i;
- struct m3_card *card = pci_dev->driver_data;
+ struct m3_card *card = pci_get_drvdata(pci_dev);
X
X save_flags(flags); /* paranoia */
X cli();
diff -u --recursive --new-file v2.4.14/linux/drivers/sound/trident.c linux/drivers/sound/trident.c
--- v2.4.14/linux/drivers/sound/trident.c Mon Nov 5 15:55:32 2001
+++ linux/drivers/sound/trident.c Tue Nov 13 09:19:41 2001
@@ -640,13 +640,21 @@
X static void trident_free_pcm_channel(struct trident_card *card, unsigned int channel)
X {
X int bank;
+ unsigned char b;
X
X if (channel < 31 || channel > 63)
X return;
X
+ if (card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_DX ||
+ card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_NX) {
+ b = inb (TRID_REG(card, T4D_REC_CH));
+ if ((b & ~0x80) == channel)
+ outb(0x0, TRID_REG(card, T4D_REC_CH));
+ }
+
X bank = channel >> 5;
X channel = channel & 0x1f;
-
+
X card->banks[bank].bitmap &= ~(1 << (channel));
X }
X
@@ -3934,7 +3942,6 @@
X {
X unsigned long iobase;
X struct trident_card *card;
- dma_addr_t mask;
X u8 bits;
X u8 revision;
X int i = 0;
diff -u --recursive --new-file v2.4.14/linux/drivers/sound/trident.h linux/drivers/sound/trident.h
--- v2.4.14/linux/drivers/sound/trident.h Sun Sep 23 11:40:59 2001
+++ linux/drivers/sound/trident.h Fri Nov 9 14:07:41 2001
@@ -29,7 +29,7 @@
X #endif
X
X #ifndef PCI_VENDOR_ID_SI
-#define PCI_VENDOR_ID_SI 0x0139
+#define PCI_VENDOR_ID_SI 0x1039
X #endif
X
X #ifndef PCI_VENDOR_ID_ALI
diff -u --recursive --new-file v2.4.14/linux/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c
--- v2.4.14/linux/drivers/sound/via82cxxx_audio.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/sound/via82cxxx_audio.c Fri Nov 9 13:45:35 2001
@@ -15,7 +15,7 @@
X */
X
X
-#define VIA_VERSION "1.1.14b"
+#define VIA_VERSION "1.9.1"
X
X
X #include <linux/config.h>
@@ -88,9 +88,10 @@
X #define VIA_MAX_FRAG_SIZE PAGE_SIZE
X #define VIA_MIN_FRAG_SIZE 64
X
-#define VIA_MIN_FRAG_NUMBER 2
+#define VIA_MIN_FRAG_NUMBER 2
X
X /* 82C686 function 5 (audio codec) PCI configuration registers */
+#define VIA_ACLINK_STATUS 0x40
X #define VIA_ACLINK_CTRL 0x41
X #define VIA_FUNC_ENABLE 0x42
X #define VIA_PNP_CONTROL 0x43
@@ -188,6 +189,7 @@
X /* controller base 0 register bitmasks */
X #define VIA_INT_DISABLE_MASK (~(0x01|0x02))
X #define VIA_SGD_STOPPED (1 << 2)
+#define VIA_SGD_PAUSED (1 << 6)
X #define VIA_SGD_ACTIVE (1 << 7)
X #define VIA_SGD_TERMINATE (1 << 6)
X #define VIA_SGD_FLAG (1 << 0)
@@ -353,7 +355,10 @@
X
X
X static struct pci_device_id via_pci_tbl[] __initdata = {
- { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_5,
+ PCI_ANY_ID, PCI_ANY_ID, },
X { 0, }
X };
X MODULE_DEVICE_TABLE(pci,via_pci_tbl);
@@ -387,7 +392,7 @@
X *
X */
X
-static inline void via_chan_stop (int iobase)
+static inline void via_chan_stop (long iobase)
X {
X if (inb (iobase + VIA_PCM_STATUS) & VIA_SGD_ACTIVE)
X outb (VIA_SGD_TERMINATE, iobase + VIA_PCM_CONTROL);
@@ -408,7 +413,7 @@
X *
X */
X
-static inline void via_chan_status_clear (int iobase)
+static inline void via_chan_status_clear (long iobase)
X {
X u8 tmp = inb (iobase + VIA_PCM_STATUS);
X
@@ -431,6 +436,19 @@
X }
X
X
+static int sg_active (long iobase)
+{
+ u8 tmp = inb (iobase + VIA_PCM_STATUS);
+ if ((tmp & VIA_SGD_STOPPED) || (tmp & VIA_SGD_PAUSED)) {
+ printk(KERN_WARNING "via82cxxx warning: SG stopped or paused\n");
+ return 0;
+ }
+ if (tmp & VIA_SGD_ACTIVE)
+ return 1;


+ return 0;
+}
+

+
X /****************************************************************
X *
X * Miscellaneous debris
@@ -451,6 +469,14 @@
X
X static inline int via_syscall_down (struct via_info *card, int nonblock)
X {
+ /* Thomas Sailer:
+ * EAGAIN is supposed to be used if IO is pending,
+ * not if there is contention on some internal
+ * synchronization primitive which should be
+ * held only for a short time anyway
+ */
+ nonblock = 0;
+
X if (nonblock) {
X if (down_trylock (&card->syscall_sem))
X return -EAGAIN;
@@ -473,6 +499,8 @@
X
X static void via_stop_everything (struct via_info *card)
X {
+ u8 tmp, new_tmp;
+
X DPRINTK ("ENTER\n");
X
X assert (card != NULL);
@@ -492,11 +520,32 @@
X via_chan_status_clear (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
X
X /*
- * clear any enabled interrupt bits, reset to 8-bit mono PCM mode
+ * clear any enabled interrupt bits
X */
- outb (0, card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
- outb (0, card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
- outb (0, card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
+ tmp = inb (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
+ new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
+ if (tmp != new_tmp)
+ outb (0, card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
+
+ tmp = inb (card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
+ new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
+ if (tmp != new_tmp)
+ outb (0, card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
+
+ tmp = inb (card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
+ new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
+ if (tmp != new_tmp)
+ outb (0, card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
+
+ udelay(10);
+
+ /*
+ * clear any existing flags
+ */
+ via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN);
+ via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_IN_CHAN);
+ via_chan_status_clear (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
+
X DPRINTK ("EXIT\n");
X }
X
@@ -521,6 +570,8 @@
X
X DPRINTK ("ENTER, rate = %d\n", rate);
X
+ if (chan->rate == rate)
+ goto out;
X if (card->locked_rate) {
X chan->rate = 48000;
X goto out;
@@ -614,7 +665,7 @@
X * Performs some of the preparations necessary to begin
X * using a PCM channel.
X *
- * Currently the preparations consist in
+ * Currently the preparations consist in
X * setting the
X * PCM channel to a known state.
X */
@@ -682,7 +733,7 @@
X
X /* alloc DMA-able memory for scatter-gather buffers */
X
- chan->page_number = (chan->frag_number * chan->frag_size) / PAGE_SIZE +
+ chan->page_number = (chan->frag_number * chan->frag_size) / PAGE_SIZE +
X (((chan->frag_number * chan->frag_size) % PAGE_SIZE) ? 1 : 0);
X
X for (i = 0; i < chan->page_number; i++) {
@@ -719,7 +770,7 @@
X i,
X (long)chan->sgtable[i].addr);
X #endif
- }
+ }
X
X /* overwrite the last buffer information */
X chan->sgtable[chan->frag_number - 1].count = cpu_to_le32 (chan->frag_size | VIA_EOL);
@@ -766,17 +817,17 @@
X {
X DPRINTK ("ENTER\n");
X
- synchronize_irq();
-
X spin_lock_irq (&card->lock);
X
X /* stop any existing channel output */
+ via_chan_status_clear (chan->iobase);
X via_chan_stop (chan->iobase);
X via_chan_status_clear (chan->iobase);
- via_chan_pcm_fmt (chan, 1);
X
X spin_unlock_irq (&card->lock);
X
+ synchronize_irq();
+
X DPRINTK ("EXIT\n");
X }
X
@@ -844,7 +895,7 @@
X /* if we are recording, enable recording fifo bit */
X if (chan->is_record)
X chan->pcm_fmt |= VIA_PCM_REC_FIFO;
- /* set interrupt select bits where applicable (PCM & FM out channels) */
+ /* set interrupt select bits where applicable (PCM in & out channels) */
X if (!chan->is_record)
X chan->pcm_fmt |= VIA_CHAN_TYPE_INT_SELECT;
X
@@ -1017,7 +1068,7 @@
X DPRINTK ("ENTER\n");
X
X /* in both cases the buffer cannot be changed */
- if (chan->is_active || chan->is_mapped) {
+ if (chan->is_active || chan->is_mapped) {
X DPRINTK ("EXIT\n");
X return -EINVAL;
X }
@@ -1147,6 +1198,8 @@
X
X static inline void via_chan_maybe_start (struct via_channel *chan)
X {
+ assert (chan->is_active == sg_active(chan->iobase));
+
X if (!chan->is_active && chan->is_enabled) {
X chan->is_active = 1;
X sg_begin (chan);
@@ -1227,10 +1280,12 @@
X data = (reg << 16) | VIA_CR80_READ | VIA_CR80_VALID;
X
X outl (data, card->baseaddr + VIA_BASE0_AC97_CTRL);
+ udelay (20);
+
X for (counter = VIA_COUNTER_LIMIT; counter > 0; counter--) {
- udelay (1);
- if ((((data = inl(card->baseaddr + 0x80)) &
- (VIA_CR80_VALID|VIA_CR80_BUSY)) == VIA_CR80_VALID))
+ udelay (1);
+ if ((((data = inl(card->baseaddr + VIA_BASE0_AC97_CTRL)) &
+ (VIA_CR80_VALID|VIA_CR80_BUSY)) == VIA_CR80_VALID))


X goto out;
X }
X

@@ -1240,9 +1295,11 @@
X out:
X /* Once the valid bit has become set, we must wait a complete AC97
X frame before the data has settled. */
- udelay(25);
- data = (unsigned long) inl (card->baseaddr + 0x80);
-
+ udelay(25);
+ data = (unsigned long) inl (card->baseaddr + VIA_BASE0_AC97_CTRL);
+
+ outb (0x02, card->baseaddr + 0x83);
+
X if (((data & 0x007F0000) >> 16) == reg) {
X DPRINTK ("EXIT, success, data=0x%lx, retval=0x%lx\n",
X data, data & 0x0000FFFF);
@@ -1370,6 +1427,7 @@
X static int __init via_ac97_reset (struct via_info *card)
X {
X struct pci_dev *pdev = card->pdev;
+ u8 tmp8;
X u16 tmp16;
X
X DPRINTK ("ENTER\n");
@@ -1403,20 +1461,43 @@
X #endif
X
X /*
- * reset AC97 controller: enable, disable, enable
- * pause after each command for good luck
+ * Reset AC97 controller: enable, disable, enable,
+ * pausing after each command for good luck. Only
+ * do this if the codec is not ready, because it causes
+ * loud pops and such due to such a hard codec reset.
X */
- pci_write_config_byte (pdev, VIA_ACLINK_CTRL, VIA_CR41_AC97_ENABLE |
- VIA_CR41_AC97_RESET | VIA_CR41_AC97_WAKEUP);
- udelay (100);
-
- pci_write_config_byte (pdev, VIA_ACLINK_CTRL, 0);
- udelay (100);
-
- pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
- VIA_CR41_AC97_ENABLE | VIA_CR41_PCM_ENABLE |
- VIA_CR41_VRA | VIA_CR41_AC97_RESET);
- udelay (100);
+ pci_read_config_byte (pdev, VIA_ACLINK_STATUS, &tmp8);
+ if ((tmp8 & VIA_CR40_AC97_READY) == 0) {
+ pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
+ VIA_CR41_AC97_ENABLE |
+ VIA_CR41_AC97_RESET |
+ VIA_CR41_AC97_WAKEUP);
+ udelay (100);
+
+ pci_write_config_byte (pdev, VIA_ACLINK_CTRL, 0);
+ udelay (100);
+
+ pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
+ VIA_CR41_AC97_ENABLE |
+ VIA_CR41_PCM_ENABLE |
+ VIA_CR41_VRA | VIA_CR41_AC97_RESET);
+ udelay (100);
+ }
+
+ /* Make sure VRA is enabled, in case we didn't do a
+ * complete codec reset, above
+ */
+ pci_read_config_byte (pdev, VIA_ACLINK_CTRL, &tmp8);
+ if (((tmp8 & VIA_CR41_VRA) == 0) ||
+ ((tmp8 & VIA_CR41_AC97_ENABLE) == 0) ||
+ ((tmp8 & VIA_CR41_PCM_ENABLE) == 0) ||
+ ((tmp8 & VIA_CR41_AC97_RESET) == 0)) {
+ pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
+ VIA_CR41_AC97_ENABLE |
+ VIA_CR41_PCM_ENABLE |
+ VIA_CR41_VRA | VIA_CR41_AC97_RESET);
+ udelay (100);
+ }
X
X #if 0 /* this breaks on K7M */
X /* disable legacy stuff */
@@ -1433,20 +1514,10 @@
X
X /* WARNING: this line is magic. Remove this
X * and things break. */
- /* enable variable rate, variable rate MIC ADC */
- /*
- * If we cannot enable VRA, we have a locked-rate codec.
- * We try again to enable VRA before assuming so, however.
- */
+ /* enable variable rate */
X tmp16 = via_ac97_read_reg (&card->ac97, AC97_EXTENDED_STATUS);
- if ((tmp16 & 1) == 0) {
+ if ((tmp16 & 1) == 0)
X via_ac97_write_reg (&card->ac97, AC97_EXTENDED_STATUS, tmp16 | 1);
- tmp16 = via_ac97_read_reg (&card->ac97, AC97_EXTENDED_STATUS);
- if ((tmp16 & 1) == 0) {
- card->locked_rate = 1;
- printk (KERN_WARNING PFX "Codec rate locked at 48Khz\n");
- }
- }
X
X DPRINTK ("EXIT, returning 0\n");
X return 0;
@@ -1494,10 +1565,24 @@
X goto err_out;
X }
X
- /* enable variable rate, variable rate MIC ADC */
+ /* enable variable rate */
X tmp16 = via_ac97_read_reg (&card->ac97, AC97_EXTENDED_STATUS);
X via_ac97_write_reg (&card->ac97, AC97_EXTENDED_STATUS, tmp16 | 1);
X
+ /*
+ * If we cannot enable VRA, we have a locked-rate codec.
+ * We try again to enable VRA before assuming so, however.
+ */
+ tmp16 = via_ac97_read_reg (&card->ac97, AC97_EXTENDED_STATUS);
+ if ((tmp16 & 1) == 0) {
+ via_ac97_write_reg (&card->ac97, AC97_EXTENDED_STATUS, tmp16 | 1);
+ tmp16 = via_ac97_read_reg (&card->ac97, AC97_EXTENDED_STATUS);
+ if ((tmp16 & 1) == 0) {
+ card->locked_rate = 1;
+ printk (KERN_WARNING PFX "Codec rate locked at 48Khz\n");
+ }
+ }
+
X DPRINTK ("EXIT, returning 0\n");
X return 0;


X
@@ -1632,7 +1717,7 @@

X uart401intr(irq, card->midi_devc, regs);
X #endif
X return;
- }
+ }
X DPRINTK ("intr, status32 == 0x%08X\n", status32);
X
X /* synchronize interrupt handling under SMP. this spinlock
@@ -1652,47 +1737,6 @@
X
X
X /**
- * via_interrupt_disable - Disable all interrupt-generating sources
- * @card: Private info for specified board
- *
- * Disables all interrupt-generation flags in the Via
- * audio hardware registers.
- */
-
-static void via_interrupt_disable (struct via_info *card)
-{
- u8 tmp8;


- unsigned long flags;
-

- DPRINTK ("ENTER\n");
-
- assert (card != NULL);
-
- spin_lock_irqsave (&card->lock, flags);
-
- pci_read_config_byte (card->pdev, VIA_FM_NMI_CTRL, &tmp8);
- if ((tmp8 & VIA_CR48_FM_TRAP_TO_NMI) == 0) {
- tmp8 |= VIA_CR48_FM_TRAP_TO_NMI;
- pci_write_config_byte (card->pdev, VIA_FM_NMI_CTRL, tmp8);
- }
-
- outb (inb (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE) &
- VIA_INT_DISABLE_MASK,
- card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
- outb (inb (card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE) &
- VIA_INT_DISABLE_MASK,
- card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
- outb (inb (card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE) &
- VIA_INT_DISABLE_MASK,
- card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
-
- spin_unlock_irqrestore (&card->lock, flags);
-
- DPRINTK ("EXIT\n");
-}
-
-
-/**
X * via_interrupt_init - Initialize interrupt handling
X * @card: Private info for specified board
X *
@@ -1703,6 +1747,8 @@
X
X static int via_interrupt_init (struct via_info *card)
X {
+ u8 tmp8;
+
X DPRINTK ("ENTER\n");
X
X assert (card != NULL);
@@ -1716,6 +1762,13 @@


X return -EIO;
X }
X

+ /* make sure FM irq is not routed to us */
+ pci_read_config_byte (card->pdev, VIA_FM_NMI_CTRL, &tmp8);
+ if ((tmp8 & VIA_CR48_FM_TRAP_TO_NMI) == 0) {
+ tmp8 |= VIA_CR48_FM_TRAP_TO_NMI;
+ pci_write_config_byte (card->pdev, VIA_FM_NMI_CTRL, tmp8);
+ }
+
X if (request_irq (card->pdev->irq, via_interrupt, SA_SHIRQ, VIA_MODULE_NAME, card)) {
X printk (KERN_ERR PFX "unable to obtain IRQ %d, aborting\n",
X card->pdev->irq);
@@ -1723,38 +1776,11 @@
X return -EBUSY;
X }
X
- /* we don't want interrupts until we're opened */
- via_interrupt_disable (card);
-
X DPRINTK ("EXIT, returning 0\n");


X return 0;
X }
X

X
-/**
- * via_interrupt_cleanup - Shutdown driver interrupt handling
- * @card: Private info for specified board
- *
- * Disable any potential interrupt sources in the Via audio
- * hardware, and then release (un-reserve) the IRQ line
- * in the kernel core.
- */
-
-static void via_interrupt_cleanup (struct via_info *card)
-{
- DPRINTK ("ENTER\n");
-
- assert (card != NULL);
- assert (card->pdev != NULL);
-
- via_interrupt_disable (card);
-
- free_irq (card->pdev->irq, card);
-
- DPRINTK ("EXIT\n");
-}
-
-
X /****************************************************************
X *
X * OSS DSP device
@@ -1958,18 +1984,27 @@
X char *userbuf, size_t count,
X int nonblock)
X {
+ DECLARE_WAITQUEUE(wait, current);
X const char *orig_userbuf = userbuf;
X struct via_channel *chan = &card->ch_in;
X size_t size;
X int n, tmp;
+ ssize_t ret = 0;
X
X /* if SGD has not yet been started, start it */
X via_chan_maybe_start (chan);
X
X handle_one_block:
X /* just to be a nice neighbor */
- if (current->need_resched)
+ /* Thomas Sailer:
+ * But also to ourselves, release semaphore if we do so */
+ if (current->need_resched) {
+ up(&card->syscall_sem);
X schedule ();
+ ret = via_syscall_down (card, nonblock);
+ if (ret)
+ goto out;
+ }
X
X /* grab current channel software pointer. In the case of
X * recording, this is pointing to the next buffer that
@@ -1981,33 +2016,53 @@
X * to be copied to userland. sleep until at least
X * one buffer has been read from the audio hardware.
X */
- tmp = atomic_read (&chan->n_frags);
- assert (tmp >= 0);
- assert (tmp <= chan->frag_number);
- while (tmp == 0) {
- if (nonblock || !chan->is_active)
- return -EAGAIN;
+ add_wait_queue(&chan->wait, &wait);
+ for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
+ tmp = atomic_read (&chan->n_frags);
+ assert (tmp >= 0);
+ assert (tmp <= chan->frag_number);
+ if (tmp)
+ break;
+ if (nonblock || !chan->is_active) {
+ ret = -EAGAIN;
+ break;
+ }
+
+ up(&card->syscall_sem);
X
X DPRINTK ("Sleeping on block %d\n", n);
- interruptible_sleep_on (&chan->wait);
+ schedule();
X
- if (signal_pending (current))
- return -ERESTARTSYS;
+ ret = via_syscall_down (card, nonblock);
+ if (ret)
+ break;
X
- tmp = atomic_read (&chan->n_frags);
+ if (signal_pending (current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
X }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&chan->wait, &wait);
+ if (ret)
+ goto out;
X
X /* Now that we have a buffer we can read from, send
X * as much as sample data possible to userspace.
X */
X while ((count > 0) && (chan->slop_len < chan->frag_size)) {
X size_t slop_left = chan->frag_size - chan->slop_len;
+ void *base = chan->pgtbl[n / (PAGE_SIZE / chan->frag_size)].cpuaddr;
+ unsigned ofs = n % (PAGE_SIZE / chan->frag_size);
X
X size = (count < slop_left) ? count : slop_left;
X if (copy_to_user (userbuf,
- chan->pgtbl[n / (PAGE_SIZE / chan->frag_size)].cpuaddr + n % (PAGE_SIZE / chan->frag_size) + chan->slop_len,
- size))
- return -EFAULT;
+ base + ofs + chan->slop_len,
+ size)) {
+ ret = -EFAULT;
+ goto out;
+ }
X
X count -= size;
X chan->slop_len += size;
@@ -2056,7 +2111,7 @@
X goto handle_one_block;
X
X out:
- return userbuf - orig_userbuf;
+ return (userbuf != orig_userbuf) ? (userbuf - orig_userbuf) : ret;
X }
X
X
@@ -2107,16 +2162,25 @@
X const char *userbuf, size_t count,
X int nonblock)
X {
+ DECLARE_WAITQUEUE(wait, current);
X const char *orig_userbuf = userbuf;
X struct via_channel *chan = &card->ch_out;
X volatile struct via_sgd_table *sgtable = chan->sgtable;
X size_t size;
X int n, tmp;
+ ssize_t ret = 0;
X
X handle_one_block:
X /* just to be a nice neighbor */
- if (current->need_resched)
+ /* Thomas Sailer:
+ * But also to ourselves, release semaphore if we do so */
+ if (current->need_resched) {
+ up(&card->syscall_sem);
X schedule ();
+ ret = via_syscall_down (card, nonblock);
+ if (ret)
+ goto out;
+ }
X
X /* grab current channel fragment pointer. In the case of
X * playback, this is pointing to the next fragment that
@@ -2128,21 +2192,37 @@
X * to be filled by userspace. Sleep until
X * at least one fragment is available for our use.
X */
- tmp = atomic_read (&chan->n_frags);
- assert (tmp >= 0);
- assert (tmp <= chan->frag_number);
- while (tmp == 0) {
- if (nonblock || !chan->is_enabled)
- return -EAGAIN;
+ add_wait_queue(&chan->wait, &wait);
+ for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
+ tmp = atomic_read (&chan->n_frags);
+ assert (tmp >= 0);
+ assert (tmp <= chan->frag_number);
+ if (tmp)
+ break;
+ if (nonblock || !chan->is_active) {
+ ret = -EAGAIN;
+ break;
+ }
+
+ up(&card->syscall_sem);
X
X DPRINTK ("Sleeping on page %d, tmp==%d, ir==%d\n", n, tmp, chan->is_record);
- interruptible_sleep_on (&chan->wait);
+ schedule();
X
- if (signal_pending (current))
- return -ERESTARTSYS;
+ ret = via_syscall_down (card, nonblock);
+ if (ret)
+ break;
X
- tmp = atomic_read (&chan->n_frags);
+ if (signal_pending (current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
X }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&chan->wait, &wait);
+ if (ret)
+ goto out;
X
X /* Now that we have at least one fragment we can write to, fill the buffer
X * as much as possible with data from userspace.
@@ -2152,8 +2232,10 @@
X
X size = (count < slop_left) ? count : slop_left;
X if (copy_from_user (chan->pgtbl[n / (PAGE_SIZE / chan->frag_size)].cpuaddr + (n % (PAGE_SIZE / chan->frag_size)) * chan->frag_size + chan->slop_len,
- userbuf, size))
- return -EFAULT;
+ userbuf, size)) {
+ ret = -EFAULT;
+ goto out;
+ }
X
X count -= size;
X chan->slop_len += size;
@@ -2264,7 +2346,8 @@
X static unsigned int via_dsp_poll(struct file *file, struct poll_table_struct *wait)
X {
X struct via_info *card;
- unsigned int mask = 0, rd, wr;
+ struct via_channel *chan;
+ unsigned int mask = 0;
X
X DPRINTK ("ENTER\n");
X
@@ -2272,28 +2355,21 @@
X card = file->private_data;
X assert (card != NULL);
X
- rd = (file->f_mode & FMODE_READ);
- wr = (file->f_mode & FMODE_WRITE);
-
- if (wr && (atomic_read (&card->ch_out.n_frags) == 0)) {
- assert (card->ch_out.is_active);
- poll_wait(file, &card->ch_out.wait, wait);
- }
- if (rd) {
- /* XXX is it ok, spec-wise, to start DMA here? */
- if (!card->ch_in.is_active) {
- via_chan_set_buffering(card, &card->ch_in, -1);
- via_chan_buffer_init(card, &card->ch_in);
- }
- via_chan_maybe_start (&card->ch_in);
- if (atomic_read (&card->ch_in.n_frags) == 0)
- poll_wait(file, &card->ch_in.wait, wait);
+ if (file->f_mode & FMODE_READ) {
+ chan = &card->ch_in;
+ if (sg_active (chan->iobase))
+ poll_wait(file, &chan->wait, wait);
+ if (atomic_read (&chan->n_frags) > 0)
+ mask |= POLLIN | POLLRDNORM;
X }
X
- if (wr && ((atomic_read (&card->ch_out.n_frags) > 0) || !card->ch_out.is_active))
- mask |= POLLOUT | POLLWRNORM;
- if (rd && (atomic_read (&card->ch_in.n_frags) > 0))
- mask |= POLLIN | POLLRDNORM;
+ if (file->f_mode & FMODE_WRITE) {
+ chan = &card->ch_out;
+ if (sg_active (chan->iobase))
+ poll_wait(file, &chan->wait, wait);
+ if (atomic_read (&chan->n_frags) > 0)
+ mask |= POLLOUT | POLLWRNORM;
+ }
X
X DPRINTK ("EXIT, returning %u\n", mask);
X return mask;
@@ -2315,6 +2391,9 @@
X static int via_dsp_drain_playback (struct via_info *card,
X struct via_channel *chan, int nonblock)
X {
+ DECLARE_WAITQUEUE(wait, current);


+ int ret = 0;
+

X DPRINTK ("ENTER, nonblock = %d\n", nonblock);
X
X if (chan->slop_len > 0)
@@ -2325,10 +2404,16 @@
X
X via_chan_maybe_start (chan);
X
- while (atomic_read (&chan->n_frags) < chan->frag_number) {
+ add_wait_queue(&chan->wait, &wait);
+ for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
+ if (atomic_read (&chan->n_frags) >= chan->frag_number)
+ break;
+
X if (nonblock) {
X DPRINTK ("EXIT, returning -EAGAIN\n");
- return -EAGAIN;
+ ret = -EAGAIN;
+ break;
X }
X
X #ifdef VIA_DEBUG
@@ -2357,14 +2442,22 @@
X printk (KERN_ERR "sleeping but not active\n");
X #endif
X
+ up(&card->syscall_sem);
+
X DPRINTK ("sleeping, nbufs=%d\n", atomic_read (&chan->n_frags));
- interruptible_sleep_on (&chan->wait);
+ schedule();
+
+ if ((ret = via_syscall_down (card, nonblock)))
+ break;
X
X if (signal_pending (current)) {
X DPRINTK ("EXIT, returning -ERESTARTSYS\n");
- return -ERESTARTSYS;
+ ret = -ERESTARTSYS;
+ break;
X }
X }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&chan->wait, &wait);
X
X #ifdef VIA_DEBUG
X {
@@ -2392,8 +2485,8 @@
X #endif
X
X out:
- DPRINTK ("EXIT, returning 0\n");
- return 0;
+ DPRINTK ("EXIT, returning %d\n", ret);
+ return ret;
X }
X
X
@@ -2695,7 +2788,6 @@
X DPRINTK ("DSP_RESET\n");
X if (rd) {
X via_chan_clear (card, &card->ch_in);
- via_chan_pcm_fmt (&card->ch_in, 1);
X card->ch_in.frag_number = 0;
X card->ch_in.frag_size = 0;
X atomic_set(&card->ch_in.n_frags, 0);
@@ -2703,7 +2795,6 @@
X
X if (wr) {
X via_chan_clear (card, &card->ch_out);
- via_chan_pcm_fmt (&card->ch_out, 1);
X card->ch_out.frag_number = 0;
X card->ch_out.frag_size = 0;
X atomic_set(&card->ch_out.n_frags, 0);
@@ -2712,6 +2803,11 @@
X rc = 0;
X break;
X
+ case SNDCTL_DSP_NONBLOCK:
+ file->f_flags |= O_NONBLOCK;
+ rc = 0;
+ break;
+
X /* obtain bitmask of device capabilities, such as mmap, full duplex, etc. */
X case SNDCTL_DSP_GETCAPS:
X DPRINTK ("DSP_GETCAPS\n");


@@ -2812,6 +2908,15 @@
X

X break;
X
+ case SNDCTL_DSP_GETTRIGGER:
+ val = 0;
+ if ((file->f_mode & FMODE_READ) && card->ch_in.is_enabled)
+ val |= PCM_ENABLE_INPUT;
+ if ((file->f_mode & FMODE_WRITE) && card->ch_out.is_enabled)
+ val |= PCM_ENABLE_OUTPUT;
+ rc = put_user(val, (int *)arg);
+ break;
+
X /* Enable full duplex. Since we do this as soon as we are opened
X * with O_RDWR, this is mainly a no-op that always returns success.
X */
@@ -2834,7 +2939,7 @@
X rc = via_chan_set_buffering(card, &card->ch_in, val);
X
X if (wr)
- rc = via_chan_set_buffering(card, &card->ch_out, val);
+ rc = via_chan_set_buffering(card, &card->ch_out, val);
X
X DPRINTK ("SNDCTL_DSP_SETFRAGMENT (fragshift==0x%04X (%d), maxfrags==0x%04X (%d))\n",
X val & 0xFFFF,
@@ -2952,7 +3057,7 @@
X via_chan_pcm_fmt (chan, 0);
X via_set_rate (&card->ac97, chan, 44100);
X } else {
- via_chan_pcm_fmt (chan, 0);
+ via_chan_pcm_fmt (chan, 1);
X via_set_rate (&card->ac97, chan, 8000);
X }
X }
@@ -3127,7 +3232,7 @@
X pci_read_config_byte (pdev, 0x43, &r43);
X card->midi_info.io_base = 0x300 + ((r43 & 0x0c) << 2);
X }
-
+
X card->midi_info.irq = -pdev->irq;
X if (probe_uart401(& card->midi_info, THIS_MODULE))
X {
@@ -3181,10 +3286,10 @@
X
X #ifdef CONFIG_MIDI_VIA82CXXX
X if (card->midi_info.io_base)
- unload_uart401(&card->midi_info);
+ unload_uart401(&card->midi_info);
X #endif
X
- via_interrupt_cleanup (card);
+ free_irq (card->pdev->irq, card);
X via_card_cleanup_proc (card);
X via_dsp_cleanup (card);
X via_ac97_cleanup (card);
@@ -3197,8 +3302,8 @@
X pci_set_drvdata (pdev, NULL);
X
X pci_release_regions (pdev);
- pci_set_power_state (pdev, 3); /* ...zzzzzz */
X pci_disable_device (pdev);
+ pci_set_power_state (pdev, 3); /* ...zzzzzz */
X
X DPRINTK ("EXIT\n");
X return;
diff -u --recursive --new-file v2.4.14/linux/drivers/sound/vwsnd.c linux/drivers/sound/vwsnd.c
--- v2.4.14/linux/drivers/sound/vwsnd.c Mon Aug 27 12:41:45 2001
+++ linux/drivers/sound/vwsnd.c Fri Nov 9 14:07:41 2001
@@ -3449,6 +3449,7 @@
X
X MODULE_DESCRIPTION("SGI Visual Workstation sound module");
X MODULE_AUTHOR("Bob Miller <kb...@sgi.com>");
+MODULE_LICENSE("GPL");
X
X static int __init init_vwsnd(void)
X {
diff -u --recursive --new-file v2.4.14/linux/drivers/sound/ymfpci.c linux/drivers/sound/ymfpci.c
--- v2.4.14/linux/drivers/sound/ymfpci.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/sound/ymfpci.c Mon Nov 19 14:53:19 2001
@@ -1824,7 +1824,7 @@
X }
X
X unit = NULL; /* gcc warns */
- for (list = ymf_devs.next; list != &ymf_devs; list = list->next) {
+ list_for_each(list, &ymf_devs) {
X unit = list_entry(list, ymfpci_t, ymf_devs);
X if (((unit->dev_audio ^ minor) & ~0x0F) == 0)
X break;
@@ -1935,7 +1935,7 @@
X struct list_head *list;
X ymfpci_t *unit;
X
- for (list = ymf_devs.next; list != &ymf_devs; list = list->next) {
+ list_for_each(list, &ymf_devs) {
X unit = list_entry(list, ymfpci_t, ymf_devs);
X for (i = 0; i < NR_AC97; i++) {
X if (unit->ac97_codec[i] != NULL &&
@@ -1990,16 +1990,25 @@
X
X static int ymf_suspend(struct pci_dev *pcidev, u32 unused)
X {
+ int i;
X struct ymf_unit *unit = pci_get_drvdata(pcidev);
X unsigned long flags;
X struct ymf_dmabuf *dmabuf;
X struct list_head *p;
X struct ymf_state *state;
+ struct ac97_codec *codec;
X
X spin_lock_irqsave(&unit->reg_lock, flags);
X
X unit->suspended = 1;
X
+ for (i = 0; i < NR_AC97; i++) {
+ codec = unit->ac97_codec[i];
+ if (!codec)
+ continue;
+ ac97_save_state(codec);
+ }
+
X list_for_each(p, &unit->states) {
X state = list_entry(p, struct ymf_state, chain);
X
@@ -2024,14 +2033,23 @@
X
X static int ymf_resume(struct pci_dev *pcidev)
X {
+ int i;
X struct ymf_unit *unit = pci_get_drvdata(pcidev);
X unsigned long flags;
X struct list_head *p;
X struct ymf_state *state;
+ struct ac97_codec *codec;
X
X ymfpci_aclink_reset(unit->pci);
X ymfpci_codec_ready(unit, 0, 1); /* prints diag if not ready. */
X
+ for (i = 0; i < NR_AC97; i++) {
+ codec = unit->ac97_codec[i];
+ if (!codec)
+ continue;
+ ac97_restore_state(codec);
+ }
+
X #ifdef CONFIG_SOUND_YMFPCI_LEGACY
X /* XXX At this time the legacy registers are probably deprogrammed. */
X #endif
@@ -2409,6 +2427,8 @@
X printk(KERN_ERR "ymfpci: unable to map registers\n");
X goto out_free;
X }
+
+ pci_set_master(pcidev);
X
X printk(KERN_INFO "ymfpci: %s at 0x%lx IRQ %d\n",
X (char *)ent->driver_data, pci_resource_start(pcidev, 0), pcidev->irq);
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/bluetooth.c linux/drivers/usb/bluetooth.c
--- v2.4.14/linux/drivers/usb/bluetooth.c Sun Sep 23 11:41:00 2001
+++ linux/drivers/usb/bluetooth.c Tue Nov 13 09:19:41 2001
@@ -322,9 +322,9 @@
X
X dr->requesttype = BLUETOOTH_CONTROL_REQUEST_TYPE;
X dr->request = request;
- dr->value = cpu_to_le16p(&value);
- dr->index = cpu_to_le16p(&bluetooth->control_out_bInterfaceNum);
- dr->length = cpu_to_le16p(&len);
+ dr->value = cpu_to_le16((u16) value);
+ dr->index = cpu_to_le16((u16) bluetooth->control_out_bInterfaceNum);
+ dr->length = cpu_to_le16((u16) len);
X
X FILL_CONTROL_URB (urb, bluetooth->dev, usb_sndctrlpipe(bluetooth->dev, 0),
X (unsigned char*)dr, urb->transfer_buffer, len, bluetooth_ctrl_callback, bluetooth);
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/catc.c linux/drivers/usb/catc.c
--- v2.4.14/linux/drivers/usb/catc.c Sun Sep 23 11:41:00 2001
+++ linux/drivers/usb/catc.c Tue Nov 13 09:19:41 2001
@@ -330,7 +330,7 @@
X
X catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6;
X tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr;
- *((u16*)tx_buf) = cpu_to_le16p(&skb->len);
+ *((u16*)tx_buf) = cpu_to_le16((u16)skb->len);
X memcpy(tx_buf + 2, skb->data, skb->len);
X catc->tx_ptr += skb->len + 2;
X
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/hid-input.c linux/drivers/usb/hid-input.c
--- v2.4.14/linux/drivers/usb/hid-input.c Sun Sep 23 11:41:00 2001
+++ linux/drivers/usb/hid-input.c Sun Nov 11 10:09:37 2001
@@ -131,7 +131,8 @@
X
X if (usage->hid == HID_GD_HATSWITCH) {
X usage->code = ABS_HAT0X;
- usage->hat = 1 + (field->logical_maximum == 4);
+ usage->hat_min = field->logical_minimum;
+ usage->hat_max = field->logical_maximum;
X }
X break;
X
@@ -285,7 +286,7 @@
X input->absflat[usage->code] = (b - a) >> 4;
X }
X
- if (usage->hat) {
+ if (usage->hat_min != usage->hat_max) {
X int i;
X for (i = usage->code; i < usage->code + 2 && i <= max; i++) {
X input->absmax[i] = 1;
@@ -302,9 +303,9 @@
X struct input_dev *input = &hid->input;
X int *quirks = &hid->quirks;
X
- if (usage->hat) {
- if (usage->hat == 2) value = value * 2;
- if (value > 8) value = 8;
+ if (usage->hat_min != usage->hat_max) {
+ value = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
+ if (value < 0 || value > 8) value = 0;
X input_event(input, usage->type, usage->code , hid_hat_to_axis[value].x);
X input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[value].y);
X return;
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/hid.h linux/drivers/usb/hid.h
--- v2.4.14/linux/drivers/usb/hid.h Sun Sep 23 11:41:00 2001
+++ linux/drivers/usb/hid.h Tue Nov 13 17:45:27 2001
@@ -234,7 +234,8 @@
X unsigned hid; /* hid usage code */
X __u16 code; /* input driver code */
X __u8 type; /* input driver type */
- __u8 hat; /* hat switch fun */
+ __s8 hat_min; /* hat switch fun */
+ __s8 hat_max; /* ditto */
X };
X
X struct hid_field {
@@ -362,7 +363,7 @@
X
X #endif
X
-#define IS_INPUT_APPLICATION(a) ((a >= 0x00010000) && (a <= 0x00010008))
+#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || ( a == 0x000c0001))
X
X int hid_open(struct hid_device *);
X void hid_close(struct hid_device *);
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- v2.4.14/linux/drivers/usb/hub.c Tue Oct 9 17:06:52 2001
+++ linux/drivers/usb/hub.c Mon Nov 12 09:34:16 2001
@@ -356,7 +356,7 @@
X
X INIT_LIST_HEAD(&hub->event_list);
X hub->dev = dev;
- atomic_set(&hub->refcnt, 1);
+ init_MUTEX(&hub->khubd_sem);
X
X /* Record the new hub's existence */
X spin_lock_irqsave(&hub_event_lock, flags);
@@ -385,34 +385,11 @@


X return NULL;
X }
X

-static void hub_get(struct usb_hub *hub)
-{
- atomic_inc(&hub->refcnt);
-}
-
-static void hub_put(struct usb_hub *hub)
-{
- if (atomic_dec_and_test(&hub->refcnt)) {
- if (hub->descriptor) {
- kfree(hub->descriptor);
- hub->descriptor = NULL;
- }
-
- kfree(hub);
- }
-}
-
X static void hub_disconnect(struct usb_device *dev, void *ptr)
X {
X struct usb_hub *hub = (struct usb_hub *)ptr;


X unsigned long flags;
X

- if (hub->urb) {
- usb_unlink_urb(hub->urb);
- usb_free_urb(hub->urb);
- hub->urb = NULL;
- }
-
X spin_lock_irqsave(&hub_event_lock, flags);
X
X /* Delete it and then reset it */
@@ -423,7 +400,22 @@
X
X spin_unlock_irqrestore(&hub_event_lock, flags);
X
- hub_put(hub);
+ down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */
+ up(&hub->khubd_sem);
+
+ if (hub->urb) {
+ usb_unlink_urb(hub->urb);
+ usb_free_urb(hub->urb);
+ hub->urb = NULL;
+ }
+
+ if (hub->descriptor) {
+ kfree(hub->descriptor);
+ hub->descriptor = NULL;
+ }
+
+ /* Free the memory */
+ kfree(hub);
X }
X
X static int hub_ioctl(struct usb_device *hub, unsigned int code, void *user_data)
@@ -534,10 +526,6 @@
X dbg("port %d, portstatus %x, change %x, %s", port + 1,
X portstatus, portchange, portspeed (portstatus));
X
- /* Device went away? */
- if (!(portstatus & USB_PORT_STAT_CONNECTION))
- return 1;
-
X /* bomb out completely if something weird happened */
X if ((portchange & USB_PORT_STAT_C_CONNECTION))
X return -1;
@@ -745,7 +733,7 @@
X list_del(tmp);
X INIT_LIST_HEAD(tmp);
X
- hub_get(hub);
+ down(&hub->khubd_sem); /* never blocks, we were on list */
X spin_unlock_irqrestore(&hub_event_lock, flags);
X
X if (hub->error) {
@@ -753,8 +741,8 @@
X
X if (usb_hub_reset(hub)) {
X err("error resetting hub %d - disconnecting", dev->devnum);
+ up(&hub->khubd_sem);
X usb_hub_disconnect(dev);
- hub_put(hub);
X continue;
X }
X
@@ -830,7 +818,7 @@
X usb_hub_power_on(hub);
X }
X }
- hub_put(hub);
+ up(&hub->khubd_sem);
X } /* end while (1) */
X
X spin_unlock_irqrestore(&hub_event_lock, flags);
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/hub.h linux/drivers/usb/hub.h
--- v2.4.14/linux/drivers/usb/hub.h Thu Oct 18 13:50:37 2001
+++ linux/drivers/usb/hub.h Thu Nov 22 11:49:52 2001
@@ -135,7 +135,7 @@
X
X struct usb_hub_descriptor *descriptor;
X
- atomic_t refcnt;
+ struct semaphore khubd_sem;
X };
X
-#endif
+#endif /* __LINUX_HUB_H */
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/kaweth.c linux/drivers/usb/kaweth.c
--- v2.4.14/linux/drivers/usb/kaweth.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/usb/kaweth.c Tue Nov 13 09:19:41 2001
@@ -374,9 +374,9 @@
X kaweth_dbg("High: %i, Low:%i", kaweth->firmware_buf[3],
X kaweth->firmware_buf[2]);
X
- kaweth_dbg("Downloading firmware at %x to kaweth device at %x",
- (int)data,
- (int)kaweth);
+ kaweth_dbg("Downloading firmware at %p to kaweth device at %p",
+ data,
+ kaweth);
X kaweth_dbg("Firmware length: %d", data_len);
X
X return kaweth_control(kaweth,
@@ -480,7 +480,7 @@
X int count = urb->actual_length;
X int count2 = urb->transfer_buffer_length;
X
- __u16 pkt_len = le16_to_cpup(kaweth->rx_buf);
+ __u16 pkt_len = le16_to_cpup((u16 *)kaweth->rx_buf);
X
X struct sk_buff *skb;
X
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c
--- v2.4.14/linux/drivers/usb/serial/ftdi_sio.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/usb/serial/ftdi_sio.c Tue Nov 13 09:19:41 2001
@@ -12,9 +12,18 @@
X *
X * See Documentation/usb/usb-serial.txt for more information on using this driver
X *
- * See http://reality.sgi.com/bryder_wellington/ftdi_sio for upto date testing info
+ * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
X * and extra documentation
X *
+ * (04/Nov/2001) Bill Ryder
+ * Fixed bug in read_bulk_callback where incorrect urb buffer was used.
+ * cleaned up write offset calculation
+ * added write_room since default values can be incorrect for sio
+ * changed write_bulk_callback to use same queue_task as other drivers
+ * (the previous version caused panics)
+ * Removed port iteration code since the device only has one I/O port and it
+ * was wrong anyway.
+ *
X * (31/May/2001) gkh
X * switched from using spinlock to a semaphore, which fixes lots of problems.
X *
@@ -97,7 +106,6 @@
X #include <linux/module.h>
X #include <linux/spinlock.h>
X #include <linux/usb.h>
-
X #ifdef CONFIG_USB_SERIAL_DEBUG
X static int debug = 1;
X #else
@@ -111,7 +119,7 @@
X /*
X * Version Information
X */
-#define DRIVER_VERSION "v1.1.0"
+#define DRIVER_VERSION "v1.2.0"
X #define DRIVER_AUTHOR "Greg Kroah-Hartman <gr...@kroah.com>, Bill Ryder <bry...@sgi.com>"
X #define DRIVER_DESC "USB FTDI RS232 Converters Driver"
X
@@ -146,6 +154,7 @@
X struct ftdi_private {
X ftdi_type_t ftdi_type;
X __u16 last_set_data_urb_value ; /* the last data state set - needed for doing a break */
+ int write_offset;
X };
X /* function prototypes for a FTDI serial converter */
X static int ftdi_sio_startup (struct usb_serial *serial);
@@ -154,6 +163,7 @@
X static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp);
X static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp);
X static int ftdi_sio_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+static int ftdi_sio_write_room (struct usb_serial_port *port);
X static void ftdi_sio_write_bulk_callback (struct urb *urb);
X static void ftdi_sio_read_bulk_callback (struct urb *urb);
X static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * old);
@@ -176,6 +186,7 @@
X open: ftdi_sio_open,
X close: ftdi_sio_close,
X write: ftdi_sio_write,
+ write_room: ftdi_sio_write_room,
X read_bulk_callback: ftdi_sio_read_bulk_callback,
X write_bulk_callback: ftdi_sio_write_bulk_callback,
X ioctl: ftdi_sio_ioctl,
@@ -198,6 +209,7 @@
X open: ftdi_sio_open,
X close: ftdi_sio_close,
X write: ftdi_sio_write,
+ write_room: ftdi_sio_write_room,
X read_bulk_callback: ftdi_sio_read_bulk_callback,
X write_bulk_callback: ftdi_sio_write_bulk_callback,
X ioctl: ftdi_sio_ioctl,
@@ -252,7 +264,6 @@
X {
X struct ftdi_private *priv;
X
- init_waitqueue_head(&serial->port[0].write_wait);
X
X priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
X if (!priv){
@@ -261,6 +272,7 @@
X }
X
X priv->ftdi_type = sio;
+ priv->write_offset = 1;
X
X return (0);
X }
@@ -270,7 +282,6 @@
X {
X struct ftdi_private *priv;
X
- init_waitqueue_head(&serial->port[0].write_wait);
X
X priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
X if (!priv){
@@ -279,6 +290,7 @@
X }
X
X priv->ftdi_type = F8U232AM;
+ priv->write_offset = 0;
X
X return (0);
X }
@@ -288,13 +300,14 @@
X
X dbg (__FUNCTION__);
X
- /* Close ports if they are open */
+
+ /* stop reads and writes on all ports */
X while (serial->port[0].open_count > 0) {
- ftdi_sio_close (&serial->port[0], NULL);
+ ftdi_sio_close (&serial->port[0], NULL);
X }
- if (serial->port->private){
- kfree(serial->port->private);
- serial->port->private = NULL;
+ if (serial->port[0].private){
+ kfree(serial->port[0].private);
+ serial->port[0].private = NULL;
X }
X }
X
@@ -361,7 +374,7 @@
X
X static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp)
X { /* ftdi_sio_close */
- struct usb_serial *serial = port->serial;
+ struct usb_serial *serial = port->serial; /* Checked in usbserial.c */
X unsigned int c_cflag = port->tty->termios->c_cflag;
X char buf[1];


X
@@ -393,6 +406,7 @@

X } /* Note change no line is hupcl is off */
X
X /* shutdown our bulk reads and writes */
+ /* ***CHECK*** behaviour when there is nothing queued */
X usb_unlink_urb (port->write_urb);
X usb_unlink_urb (port->read_urb);
X }
@@ -403,7 +417,6 @@
X if (!(port->tty->termios->c_cflag & CLOCAL)){
X tty_hangup(port->tty);
X }
-
X }
X
X up (&port->sem);
@@ -423,10 +436,9 @@
X { /* ftdi_sio_write */
X struct usb_serial *serial = port->serial;
X struct ftdi_private *priv = (struct ftdi_private *)port->private;
+ unsigned char *first_byte = port->write_urb->transfer_buffer;
X int data_offset ;
- int rc;
X int result;
- DECLARE_WAITQUEUE(wait, current);
X
X dbg(__FUNCTION__ " port %d, %d bytes", port->number, count);
X
@@ -435,95 +447,70 @@
X return 0;
X }
X
- if (priv->ftdi_type == sio){
- data_offset = 1;
- } else {
- data_offset = 0;
- }
+ data_offset = priv->write_offset;
X dbg("data_offset set to %d",data_offset);
X
- /* only do something if we have a bulk out endpoint */
- if (serial->num_bulk_out) {
- unsigned char *first_byte = port->write_urb->transfer_buffer;
-
- /* Was seeing a race here, got a read callback, then write callback before
- hitting interuptible_sleep_on - so wrapping in a wait_queue */
-
- add_wait_queue(&port->write_wait, &wait);
- set_current_state (TASK_INTERRUPTIBLE);
- while (port->write_urb->status == -EINPROGRESS) {
- dbg(__FUNCTION__ " write in progress - retrying");
- if (signal_pending(current)) {
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->write_wait, &wait);
- rc = -ERESTARTSYS;
- goto err;
- }
- schedule();
- }
- remove_wait_queue(&port->write_wait, &wait);
- set_current_state(TASK_RUNNING);
-
- count += data_offset;
- count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
- if (count == 0) {
- return 0;
- }
+ if (port->write_urb->status == -EINPROGRESS) {
+ dbg (__FUNCTION__ " - already writing");
+ return (0);
+ }
+
+ down(&port->sem);
+
+ count += data_offset;
+ count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
X
X /* Copy in the data to send */
- if (from_user) {
- if (copy_from_user(port->write_urb->transfer_buffer + data_offset,
- buf, count - data_offset ))
- return -EFAULT;
- }
- else {
- memcpy(port->write_urb->transfer_buffer + data_offset,
- buf, count - data_offset );
- }
-
- first_byte = port->write_urb->transfer_buffer;
- if (data_offset > 0){
- /* Write the control byte at the front of the packet*/
- *first_byte = 1 | ((count-data_offset) << 2) ;
+ if (from_user) {
+ if (copy_from_user(port->write_urb->transfer_buffer + data_offset,
+ buf, count - data_offset )){
+ up (&port->sem);
+ return -EFAULT;
X }
+ } else {
+ memcpy(port->write_urb->transfer_buffer + data_offset,
+ buf, count - data_offset );
+ }
+
+ first_byte = port->write_urb->transfer_buffer;
+ if (data_offset > 0){
+ /* Write the control byte at the front of the packet*/
+ *first_byte = 1 | ((count-data_offset) << 2) ;
+ }
X
- dbg(__FUNCTION__ " Bytes: %d, First Byte: 0o%03o",count, first_byte[0]);
- usb_serial_debug_data (__FILE__, __FUNCTION__, count, first_byte);
+ dbg(__FUNCTION__ " Bytes: %d, First Byte: 0x%02x",count, first_byte[0]);
+ usb_serial_debug_data (__FILE__, __FUNCTION__, count, first_byte);
X
- /* send the data out the bulk port */
- FILL_BULK_URB(port->write_urb, serial->dev,
- usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
- port->write_urb->transfer_buffer, count,
- ftdi_sio_write_bulk_callback, port);
+ /* send the data out the bulk port */
+ FILL_BULK_URB(port->write_urb, serial->dev,
+ usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, count,
+ ftdi_sio_write_bulk_callback, port);
X
- result = usb_submit_urb(port->write_urb);
- if (result) {
- err(__FUNCTION__ " - failed submitting write urb, error %d", result);


- return 0;
- }
-

- dbg(__FUNCTION__ " write returning: %d", count - data_offset);
- return (count - data_offset);
+ result = usb_submit_urb(port->write_urb);
+ if (result) {
+ err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+ up (&port->sem);


+ return 0;
X }
-

- /* no bulk out, so return 0 bytes written */
- return 0;
- err: /* error exit */
- return(rc);
+ up (&port->sem);
+
+ dbg(__FUNCTION__ " write returning: %d", count - data_offset);
+ return (count - data_offset);
+
X } /* ftdi_sio_write */
X
X static void ftdi_sio_write_bulk_callback (struct urb *urb)
X {
X struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
X struct usb_serial *serial;
- struct tty_struct *tty = port->tty;
X
X dbg("ftdi_sio_write_bulk_callback");
X
X if (port_paranoia_check (port, "ftdi_sio_write_bulk_callback")) {
X return;
X }
-
+
X serial = port->serial;
X if (serial_paranoia_check (serial, "ftdi_sio_write_bulk_callback")) {
X return;
@@ -533,16 +520,29 @@
X dbg("nonzero write bulk status received: %d", urb->status);
X return;
X }
+ queue_task(&port->tqueue, &tq_immediate);


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

echo 'End of part 069'
echo 'File patch-2.4.15 is continued in part 070'
echo "070" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:54 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part078

#!/bin/sh -x
# this is part 078 of a 115 - part archive


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

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

+ temp = tempbx & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x1C, temp); /* Part1_1Ch */
+ temp = tempcx & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x1B, temp); /* Part1_1Bh */
+
+ tempecx = SiS_VGAHDE;
+ tempebx = SiS_HDE;
+ tempeax = tempecx;
+ tempeax = tempeax << 6;
+ tempeax = tempeax << 10;
+ tempeax = tempeax / tempebx;
+ if (tempebx == tempecx) {
+ tempeax = 65535;
+ }
+ tempecx = tempeax;
+ tempeax = SiS_VGAHDE; /*change VGAHT->VGAHDE */
+ tempeax = tempeax << 6;
+ tempeax = tempeax << 10;
+ tempeax = tempeax / tempecx;
+ tempecx = tempecx << 16;
+ tempeax = tempeax - 1;
+ tempecx = tempecx | (tempeax & 0x00FFFF);
+ temp = (USHORT) (tempecx & 0x00FF);
+ SiS_SetReg1 (SiS_Part1Port, 0x1F, temp); /* Part1_1Fh */
+
+ tempeax = SiS_VGAVDE;
+ tempeax = tempeax << 18; /*301b */
+ tempeax = tempeax / tempvcfact;
+ tempbx = (USHORT) (tempeax & 0x0FFFF);
+ if (SiS_LCDResInfo == Panel1024x768)
+ tempbx--;
+ if (SiS_SetFlag & EnableLVDSDDA) {
+ tempbx = 1;
+ }
+ temp = ((tempbx & 0xFF00) >> 8) << 3;
+ temp = temp | (USHORT) (((tempecx & 0x0000FF00) >> 8) & 0x07);
+ SiS_SetReg1 (SiS_Part1Port, 0x20, temp); /* Part1_20h */
+ temp = tempbx & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x21, temp); /* Part1_21h */
+ tempecx = tempecx >> 16; /* BPLHCFACT */
+ if (modeflag & HalfDCLK) {
+ tempecx = tempecx >> 1;
+ }
+ temp = (USHORT) ((tempecx & 0x0000FF00) >> 8);
+ SiS_SetReg1 (SiS_Part1Port, 0x22, temp); /* Part1_22h */
+ temp = (USHORT) (tempecx & 0x000000FF);
+ SiS_SetReg1 (SiS_Part1Port, 0x23, temp);
+ /*add dstn new register */
+ if (SiS_IF_DEF_DSTN) {
+ SiS_SetReg1 (SiS_Part1Port, 0x1E, 0x01);
+ SiS_SetReg1 (SiS_Part1Port, 0x25, 0x00);
+ SiS_SetReg1 (SiS_Part1Port, 0x26, 0x00);
+ SiS_SetReg1 (SiS_Part1Port, 0x27, 0x00);
+ SiS_SetReg1 (SiS_Part1Port, 0x28, 0x87);
+ SiS_SetReg1 (SiS_Part1Port, 0x29, 0x5A);
+ SiS_SetReg1 (SiS_Part1Port, 0x2A, 0x4B);
+ SiS_SetRegANDOR (SiS_Part1Port, 0x44, ~0x007, 0x03);
+ tempbx = SiS_HDE; /*Blps=lcdhdee(lcdhdes+HDE) +64 */
+ tempbx = tempbx + 64;
+ temp = tempbx & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x38, temp);
+ temp = ((tempbx & 0xFF00) >> 8) << 3;
+ SiS_SetRegANDOR (SiS_Part1Port, 0x35, ~0x078, temp);
+ tempbx = tempbx + 32; /*Blpe=lBlps+32 */
+ temp = tempbx & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x39, temp);
+ SiS_SetReg1 (SiS_Part1Port, 0x3A, 0x00); /*Bflml=0 */
+ SiS_SetRegANDOR (SiS_Part1Port, 0x3C, ~0x007, 0x00);
+ tempbx = SiS_VDE;
+ tempbx = tempbx / 2;
+ temp = tempbx & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x3B, temp);
+ temp = ((tempbx & 0xFF00) >> 8) << 3;
+ SiS_SetRegANDOR (SiS_Part1Port, 0x3C, ~0x038, temp);
+ tempeax = SiS_HDE; /* BDxFIFOSTOP= (HDE*4)/128 */
+ tempeax = tempeax * 4;
+ tempebx = 128;
+ temp = (USHORT) (tempeax % tempebx);
+ tempeax = tempeax / tempebx;
+ if (temp != 0) {
+ tempeax++;
+ }
+ temp = (USHORT) (tempeax & 0x0000003F);
+ SiS_SetRegANDOR (SiS_Part1Port, 0x45, ~0x0FF, temp);
+ SiS_SetReg1 (SiS_Part1Port, 0x3F, 0x00); /*BDxWadrst0 */
+ SiS_SetReg1 (SiS_Part1Port, 0x3E, 0x00);
+ SiS_SetReg1 (SiS_Part1Port, 0x3D, 0x10);
+ SiS_SetRegANDOR (SiS_Part1Port, 0x3C, ~0x040, 0x00);
+ tempax = SiS_HDE;
+ tempax = tempax >> 4; /*BDxWadroff = HDE*4/8/8 */
+ pushcx = tempax;
+ temp = tempax & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x43, temp);
+ temp = ((tempax & 0xFF00) >> 8) << 3;
+ SiS_SetRegANDOR (SiS_Part1Port, 0x44, ~0x0F8, temp);
+ tempax = SiS_VDE; /*BDxWadrst1 = BDxWadrst0+BDxWadroff*VDE */
+ tempeax = (tempax * pushcx);
+ tempebx = 0x00100000 + tempeax;
+ temp = (USHORT) tempebx & 0x000000FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x42, temp);
+ temp = (USHORT) ((tempebx & 0x0000FF00) >> 8);
+ SiS_SetReg1 (SiS_Part1Port, 0x41, temp);
+ temp = (USHORT) ((tempebx & 0x00FF0000) >> 16);
+ SiS_SetReg1 (SiS_Part1Port, 0x40, temp);
+ temp = (USHORT) ((tempebx & 0x01000000) >> 24);
+ temp = temp << 7;
+ SiS_SetRegANDOR (SiS_Part1Port, 0x3C, ~0x080, temp);
+ SiS_SetReg1 (SiS_Part1Port, 0x2F, 0x03);
+ SiS_SetReg1 (SiS_Part1Port, 0x03, 0x50);
+ SiS_SetReg1 (SiS_Part1Port, 0x04, 0x00);
+ SiS_SetReg1 (SiS_Part1Port, 0x2F, 0x01);
+ SiS_SetReg1 (SiS_Part1Port, 0x13, 0x00);


+ SiS_SetReg1 (SiS_P3c4, 0x05, 0x86);

+ SiS_SetReg1 (SiS_P3c4, 0x1e, 0x62);
+ SiS_SetReg1 (SiS_Part1Port, 0x19, 0x38);
+ SiS_SetReg1 (SiS_Part1Port, 0x1e, 0x7d);
+ }
+ /*end add dstn */


+
+ return;
+}
+

+/*301b*/
+void
+SiS_SetGroup1_LCDA (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT RefreshRateTableIndex)
+{
+ USHORT modeflag, resinfo;
+ USHORT push1, push2, tempax, tempbx, tempcx, temp;
+ ULONG tempeax = 0, tempebx, tempecx, tempvcfact; /*301b */
+ SiS_SetRegOR (SiS_Part1Port, 0x2D, 0x20);
+
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+ resinfo = SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+ resinfo = SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ }
+
+ tempax = SiS_LCDHDES;
+ tempbx = SiS_HDE;
+ tempcx = SiS_HT;
+
+ if (SiS_LCDInfo & LCDNonExpanding) {
+ if (SiS_LCDResInfo == Panel1280x1024)
+ tempbx = 1280;
+ if (SiS_LCDResInfo == Panel1024x768)
+ tempbx = 1024;
+ }
+ tempcx = tempcx - tempbx; /* HT-HDE */
+ push1 = tempax;
+ tempax = tempax + tempbx; /* lcdhdee */
+ tempbx = SiS_HT;
+ if (tempax >= tempbx) {
+ tempax = tempax - tempbx;
+ }
+ push2 = tempax;
+ /* push ax lcdhdee */
+ tempcx = tempcx >> 2; /* temp */
+ tempcx = tempcx + tempax; /* lcdhrs */
+ if (tempcx >= tempbx) {
+ tempcx = tempcx - tempbx;
+ }
+ /* v ah,cl */
+ tempax = tempcx;
+ tempax = tempax >> 3; /* BPLHRS */
+ temp = tempax & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x14, temp); /* Part1_14h */
+ temp = (tempax & 0x00FF) + 10;
+ temp = temp & 0x01F;
+ temp = temp | (((tempcx & 0x00ff) & 0x07) << 5);
+ SiS_SetReg1 (SiS_Part1Port, 0x15, temp); /* Part1_15h */
+ tempbx = push2; /* lcdhdee */
+ tempcx = push1; /* lcdhdes */
+ temp = (tempcx & 0x00FF);
+ temp = temp & 0x07; /* BPLHDESKEW */
+ SiS_SetReg1 (SiS_Part1Port, 0x1A, temp); /* Part1_1Ah */
+ tempcx = tempcx >> 3; /* BPLHDES */
+ temp = (tempcx & 0x00FF);
+ SiS_SetReg1 (SiS_Part1Port, 0x16, temp); /* Part1_16h */
+ if (tempbx & 0x07)
+ tempbx = tempbx + 8;
+ tempbx = tempbx >> 3; /* BPLHDEE */
+ temp = tempbx & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x17, temp); /* Part1_17h */
+
+ tempcx = SiS_VGAVT;
+ tempbx = SiS_VGAVDE;
+ tempcx = tempcx - tempbx; /* GAVT-VGAVDE */
+ tempbx = SiS_LCDVDES; /* VGAVDES */
+ push1 = tempbx; /* push bx temppush1 */
+ if (SiS_IF_DEF_TRUMPION == 0) {
+ if (SiS_IF_DEF_CH7005 == 1) {
+ if (SiS_VBInfo & SetCRT2ToTV) {
+ tempax = SiS_VGAVDE;
+ }
+ }
+
+ if (SiS_LCDResInfo == Panel1024x768)
+ tempax = 768;
+ if (SiS_LCDResInfo == Panel1280x1024)
+ tempax = 1024;
+
+ } else
+ tempax = SiS_VGAVDE;
+ tempbx = tempbx + tempax;
+ tempax = SiS_VT; /* VT */
+ if (tempbx >= SiS_VT) {
+ tempbx = tempbx - tempax;
+ }
+ push2 = tempbx; /* push bx temppush2 */
+ tempcx = tempcx >> 1;
+ tempbx = tempbx + tempcx;
+ tempbx++; /* BPLVRS */
+ if (tempbx >= tempax) {
+ tempbx = tempbx - tempax;
+ }
+ temp = tempbx & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x18, temp); /* Part1_18h */
+ tempcx = tempcx >> 3;
+ tempcx = tempcx + tempbx;
+ tempcx++; /* BPLVRE */
+ temp = tempcx & 0x00FF;
+ temp = temp & 0x0F;
+ SiS_SetRegANDOR (SiS_Part1Port, 0x19, ~0x00F, temp); /* Part1_19h */
+ temp = (tempbx & 0xFF00) >> 8;
+ temp = temp & 0x07;
+ temp = temp << 3; /* BPLDESKEW =0 */
+ tempbx = SiS_VGAVDE;
+ if (tempbx != SiS_VDE) {
+ temp = temp | 0x40;
+ }
+ if (SiS_SetFlag & EnableLVDSDDA) {
+ temp = temp | 0x40;
+ }
+ if (SiS_LCDInfo & LCDRGB18Bit) {
+ temp = temp | 0x80;
+ }
+ SiS_SetRegANDOR (SiS_Part1Port, 0x1A, 0x07, temp); /* Part1_1Ah */
+
+ tempbx = push2; /* p bx temppush2 BPLVDEE */
+ tempcx = push1; /* pop cx temppush1 NPLVDES */
+ push1 = (USHORT) (tempeax & 0xFFFF);
+
+ if (!(SiS_VBInfo & SetInSlaveMode)) {
+ if (SiS_LCDResInfo == Panel800x600) {
+ if (resinfo == 7)
+ tempcx++;
+ } else {
+ if (SiS_LCDResInfo == Panel1024x768) {
+ if (resinfo == 8)
+ tempcx++;
+ }
+ }
+ }
+
+ temp = (tempbx & 0xFF00) >> 8;
+ temp = temp & 0x07;
+ temp = temp << 3;
+ temp = temp | (((tempcx & 0xFF00) >> 8) & 0x07);
+ SiS_SetReg1 (SiS_Part1Port, 0x1D, temp); /* Part1_1Dh */
+ temp = tempbx & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x1C, temp); /* Part1_1Ch */
+ temp = tempcx & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x1B, temp); /* Part1_1Bh */
+
+ tempecx = SiS_VGAVT;
+ tempebx = SiS_VDE;
+ tempeax = SiS_VGAVDE;
+ tempecx = tempecx - tempeax; /* VGAVT-VGAVDE */
+ tempeax = tempeax << 18;
+ temp = (USHORT) (tempeax % tempebx);
+ tempeax = tempeax / tempebx;
+ if (temp != 0) {
+ tempeax++;
+ }
+ tempebx = tempeax; /* BPLVCFACT */
+ tempvcfact = tempeax; /*301b */
+ temp = (USHORT) (tempebx & 0x00FF);
+ SiS_SetReg1 (SiS_Part1Port, 0x37, temp);
+ temp = (USHORT) ((tempebx & 0x00FF00) >> 8);
+ SiS_SetReg1 (SiS_Part1Port, 0x36, temp);
+ temp = (USHORT) ((tempebx & 0x00030000) >> 16);
+ if (SiS_VDE == SiS_VGAVDE) {
+ temp = temp | 0x04;
+ }
+
+ SiS_SetReg1 (SiS_Part1Port, 0x35, temp);
+
+ tempecx = SiS_VGAHDE;
+ tempebx = SiS_HDE;
+ tempeax = tempecx;
+ tempeax = tempeax << 6;
+ tempeax = tempeax << 10;
+ tempeax = tempeax / tempebx;
+ if (tempebx == tempecx) {
+ tempeax = 65535;
+ }
+ tempecx = tempeax;
+ tempeax = SiS_VGAHDE; /*301b to change HT->HDE */
+ tempeax = tempeax << 6;
+ tempeax = tempeax << 10;
+ tempeax = tempeax / tempecx;
+ tempecx = tempecx << 16;
+ tempeax = tempeax - 1;
+ tempecx = tempecx | (tempeax & 0x00FFFF);
+ temp = (USHORT) (tempecx & 0x00FF);
+ SiS_SetReg1 (SiS_Part1Port, 0x1F, temp); /* Part1_1Fh */
+
+ tempeax = SiS_VGAVDE;
+ tempeax = tempeax << 18; /*301b */
+ tempeax = tempeax / tempvcfact;
+ tempbx = (USHORT) (tempeax & 0x0FFFF);
+ if (SiS_LCDResInfo == Panel1024x768)
+ tempbx--;
+ if (SiS_SetFlag & EnableLVDSDDA) {
+ tempbx = 1;
+ }
+ temp = ((tempbx & 0xFF00) >> 8) << 3;
+ temp = temp | (USHORT) (((tempecx & 0x0000FF00) >> 8) & 0x07);
+ SiS_SetReg1 (SiS_Part1Port, 0x20, temp); /* Part1_20h */
+ temp = tempbx & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x21, temp); /* Part1_21h */
+ tempecx = tempecx >> 16; /* BPLHCFACT */
+
+ temp = (USHORT) ((tempecx & 0x0000FF00) >> 8);
+ SiS_SetReg1 (SiS_Part1Port, 0x22, temp); /* Part1_22h */
+ temp = (USHORT) (tempecx & 0x000000FF);
+ SiS_SetReg1 (SiS_Part1Port, 0x23, temp);
+ return;
+}
+
+/*end 301b*/
+void
+SiS_SetTPData ()


+{
+ return;
+}
+

+void
+SiS_SetCRT2Offset (USHORT SiS_Part1Port, ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex, USHORT RefreshRateTableIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+ USHORT offset;
+ UCHAR temp;
+
+ if (SiS_VBInfo & SetInSlaveMode) {
+ return;
+ }
+ offset =
+ SiS_GetOffset (ROMAddr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
+ HwDeviceExtension);
+ temp = (UCHAR) (offset & 0xFF);
+ SiS_SetReg1 (SiS_Part1Port, 0x07, temp);
+ temp = (UCHAR) ((offset & 0xFF00) >> 8);
+ SiS_SetReg1 (SiS_Part1Port, 0x09, temp);
+ temp = (UCHAR) (((offset >> 3) & 0xFF) + 1);
+ SiS_SetReg1 (SiS_Part1Port, 0x03, temp);
+}
+
+USHORT
+SiS_GetOffset (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+ USHORT temp, colordepth;
+ USHORT modeinfo, index, infoflag;
+ USHORT ColorDepth[] = { 0x01, 0x02, 0x04 };
+
+ modeinfo = SiS_EModeIDTable[ModeIdIndex].Ext_ModeInfo;
+ infoflag = SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+ if (HwDeviceExtension->jChipType < SIS_315H) { /* 300 series */
+ index = (modeinfo >> 4) & 0xFF;
+ } else { /* 310 series */
+
+ index = (modeinfo >> 8) & 0xFF;
+ }
+ temp = SiS_ScreenOffset[index];
+ if (infoflag & InterlaceMode) {
+ temp = temp << 1;
+ }
+ colordepth = SiS_GetColorDepth (ROMAddr, ModeNo, ModeIdIndex);
+
+ if ((ModeNo >= 0x7C) && (ModeNo <= 0x7E)) {
+ temp = ModeNo - 0x7C;
+ colordepth = ColorDepth[temp];
+ temp = 0x6B;
+ if (infoflag & InterlaceMode) {
+ temp = temp << 1;
+ }
+ return (temp * colordepth);
+ } else
+ return (temp * colordepth);
+}
+
+USHORT
+SiS_GetColorDepth (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex)
+{
+ USHORT ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
+ SHORT index;
+ USHORT modeflag;
+
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+ index = (modeflag & ModeInfoFlag) - ModeEGA;
+ if (index < 0)
+ index = 0;
+ return (ColorDepth[index]);
+}
+
+void
+SiS_SetCRT2Sync (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT RefreshRateTableIndex)
+{
+ USHORT tempah = 0, infoflag, flag;
+
+ flag = 0;
+ infoflag = SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+ if (SiS_IF_DEF_LVDS == 1) {
+ if (SiS_VBInfo & SetCRT2ToLCD) {
+ tempah = SiS_LCDInfo;
+ if (tempah & LCDSync) {
+ flag = 1;
+ }
+ }
+ }
+ if (flag != 1)
+ tempah = infoflag >> 8;
+ tempah = tempah & 0xC0;
+ tempah = tempah | 0x20;
+ if (!(SiS_LCDInfo & LCDRGB18Bit))
+ tempah = tempah | 0x10;
+ if (SiS_IF_DEF_CH7005 == 1)
+ tempah = tempah | 0xC0;
+
+ SiS_SetRegANDOR (SiS_Part1Port, 0x19, 0x3F, tempah);
+}
+
+void
+SiS_SetCRT2FIFO (USHORT SiS_Part1Port, ULONG ROMAddr, USHORT ModeNo,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+ USHORT temp, index;
+ USHORT modeidindex, refreshratetableindex;
+ USHORT VCLK, MCLK, colorth = 0, data, data2;
+ ULONG eax;
+ UCHAR LatencyFactor[] = { 97, 88, 86, 79, 77, 00, /*; 64 bit BQ=2 */
+ 00, 87, 85, 78, 76, 54, /*; 64 bit BQ=1 */
+ 97, 88, 86, 79, 77, 00, /*; 128 bit BQ=2 */
+ 00, 79, 77, 70, 68, 48, /*; 128 bit BQ=1 */
+ 80, 72, 69, 63, 61, 00, /*; 64 bit BQ=2 */
+ 00, 70, 68, 61, 59, 37, /*; 64 bit BQ=1 */
+ 86, 77, 75, 68, 66, 00, /*; 128 bit BQ=2 */
+ 00, 68, 66, 59, 57, 37
+ }; /*; 128 bit BQ=1 */
+
+ SiS_SearchModeID (ROMAddr, ModeNo, &modeidindex);
+ SiS_SetFlag = SiS_SetFlag & (~ProgrammingCRT2);
+ SiS_SelectCRT2Rate = 0;
+ refreshratetableindex = SiS_GetRatePtrCRT2 (ROMAddr, ModeNo, modeidindex); /* 11.GetRatePtr */
+ if (ModeNo >= 0x13) {
+ index = SiS_RefIndex[refreshratetableindex].Ext_CRTVCLK;
+ index = index & 0x3F;
+ VCLK = SiS_VCLKData[index].CLOCK; /* Get VCLK */
+ index = SiS_GetReg1 (SiS_P3c4, 0x1A);
+ index = index & 07;
+ MCLK = SiS_MCLKData[index].CLOCK; /* Get MCLK */
+ data2 = SiS_ModeType - 0x02;
+ switch (data2) {
+ case 0:
+ colorth = 1;


+ break;
+ case 1:

+ colorth = 1;
+ break;
+ case 2:
+ colorth = 2;
+ break;
+ case 3:
+ colorth = 2;


+ break;
+ case 4:

+ colorth = 3;


+ break;
+ case 5:

+ colorth = 4;
+ break;
+ }
+ data2 = (data2 * VCLK) / MCLK; /* bx */
+
+ temp = SiS_GetReg1 (SiS_P3c4, 0x14);
+ temp = ((temp & 0x00FF) >> 6) << 1;
+ if (temp == 0)
+ temp = 1;
+ temp = temp << 2;
+
+ data2 = temp - data2;
+ if (data2 % (28 * 16)) {
+ data2 = data2 / (28 * 16);
+ data2++;
+ } else {
+ data2 = data2 / (28 * 16);


+ }
+
+ index = 0;

+ temp = SiS_GetReg1 (SiS_P3c4, 0x14);
+ if (temp & 0x0080)
+ index = index + 12;
+ SiS_SetReg4 (0xcf8, 0x800000A0);
+ eax = SiS_GetReg3 (0xcfc);
+ temp = (USHORT) (eax >> 24);
+ if (!(temp & 0x01))
+ index = index + 24;
+
+ SiS_SetReg4 (0xcf8, 0x80000050);
+ eax = SiS_GetReg3 (0xcfc);
+ temp = (USHORT) (eax >> 24);
+ if (temp & 0x01)
+ index = index + 6;
+ temp = (temp & 0x0F) >> 1;
+ index = index + temp;
+ data = LatencyFactor[index];
+ data = data + 15;
+ temp = SiS_GetReg1 (SiS_P3c4, 0x14);
+ if (!(temp & 0x80))
+ data = data + 5;
+ data = data + data2;
+
+ SiS_SetFlag = SiS_SetFlag | ProgrammingCRT2;
+ data = data * VCLK * colorth;
+ if (data % (MCLK << 4)) {
+ data = data / (MCLK << 4);
+ data++;
+ } else {
+ data = data / (MCLK << 4);
+ }
+ temp = 0x16;
+/* Revision ID */
+ temp = 0x13;
+/* Revision ID */
+ SiS_SetRegANDOR (SiS_Part1Port, 0x01, ~0x01F, temp);
+ SiS_SetRegANDOR (SiS_Part1Port, 0x02, ~0x01F, temp);
+ }
+}
+
+void
+SiS_SetCRT2FIFO2 (USHORT SiS_Part1Port, ULONG ROMAddr, USHORT ModeNo,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+#ifdef CONFIG_FB_SIS_315
+ UCHAR CombCode[] = { 1, 1, 1, 4, 3, 1, 3, 4, 4, 1, 4, 4, 5, 1, 5, 4 };
+ UCHAR CRT2ThLow[] =
+ { 39, 63, 55, 79, 78, 102, 90, 114, 55, 87, 84, 116, 103, 135, 119,
+ 151 };
+#endif
+ USHORT temp, temp1, temp2, temp3;
+ USHORT index;
+ USHORT CRT1ModeNo, CRT2ModeNo;
+ USHORT ModeIdIndex;
+ USHORT RefreshRateTableIndex;
+
+ SiS_SetReg1 (SiS_Part1Port, 0x1, 0x3B);
+/* CRT1ModeNo=(UCHAR)SiS_GetReg1(SiS_P3d4,0x34); *//* get CRT1 ModeNo */
+ CRT1ModeNo = SiS_CRT1Mode;
+ /* CRT1ModeNo =ModeNo; */
+ SiS_SearchModeID (ROMAddr, CRT1ModeNo, &ModeIdIndex); /* Get ModeID Table */
+ SiS_SetFlag = SiS_SetFlag & (~ProgrammingCRT2);
+
+ RefreshRateTableIndex = SiS_GetRatePtrCRT2 (ROMAddr, CRT1ModeNo, ModeIdIndex); /* Set REFIndex-> for crt1 refreshrate */
+ index =
+ SiS_GetVCLK2Ptr (ROMAddr, CRT1ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, HwDeviceExtension);
+ temp1 = SiS_VCLKData[index].CLOCK; /* Get VCLK */
+
+ temp2 = SiS_GetColorDepth (ROMAddr, CRT1ModeNo, ModeIdIndex);
+#ifdef CONFIG_FB_SIS_315
+ index = SiS_Get310DRAMType (ROMAddr);
+#endif
+ temp3 = SiS_MCLKData[index].CLOCK; /* Get MCLK */
+
+ temp = SiS_GetReg1 (SiS_P3c4, 0x14);
+ if (temp & 0x02)
+ temp = 16;
+ else
+ temp = 8;
+
+ temp = temp - temp1 * temp2 / temp3; /* 16-DRamBus - DCLK*BytePerPixel/MCLK */
+
+ if ((52 * 16 % temp) == 0)
+ temp = 52 * 16 / temp + 40;
+ else
+ temp = 52 * 16 / temp + 40 + 1;
+
+ /* get DRAM latency */
+ temp1 = (SiS_GetReg1 (SiS_P3c4, 0x17) >> 3) & 0x7; /* SR17[5:3] DRAM Queue depth */
+ temp2 = (SiS_GetReg1 (SiS_P3c4, 0x17) >> 6) & 0x3; /* SR17[7:6] DRAM Grant length */
+
+#ifdef CONFIG_FB_SIS_315
+ if (SiS_Get310DRAMType (ROMAddr) < 2) {
+ for (temp3 = 0; temp3 < 16; temp3 += 2) {
+ if ((CombCode[temp3] == temp1)
+ && (CombCode[temp3 + 1] == temp2)) {
+ temp3 = CRT2ThLow[temp3 >> 1];
+ }
+ }
+ } else {
+ for (temp3 = 0; temp3 < 16; temp3 += 2) {
+ if ((CombCode[temp3] == temp1)
+ && (CombCode[temp3 + 1] == temp2)) {
+ temp3 = CRT2ThLow[8 + (temp3 >> 1)];


+ }
+ }
+ }
+#endif
+

+ temp += temp3; /* CRT1 Request Period */
+
+ CRT2ModeNo = ModeNo; /* get CRT2 ModeNo */
+ SiS_SearchModeID (ROMAddr, CRT2ModeNo, &ModeIdIndex); /* Get ModeID Table */
+ SiS_SetFlag = SiS_SetFlag | ProgrammingCRT2;
+ RefreshRateTableIndex = SiS_GetRatePtrCRT2 (ROMAddr, CRT1ModeNo, ModeIdIndex); /* Set REFIndex-> for crt1 refreshrate */
+ index =
+ SiS_GetVCLK2Ptr (ROMAddr, CRT2ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, HwDeviceExtension);
+ temp1 = SiS_VCLKData[index].CLOCK; /* Get VCLK */
+
+ temp2 = SiS_GetColorDepth (ROMAddr, CRT2ModeNo, ModeIdIndex);
+#ifdef CONFIG_FB_SIS_315
+ index = SiS_Get310DRAMType (ROMAddr);
+#endif
+ temp3 = SiS_MCLKData[index].CLOCK; /* Get MCLK */
+
+ if ((temp * temp1 * temp2) % (16 * temp3) == 0)
+ temp = temp * temp1 * temp2 / (16 * temp3); /* CRT1 Request period * TCLK*BytePerPixel/(MCLK*16) */
+ else
+ temp = temp * temp1 * temp2 / (16 * temp3) + 1; /* CRT1 Request period * TCLK*BytePerPixel/(MCLK*16) */
+
+ if (temp > 0x37)
+ temp = 0x37;
+
+ SiS_SetRegANDOR (SiS_Part1Port, 0x02, ~0x3F, temp);
+
+}
+
+void
+SiS_GetLVDSDesData (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex)
+{
+
+ USHORT modeflag;
+ USHORT PanelIndex, ResIndex;
+ SiS_LVDSDesStruct *PanelDesPtr = NULL;
+ if ((SiS_IF_DEF_LVDS == 0)
+ && ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))) { /*301b *//*for test */
+ SiS_GetLVDSDesPtrA (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, &PanelIndex,
+ &ResIndex);
+ switch (PanelIndex) {
+ case 0:
+ PanelDesPtr = LVDS1024x768Des_1;


+ break;
+ case 1:

+ PanelDesPtr = LVDS1280x1024Des_1;
+ break;
+ case 2:
+ PanelDesPtr = LVDS1280x960Des_1;
+ break;
+ case 3:
+ PanelDesPtr = LVDS1024x768Des_2;


+ break;
+ case 4:

+ PanelDesPtr = LVDS1280x1024Des_2;


+ break;
+ case 5:

+ PanelDesPtr = LVDS1280x960Des_2;


+ break;
+ }
+ } else {

+ SiS_GetLVDSDesPtr (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, &PanelIndex,
+ &ResIndex);
+ switch (PanelIndex) {
+ case 0:
+ PanelDesPtr = SiS_PanelType00_1;


+ break;
+ case 1:

+ PanelDesPtr = SiS_PanelType01_1;
+ break;
+ case 2:
+ PanelDesPtr = SiS_PanelType02_1;
+ break;
+ case 3:
+ PanelDesPtr = SiS_PanelType03_1;


+ break;
+ case 4:

+ PanelDesPtr = SiS_PanelType04_1;


+ break;
+ case 5:

+ PanelDesPtr = SiS_PanelType05_1;


+ break;
+ case 6:

+ PanelDesPtr = SiS_PanelType06_1;


+ break;
+ case 7:

+ PanelDesPtr = SiS_PanelType07_1;


+ break;
+ case 8:

+ PanelDesPtr = SiS_PanelType08_1;


+ break;
+ case 9:

+ PanelDesPtr = SiS_PanelType09_1;
+ break;
+ case 10:
+ PanelDesPtr = SiS_PanelType0a_1;
+ break;
+ case 11:
+ PanelDesPtr = SiS_PanelType0b_1;
+ break;
+ case 12:
+ PanelDesPtr = SiS_PanelType0c_1;
+ break;
+ case 13:
+ PanelDesPtr = SiS_PanelType0d_1;
+ break;
+ case 14:
+ PanelDesPtr = SiS_PanelType0e_1;
+ break;
+ case 15:
+ PanelDesPtr = SiS_PanelType0f_1;
+ break;
+ case 16:
+ PanelDesPtr = SiS_PanelType00_2;
+ break;
+ case 17:
+ PanelDesPtr = SiS_PanelType01_2;
+ break;
+ case 18:
+ PanelDesPtr = SiS_PanelType02_2;
+ break;
+ case 19:
+ PanelDesPtr = SiS_PanelType03_2;
+ break;
+ case 20:
+ PanelDesPtr = SiS_PanelType04_2;
+ break;
+ case 21:
+ PanelDesPtr = SiS_PanelType05_2;
+ break;
+ case 22:
+ PanelDesPtr = SiS_PanelType06_2;
+ break;
+ case 23:
+ PanelDesPtr = SiS_PanelType07_2;
+ break;
+ case 24:
+ PanelDesPtr = SiS_PanelType08_2;
+ break;
+ case 25:
+ PanelDesPtr = SiS_PanelType09_2;
+ break;
+ case 26:
+ PanelDesPtr = SiS_PanelType0a_2;
+ break;
+ case 27:
+ PanelDesPtr = SiS_PanelType0b_2;
+ break;
+ case 28:
+ PanelDesPtr = SiS_PanelType0c_2;
+ break;
+ case 29:
+ PanelDesPtr = SiS_PanelType0d_2;
+ break;
+ case 30:
+ PanelDesPtr = SiS_PanelType0e_2;
+ break;
+ case 31:
+ PanelDesPtr = SiS_PanelType0f_2;
+ break;
+ case 32:
+ PanelDesPtr = SiS_CHTVUNTSCDesData;
+ break;
+ case 33:
+ PanelDesPtr = SiS_CHTVONTSCDesData;
+ break;
+ case 34:
+ PanelDesPtr = SiS_CHTVUPALDesData;
+ break;
+ case 35:
+ PanelDesPtr = SiS_CHTVOPALDesData;
+ break;
+ }
+ }
+ SiS_LCDHDES = (PanelDesPtr + ResIndex)->LCDHDES;
+ SiS_LCDVDES = (PanelDesPtr + ResIndex)->LCDVDES;
+ if (SiS_LCDInfo & LCDNonExpanding) {
+ if (SiS_LCDResInfo >= Panel1024x768) {
+ if (ModeNo <= 0x13) {
+ modeflag =
+ SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ if (!(modeflag & HalfDCLK)) {
+ SiS_LCDHDES = 320;
+ }
+ }
+ }
+ }
+ return;
+
+}
+
+void
+SiS_GetLVDSDesPtr (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex, USHORT * PanelIndex,
+ USHORT * ResIndex)
+{
+ USHORT tempbx, tempal;
+
+ tempbx = 0;
+ if (SiS_IF_DEF_CH7005 == 1) {
+ if (!(SiS_VBInfo & SetCRT2ToLCD)) {
+ tempbx = 32;
+ if (SiS_VBInfo & SetPALTV)
+ tempbx = tempbx + 2;
+ if (SiS_VBInfo & SetCHTVOverScan)
+ tempbx = tempbx + 1;
+ }
+ }
+ if (SiS_VBInfo & SetCRT2ToLCD) {
+ tempbx = SiS_LCDTypeInfo;
+ if (SiS_LCDInfo & LCDNonExpanding) {
+ tempbx = tempbx + 16;
+ }
+ }
+ if (ModeNo <= 0x13) {
+ tempal = SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {
+ tempal = SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ }
+ tempal = tempal & 0x1F;
+ *PanelIndex = tempbx;
+ *ResIndex = tempal;
+}
+
+/*301b*/
+void
+SiS_GetLVDSDesPtrA (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex, USHORT * PanelIndex,
+ USHORT * ResIndex)
+{
+ USHORT tempbx, tempal;
+
+ tempbx = 0;
+ tempbx = SiS_LCDResInfo;
+ tempbx = tempbx - Panel1024x768;
+ if (SiS_LCDInfo & LCDNonExpanding) {
+ tempbx = tempbx + 3;
+ }
+
+ if (ModeNo <= 0x13) {
+ tempal = SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {
+ tempal = SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ }
+ tempal = tempal & 0x1F;
+ *PanelIndex = tempbx;
+ *ResIndex = tempal;
+}
+
+/*end 301b*/
+
+void
+SiS_SetCRT2ModeRegs (USHORT BaseAddr, USHORT ModeNo,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+ USHORT i, j;
+ USHORT tempcl, tempah;
+/*301b*/
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))
+ && (SiS_VBInfo & SetCRT2ToLCDA)) {
+ SiS_SetRegANDOR (SiS_Part1Port, 0x00, ~0x050, 0x40);
+ SiS_SetRegAND (SiS_Part1Port, 0x2E, 0xF7);
+ SiS_SetRegANDOR (SiS_Part1Port, 0x13, 0xFB, 0x04);
+ SiS_SetRegANDOR (SiS_Part1Port, 0x2c, 0xCF, 0x30);
+ SiS_SetRegANDOR (SiS_Part4Port, 0x21, 0x3F, 0xC0);
+ SiS_SetRegANDOR (SiS_Part4Port, 0x23, 0x7F, 0x00);
+ }
+ /*end 301b */
+ else {
+ for (i = 0, j = 4; i < 3; i++, j++)
+ SiS_SetReg1 (SiS_Part1Port, j, 0);
+
+ tempcl = SiS_ModeType;
+ if (HwDeviceExtension->jChipType < SIS_315H) { /* 300 series */
+ if (ModeNo > 0x13) {
+ tempcl = tempcl - ModeVGA;
+ if ((tempcl > 0) || (tempcl == 0)) {
+ tempah = ((0x010 >> tempcl) | 0x080);
+ }
+ } else {
+ tempah = 0x080;
+ }
+ if (SiS_VBInfo & SetInSlaveMode) {
+ tempah = (tempah ^ 0x0A0);
+ }
+ } else { /* 310 series */
+
+ if (ModeNo > 0x13) {
+ tempcl = tempcl - ModeVGA;
+ if ((tempcl > 0) || (tempcl == 0)) {
+ tempah = (0x008 >> tempcl);
+ if (tempah == 0)
+ tempah = 1;
+ tempah |= 0x040;
+ }
+ } else {
+ tempah = 0x040;
+ }
+
+ if (SiS_VBInfo & SetInSlaveMode) {
+ tempah = (tempah ^ 0x050);
+ }
+
+ }
+
+ if (SiS_VBInfo & CRT2DisplayFlag) {
+ tempah = 0;
+ }
+ SiS_SetReg1 (SiS_Part1Port, 0x00, tempah);
+
+ if (SiS_IF_DEF_LVDS == 0) { /* ifdef 301 */
+ tempah = 0x01;
+ if (!(SiS_VBInfo & SetInSlaveMode)) {
+ tempah = (tempah | 0x02);
+ }
+ if (!(SiS_VBInfo & SetCRT2ToRAMDAC)) {
+ tempah = (tempah ^ 0x05);
+ if (!(SiS_VBInfo & SetCRT2ToLCD)) {
+ tempah = (tempah ^ 0x01);
+ }
+ }
+
+ tempcl = tempah; /* 05/03/01 ynlai for TV display bug */
+
+ if (HwDeviceExtension->jChipType < SIS_315H) { /* 300 series */
+ tempah = (tempah << 5) & 0xFF;
+ if (SiS_VBInfo & CRT2DisplayFlag) {
+ tempah = 0;
+ }
+ SiS_SetReg1 (SiS_Part1Port, 0x01, tempah);
+
+ tempah = tempah >> 5;
+ } else { /* 310 series */
+
+ if (SiS_VBInfo & CRT2DisplayFlag) {
+ tempah = 0;
+ }
+ tempah =
+ (SiS_GetReg1 (SiS_Part1Port, 0x2E) & 0xF8) |
+ tempah;
+ SiS_SetReg1 (SiS_Part1Port, 0x2E, tempah);
+ tempah = tempcl;
+ }
+
+ if ((SiS_ModeType == ModeVGA)
+ && (!(SiS_VBInfo & SetInSlaveMode))) {
+ tempah = tempah | 0x010;
+ }
+
+ if (SiS_LCDResInfo == Panel1024x768)
+ tempah = tempah | 0x080;
+
+ if ((SiS_LCDResInfo == Panel1280x1024)
+ || (SiS_LCDResInfo == Panel1280x960)) {
+ tempah = tempah | 0x080;
+ }
+ if (SiS_VBInfo & SetCRT2ToTV) {
+ if (SiS_VBInfo & SetInSlaveMode) {
+ if (
+ ((SiS_VBType & VB_SIS301B)
+ || (SiS_VBType & VB_SIS302B))) { /*301b */
+ if (SiS_SetFlag & TVSimuMode)
+ tempah = tempah | 0x020;
+ } else
+ tempah = tempah | 0x020;
+ }
+ }
+ SiS_SetRegANDOR (SiS_Part4Port, 0x0D, ~0x0BF, tempah);
+ tempah = 0;
+ if (SiS_VBInfo & SetCRT2ToTV) {
+ if (SiS_VBInfo & SetInSlaveMode) {
+ if (
+ ((SiS_VBType & VB_SIS301B)
+ || (SiS_VBType & VB_SIS302B))) { /*301b */
+ {
+ SiS_SetFlag =
+ SiS_SetFlag |
+ RPLLDIV2XO;
+ tempah = tempah | 0x40;
+ }
+ } else {
+ if (!(SiS_SetFlag & TVSimuMode)) {
+ if (!
+ (SiS_VBInfo &
+ SetCRT2ToHiVisionTV))
+ {
+ SiS_SetFlag =
+ SiS_SetFlag
+ |
+ RPLLDIV2XO;
+ tempah =
+ tempah |
+ 0x40;
+ }
+ }
+ }
+ } else {
+ SiS_SetFlag = SiS_SetFlag | RPLLDIV2XO;
+ tempah = tempah | 0x40;
+ }
+ }
+ if (SiS_LCDResInfo == Panel1280x1024)
+ tempah = tempah | 0x80;
+ if (SiS_LCDResInfo == Panel1280x960)
+ tempah = tempah | 0x80;
+ SiS_SetReg1 (SiS_Part4Port, 0x0C, tempah);
+ } else {
+ /*LVDS*/ tempah = 0;
+ if (!(SiS_VBInfo & SetInSlaveMode)) {
+ tempah = tempah | 0x02;
+ }
+ SiS_SetRegANDOR (SiS_Part1Port, 0x2e, 0xF0, tempah);
+ }
+ }
+/*301b*/
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))
+ && (!(SiS_VBInfo & SetCRT2ToLCDA))) {
+ if (SiS_IsDualEdge (BaseAddr))
+ SiS_SetRegANDOR (SiS_Part1Port, 0x13, 0xFB, 0x00);
+ else
+ SiS_SetRegANDOR (SiS_Part1Port, 0x13, 0xFF, 0x00);
+ if (SiS_IsDualEdge (BaseAddr))
+ SiS_SetRegANDOR (SiS_Part1Port, 0x2c, 0xCF, 0x00);
+ else
+ SiS_SetRegANDOR (SiS_Part1Port, 0x2c, 0xFF, 0x00);
+ if (SiS_IsDualEdge (BaseAddr))
+ SiS_SetRegANDOR (SiS_Part4Port, 0x21, 0x3F, 0x00);
+ else
+ SiS_SetRegANDOR (SiS_Part4Port, 0x21, 0xFF, 0x00);
+
+ if (SiS_IsDualEdge (BaseAddr))
+ SiS_SetRegANDOR (SiS_Part4Port, 0x23, 0xFF, 0x80);
+ else
+ SiS_SetRegANDOR (SiS_Part4Port, 0x23, 0xFF, 0x00);
+ }
+
+/*end 301b*/
+}
+void
+SiS_GetCRT2Data (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex)
+{
+ if (SiS_IF_DEF_LVDS == 0) { /*301 */
+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B)) {
+ if (SiS_VBInfo & SetCRT2ToLCDA)
+ SiS_GetCRT2DataLVDS (ROMAddr, ModeNo,
+ ModeIdIndex,
+ RefreshRateTableIndex);
+ else
+ SiS_GetCRT2Data301 (ROMAddr, ModeNo,
+ ModeIdIndex,
+ RefreshRateTableIndex);
+ } else
+ SiS_GetCRT2Data301 (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex);
+ return;
+ } else { /*LVDS */
+ SiS_GetCRT2DataLVDS (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex);


+ return;
+ }
+}
+

+void
+SiS_GetCRT2DataLVDS (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex)
+{
+ USHORT tempax, tempbx;
+ USHORT CRT2Index, ResIndex;
+ SiS_LVDSDataStruct *LVDSData = NULL;
+
+ SiS_GetCRT2ResInfo (ROMAddr, ModeNo, ModeIdIndex);
+ /*301b */
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))
+ && (SiS_VBInfo & SetCRT2ToLCDA)) {
+ SiS_GetCRT2PtrA (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, &CRT2Index, &ResIndex);
+ switch (CRT2Index) {
+ case 0:
+ LVDSData = SiS_LVDS1024x768Data_1;


+ break;
+ case 1:

+ LVDSData = SiS_LVDS1280x1024Data_1;
+ break;
+ case 2:
+ LVDSData = SiS_LVDS1280x1024Data_1;
+ break;
+ /* case 2: LVDSData=SiS_LVDS1280x960Data_1; break; */
+ case 3:
+ LVDSData = SiS_LVDS1024x768Data_2;


+ break;
+ case 4:

+ LVDSData = SiS_LVDS1280x1024Data_2;


+ break;
+ case 5:

+ LVDSData = SiS_LVDS1280x1024Data_2;
+ break;
+ /* case 5: LVDSData=SiS_LVDS1280x960Data_2; break; */
+ }
+ }
+
+ else {
+ SiS_GetCRT2Ptr (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, &CRT2Index, &ResIndex);
+ switch (CRT2Index) {
+ case 0:
+ LVDSData = SiS_LVDS800x600Data_1;


+ break;
+ case 1:

+ LVDSData = SiS_LVDS1024x768Data_1;
+ break;
+ case 2:
+ LVDSData = SiS_LVDS1280x1024Data_1;
+ break;
+ case 3:
+ LVDSData = SiS_LVDS800x600Data_2;


+ break;
+ case 4:

+ LVDSData = SiS_LVDS1024x768Data_2;


+ break;
+ case 5:

+ LVDSData = SiS_LVDS1280x1024Data_2;


+ break;
+ case 6:

+ LVDSData = SiS_LVDS640x480Data_1;


+ break;
+ case 7:

+ LVDSData = SiS_CHTVUNTSCData;


+ break;
+ case 8:

+ LVDSData = SiS_CHTVONTSCData;


+ break;
+ case 9:

+ LVDSData = SiS_CHTVUPALData;
+ break;
+ case 10:
+ LVDSData = SiS_CHTVOPALData;
+ break;
+ }
+ }
+ SiS_VGAHT = (LVDSData + ResIndex)->VGAHT;
+ SiS_VGAVT = (LVDSData + ResIndex)->VGAVT;
+ SiS_HT = (LVDSData + ResIndex)->LCDHT;
+ SiS_VT = (LVDSData + ResIndex)->LCDVT;
+/*301b*/
+ if ((SiS_IF_DEF_LVDS == 0)
+ && ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))) { /*for test */
+ if (!(SiS_LCDInfo & LCDNonExpanding)) {
+ if (SiS_LCDResInfo == Panel1024x768) {
+ tempax = 1024;
+ tempbx = 768;
+ } else {
+ tempax = 1280;
+ tempbx = 1024;
+ }
+ SiS_HDE = tempax;
+ SiS_VDE = tempbx;
+ }
+ } else {
+ if (SiS_IF_DEF_TRUMPION == 0) {
+ if (SiS_VBInfo & SetCRT2ToLCD) {
+ if (!(SiS_LCDInfo & LCDNonExpanding)) {
+ if (SiS_LCDResInfo == Panel800x600) {
+ tempax = 800;
+ tempbx = 600;
+ } else if (SiS_LCDResInfo ==
+ Panel1024x768) {
+ tempax = 1024;
+ tempbx = 768;
+ } else {
+ tempax = 1280;
+ tempbx = 1024;
+ }
+ SiS_HDE = tempax;
+ SiS_VDE = tempbx;
+ }
+ }
+ }
+ }
+ return;
+}
+
+void
+SiS_GetCRT2Data301 (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex)
+{
+ USHORT tempax, tempbx, modeflag;
+ USHORT resinfo;
+ USHORT CRT2Index, ResIndex;
+ SiS_LCDDataStruct *LCDPtr = NULL;
+ SiS_TVDataStruct *TVPtr = NULL;
+
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+ resinfo = SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+ resinfo = SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ }
+ SiS_NewFlickerMode = 0;
+ SiS_RVBHRS = 50;
+ SiS_RY1COE = 0;
+ SiS_RY2COE = 0;
+ SiS_RY3COE = 0;
+ SiS_RY4COE = 0;
+
+ SiS_GetCRT2ResInfo (ROMAddr, ModeNo, ModeIdIndex);
+ if (SiS_VBInfo & SetCRT2ToRAMDAC) {
+ SiS_GetRAMDAC2DATA (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex);
+ return;
+ }
+
+ if (SiS_VBInfo & SetCRT2ToTV) {
+ SiS_GetCRT2Ptr (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, &CRT2Index, &ResIndex);
+ switch (CRT2Index) {
+ case 2:
+ TVPtr = SiS_ExtHiTVData;
+ break;
+ case 3:
+ TVPtr = SiS_ExtPALData;


+ break;
+ case 4:

+ TVPtr = SiS_ExtNTSCData;


+ break;
+ case 7:

+ TVPtr = SiS_St1HiTVData;


+ break;
+ case 8:

+ TVPtr = SiS_StPALData;


+ break;
+ case 9:

+ TVPtr = SiS_StNTSCData;
+ break;
+ case 12:
+ TVPtr = SiS_St2HiTVData;
+ break;
+ }
+
+ SiS_RVBHCMAX = (TVPtr + ResIndex)->RVBHCMAX;
+ SiS_RVBHCFACT = (TVPtr + ResIndex)->RVBHCFACT;
+ SiS_VGAHT = (TVPtr + ResIndex)->VGAHT;
+ SiS_VGAVT = (TVPtr + ResIndex)->VGAVT;
+ SiS_HDE = (TVPtr + ResIndex)->TVHDE;
+ SiS_VDE = (TVPtr + ResIndex)->TVVDE;
+ SiS_RVBHRS = (TVPtr + ResIndex)->RVBHRS;
+ SiS_NewFlickerMode = (TVPtr + ResIndex)->FlickerMode;
+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) {
+ if (resinfo == 0x08)
+ SiS_NewFlickerMode = 0x40;
+ if (resinfo == 0x09)
+ SiS_NewFlickerMode = 0x40;
+ if (resinfo == 0x10)
+ SiS_NewFlickerMode = 0x40;
+ }
+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) {
+ if (SiS_VGAVDE == 350)
+ SiS_SetFlag = SiS_SetFlag | TVSimuMode;
+ tempax = ExtHiTVHT;
+ tempbx = ExtHiTVVT;
+ if (SiS_VBInfo & SetInSlaveMode) {
+ if (SiS_SetFlag & TVSimuMode) {
+ tempax = StHiTVHT;
+ tempbx = StHiTVVT;
+ if (!(modeflag & Charx8Dot)) {
+ tempax = StHiTextTVHT;
+ tempbx = StHiTextTVVT;
+ }
+ }
+ }
+ }
+ if (!(SiS_VBInfo & SetCRT2ToHiVisionTV)) {
+ SiS_RY1COE = (TVPtr + ResIndex)->RY1COE;
+ SiS_RY2COE = (TVPtr + ResIndex)->RY2COE;
+ if (modeflag & HalfDCLK) {
+ SiS_RY1COE = 0x00;
+ SiS_RY2COE = 0xf4;
+ }
+ SiS_RY3COE = (TVPtr + ResIndex)->RY3COE;
+ SiS_RY4COE = (TVPtr + ResIndex)->RY4COE;
+ if (modeflag & HalfDCLK) {
+ SiS_RY3COE = 0x10;
+ SiS_RY4COE = 0x38;
+ }
+ if (!(SiS_VBInfo & SetPALTV)) {
+ tempax = NTSCHT;
+ tempbx = NTSCVT;
+ } else {
+ tempax = PALHT;
+ tempbx = PALVT;
+ }
+ }
+ SiS_HT = tempax;
+ SiS_VT = tempbx;
+ return;
+ }
+
+ if (SiS_VBInfo & SetCRT2ToLCD) {
+ SiS_GetCRT2Ptr (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, &CRT2Index, &ResIndex);
+ switch (CRT2Index) {
+ case 0:
+ LCDPtr = SiS_ExtLCD1024x768Data;


+ break;
+ case 1:

+ LCDPtr = SiS_ExtLCD1280x1024Data;


+ break;
+ case 5:

+ LCDPtr = SiS_StLCD1024x768Data;


+ break;
+ case 6:

+ LCDPtr = SiS_StLCD1280x1024Data;
+ break;
+ case 10:
+ LCDPtr = SiS_St2LCD1024x768Data;
+ break;
+ case 11:
+ LCDPtr = SiS_St2LCD1280x1024Data;
+ break;
+ case 13:
+ LCDPtr = SiS_NoScaleData;
+ break;
+ case 14:
+ LCDPtr = SiS_LCD1280x960Data;
+ break;
+ }
+
+ SiS_RVBHCMAX = (LCDPtr + ResIndex)->RVBHCMAX;
+ SiS_RVBHCFACT = (LCDPtr + ResIndex)->RVBHCFACT;
+ SiS_VGAHT = (LCDPtr + ResIndex)->VGAHT;
+ SiS_VGAVT = (LCDPtr + ResIndex)->VGAVT;
+ SiS_HT = (LCDPtr + ResIndex)->LCDHT;
+ SiS_VT = (LCDPtr + ResIndex)->LCDVT;
+ tempax = 1024;
+ if (SiS_SetFlag & LCDVESATiming) {
+ if (SiS_VGAVDE == 350)
+ tempbx = 560;
+ else if (SiS_VGAVDE == 400)
+ tempbx = 640;
+ else
+ tempbx = 768;
+ } else {
+ if (SiS_VGAVDE == 357)
+ tempbx = 527;
+ else if (SiS_VGAVDE == 420)
+ tempbx = 620;
+ else if (SiS_VGAVDE == 525)
+ tempbx = 775;
+ else if (SiS_VGAVDE == 600)
+ tempbx = 775;
+ else if (SiS_VGAVDE == 350)
+ tempbx = 560;
+ else if (SiS_VGAVDE == 400)
+ tempbx = 640;
+ else
+ tempbx = 768;
+ }
+ if (SiS_LCDResInfo == Panel1280x1024) {
+ tempax = 1280;
+ if (SiS_VGAVDE == 360)
+ tempbx = 768;
+ else if (SiS_VGAVDE == 375)
+ tempbx = 800;
+ else if (SiS_VGAVDE == 405)
+ tempbx = 864;
+ else
+ tempbx = 1024;
+ }
+ if (SiS_LCDResInfo == Panel1280x960) {
+ tempax = 1280;
+ if (SiS_VGAVDE == 350)
+ tempbx = 700;
+ else if (SiS_VGAVDE == 400)
+ tempbx = 800;
+ else if (SiS_VGAVDE == 1024)
+ tempbx = 960;
+ else
+ tempbx = 960;
+ }
+ if (SiS_LCDInfo & LCDNonExpanding) {
+ tempax = SiS_VGAHDE;
+ tempbx = SiS_VGAVDE;
+ }
+ SiS_HDE = tempax;
+ SiS_VDE = tempbx;


+ return;
+ }
+}
+

+USHORT
+SiS_GetResInfo (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex)
+{
+ USHORT resindex;
+
+ if (ModeNo <= 0x13) {
+ resindex = SiS_SModeIDTable[ModeIdIndex].St_ResInfo; /* si+St_ResInfo */
+ } else {
+ resindex = SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; /* si+Ext_ResInfo */
+ }
+ return (resindex);
+}
+
+void
+SiS_GetCRT2ResInfo (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex)
+{
+ USHORT xres, yres, modeflag, resindex;
+
+ resindex = SiS_GetResInfo (ROMAddr, ModeNo, ModeIdIndex);
+ if (ModeNo <= 0x13) {
+ xres = SiS_StResInfo[resindex].HTotal;
+ yres = SiS_StResInfo[resindex].VTotal;
+ } else {
+ xres = SiS_ModeResInfo[resindex].HTotal; /* xres->ax */
+ yres = SiS_ModeResInfo[resindex].VTotal; /* yres->bx */
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+St_ModeFlag */
+ if (modeflag & HalfDCLK) {
+ xres = xres * 2;
+ }
+ if (modeflag & DoubleScanMode) {
+ yres = yres * 2;
+ }
+ }
+ if (SiS_IF_DEF_LVDS == 0) {
+ if (SiS_LCDResInfo == Panel1280x1024) {
+ if (yres == 400)
+ yres = 405;
+ if (yres == 350)
+ yres = 360;
+ if (SiS_SetFlag & LCDVESATiming) {
+ if (yres == 360)
+ yres = 375;
+ }
+ }
+ if (SiS_LCDResInfo == Panel1024x768) {
+ if (!(SiS_SetFlag & LCDVESATiming)) {
+ if (!(SiS_LCDInfo & LCDNonExpanding)) {
+ if (yres == 350)
+ yres = 357;
+ if (yres == 400)
+ yres = 420;
+/* if(!OldBios) */
+ if (yres == 480)
+ yres = 525;
+ }
+ }
+ }
+ } else {
+ if (xres == 720)
+ xres = 640;
+ }
+ SiS_VGAHDE = xres;
+ SiS_HDE = xres;
+ SiS_VGAVDE = yres;
+ SiS_VDE = yres;
+}
+
+void
+SiS_GetCRT2Ptr (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex, USHORT * CRT2Index,
+ USHORT * ResIndex)
+{
+ USHORT tempbx, tempal;
+ USHORT Flag;
+ if (SiS_IF_DEF_LVDS == 0) {
+ if (SiS_VBInfo & SetCRT2ToLCD) { /* LCD */
+ tempbx = SiS_LCDResInfo;
+ tempbx = tempbx - Panel1024x768;
+ if (!(SiS_SetFlag & LCDVESATiming)) {
+ tempbx += 5;
+/* GetRevisionID(); */
+ tempbx += 5;
+ }
+ } else {
+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) { /* TV */
+ if (SiS_VGAVDE > 480)
+ SiS_SetFlag =
+ SiS_SetFlag & (!TVSimuMode);
+ tempbx = 2;
+ if (SiS_VBInfo & SetInSlaveMode) {
+ if (!(SiS_SetFlag & TVSimuMode))
+ tempbx = 10;
+ }
+ } else {
+ if (SiS_VBInfo & SetPALTV) {
+ tempbx = 3;
+ } else {
+ tempbx = 4;
+ }
+ if (SiS_SetFlag & TVSimuMode) {
+ tempbx = tempbx + 5;
+ }
+ }
+ }
+ if (ModeNo <= 0x13) {
+ tempal = SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {
+ tempal =
+ SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ }
+ tempal = tempal & 0x3F;
+ /*301b */
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))
+ && (SiS_VBInfo & SetCRT2ToTV)) {
+ /*look */
+ if (tempal == 0x06)
+ tempal = 0x07;
+
+ }
+ /*end 301b */
+ if ((0x31 <= ModeNo) && (ModeNo <= 0x35))
+ tempal = 6;
+ if (SiS_LCDInfo & LCDNonExpanding)
+ tempbx = 0x0D;
+ if (SiS_LCDResInfo == Panel1280x960)
+ tempbx = 0x0E;
+ *CRT2Index = tempbx;
+ *ResIndex = tempal;
+ } else { /* LVDS */
+ Flag = 1;
+ tempbx = 0;
+ if (SiS_IF_DEF_CH7005 == 1) {
+ if (!(SiS_VBInfo & SetCRT2ToLCD)) {
+ Flag = 0;
+ tempbx = 7;
+ if (SiS_VBInfo & SetPALTV)
+ tempbx = tempbx + 2;
+ if (SiS_VBInfo & SetCHTVOverScan)
+ tempbx = tempbx + 1;
+ }
+ }
+ if (Flag == 1) {
+ tempbx = SiS_LCDResInfo - Panel800x600;
+ if (SiS_LCDInfo & LCDNonExpanding) {
+ tempbx = tempbx + 3;
+ }
+ }
+ if (ModeNo <= 0x13) {
+ tempal = SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {
+ tempal =
+ SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ }
+ tempal = tempal & 0x1F;
+ *CRT2Index = tempbx;
+ *ResIndex = tempal;
+ }
+}
+
+void
+SiS_GetCRT2PtrA (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex, USHORT * CRT2Index,
+ USHORT * ResIndex)
+{
+ USHORT tempbx, tempal;
+
+ tempbx = SiS_LCDResInfo - Panel1024x768;
+ if (SiS_LCDInfo & LCDNonExpanding) {
+ tempbx = tempbx + 3;
+ }
+ if (ModeNo <= 0x13) {
+ tempal = SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {
+ tempal = SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ }
+ tempal = tempal & 0x1F;
+ *CRT2Index = tempbx;
+ *ResIndex = tempal;
+}
+
+/*end 301b*/
+
+USHORT
+SiS_GetRatePtrCRT2 (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex)
+{
+ SHORT LCDRefreshIndex[] = { 0x00, 0x00, 0x03, 0x01 };
+ SHORT LCDARefreshIndex[] = { 0x00, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01 };
+ USHORT RefreshRateTableIndex, i;
+ USHORT modeflag, index, temp;
+
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+
+ if (SiS_IF_DEF_CH7005 == 1) {
+ if (SiS_VBInfo & SetCRT2ToTV) {
+ if (modeflag & HalfDCLK)


+ return (0);
+ }
+ }

+ if (ModeNo < 0x14)
+ return (0xFFFF);
+ index = SiS_GetReg1 (SiS_P3d4, 0x33);
+ index = index >> SiS_SelectCRT2Rate;
+ index = index & 0x0F;
+ if (SiS_LCDInfo & LCDNonExpanding)
+ index = 0;
+ if (index > 0)
+ index--;
+
+ if (SiS_SetFlag & ProgrammingCRT2) {
+ if (SiS_IF_DEF_CH7005 == 1) {
+ if (SiS_VBInfo & SetCRT2ToTV) {
+ index = 0;
+ }
+ }
+ if (SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+ if (SiS_IF_DEF_LVDS == 0) {
+ if ((SiS_VBType & VB_SIS301B)
+ || (SiS_VBType & VB_SIS302B)) temp =
+ LCDARefreshIndex[SiS_LCDResInfo]; /*301b */
+ else
+ temp = LCDRefreshIndex[SiS_LCDResInfo];
+ if (index > temp) {
+ index = temp;
+ }
+ } else {
+ index = 0;
+ }
+ }
+ }
+
+ RefreshRateTableIndex = SiS_EModeIDTable[ModeIdIndex].REFindex;
+ ModeNo = SiS_RefIndex[RefreshRateTableIndex].ModeID;
+ i = 0;
+ do {
+ if (SiS_RefIndex[RefreshRateTableIndex + i].ModeID != ModeNo)
+ break;
+ temp = SiS_RefIndex[RefreshRateTableIndex + i].Ext_InfoFlag;
+ temp = temp & ModeInfoFlag;
+ if (temp < SiS_ModeType)
+ break;
+
+ i++;
+ index--;
+ } while (index != 0xFFFF);
+
+ if (!(SiS_VBInfo & SetCRT2ToRAMDAC)) {
+ if (SiS_VBInfo & SetInSlaveMode) {
+ temp =
+ SiS_RefIndex[RefreshRateTableIndex + i -
+ 1].Ext_InfoFlag;
+ if (temp & InterlaceMode) {
+ i++;
+ }
+ }
+ }
+
+ i--;
+ if ((SiS_SetFlag & ProgrammingCRT2)) {
+ temp =
+ SiS_AjustCRT2Rate (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, &i);
+ }
+ return (RefreshRateTableIndex + i); /*return(0x01|(temp1<<1)); */
+}
+
+BOOLEAN
+SiS_AjustCRT2Rate (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex, USHORT * i)
+{
+ USHORT tempax, tempbx, resinfo;
+ USHORT modeflag, infoflag;
+
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ModeFlag */
+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+
+ resinfo = SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ tempbx = SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID;
+ tempax = 0;
+ if (SiS_IF_DEF_LVDS == 0) {
+ if (SiS_VBInfo & SetCRT2ToRAMDAC) {
+ tempax = tempax | SupportRAMDAC2;
+ }
+ if (SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /*301b */
+ tempax = tempax | SupportLCD;
+ if (SiS_LCDResInfo != Panel1280x1024) {
+ if (SiS_LCDResInfo != Panel1280x960) {
+ if (SiS_LCDInfo & LCDNonExpanding) {
+ if (resinfo >= 9) {
+ tempax = 0;


+ return (0);
+ }
+ }
+ }

+ }
+ }
+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) { /* for HiTV */
+ tempax = tempax | SupportHiVisionTV;
+ if (SiS_VBInfo & SetInSlaveMode) {
+ if (resinfo == 4)
+ return (0);
+ if (resinfo == 3) {
+ if (SiS_SetFlag & TVSimuMode)
+ return (0);
+ }
+ if (resinfo > 7)
+ return (0);
+ }
+ } else {
+ if (SiS_VBInfo &
+ (SetCRT2ToAVIDEO | SetCRT2ToSVIDEO |
+ SetCRT2ToSCART)) {
+ tempax = tempax | SupportTV;
+ /*301b */
+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B)) { /*301b */
+
+ tempax = tempax | SupportTV1024;
+
+ }


+ /*end 301b */
+

+ if (!(SiS_VBInfo & SetPALTV)) {
+ if (modeflag & NoSupportSimuTV) {
+ if (SiS_VBInfo & SetInSlaveMode) {
+ if (!
+ (SiS_VBInfo &
+ SetNotSimuMode)) {


+ return 0;
+ }
+ }
+ }

+ }
+ }
+ }
+ } else { /* for LVDS */
+ if (SiS_IF_DEF_CH7005 == 1) {
+ if (SiS_VBInfo & SetCRT2ToTV) {
+ tempax = tempax | SupportCHTV;
+ }
+ }
+ if (SiS_VBInfo & SetCRT2ToLCD) {
+ tempax = tempax | SupportLCD;
+ if (resinfo > 0x08)
+ return (0); /*1024x768 */
+ if (SiS_LCDResInfo < Panel1024x768) {
+ if (resinfo > 0x07)
+ return (0); /*800x600 */
+ if (resinfo == 0x04)
+ return (0); /*512x384 */
+ }
+ }
+ }
+
+ for (; SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID == tempbx;
+ (*i)--) {
+ infoflag =
+ SiS_RefIndex[RefreshRateTableIndex + (*i)].Ext_InfoFlag;
+ if (infoflag & tempax) {
+ return (1);
+ }
+ if ((*i) == 0)
+ break;
+ }
+
+ for ((*i) = 0;; (*i)++) {
+ infoflag =
+ SiS_RefIndex[RefreshRateTableIndex + (*i)].Ext_InfoFlag;
+ if (SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID != tempbx) {
+ return (0);
+ }
+ if (infoflag & tempax) {


+ return (1);
+ }
+ }
+ return (1);
+}
+

+void
+SiS_SaveCRT2Info (USHORT ModeNo)
+{
+ USHORT temp1, temp2;
+
+ SiS_SetReg1 (SiS_P3d4, 0x34, ModeNo); /* reserve CR34 for CRT1 Mode No */
+ temp1 = (SiS_VBInfo & SetInSlaveMode) >> 8;
+ temp2 = ~(SetInSlaveMode >> 8);
+ SiS_SetRegANDOR (SiS_P3d4, 0x31, temp2, temp1);
+}
+
+void
+SiS_GetVBInfo301 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex, PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+ USHORT tempax, tempbx, temp;
+ USHORT modeflag;
+ UCHAR OutputSelect = *pSiS_OutputSelect;
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+ SiS_SetFlag = 0;
+
+ SiS_ModeType = modeflag & ModeInfoFlag;
+ tempbx = 0;
+ if (SiS_BridgeIsOn (BaseAddr)) {
+ temp = SiS_GetReg1 (SiS_P3d4, 0x30);
+ tempbx = tempbx | temp;
+ temp = SiS_GetReg1 (SiS_P3d4, 0x31);
+ tempax = temp << 8;
+ tempbx = tempbx | tempax;
+ temp = SetCHTVOverScan | SetInSlaveMode | DisableCRT2Display; /* ynlai */
+ temp = 0xFFFF ^ temp;
+ tempbx = tempbx & temp;
+#ifdef CONFIG_FB_SIS_315
+ /*301b */
+ if ((SiS_VBType & VB_SIS302B)) {
+ temp = SiS_GetReg1 (SiS_P3d4, 0x38);
+ if (temp == 0x03)
+ tempbx = tempbx | (SetCRT2ToLCDA);
+ }
+ /*end301b */
+#endif
+ if (SiS_IF_DEF_LVDS == 0) {
+ if (SiS_IF_DEF_HiVision)
+ temp = 0x80FC;
+ else
+ temp = 0x807C;
+ } else {
+ if (SiS_IF_DEF_CH7005 == 1) {
+ temp = SetCRT2ToTV | SetCRT2ToLCD;
+ } else {
+ temp = SetCRT2ToLCD;
+ }
+ }
+ if (!(tempbx & temp)) {
+ tempax = tempax | DisableCRT2Display;
+ tempbx = 0;
+ }
+
+ if (SiS_IF_DEF_LVDS == 0) {
+ if (tempbx & SetCRT2ToLCDA) { /*301b */
+ tempbx =
+ tempbx & (0xFF00 | SwitchToCRT2 |
+ SetSimuScanMode);
+ } else if (tempbx & SetCRT2ToRAMDAC) {
+ tempbx =
+ tempbx & (0xFF00 | SetCRT2ToRAMDAC |
+ SwitchToCRT2 | SetSimuScanMode);
+ } else if ((tempbx & SetCRT2ToLCD) && (!(SiS_VBType & VB_NoLCD))) { /*301dlvds */
+ tempbx =
+ tempbx & (0xFF00 | SetCRT2ToLCD |
+ SwitchToCRT2 | SetSimuScanMode);
+ } else if (tempbx & SetCRT2ToSCART) {
+ tempbx =
+ tempbx & (0xFF00 | SetCRT2ToSCART |
+ SwitchToCRT2 | SetSimuScanMode);
+ tempbx = tempbx | SetPALTV;
+ } else if (tempbx & SetCRT2ToHiVisionTV) {
+ tempbx =
+ tempbx & (0xFF00 | SetCRT2ToHiVisionTV |
+ SwitchToCRT2 | SetSimuScanMode);
+ /* ynlai begin */
+ tempbx = tempbx | SetPALTV;
+ /* ynlai end */
+ }
+ } else {
+ if (SiS_IF_DEF_CH7005 == 1) {
+ if (tempbx & SetCRT2ToTV)
+ tempbx =
+ tempbx & (0xFF00 | SetCRT2ToTV |
+ SwitchToCRT2 |
+ SetSimuScanMode);
+ }
+ if (tempbx & SetCRT2ToLCD)
+ tempbx =
+ tempbx & (0xFF00 | SetCRT2ToLCD |
+ SwitchToCRT2 | SetSimuScanMode);
+ }
+ if (tempax & DisableCRT2Display) {
+ if (!(tempbx & (SwitchToCRT2 | SetSimuScanMode))) {
+ tempbx = SetSimuScanMode | DisableCRT2Display;
+ }
+ }
+ if (!(tempbx & DriverMode)) {
+ tempbx = tempbx | SetSimuScanMode;
+ }
+ if (!(tempbx & SetSimuScanMode)) {
+ if (tempbx & SwitchToCRT2) {
+ if (!(modeflag & CRT2Mode)) {
+ tempbx = tempbx | SetSimuScanMode;
+ }
+ } else {
+ if (!
+ (SiS_BridgeIsEnable
+ (BaseAddr, HwDeviceExtension))) {
+ if (!(tempbx & DriverMode)) {
+ if (SiS_BridgeInSlave ()) {
+ tempbx =
+ tempbx |
+ SetInSlaveMode;
+ }
+ }
+ }
+ }
+ }
+ if (!(tempbx & DisableCRT2Display)) {
+ if (tempbx & DriverMode) {
+ if (tempbx & SetSimuScanMode) {
+ if (!(modeflag & CRT2Mode)) {
+ tempbx =
+ tempbx | SetInSlaveMode;
+ if (SiS_IF_DEF_LVDS == 0) {
+ if (tempbx &
+ SetCRT2ToTV) {
+ if (!
+ (tempbx &
+ SetNotSimuMode))
+ SiS_SetFlag =
+ SiS_SetFlag
+ |
+ TVSimuMode;
+ }
+ }
+ }
+ }
+ } else {
+ tempbx = tempbx | SetInSlaveMode;
+ if (SiS_IF_DEF_LVDS == 0) {
+ if (tempbx & SetCRT2ToTV) {
+ if (!(tempbx & SetNotSimuMode))
+ SiS_SetFlag =
+ SiS_SetFlag |
+ TVSimuMode;
+ }
+ }
+ }
+ }
+ if (SiS_IF_DEF_CH7005 == 1) {
+ temp = SiS_GetReg1 (SiS_P3d4, 0x35);
+ if (temp & TVOverScan)
+ tempbx = tempbx | SetCHTVOverScan;
+ }
+ }
+#ifdef CONFIG_FB_SIS_300
+ /*add PALMN */
+ if (SiS_IF_DEF_LVDS == 0) {
+ if ((HwDeviceExtension->jChipType == SIS_630) ||


+ (HwDeviceExtension->jChipType == SIS_730)) {

+ if (!(OutputSelect & EnablePALMN))
+ SiS_SetRegAND (SiS_P3d4, 0x35, 0x3F);
+ if (tempbx & SetCRT2ToTV) {
+ if (tempbx & SetPALTV) {
+ temp = SiS_GetReg1 (SiS_P3d4, 0x35);
+ temp = temp & 0xC0;
+ if (temp == 0x40)
+ tempbx = tempbx & (~SetPALTV);
+ }
+ }
+ }
+ }
+ /*end add */
+#endif
+#ifdef CONFIG_FB_SIS_315
+ /*add PALMN */
+ if (SiS_IF_DEF_LVDS == 0) {
+ if (!(OutputSelect & EnablePALMN))
+ SiS_SetRegAND (SiS_P3d4, 0x38, 0x3F);
+ if (tempbx & SetCRT2ToTV) {
+ if (tempbx & SetPALTV) {
+ temp = SiS_GetReg1 (SiS_P3d4, 0x38);
+ temp = temp & 0xC0;
+ if (temp == 0x40)
+ tempbx = tempbx & (~SetPALTV);
+ }
+ }
+ }
+ /*end add */
+#endif
+ SiS_VBInfo = tempbx;
+}
+
+void
+SiS_GetRAMDAC2DATA (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex)
+{
+ USHORT tempax, tempbx, temp;
+ USHORT temp1, temp2, modeflag = 0, tempcx;
+
+ USHORT StandTableIndex, CRT1Index;
+ USHORT ResInfo, DisplayType;
+ SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr = NULL;
+
+ SiS_RVBHCMAX = 1;
+ SiS_RVBHCFACT = 1;
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ StandTableIndex = SiS_GetModePtr (ROMAddr, ModeNo, ModeIdIndex);
+ tempax = SiS_StandTable[StandTableIndex].CRTC[0];
+ tempbx = SiS_StandTable[StandTableIndex].CRTC[6];
+ temp1 = SiS_StandTable[StandTableIndex].CRTC[7];
+ } else {
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))
+ && (SiS_VBInfo & SetCRT2ToLCDA)) {
+ /*add crt1ptr */
+ temp =
+ SiS_GetLVDSCRT1Ptr (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, &ResInfo,
+ &DisplayType);
+ if (temp == 0) {
+ return;
+ }
+ switch (DisplayType) {
+ case 0:
+ LVDSCRT1Ptr = SiS_LVDSCRT1800x600_1;


+ break;
+ case 1:

+ LVDSCRT1Ptr = SiS_LVDSCRT11024x768_1;
+ break;
+ case 2:
+ LVDSCRT1Ptr = SiS_LVDSCRT11280x1024_1;
+ break;
+ case 3:
+ LVDSCRT1Ptr = SiS_LVDSCRT1800x600_1_H;


+ break;
+ case 4:

+ LVDSCRT1Ptr = SiS_LVDSCRT11024x768_1_H;


+ break;
+ case 5:

+ LVDSCRT1Ptr = SiS_LVDSCRT11280x1024_1_H;


+ break;
+ case 6:

+ LVDSCRT1Ptr = SiS_LVDSCRT1800x600_2;


+ break;
+ case 7:

+ LVDSCRT1Ptr = SiS_LVDSCRT11024x768_2;


+ break;
+ case 8:

+ LVDSCRT1Ptr = SiS_LVDSCRT11280x1024_2;


+ break;
+ case 9:

+ LVDSCRT1Ptr = SiS_LVDSCRT1800x600_2_H;
+ break;
+ case 10:
+ LVDSCRT1Ptr = SiS_LVDSCRT11024x768_2_H;
+ break;
+ case 11:
+ LVDSCRT1Ptr = SiS_LVDSCRT11280x1024_2_H;
+ break;
+ case 12:
+ LVDSCRT1Ptr = SiS_CHTVCRT1UNTSC;
+ break;
+ case 13:
+ LVDSCRT1Ptr = SiS_CHTVCRT1ONTSC;
+ break;
+ case 14:
+ LVDSCRT1Ptr = SiS_CHTVCRT1UPAL;
+ break;
+ case 15:
+ LVDSCRT1Ptr = SiS_CHTVCRT1OPAL;
+ break;
+ }
+ temp1 = (LVDSCRT1Ptr + ResInfo)->CR[0];
+ temp2 = (LVDSCRT1Ptr + ResInfo)->CR[14];
+ tempax = (temp1 & 0xFF) | ((temp2 & 0x03) << 8);
+ tempbx = (LVDSCRT1Ptr + ResInfo)->CR[6];
+ tempcx = (LVDSCRT1Ptr + ResInfo)->CR[13] << 8;
+ tempcx = tempcx & 0x0100;
+ tempcx = tempcx << 2;
+ tempbx = tempbx | tempcx;
+ temp1 = (LVDSCRT1Ptr + ResInfo)->CR[7];
+ } /*add 301b */
+ else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ CRT1Index =
+ SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+ CRT1Index = CRT1Index & 0x3F;
+ temp1 = (USHORT) SiS_CRT1Table[CRT1Index].CR[0];
+ temp2 = (USHORT) SiS_CRT1Table[CRT1Index].CR[14];
+ tempax = (temp1 & 0xFF) | ((temp2 & 0x03) << 8);
+ tempbx = (USHORT) SiS_CRT1Table[CRT1Index].CR[6];
+ tempcx = (USHORT) SiS_CRT1Table[CRT1Index].CR[13] << 8;
+ tempcx = tempcx & 0x0100;
+ tempcx = tempcx << 2;
+ tempbx = tempbx | tempcx;
+ temp1 = (USHORT) SiS_CRT1Table[CRT1Index].CR[7];
+ }
+ }
+ if (temp1 & 0x01)
+ tempbx = tempbx | 0x0100;
+ if (temp1 & 0x20)
+ tempbx = tempbx | 0x0200;
+ tempax = tempax + 5;
+ if (modeflag & Charx8Dot)
+ tempax = tempax * 8;
+ else
+ tempax = tempax * 9;
+
+ SiS_VGAHT = tempax;
+ SiS_HT = tempax;
+ tempbx++;
+ SiS_VGAVT = tempbx;
+ SiS_VT = tempbx;
+}
+
+void
+SiS_UnLockCRT2 (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr)
+{
+ if (HwDeviceExtension->jChipType >= SIS_315H) {
+ SiS_SetRegANDOR (SiS_Part1Port, 0x2f, 0xFF, 0x01);
+ } else {
+ SiS_SetRegANDOR (SiS_Part1Port, 0x24, 0xFF, 0x01);
+ }
+}
+
+void
+SiS_LockCRT2 (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr)
+{
+ if (HwDeviceExtension->jChipType >= SIS_315H) {
+ SiS_SetRegANDOR (SiS_Part1Port, 0x2F, 0xFE, 0x00);
+ } else {
+ SiS_SetRegANDOR (SiS_Part1Port, 0x24, 0xFE, 0x00);
+ }
+}
+
+void
+SiS_EnableCRT2 ()
+{
+ SiS_SetRegANDOR (SiS_P3c4, 0x1E, 0xFF, 0x20);
+}
+
+void
+SiS_DisableBridge (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr)
+{
+
+ USHORT temp1, tempah, temp;
+ SiS_SetRegANDOR (SiS_P3c4, 0x11, 0xF7, 0x08);
+/*SetPanelDelay(1); */
+ temp1 = 0x01;
+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B)) { /*301b */
+ if ((SiS_IsVAMode (BaseAddr)))
+ temp1 = 0x00; /*no disable vb */
+ }
+
+ if (SiS_IF_DEF_LVDS == 0) {
+ if (!temp1) { /*301b */
+ SiS_SetRegANDOR (SiS_Part2Port, 0x00, 0x0DF, 0x00); /* disable VB */
+ SiS_DisplayOff ();
+ if (HwDeviceExtension->jChipType >= SIS_315H) { /* 310 series */
+ SiS_SetRegOR (SiS_Part1Port, 0x00, 0x80); /* alan,BScreenOff */
+ }
+ SiS_SetRegANDOR (SiS_P3c4, 0x32, 0xDF, 0x00);
+
+ temp = SiS_GetReg1 (SiS_Part1Port, 0);
+ SiS_SetRegOR (SiS_Part1Port, 0x00, 0x10); /* alan,BScreenOff */
+/*
+ if(HwDeviceExtension->jChipType >= SIS_315H)
+ {
+ SiS_SetRegAND(SiS_Part1Port,0x2E,0x7F);
+ }
+ */
+ SiS_SetRegANDOR (SiS_P3c4, 0x1E, 0xDF, 0x00);
+ SiS_SetReg1 (SiS_Part1Port, 0, temp);
+ } else {
+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B)) { /*301b */
+ if (!(SiS_Is301B (BaseAddr))) {
+ SiS_SetRegAND (SiS_P3c4, 0x32, 0xDF);
+ if ((!(SiS_IsDualEdge (BaseAddr)))
+ && (!(SiS_IsVAMode (BaseAddr))))
+ tempah = 0x7F;
+ else if ((!(SiS_IsDualEdge (BaseAddr)))
+ && (SiS_IsVAMode (BaseAddr)))
+ tempah = 0xBF;
+ else
+ tempah = 0x3F;
+ SiS_SetRegAND (SiS_Part4Port, 0x1F,
+ tempah);
+ }
+ }
+ }
+ } else {
+ if (SiS_IF_DEF_CH7005) {


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

echo 'End of part 078'
echo 'File patch-2.4.15 is continued in part 079'
echo "079" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:52 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part076

#!/bin/sh -x
# this is part 076 of a 115 - part archive


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

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

+ SR17 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x17);
+ SR18 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x18);
+ SR19 = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x19);
+ SR1A = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x1A);
+ }

+#endif
+/* ResetExtReg begin */
+ for (i = 0x06; i < 0x20; i++)
+ SiS_SetReg1 (SiS_P3c4, i, 0); /* 2.Reset Extended register */
+ for (i = 0x21; i <= 0x27; i++)
+ SiS_SetReg1 (SiS_P3c4, i, 0); /* Reset Extended register */
+ for (i = 0x31; i <= 0x3D; i++)
+ SiS_SetReg1 (SiS_P3c4, i, 0);
+
+#ifdef CONFIG_FB_SIS_300H
+ for (i = 0x38; i <= 0x3F; i++)
+ SiS_SetReg1 (SiS_P3d4, i, 0);
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+ for (i = 0x37; i <= 0x3F; i++)
+ SiS_SetReg1 (SiS_P3d4, i, 0);
+ for (i = 0x79; i <= 0x7C; i++)
+ SiS_SetReg1 (SiS_P3d4, i, 0);
+#endif
+/* ResetExtReg end */


+#ifdef CONFIG_FB_SIS_300
+ if ((HwDeviceExtension->jChipType == SIS_540) ||
+ (HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_730)) {

+ SiS_SetReg1 (SiS_P3c4, 0x12, SR12);
+ SiS_SetReg1 (SiS_P3c4, 0x13, SR13);
+ SiS_SetReg1 (SiS_P3c4, 0x14, SR14);
+ SiS_SetReg1 (SiS_P3c4, 0x16, SR16);
+ SiS_SetReg1 (SiS_P3c4, 0x17, SR17);
+ SiS_SetReg1 (SiS_P3c4, 0x18, SR18);
+ SiS_SetReg1 (SiS_P3c4, 0x19, SR19);
+ SiS_SetReg1 (SiS_P3c4, 0x1A, SR1A);


+ }
+#endif
+#ifdef CONFIG_FB_SIS_315
+ if ((HwDeviceExtension->jChipType == SIS_550)) {

+ SiS_SetReg1 (SiS_P3d4, 0x39, CR39);
+ SiS_SetReg1 (SiS_P3d4, 0x3A, CR3A);
+ SiS_SetReg1 (SiS_P3d4, 0x3B, CR3B);
+ SiS_SetReg1 (SiS_P3d4, 0x3C, CR3C);
+ SiS_SetReg1 (SiS_P3d4, 0x3D, CR3D);
+ SiS_SetReg1 (SiS_P3d4, 0x3E, CR3E);
+ SiS_SetReg1 (SiS_P3d4, 0x3F, CR3F);
+ SiS_SetReg1 (SiS_P3d4, 0x79, CR79);
+ SiS_SetReg1 (SiS_P3d4, 0x7A, CR7A);
+ SiS_SetReg1 (SiS_P3d4, 0x7B, CR7B);
+ SiS_SetReg1 (SiS_P3d4, 0x7C, CR7C);


+ } else if ((HwDeviceExtension->jChipType == SIS_640) || /* 08/20/01 chiawen for 640/740 */
+ (HwDeviceExtension->jChipType == SIS_740)) {

+ SiS_SetReg1 (SiS_P3c4, 0x12, SR12);
+ SiS_SetReg1 (SiS_P3c4, 0x13, SR13);
+ SiS_SetReg1 (SiS_P3c4, 0x14, SR14);
+ SiS_SetReg1 (SiS_P3c4, 0x16, SR16);
+ SiS_SetReg1 (SiS_P3c4, 0x17, SR17);
+ SiS_SetReg1 (SiS_P3c4, 0x18, SR18);
+ SiS_SetReg1 (SiS_P3c4, 0x19, SR19);
+ SiS_SetReg1 (SiS_P3c4, 0x1A, SR1A);
+ }
+#endif
+
+/* detect ExtChip Type */


+ SiS_Set_LVDS_TRUMPION (HwDeviceExtension); /*2/29/00 by Mars Wen for LVDS and Trumpion */
+

+#ifdef CONFIG_FB_SIS_300
+ if ((HwDeviceExtension->jChipType == SIS_540) ||
+ (HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_730)) {

+ temp = (UCHAR) SR1A;
+ } else
+#endif
+ {
+ if ((*pSiS_SoftSetting & SoftDRAMType) == 0) {
+ temp = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x3A);
+ }
+ }
+
+ SiS_RAMType = temp & 0x03;
+ SiS_SetMemoryClock (ROMAddr);
+
+/* SetDefExt1Regs begin */
+ SiS_SetReg1 (SiS_P3c4, 0x07, *pSiS_SR07);
+ if ((HwDeviceExtension->jChipType != SIS_540) &&
+ (HwDeviceExtension->jChipType != SIS_630) &&
+ (HwDeviceExtension->jChipType != SIS_730)) {
+ for (i = 0x15; i < 0x1C; i++) {
+ SiS_SetReg1 (SiS_P3c4, i,
+ SiS_SR15[i - 0x15][SiS_RAMType]);
+ }


+ }
+#ifdef CONFIG_FB_SIS_315
+ if ((HwDeviceExtension->jChipType == SIS_315H) ||

+ (HwDeviceExtension->jChipType == SIS_315PRO)) {
+ for (i = 0x40; i <= 0x44; i++) {
+ SiS_SetReg1 (SiS_P3d4, i,
+ SiS_CR40[i - 0x40][SiS_RAMType]);
+ }
+ SiS_SetReg1 (SiS_P3d4, 0x48, 0x23);
+ SiS_SetReg1 (SiS_P3d4, 0x49, SiS_CR49[0]);
+ /* /SiS_SetReg1(SiS_P3c4,0x25,SiS_SR25[0]); */
+ }
+#endif
+
+ SiS_SetReg1 (SiS_P3c4, 0x1F, *pSiS_SR1F);
+ /*SiS_SetReg1(SiS_P3c4,0x20,0x20); */
+ SiS_SetReg1 (SiS_P3c4, 0x20, 0xA0); /* alan, 2001/6/26 Frame buffer can read/write */
+ SiS_SetReg1 (SiS_P3c4, 0x23, *pSiS_SR23);
+ SiS_SetReg1 (SiS_P3c4, 0x24, *pSiS_SR24);
+ SiS_SetReg1 (SiS_P3c4, 0x25, SiS_SR25[0]);
+#ifdef CONFIG_FB_SIS_300
+ if (HwDeviceExtension->jChipType == SIS_300) {
+ SiS_SetReg1 (SiS_P3c4, 0x21, 0x84);
+ SiS_SetReg1 (SiS_P3c4, 0x22, 0x00);
+ }
+#endif
+ SR11 = 0x0F;
+ SiS_SetReg1 (SiS_P3c4, 0x11, SR11);
+
+ SiS_UnLockCRT2 (HwDeviceExtension, BaseAddr);
+ SiS_SetReg1 (SiS_Part1Port, 0x00, 0x00);
+ SiS_SetReg1 (SiS_Part1Port, 0x02, *pSiS_CRT2Data_1_2);
+#ifdef CONFIG_FB_SIS_315 /* 05/02/01 ynlai for sis550 */


+ if ((HwDeviceExtension->jChipType == SIS_315H) ||
+ (HwDeviceExtension->jChipType == SIS_315PRO) ||
+ (HwDeviceExtension->jChipType == SIS_550) ||

+ (HwDeviceExtension->jChipType == SIS_640) || /* 08/20/01 chiawen for 640/740 */
+ (HwDeviceExtension->jChipType == SIS_740))

+ /* 09/03/01 chiawen for 650 */
+ SiS_SetReg1 (SiS_Part1Port, 0x2E, 0x08); /* use VB */
+#endif
+
+ temp = *pSiS_SR32;
+ if (SiS_BridgeIsOn (BaseAddr)) {
+ temp = temp & 0xEF;
+ }
+ SiS_SetReg1 (SiS_P3c4, 0x32, temp);


+
+#ifdef CONFIG_FB_SIS_315
+ if ((HwDeviceExtension->jChipType == SIS_315H) ||

+ (HwDeviceExtension->jChipType == SIS_315PRO)) {
+ HwDeviceExtension->pQueryVGAConfigSpace (HwDeviceExtension,
+ 0x50, 0, &Temp); /* Get */
+
+ Temp >>= 20;
+ Temp &= 0xF;
+ if (Temp != 1) {
+ SiS_SetReg1 (SiS_P3c4, 0x25, SiS_SR25[1]);
+ SiS_SetReg1 (SiS_P3d4, 0x49, SiS_CR49[1]);
+ }
+
+ SiS_SetReg1 (SiS_P3c4, 0x27, 0x1F);
+
+ SiS_SetReg1 (SiS_P3c4, 0x31, *pSiS_SR31);
+ SiS_SetReg1 (SiS_P3c4, 0x32, *pSiS_SR32);
+ SiS_SetReg1 (SiS_P3c4, 0x33, *pSiS_SR33);
+ }
+#endif
+
+ if (SiS_BridgeIsOn (BaseAddr) == 1) {


+ if (SiS_IF_DEF_LVDS == 0) {

+ SiS_SetReg1 (SiS_Part2Port, 0x00, 0x1C);
+ SiS_SetReg1 (SiS_Part4Port, 0x0D, *pSiS_CRT2Data_4_D);
+ SiS_SetReg1 (SiS_Part4Port, 0x0E, *pSiS_CRT2Data_4_E);
+ SiS_SetReg1 (SiS_Part4Port, 0x10, *pSiS_CRT2Data_4_10);
+ SiS_SetReg1 (SiS_Part4Port, 0x0F, 0x3F);
+ }
+ SiS_LockCRT2 (HwDeviceExtension, BaseAddr);
+ }
+ SiS_SetReg1 (SiS_P3d4, 0x83, 0x00);
+/* SetDefExt1Regs end */


+
+#ifdef CONFIG_FB_SIS_315
+ if ((HwDeviceExtension->jChipType == SIS_315H) ||
+ (HwDeviceExtension->jChipType == SIS_315PRO)

+ ) { /* 05/02/01 ynlai */
+ /* For SiS 300,310 Chip */
+ if (HwDeviceExtension->bSkipDramSizing == TRUE) {
+ SiS_SetDRAMModeRegister (ROMAddr);
+ pSR = HwDeviceExtension->pSR;
+ if (pSR != NULL) {
+ while (pSR->jIdx != 0xFF) {
+ SiS_SetReg1 (SiS_P3c4, pSR->jIdx,
+ pSR->jVal);
+ pSR++;
+ }
+ }
+ } else
+ SiS_SetDRAMSize_310 (HwDeviceExtension);
+ }
+#endif
+#ifdef CONFIG_FB_SIS_315
+ if ((HwDeviceExtension->jChipType == SIS_550)) { /* 05/02/01 ynlai For SiS 550 */
+ /* SetDRAMConfig begin */
+/* SiS_SetReg1(SiS_P3c4,0x12,SR12);
+ SiS_SetReg1(SiS_P3c4,0x13,SR13);
+ SiS_SetReg1(SiS_P3c4,0x14,SR14);
+ SiS_SetReg1(SiS_P3c4,0x16,SR16);
+ SiS_SetReg1(SiS_P3c4,0x17,SR17);
+ SiS_SetReg1(SiS_P3c4,0x18,SR18);
+ SiS_SetReg1(SiS_P3c4,0x19,SR19);
+ SiS_SetReg1(SiS_P3c4,0x1A,SR1A); */
+ /* SetDRAMConfig end */
+ }
+#endif
+#ifdef CONFIG_FB_SIS_300
+ if (HwDeviceExtension->jChipType == SIS_300) { /* For SiS 300 Chip */
+ if (HwDeviceExtension->bSkipDramSizing == TRUE) {
+/* SiS_SetDRAMModeRegister(ROMAddr);
+ temp = (HwDeviceExtension->pSR)->jVal;
+ SiS_SetReg1(SiS_P3c4,0x13,temp);
+ temp = (HwDeviceExtension->pSR)->jVal;
+ SiS_SetReg1(SiS_P3c4,0x14,temp); */
+ } else {
+#ifdef TC
+ SiS_SetReg1 (SiS_P3c4, 0x13, SR13);
+ SiS_SetReg1 (SiS_P3c4, 0x14, SR14);
+ SiS_SetRegANDOR (SiS_P3c4, 0x15, 0xFF, 0x04);
+#else
+ SiS_SetDRAMSize_300 (HwDeviceExtension);
+ SiS_SetDRAMSize_300 (HwDeviceExtension);
+#endif
+ }
+ }
+ if ((HwDeviceExtension->jChipType == SIS_540) || /* For SiS 630/540/730 Chip */


+ (HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_730)) {

+ /* SetDRAMConfig begin */
+/* SiS_SetReg1(SiS_P3c4,0x12,SR12);
+ SiS_SetReg1(SiS_P3c4,0x13,SR13);
+ SiS_SetReg1(SiS_P3c4,0x14,SR14);
+ SiS_SetReg1(SiS_P3c4,0x16,SR16);
+ SiS_SetReg1(SiS_P3c4,0x17,SR17);
+ SiS_SetReg1(SiS_P3c4,0x18,SR18);
+ SiS_SetReg1(SiS_P3c4,0x19,SR19);
+ SiS_SetReg1(SiS_P3c4,0x1A,SR1A); */
+ /* SetDRAMConfig end */
+ }
+/* SetDRAMSize end */
+#endif
+
+/* SetDefExt2Regs begin */
+/* AGP=1;
+ temp=(UCHAR)SiS_GetReg1(SiS_P3c4,0x3A);
+ temp=temp&0x30;
+ if(temp==0x30) AGP=0;
+ if(AGP==0) *pSiS_SR21=*pSiS_SR21&0xEF;
+ SiS_SetReg1(SiS_P3c4,0x21,*pSiS_SR21);
+ if(AGP==1) *pSiS_SR22=*pSiS_SR22&0x20;
+ SiS_SetReg1(SiS_P3c4,0x22,*pSiS_SR22); */
+
+ SiS_SetReg1 (SiS_P3c4, 0x21, *pSiS_SR21);
+ SiS_SetReg1 (SiS_P3c4, 0x22, *pSiS_SR22);
+/* SetDefExt2Regs end */
+
+/* SiS_SetReg3(SiS_P3c6,0xff);
+ SiS_ClearDAC(SiS_P3c8); [ynlai] 05/22/01 */
+
+ SiS_DetectMonitor (HwDeviceExtension, BaseAddr);
+ SiS_GetSenseStatus (HwDeviceExtension, ROMAddr); /* sense CRT2 */
+
+ return (TRUE);
+}
+
+void
+SiS_Set_LVDS_TRUMPION (PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+ USHORT temp;


+
+#ifdef CONFIG_FB_SIS_300
+ if ((HwDeviceExtension->jChipType == SIS_540) ||
+ (HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_730)) {

+ temp = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x1A);
+ temp = (temp & 0xE0) >> 4;
+ SiS_SetRegANDOR (SiS_P3d4, 0x37, 0xF1, temp);


+ temp = temp >> 1;

+ if ((temp == 0) || (temp == 1)) { /* for 301 */
+ SiS_IF_DEF_LVDS = 0;
+ SiS_IF_DEF_CH7005 = 0;
+ SiS_IF_DEF_TRUMPION = 0;
+ }
+ if ((temp >= 2) && (temp <= 5)) {
+ SiS_IF_DEF_LVDS = 1;
+ }
+ if (temp == 3)
+ SiS_IF_DEF_TRUMPION = 1;
+ if ((temp == 4) || (temp == 5))
+ SiS_IF_DEF_CH7005 = 1;
+ } else {
+ SiS_IF_DEF_LVDS = 0;
+ SiS_IF_DEF_TRUMPION = 0;
+ SiS_IF_DEF_CH7005 = 0;
+ }
+#else
+ if ((HwDeviceExtension->jChipType == SIS_550) ||


+ (HwDeviceExtension->jChipType == SIS_640) || /* 08/20/01 chiawen for 640/740 */
+ (HwDeviceExtension->jChipType == SIS_740))

+ { /* 09/03/01 chiawen for 650 */
+ SiS_IF_DEF_LVDS = 0;
+ SiS_IF_DEF_TRUMPION = 0;
+ SiS_IF_DEF_CH7005 = 0;
+ }
+#endif
+}
+
+/* =============== for 300 dram sizing begin =============== */
+#ifdef CONFIG_FB_SIS_300
+void
+SiS_SetDRAMSize_300 (PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+ /*ULONG ROMAddr = (ULONG)HwDeviceExtension->pjVirtualRomBase; */


+ ULONG FBAddr = (ULONG) HwDeviceExtension->pjVideoMemoryAddress;

+ /*USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress; */
+ USHORT SR13, SR14 = 0, buswidth, Done;
+ SHORT i, j, k;
+ USHORT data, TotalCapacity, PhysicalAdrOtherPage = 0;
+ ULONG Addr;
+ UCHAR temp;
+
+ int PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount;
+ int RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank;
+ /*int PageCapacity,PhysicalAdrHigh,PhysicalAdrHalfPage,PhysicalAdrAnotherPage; */
+ int PageCapacity, PhysicalAdrHigh, PhysicalAdrHalfPage;
+
+ SiSSetMode (HwDeviceExtension, 0x2e);
+ data = SiS_GetReg1 (SiS_P3c4, 0x1);
+ data = data | 0x20;
+ SiS_SetReg1 (SiS_P3c4, 0x01, data); /* Turn OFF Display */
+
+ SiS_SetReg1 (SiS_P3c4, 0x13, 0x00);
+ SiS_SetReg1 (SiS_P3c4, 0x14, 0xBF);
+ buswidth = SiS_ChkBUSWidth_300 (FBAddr);
+
+ MB2Bank = 16;
+ Done = 0;
+ for (i = 6; i >= 0; i--) {
+ if (Done == 1)
+ break;
+ PseudoRankCapacity = 1 << i;
+ for (j = 4; j >= 1; j--) {
+ if (Done == 1)
+ break;
+ PseudoTotalCapacity = PseudoRankCapacity * j;
+ PseudoAdrPinCount = 15 - j;
+ if (PseudoTotalCapacity <= 64) {
+ for (k = 0; k <= 16; k++) {
+ if (Done == 1)
+ break;
+ RankCapacity =
+ buswidth * SiS_DRAMType[k][3];
+ AdrPinCount =
+ SiS_DRAMType[k][2] +
+ SiS_DRAMType[k][0];
+ if (RankCapacity == PseudoRankCapacity)
+ if (AdrPinCount <=
+ PseudoAdrPinCount) {
+ if (j == 3) { /* Rank No */
+ BankNumHigh =
+ RankCapacity
+ * MB2Bank *
+ 3 - 1;
+ BankNumMid =
+ RankCapacity
+ * MB2Bank *
+ 1 - 1;
+ } else {
+ BankNumHigh =
+ RankCapacity
+ * MB2Bank *
+ j - 1;
+ BankNumMid =
+ RankCapacity
+ * MB2Bank *
+ j / 2 - 1;
+ }
+ PageCapacity =
+ (1 <<
+ SiS_DRAMType[k][1])
+ * buswidth * 4;
+ PhysicalAdrHigh =
+ BankNumHigh;
+ PhysicalAdrHalfPage =
+ (PageCapacity / 2 +
+ PhysicalAdrHigh) %
+ PageCapacity;
+ PhysicalAdrOtherPage =
+ PageCapacity *
+ SiS_DRAMType[k][2] +
+ PhysicalAdrHigh;
+ /* Write data */
+ /*Test */
+ temp =
+ (UCHAR)
+ SiS_GetReg1
+ (SiS_P3c4, 0x15);
+ SiS_SetReg1 (SiS_P3c4,
+ 0x15,
+ (USHORT)
+ (temp &
+ 0xFB));
+
+ temp =
+ (UCHAR)
+ SiS_GetReg1
+ (SiS_P3c4, 0x15);
+ SiS_SetReg1 (SiS_P3c4,
+ 0x15,
+ (USHORT)
+ (temp |
+ 0x04));
+ /*Test */
+ TotalCapacity =
+ SiS_DRAMType[k][3] *
+ buswidth;
+ SR13 =
+ SiS_DRAMType[k][4];
+ if (buswidth == 4)
+ SR14 =
+ (TotalCapacity
+ -
+ 1) | 0x80;
+ if (buswidth == 2)
+ SR14 =
+ (TotalCapacity
+ -
+ 1) | 0x40;
+ if (buswidth == 1)
+ SR14 =
+ (TotalCapacity
+ -
+ 1) | 0x00;
+ SiS_SetReg1 (SiS_P3c4,
+ 0x13,
+ SR13);
+ SiS_SetReg1 (SiS_P3c4,
+ 0x14,
+ SR14);
+
+ Addr =
+ FBAddr +
+ (BankNumHigh) * 64 *
+ 1024 +
+ PhysicalAdrHigh;
+ *((USHORT *) (Addr)) =
+ (USHORT)
+ PhysicalAdrHigh;
+ Addr =
+ FBAddr +
+ (BankNumMid) * 64 *
+ 1024 +
+ PhysicalAdrHigh;
+ *((USHORT *) (Addr)) =
+ (USHORT) BankNumMid;
+ Addr =
+ FBAddr +
+ (BankNumHigh) * 64 *
+ 1024 +
+ PhysicalAdrHalfPage;
+ *((USHORT *) (Addr)) =
+ (USHORT)
+ PhysicalAdrHalfPage;
+ Addr =
+ FBAddr +
+ (BankNumHigh) * 64 *
+ 1024 +
+ PhysicalAdrOtherPage;
+ *((USHORT *) (Addr)) =
+ PhysicalAdrOtherPage;
+
+ /* Read data */
+ Addr =
+ FBAddr +
+ (BankNumHigh) * 64 *
+ 1024 +
+ PhysicalAdrHigh;
+ data =
+ *((USHORT *)
+ (Addr));
+ if (data ==
+ PhysicalAdrHigh)
+ Done = 1;
+ } /* if struct */
+ } /* for loop (k) */
+ } /* if struct */
+ } /* for loop (j) */
+ } /* for loop (i) */
+}
+
+USHORT
+SiS_ChkBUSWidth_300 (ULONG FBAddress)
+{
+ /*USHORT data; */
+ PULONG pVideoMemory;
+
+ pVideoMemory = (PULONG) FBAddress;
+
+ pVideoMemory[0] = 0x01234567L;
+ pVideoMemory[1] = 0x456789ABL;
+ pVideoMemory[2] = 0x89ABCDEFL;
+ pVideoMemory[3] = 0xCDEF0123L;
+ if (pVideoMemory[3] == 0xCDEF0123L) { /*ChannelA128Bit */
+ return (4);
+ }
+ if (pVideoMemory[1] == 0x456789ABL) { /*ChannelB64Bit */
+ return (2);


+ }
+ return (1);
+}

+#endif
+
+/* =============== for 300 dram sizing end =============== */
+
+/* ============== alan ====================== */
+#ifdef CONFIG_FB_SIS_315
+UCHAR
+SiS_Get310DRAMType (ULONG ROMAddr)
+{
+ UCHAR data;
+
+ /*
+ index=SiS_GetReg1(SiS_P3c4,0x1A);
+ index=index&07;
+ */
+ if (*pSiS_SoftSetting & SoftDRAMType)
+ data = *pSiS_SoftSetting & 0x03;
+ else
+ data = SiS_GetReg1 (SiS_P3c4, 0x3a) & 0x03;
+
+ return data;
+}
+
+void
+SiS_Delay15us (ULONG ulMicrsoSec)
+{
+}
+
+void
+SiS_SDR_MRS (void)
+{
+ USHORT data;
+
+ data = SiS_GetReg1 (SiS_P3c4, 0x16);
+ data = data & 0x3F; /*/ SR16 D7=0,D6=0 */
+ SiS_SetReg1 (SiS_P3c4, 0x16, data); /*/ enable mode register set(MRS) low */
+ SiS_Delay15us (0x100);
+ data = data | 0x80; /*/ SR16 D7=1,D6=0 */
+ SiS_SetReg1 (SiS_P3c4, 0x16, data); /*/ enable mode register set(MRS) high */
+ SiS_Delay15us (0x100);
+}
+
+void
+SiS_DDR_MRS (void)
+{
+ USHORT data;
+
+ /* SR16 <- 1F,DF,2F,AF */
+
+ /* enable DLL of DDR SD/SGRAM , SR16 D4=1 */
+ data = SiS_GetReg1 (SiS_P3c4, 0x16);
+ data &= 0x0F;
+ data |= 0x10;
+ SiS_SetReg1 (SiS_P3c4, 0x16, data);
+
+ if (!(SiS_SR15[1][SiS_RAMType] & 0x10)) {
+ data &= 0x0F;
+ }
+ /* SR16 D7=1,D6=1 */
+ data |= 0xC0;
+ SiS_SetReg1 (SiS_P3c4, 0x16, data);
+
+ /* SR16 D7=1,D6=0,D5=1,D4=0 */
+ data &= 0x0F;
+ data |= 0x20;
+ SiS_SetReg1 (SiS_P3c4, 0x16, data);
+ if (!(SiS_SR15[1][SiS_RAMType] & 0x10)) {
+ data &= 0x0F;
+ }
+ /* SR16 D7=1 */
+ data |= 0x80;
+ SiS_SetReg1 (SiS_P3c4, 0x16, data);
+}
+
+void
+SiS_SetDRAMModeRegister (ULONG ROMAddr)
+{
+


+ if (SiS_Get310DRAMType (ROMAddr) < 2) {

+ SiS_SDR_MRS ();
+ } else {
+ /* SR16 <- 0F,CF,0F,8F */
+ SiS_DDR_MRS ();
+ }
+}
+
+void
+SiS_DisableRefresh (void)
+{
+ USHORT data;
+
+ data = SiS_GetReg1 (SiS_P3c4, 0x17);
+ data &= 0xF8;
+ SiS_SetReg1 (SiS_P3c4, 0x17, data);
+
+ data = SiS_GetReg1 (SiS_P3c4, 0x19);
+ data |= 0x03;
+ SiS_SetReg1 (SiS_P3c4, 0x19, data);
+
+}
+
+void
+SiS_EnableRefresh (ULONG ROMAddr)
+{
+
+ SiS_SetReg1 (SiS_P3c4, 0x17, SiS_SR15[2][SiS_RAMType]); /* SR17 */
+
+ SiS_SetReg1 (SiS_P3c4, 0x19, SiS_SR15[4][SiS_RAMType]); /* SR19 */
+
+}
+
+void
+SiS_DisableChannelInterleaving (int index, USHORT SiS_DDRDRAM_TYPE[][5])
+{
+ USHORT data;
+
+ data = SiS_GetReg1 (SiS_P3c4, 0x15);
+ data &= 0x1F;
+ switch (SiS_DDRDRAM_TYPE[index][3]) {
+ case 64:
+ data |= 0;


+ break;
+ case 32:

+ data |= 0x20;


+ break;
+ case 16:

+ data |= 0x40;


+ break;
+ case 4:

+ data |= 0x60;
+ break;
+ }
+ SiS_SetReg1 (SiS_P3c4, 0x15, data);
+
+}
+
+void
+SiS_SetDRAMSizingType (int index, USHORT DRAMTYPE_TABLE[][5])
+{
+ USHORT data;
+
+ data = DRAMTYPE_TABLE[index][4];
+ SiS_SetReg1 (SiS_P3c4, 0x13, data);
+
+ /* should delay 50 ns */
+
+}
+
+void
+SiS_CheckBusWidth_310 (ULONG ROMAddress, ULONG FBAddress)
+{
+ USHORT data;
+ PULONG volatile pVideoMemory;
+
+ pVideoMemory = (PULONG) FBAddress;
+ if (SiS_Get310DRAMType (ROMAddress) < 2) {
+
+ SiS_SetReg1 (SiS_P3c4, 0x13, 0x00);
+ SiS_SetReg1 (SiS_P3c4, 0x14, 0x12);
+ /* should delay */
+ SiS_SDR_MRS ();
+
+ SiS_ChannelAB = 0;
+ SiS_DataBusWidth = 128;
+ pVideoMemory[0] = 0x01234567L;
+ pVideoMemory[1] = 0x456789ABL;
+ pVideoMemory[2] = 0x89ABCDEFL;
+ pVideoMemory[3] = 0xCDEF0123L;
+ pVideoMemory[4] = 0x55555555L;
+ pVideoMemory[5] = 0x55555555L;
+ pVideoMemory[6] = 0xFFFFFFFFL;
+ pVideoMemory[7] = 0xFFFFFFFFL;
+ if ((pVideoMemory[3] != 0xCDEF0123L)
+ || (pVideoMemory[2] != 0x89ABCDEFL)) {
+ /*ChannelA64Bit */
+ SiS_DataBusWidth = 64;
+ SiS_ChannelAB = 0;
+ data = SiS_GetReg1 (SiS_P3c4, 0x14);
+ SiS_SetReg1 (SiS_P3c4, 0x14, (USHORT) (data & 0xFD));
+ }
+
+ if ((pVideoMemory[1] != 0x456789ABL)
+ || (pVideoMemory[0] != 0x01234567L)) {
+ /*ChannelB64Bit */
+ SiS_DataBusWidth = 64;
+ SiS_ChannelAB = 1;
+ data = SiS_GetReg1 (SiS_P3c4, 0x14);
+ SiS_SetReg1 (SiS_P3c4, 0x14,
+ (USHORT) ((data & 0xFD) | 0x01));
+ }
+ return;
+
+ } else {
+ /* DDR Dual channel */
+ SiS_SetReg1 (SiS_P3c4, 0x13, 0x00);
+ SiS_SetReg1 (SiS_P3c4, 0x14, 0x02); /* Channel A, 64bit */
+ /* should delay */
+ SiS_DDR_MRS ();
+
+ SiS_ChannelAB = 0;
+ SiS_DataBusWidth = 64;
+ pVideoMemory[0] = 0x01234567L;
+ pVideoMemory[1] = 0x456789ABL;
+ pVideoMemory[2] = 0x89ABCDEFL;
+ pVideoMemory[3] = 0xCDEF0123L;
+ pVideoMemory[4] = 0x55555555L;
+ pVideoMemory[5] = 0x55555555L;
+ pVideoMemory[6] = 0xAAAAAAAAL;
+ pVideoMemory[7] = 0xAAAAAAAAL;
+
+ if (pVideoMemory[1] == 0x456789ABL) {
+ if (pVideoMemory[0] == 0x01234567L) {
+ /* Channel A 64bit */
+ return;
+ }
+ } else {
+ if (pVideoMemory[0] == 0x01234567L) {
+ /* Channel A 32bit */
+ SiS_DataBusWidth = 32;
+ SiS_SetReg1 (SiS_P3c4, 0x14, 0x00);


+ return;
+ }
+
+ }
+

+ SiS_SetReg1 (SiS_P3c4, 0x14, 0x03); /* Channel B, 64bit */
+ SiS_DDR_MRS ();
+
+ SiS_ChannelAB = 1;
+ SiS_DataBusWidth = 64;
+ pVideoMemory[0] = 0x01234567L;
+ pVideoMemory[1] = 0x456789ABL;
+ pVideoMemory[2] = 0x89ABCDEFL;
+ pVideoMemory[3] = 0xCDEF0123L;
+ pVideoMemory[4] = 0x55555555L;
+ pVideoMemory[5] = 0x55555555L;
+ pVideoMemory[6] = 0xAAAAAAAAL;
+ pVideoMemory[7] = 0xAAAAAAAAL;
+ if (pVideoMemory[1] == 0x456789ABL) {
+ /* Channel B 64 */
+ if (pVideoMemory[0] == 0x01234567L) {
+ /* Channel B 64bit */
+ return;
+ } else {
+ /* error */
+ }
+ } else {
+ if (pVideoMemory[0] == 0x01234567L) {
+ /* Channel B 32 */
+ SiS_DataBusWidth = 32;
+ SiS_SetReg1 (SiS_P3c4, 0x14, 0x01);
+ } else {
+ /* error */


+ }
+ }
+ }
+}
+

+int
+SiS_SetRank (int index, UCHAR RankNo, UCHAR SiS_ChannelAB,
+ USHORT DRAMTYPE_TABLE[][5])
+{
+ USHORT data;
+ int RankSize;
+
+ if ((RankNo == 2) && (DRAMTYPE_TABLE[index][0] == 2))
+ return 0;
+
+ RankSize = DRAMTYPE_TABLE[index][3] / 2 * SiS_DataBusWidth / 32;
+
+ if (RankNo * RankSize <= 128) {
+ data = 0;
+ while ((RankSize >>= 1) > 0) {
+ data += 0x10;
+ }
+ data |= (RankNo - 1) << 2;
+ data |= (SiS_DataBusWidth / 64) & 2;
+ data |= SiS_ChannelAB;
+ SiS_SetReg1 (SiS_P3c4, 0x14, data);
+ /* should delay */
+ SiS_SDR_MRS ();
+ return 1;
+ } else


+ return 0;
+
+}
+

+int
+SiS_SetDDRChannel (int index, UCHAR ChannelNo, UCHAR SiS_ChannelAB,
+ USHORT DRAMTYPE_TABLE[][5])
+{
+ USHORT data;
+ int RankSize;
+
+ RankSize = DRAMTYPE_TABLE[index][3] / 2 * SiS_DataBusWidth / 32;
+ /* RankSize = DRAMTYPE_TABLE[index][3]; */
+ if (ChannelNo * RankSize <= 128) {
+ data = 0;
+ while ((RankSize >>= 1) > 0) {
+ data += 0x10;
+ }
+ if (ChannelNo == 2)
+ data |= 0x0C;
+
+ data |= (SiS_DataBusWidth / 32) & 2;
+ data |= SiS_ChannelAB;
+ SiS_SetReg1 (SiS_P3c4, 0x14, data);
+ /* should delay */
+ SiS_DDR_MRS ();
+ return 1;
+ } else


+ return 0;
+
+}
+

+int
+SiS_CheckColumn (int index, USHORT DRAMTYPE_TABLE[][5], ULONG FBAddress)
+{
+ int i;
+ ULONG Increment, Position;
+
+ /*Increment = 1<<(DRAMTYPE_TABLE[index][2] + SiS_DataBusWidth / 64 + 1); */
+ Increment = 1 << (10 + SiS_DataBusWidth / 64);
+
+ for (i = 0, Position = 0; i < 2; i++) {
+ *((PULONG) (FBAddress + Position)) = Position;
+ Position += Increment;
+ }
+
+ for (i = 0, Position = 0; i < 2; i++) {
+/* if (FBAddress[Position]!=Position) */
+ if ((*(PULONG) (FBAddress + Position)) != Position)
+ return 0;
+ Position += Increment;
+ }


+ return 1;
+}
+

+int
+SiS_CheckBanks (int index, USHORT DRAMTYPE_TABLE[][5], ULONG FBAddress)
+{
+ int i;
+ ULONG Increment, Position;
+ Increment = 1 << (DRAMTYPE_TABLE[index][2] + SiS_DataBusWidth / 64 + 2);
+
+ for (i = 0, Position = 0; i < 4; i++) {
+/* FBAddress[Position]=Position; */
+ *((PULONG) (FBAddress + Position)) = Position;
+ Position += Increment;
+ }
+
+ for (i = 0, Position = 0; i < 4; i++) {
+/* if (FBAddress[Position]!=Position) */
+ if ((*(PULONG) (FBAddress + Position)) != Position)
+ return 0;
+ Position += Increment;
+ }


+ return 1;
+}
+

+int
+SiS_CheckRank (int RankNo, int index, USHORT DRAMTYPE_TABLE[][5],
+ ULONG FBAddress)
+{
+ int i;
+ ULONG Increment, Position;
+ Increment = 1 << (DRAMTYPE_TABLE[index][2] + DRAMTYPE_TABLE[index][1] +
+ DRAMTYPE_TABLE[index][0] + SiS_DataBusWidth / 64 +
+ RankNo);
+
+ for (i = 0, Position = 0; i < 2; i++) {
+/* FBAddress[Position]=Position; */
+ *((PULONG) (FBAddress + Position)) = Position;
+ /* *((PULONG)(FBAddress))=Position; */
+ Position += Increment;
+ }
+
+ for (i = 0, Position = 0; i < 2; i++) {
+/* if (FBAddress[Position]!=Position) */
+ if ((*(PULONG) (FBAddress + Position)) != Position)
+ /*if ( (*(PULONG) (FBAddress )) !=Position) */
+ return 0;
+ Position += Increment;
+ }


+ return 1;
+
+}

+
+int
+SiS_CheckDDRRank (int RankNo, int index, USHORT DRAMTYPE_TABLE[][5],
+ ULONG FBAddress)
+{
+ ULONG Increment, Position;
+ USHORT data;
+
+ Increment = 1 << (DRAMTYPE_TABLE[index][2] + DRAMTYPE_TABLE[index][1] +
+ DRAMTYPE_TABLE[index][0] + SiS_DataBusWidth / 64 +
+ RankNo);
+
+ Increment += Increment / 2;
+
+ Position = 0;
+ *((PULONG) (FBAddress + Position + 0)) = 0x01234567;
+ *((PULONG) (FBAddress + Position + 1)) = 0x456789AB;
+ *((PULONG) (FBAddress + Position + 2)) = 0x55555555;
+ *((PULONG) (FBAddress + Position + 3)) = 0x55555555;
+ *((PULONG) (FBAddress + Position + 4)) = 0xAAAAAAAA;
+ *((PULONG) (FBAddress + Position + 5)) = 0xAAAAAAAA;
+
+ if ((*(PULONG) (FBAddress + 1)) == 0x456789AB)
+ return 1;
+
+ if ((*(PULONG) (FBAddress + 0)) == 0x01234567)
+ return 0;
+
+ data = SiS_GetReg1 (SiS_P3c4, 0x14);
+ data &= 0xF3;
+ data |= 0x08;
+ SiS_SetReg1 (SiS_P3c4, 0x14, data);
+ data = SiS_GetReg1 (SiS_P3c4, 0x15);
+ data += 0x20;
+ SiS_SetReg1 (SiS_P3c4, 0x15, data);
+


+ return 1;
+
+}

+
+int
+SiS_CheckRanks (int RankNo, int index, USHORT DRAMTYPE_TABLE[][5],
+ ULONG FBAddress)
+{
+ int r;
+
+ for (r = RankNo; r >= 1; r--) {
+ if (!SiS_CheckRank (r, index, DRAMTYPE_TABLE, FBAddress))
+ return 0;
+ }
+ if (!SiS_CheckBanks (index, DRAMTYPE_TABLE, FBAddress))
+ return 0;
+
+ if (!SiS_CheckColumn (index, DRAMTYPE_TABLE, FBAddress))
+ return 0;


+ return 1;
+
+}

+
+int
+SiS_CheckDDRRanks (int RankNo, int index, USHORT DRAMTYPE_TABLE[][5],
+ ULONG FBAddress)
+{
+ int r;
+
+ for (r = RankNo; r >= 1; r--) {
+ if (!SiS_CheckDDRRank (r, index, DRAMTYPE_TABLE, FBAddress))
+ return 0;
+ }
+ if (!SiS_CheckBanks (index, DRAMTYPE_TABLE, FBAddress))
+ return 0;
+
+ if (!SiS_CheckColumn (index, DRAMTYPE_TABLE, FBAddress))
+ return 0;


+ return 1;
+
+}

+
+int
+SiS_SDRSizing (ULONG FBAddress)
+{
+ int i;
+ UCHAR j;
+
+ for (i = 0; i < 13; i++) {
+ SiS_SetDRAMSizingType (i, SiS_SDRDRAM_TYPE);
+ for (j = 2; j > 0; j--) {
+
+ if (!SiS_SetRank
+ (i, (UCHAR) j, SiS_ChannelAB,
+ SiS_SDRDRAM_TYPE)) continue;
+ else {
+ if (SiS_CheckRanks
+ (j, i, SiS_SDRDRAM_TYPE,
+ FBAddress)) return 1;
+ }
+ }
+ }


+ return 0;
+}
+
+int

+SiS_DDRSizing (ULONG FBAddress)
+{
+
+ int i;
+ UCHAR j;
+
+ for (i = 0; i < 4; i++) {
+ SiS_SetDRAMSizingType (i, SiS_DDRDRAM_TYPE);
+ SiS_DisableChannelInterleaving (i, SiS_DDRDRAM_TYPE);
+ for (j = 2; j > 0; j--) {
+ SiS_SetDDRChannel (i, j, SiS_ChannelAB,
+ SiS_DDRDRAM_TYPE);
+ if (!SiS_SetRank
+ (i, (UCHAR) j, SiS_ChannelAB,
+ SiS_DDRDRAM_TYPE)) continue;
+ else {
+ if (SiS_CheckDDRRanks
+ (j, i, SiS_DDRDRAM_TYPE,
+ FBAddress)) return 1;
+ }
+ }
+ }


+ return 0;
+}
+
+/*
+

+ check if read cache pointer is correct
+
+*/
+void
+SiS_VerifyMclk (ULONG FBAddr)
+{
+ PUCHAR pVideoMemory = (PUCHAR) FBAddr;
+ UCHAR i, j;
+ USHORT Temp, SR21;
+
+ pVideoMemory[0] = 0xaa; /* alan */
+ pVideoMemory[16] = 0x55; /* note: PCI read cache is off */
+
+ if ((pVideoMemory[0] != 0xaa) || (pVideoMemory[16] != 0x55)) {
+ for (i = 0, j = 16; i < 2; i++, j += 16) {
+ SR21 = SiS_GetReg1 (SiS_P3c4, 0x21);
+ Temp = SR21 & 0xFB; /* disable PCI post write buffer empty gating */
+ SiS_SetReg1 (SiS_P3c4, 0x21, Temp);
+
+ Temp = SiS_GetReg1 (SiS_P3c4, 0x3C);
+ Temp = Temp | 0x01; /*MCLK reset */
+ SiS_SetReg1 (SiS_P3c4, 0x3C, Temp);
+ Temp = SiS_GetReg1 (SiS_P3c4, 0x3C);
+ Temp = Temp & 0xFE; /* MCLK normal operation */
+ SiS_SetReg1 (SiS_P3c4, 0x3C, Temp);
+ SiS_SetReg1 (SiS_P3c4, 0x21, SR21);
+
+ pVideoMemory[16 + j] = j;
+ if (pVideoMemory[16 + j] == j) {
+ pVideoMemory[j] = j;


+ break;
+ }
+ }
+ }

+
+}
+
+int
+Is315E (void)
+{
+ USHORT data;
+
+ data = SiS_GetReg1 (SiS_P3d4, 0x5F);
+ if (data & 0x10)
+ return 1;
+ else


+ return 0;
+}
+

+void
+SiS_SetDRAMSize_310 (PSIS_HW_DEVICE_INFO HwDeviceExtension)


+{
+ ULONG ROMAddr = (ULONG) HwDeviceExtension->pjVirtualRomBase;
+ ULONG FBAddr = (ULONG) HwDeviceExtension->pjVideoMemoryAddress;

+ /*USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress; */
+ USHORT data;
+
+#ifdef SIS301
+ /*SiS_SetReg1(SiS_P3d4,0x30,0x40); */
+#endif
+#ifdef SIS302
+ SiS_SetReg1 (SiS_P3d4, 0x30, 0x4D); /* alan,should change value */
+ SiS_SetReg1 (SiS_P3d4, 0x31, 0xc0); /* alan,should change value */
+ SiS_SetReg1 (SiS_P3d4, 0x34, 0x3F); /* alan,should change value */
+#endif
+
+ SiSSetMode (HwDeviceExtension, 0x2e);
+
+ data = SiS_GetReg1 (SiS_P3c4, 0x21);
+ SiS_SetReg1 (SiS_P3c4, 0x21, (USHORT) (data & 0xDF)); /* disable read cache */
+
+ data = SiS_GetReg1 (SiS_P3c4, 0x1);
+ data = data | 0x20;
+ SiS_SetReg1 (SiS_P3c4, 0x01, data); /* Turn OFF Display */
+
+ data = SiS_GetReg1 (SiS_P3c4, 0x16);
+ SiS_SetReg1 (SiS_P3c4, 0x16, (USHORT) (data | 0x0F)); /* assume lowest speed DRAM */
+
+ SiS_SetDRAMModeRegister (ROMAddr);
+ SiS_DisableRefresh ();
+ SiS_CheckBusWidth_310 (ROMAddr, FBAddr);
+
+ SiS_VerifyMclk (FBAddr); /* alan 2000/7/3 */
+


+ if (SiS_Get310DRAMType (ROMAddr) < 2) {

+ SiS_SDRSizing (FBAddr);
+ } else {
+ SiS_DDRSizing (FBAddr);
+ }
+
+ if (Is315E ()) {
+ data = SiS_GetReg1 (SiS_P3c4, 0x14);
+ if ((data & 0x0C) == 0x0C) { /* dual channel */
+ if ((data & 0xF0) > 0x40)
+ data = (data & 0x0F) | 0x40;
+ } else { /* single channel */
+
+ if ((data & 0xF0) > 0x50)
+ data = (data & 0x0F) | 0x50;
+ }
+
+ }
+
+ SiS_SetReg1 (SiS_P3c4, 0x16, SiS_SR15[1][SiS_RAMType]); /* restore SR16 */
+
+ SiS_EnableRefresh (ROMAddr);
+ data = SiS_GetReg1 (SiS_P3c4, 0x21);
+ SiS_SetReg1 (SiS_P3c4, 0x21, (USHORT) (data | 0x20)); /* enable read cache */
+
+}
+#endif
+
+void
+SiS_SetMemoryClock (ULONG ROMAddr)
+{
+ SiS_SetReg1 (SiS_P3c4, 0x28, SiS_MCLKData[SiS_RAMType].SR28);
+ SiS_SetReg1 (SiS_P3c4, 0x29, SiS_MCLKData[SiS_RAMType].SR29);
+ SiS_SetReg1 (SiS_P3c4, 0x2A, SiS_MCLKData[SiS_RAMType].SR2A);
+ SiS_SetReg1 (SiS_P3c4, 0x2E, SiS_ECLKData[SiS_RAMType].SR2E);
+ SiS_SetReg1 (SiS_P3c4, 0x2F, SiS_ECLKData[SiS_RAMType].SR2F);
+ SiS_SetReg1 (SiS_P3c4, 0x30, SiS_ECLKData[SiS_RAMType].SR30);
+
+#ifdef CONFIG_FB_SIS_315
+ if (Is315E ()) {
+ SiS_SetReg1 (SiS_P3c4, 0x28, 0x3B); /* 143 */
+ SiS_SetReg1 (SiS_P3c4, 0x29, 0x22);
+ SiS_SetReg1 (SiS_P3c4, 0x2E, 0x3B); /* 143 */
+ SiS_SetReg1 (SiS_P3c4, 0x2F, 0x22);
+ }


+#endif
+
+}
+
+/*

+=========================================
+ ======== SiS SetMode Function ==========
+=========================================
+*/
+BOOLEAN
+SiSSetMode (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT ModeNo)
+{
+ ULONG temp;
+ USHORT ModeIdIndex, KeepLockReg;


+ ULONG ROMAddr = (ULONG) HwDeviceExtension->pjVirtualRomBase;

+ /*ULONG FBAddr = (ULONG)HwDeviceExtension->pjVideoMemoryAddress; */


+ USHORT BaseAddr = (USHORT) HwDeviceExtension->ulIOAddress;
+

+#ifdef CONFIG_FB_SIS_315
+ if ((HwDeviceExtension->jChipType == SIS_315H) || /* 05/02/01 ynlai for sis550 */


+ (HwDeviceExtension->jChipType == SIS_315PRO) ||
+ (HwDeviceExtension->jChipType == SIS_550) ||

+ SiS_IF_DEF_LVDS = 0;
+ SiS_IF_DEF_CH7005 = 0;
+ SiS_IF_DEF_HiVision = 0;
+ SiS_IF_DEF_DSTN = 0; /*for 550 dstn */


+ if ((HwDeviceExtension->jChipType == SIS_540) ||
+ (HwDeviceExtension->jChipType == SIS_630) ||

+ (HwDeviceExtension->jChipType == SIS_730) ||

+ (HwDeviceExtension->jChipType == SIS_550) ||


+ (HwDeviceExtension->jChipType == SIS_640) || /* 08/20/01 chiawen for 640/740 */
+ (HwDeviceExtension->jChipType == SIS_740)) { /* 09/03/01 chiawen for 650 */

+ temp = SiS_GetReg1 (SiS_P3d4, 0x37);
+ temp = (temp & 0x0E) >> 1;
+ if ((temp == 0) || (temp == 1)) { /* for 301 */
+ SiS_IF_DEF_LVDS = 0;
+ SiS_IF_DEF_CH7005 = 0;
+ SiS_IF_DEF_TRUMPION = 0;
+ }
+ if ((temp >= 2) && (temp <= 5)) {
+ SiS_IF_DEF_LVDS = 1;
+ }
+ if (temp == 3)
+ SiS_IF_DEF_TRUMPION = 1;
+ if ((temp == 4) || (temp == 5))
+ SiS_IF_DEF_CH7005 = 1;
+ } else {
+ SiS_IF_DEF_LVDS = 0;
+ SiS_IF_DEF_TRUMPION = 0;
+ SiS_IF_DEF_CH7005 = 0;
+ }
+
+ if (ModeNo & 0x80) {
+ ModeNo = ModeNo & 0x7F;
+ flag_clearbuffer = 0;
+ } else {
+ flag_clearbuffer = 1;
+ }
+
+ SiS_PresetScratchregister (SiS_P3d4, HwDeviceExtension); /*add for CRT2 */
+ KeepLockReg = SiS_GetReg1 (SiS_P3c4, 0x05);


+ SiS_SetReg1 (SiS_P3c4, 0x05, 0x86); /* 1.Openkey */

+ temp = SiS_SearchModeID (ROMAddr, ModeNo, &ModeIdIndex); /* 2.Get ModeID Table */


+ if (temp == 0)

+ return (0);
+ /*301b */
+ SiS_GetVBType (BaseAddr);
+ /*end 301b */
+ SiS_GetVBInfo301 (BaseAddr, ROMAddr, ModeNo, ModeIdIndex, HwDeviceExtension); /*add for CRT2 */
+ SiS_GetLCDResInfo301 (ROMAddr, SiS_P3d4, ModeNo, ModeIdIndex); /*add for CRT2 */
+
+ temp = SiS_CheckMemorySize (ROMAddr, HwDeviceExtension, ModeNo, ModeIdIndex); /*3.Check memory size */


+ if (temp == 0)

+ return (0);
+ if (SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) { /*301b */
+ SiS_SetCRT1Group (ROMAddr, HwDeviceExtension, ModeNo,
+ ModeIdIndex);
+ } else {
+ if (!(SiS_VBInfo & SwitchToCRT2)) {
+ SiS_SetCRT1Group (ROMAddr, HwDeviceExtension, ModeNo,
+ ModeIdIndex);
+ }
+ }
+
+ if (SiS_VBInfo & (SetSimuScanMode | SwitchToCRT2 | SetCRT2ToLCDA)) { /*301b */
+ switch (HwDeviceExtension->ujVBChipID) {
+/*karl*/
+ case VB_CHIP_301:
+ case VB_CHIP_301B:
+ SiS_SetCRT2Group301 (BaseAddr, ROMAddr, ModeNo, HwDeviceExtension); /*add for CRT2 */
+ break;
+ case VB_CHIP_302:
+ SiS_SetCRT2Group301 (BaseAddr, ROMAddr, ModeNo,
+ HwDeviceExtension);
+ break;
+ case VB_CHIP_303:
+/* SetCRT2Group302(BaseAddr,ROMAddr,ModeNo, HwDeviceExtension); add for CRT2 */
+ break;
+ case VB_CHIP_UNKNOWN: /*add for lvds ch7005 */
+ temp = SiS_GetReg1 (SiS_P3d4, 0x37);
+ if (temp &
+ (ExtChipLVDS | ExtChipTrumpion | ExtChipCH7005)) {
+ SiS_SetCRT2Group301 (BaseAddr, ROMAddr, ModeNo,
+ HwDeviceExtension);
+ }
+ break;
+ }
+ }
+ if (KeepLockReg == 0xA1)
+ SiS_SetReg1 (SiS_P3c4, 0x05, 0x86); /* 05/02/01 ynlai */
+ else
+ SiS_SetReg1 (SiS_P3c4, 0x05, 0x00);
+ return TRUE;
+}
+
+void
+SiS_SetCRT1Group (ULONG ROMAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT ModeNo, USHORT ModeIdIndex)
+{
+ USHORT StandTableIndex, RefreshRateTableIndex;
+ USHORT temp;
+
+ /*SiS_SetReg1(SiS_P3d4,0x34,ModeNo); */
+ SiS_CRT1Mode = ModeNo;
+ /* set CR34->CRT1 ModeNofor CRT2 FIFO */
+ StandTableIndex = SiS_GetModePtr (ROMAddr, ModeNo, ModeIdIndex); /* 4.GetModePtr */
+ SiS_SetSeqRegs (ROMAddr, StandTableIndex); /* 5.SetSeqRegs */
+ SiS_SetMiscRegs (ROMAddr, StandTableIndex); /* 6.SetMiscRegs */
+ SiS_SetCRTCRegs (ROMAddr, HwDeviceExtension, StandTableIndex); /* 7.SetCRTCRegs */
+ SiS_SetATTRegs (ROMAddr, StandTableIndex); /* 8.SetATTRegs */
+ SiS_SetGRCRegs (ROMAddr, StandTableIndex); /* 9.SetGRCRegs */
+ SiS_ClearExt1Regs (); /* 10.Clear Ext1Regs */
+ temp = ~ProgrammingCRT2; /* 11.GetRatePtr */
+ SiS_SetFlag = SiS_SetFlag & temp;
+ SiS_SelectCRT2Rate = 0;


+ /*301b */
+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B)) {

+ if (SiS_VBInfo & SetCRT2ToLCDA) {

+ SiS_SetFlag = SiS_SetFlag | ProgrammingCRT2;

+ /* SiS_SelectCRT2Rate=4; */
+ }
+ }


+ /*end 301b */
+

+ RefreshRateTableIndex = SiS_GetRatePtrCRT2 (ROMAddr, ModeNo, ModeIdIndex); /* 11.GetRatePtr */
+


+ /*301b */
+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B)) {

+ if (!(SiS_VBInfo & SetCRT2ToLCDA)) {


+ SiS_SetFlag = SiS_SetFlag & (~ProgrammingCRT2);
+ }
+ }

+ /*end 301b */
+

+ if (RefreshRateTableIndex != 0xFFFF) {
+ SiS_SetSync (ROMAddr, RefreshRateTableIndex); /* 12.SetSync */
+ SiS_SetCRT1CRTC (ROMAddr, ModeNo, ModeIdIndex, RefreshRateTableIndex); /* 13.SetCRT1CRTC */
+ SiS_SetCRT1Offset (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, HwDeviceExtension); /* 14.SetCRT1Offset */
+ SiS_SetCRT1VCLK (ROMAddr, ModeNo, ModeIdIndex,
+ HwDeviceExtension, RefreshRateTableIndex); /* 15.SetCRT1VCLK */
+ }
+#ifdef CONFIG_FB_SIS_300
+ if ((HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_540)) {
+ SiS_SetCRT1FIFO2 (ROMAddr, ModeNo, HwDeviceExtension,
+ RefreshRateTableIndex);
+ }
+#endif
+#ifdef CONFIG_FB_SIS_315


+ if (HwDeviceExtension->jChipType >= SIS_315H) {

+ SiS_SetCRT1FIFO (ROMAddr, ModeNo, HwDeviceExtension);
+ }
+#endif
+ SiS_SetCRT1ModeRegs (ROMAddr, HwDeviceExtension, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex);
+ SiS_SetVCLKState (ROMAddr, HwDeviceExtension, ModeNo,
+ RefreshRateTableIndex);
+#ifdef CONFIG_FB_SIS_315


+ if (HwDeviceExtension->jChipType > SIS_315H)

+ SiS_SetInterlace (ROMAddr, ModeNo, RefreshRateTableIndex);
+#endif
+ SiS_LoadDAC (ROMAddr, ModeNo, ModeIdIndex);
+ if (flag_clearbuffer)
+ SiS_ClearBuffer (HwDeviceExtension, ModeNo);
+
+ if (!(SiS_VBInfo & (SetSimuScanMode | SwitchToCRT2 | SetCRT2ToLCDA))) { /*301b */
+ SiS_LongWait ();
+ SiS_DisplayOn ();
+ }
+}
+
+void
+SiS_GetVBType (USHORT BaseAddr)
+{
+ USHORT flag;
+
+ flag = SiS_GetReg1 (SiS_Part4Port, 0x00);
+ if (flag >= 2)
+ SiS_VBType = VB_SIS302B;
+ else {
+ flag = SiS_GetReg1 (SiS_Part4Port, 0x01);
+ if (flag >= 0xB0)
+ SiS_VBType = VB_SIS301B;
+ else
+ SiS_VBType = VB_SIS301;
+
+ flag = SiS_GetReg1 (SiS_Part4Port, 0x23); /*301dlvds */
+ if (!(flag & 0x02))
+ SiS_VBType = SiS_VBType | VB_NoLCD;
+ }
+
+}
+
+/* win2000 MM adapter not support standard mode */
+BOOLEAN
+SiS_SearchModeID (ULONG ROMAddr, USHORT ModeNo, USHORT * ModeIdIndex)
+{
+ PUCHAR VGA_INFO = "\0x11";
+
+ if (ModeNo <= 5)
+ ModeNo |= 1;


+ if (ModeNo <= 0x13) {

+ /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(SiS_SModeIDTable)/sizeof(SiS_StStruct);(*ModeIdIndex)++) */
+ for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
+ if (SiS_SModeIDTable[*ModeIdIndex].St_ModeID == ModeNo)
+ break;
+ if (SiS_SModeIDTable[*ModeIdIndex].St_ModeID == 0xFF)
+ return FALSE;
+ }
+
+#ifdef TC
+ VGA_INFO = (PUCHAR) MK_FP (0, 0x489);
+#endif
+ if (ModeNo == 0x07) {
+ if ((*VGA_INFO & 0x10) != 0)
+ (*ModeIdIndex)++; /* 400 lines */
+ /* else 350 lines */
+ }
+ if (ModeNo <= 3) {
+ if ((*VGA_INFO & 0x80) == 0) {
+ (*ModeIdIndex)++;
+ if ((*VGA_INFO & 0x10) != 0)
+ (*ModeIdIndex)++;; /* 400 lines */
+ /* else 350 lines */
+ }
+ /* else 200 lines */
+ }
+ } else {
+ /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(SiS_EModeIDTable)/sizeof(SiS_ExtStruct);(*ModeIdIndex)++) */
+ for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
+ if (SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == ModeNo)
+ break;
+ if (SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/*add for 300 oem util for search VBModeID*/
+BOOLEAN
+SiS_SearchVBModeID (ULONG ROMAddr, USHORT ModeNo)
+{
+ USHORT ModeIdIndex;
+
+ // PUCHAR VGA_INFO;
+
+ if (ModeNo <= 5)
+ ModeNo |= 1;
+ /* for (ModeIdIndex=0;ModeIdIndex<sizeof(SiS_SModeIDTable)/sizeof(SiS_StStruct);(*ModeIdIndex)++) */
+ for (ModeIdIndex = 0;; (ModeIdIndex)++) {
+ if (SiS_VBModeIDTable[ModeIdIndex].ModeID == ModeNo)
+ break;
+ if (SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF)
+ return FALSE;
+ }
+#ifdef TC
+ VGA_INFO = (PUCHAR) MK_FP (0, 0x489);
+ if (ModeNo == 0x07) {
+ if ((*VGA_INFO & 0x10) != 0)
+ (ModeIdIndex)++; /* 400 lines */
+ /* else 350 lines */
+ }
+ if (ModeNo <= 3) {
+ if ((*VGA_INFO & 0x80) == 0) {
+ (ModeIdIndex)++;
+ if ((*VGA_INFO & 0x10) != 0)
+ (ModeIdIndex)++;; /* 400 lines */
+ /* else 350 lines */
+ }
+ /* else 200 lines */
+ }
+#endif
+ return ((BOOLEAN) ModeIdIndex);
+}
+
+/*end*/
+
+/* win2000 MM adapter not support standard mode! */
+
+BOOLEAN
+SiS_CheckMemorySize (ULONG ROMAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT ModeNo, USHORT ModeIdIndex)
+{
+ USHORT memorysize;
+ USHORT modeflag;
+ USHORT temp;


+
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+

+/* ModeType=modeflag&ModeInfoFlag; Get mode type */
+
+ memorysize = modeflag & MemoryInfoFlag;
+ memorysize = memorysize > MemorySizeShift;
+ memorysize++; /* Get memory size */
+
+ temp = SiS_GetReg1 (SiS_P3c4, 0x14); /* Get DRAM Size */


+ if ((HwDeviceExtension->jChipType == SIS_315H) ||

+ (HwDeviceExtension->jChipType == SIS_315PRO)) {
+ temp = 1 << ((temp & 0x0F0) >> 4);
+ if ((temp & 0x0c) == 0x08) { /* DDR asymetric */
+ temp += temp / 2;
+ } else {
+ if ((temp & 0x0c) != 0) {


+ temp <<= 1;
+ }

+ }
+ } else { /* 300, 540 , 630 */
+
+ temp = temp & 0x3F;
+ temp++;
+ /* temp=1 << ((temp&0x0F0)>>4); */
+ }
+
+ if ((HwDeviceExtension->jChipType == SIS_550) || /* 05/02/01 ynlai for sis550 */


+ (HwDeviceExtension->jChipType == SIS_640) || /* 08/20/01 chiawen for 640/740 */
+ (HwDeviceExtension->jChipType == SIS_740)) { /* 09/03/01 chiawen for 650 */

+ return (TRUE);
+ }
+
+ if (temp < memorysize)
+ return (FALSE);
+ else
+ return (TRUE);
+}
+
+UCHAR
+SiS_GetModePtr (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex)
+{
+ UCHAR index;


+
+ if (ModeNo <= 0x13) {

+ index = SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
+ } else {
+ if (SiS_ModeType <= 0x02)
+ index = 0x1B; /* 02 -> ModeEGA */
+ else
+ index = 0x0F;
+ }
+
+ return index; /* Get SiS_StandTable index */
+}
+
+void
+SiS_SetSeqRegs (ULONG ROMAddr, USHORT StandTableIndex)
+{
+ UCHAR SRdata;
+ USHORT i;
+
+ SiS_SetReg1 (SiS_P3c4, 0x00, 0x03); /* Set SR0 */
+ SRdata = SiS_StandTable[StandTableIndex].SR[0];


+ /*301b */
+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B)) {

+ if (SiS_VBInfo & SetCRT2ToLCDA) {

+ SRdata = SRdata | 0x01;
+ }
+ }
+


+ /*end 301b */
+

+ if (SiS_IF_DEF_LVDS == 1) {

+ if (SiS_IF_DEF_CH7005 == 1) {
+ if (SiS_VBInfo & SetCRT2ToTV) {

+ if (SiS_VBInfo & SetInSlaveMode) {
+ SRdata = SRdata | 0x01; /* 8 dot clock */
+ }
+ }
+ }


+ if (SiS_VBInfo & SetCRT2ToLCD) {

+ if (SiS_VBInfo & SetInSlaveMode) {
+ SRdata = SRdata | 0x01; /* 8 dot clock */
+ }
+ }
+ }
+
+ SRdata = SRdata | 0x20; /* screen off */
+ SiS_SetReg1 (SiS_P3c4, 0x01, SRdata); /* Set SR1 */
+ for (i = 02; i <= 04; i++) {
+ SRdata = SiS_StandTable[StandTableIndex].SR[i - 1]; /* Get SR2,3,4 from file */
+ SiS_SetReg1 (SiS_P3c4, i, SRdata); /* Set SR2 3 4 */
+ }
+}
+
+void
+SiS_SetMiscRegs (ULONG ROMAddr, USHORT StandTableIndex)
+{
+ UCHAR Miscdata;
+
+ Miscdata = SiS_StandTable[StandTableIndex].MISC; /* Get Misc from file */


+ /*301b */
+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B)) {

+ if (SiS_VBInfo & SetCRT2ToLCDA) {

+ Miscdata = Miscdata | 0x0C;
+ }
+ }
+ /*end 301b */
+ SiS_SetReg3 (SiS_P3c2, Miscdata); /* Set Misc(3c2) */
+}
+
+void
+SiS_SetCRTCRegs (ULONG ROMAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT StandTableIndex)
+{
+ UCHAR CRTCdata;
+ USHORT i;
+
+ CRTCdata = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x11);
+ CRTCdata = CRTCdata & 0x7f;
+ SiS_SetReg1 (SiS_P3d4, 0x11, CRTCdata); /* Unlock CRTC */
+
+ for (i = 0; i <= 0x18; i++) {
+ CRTCdata = SiS_StandTable[StandTableIndex].CRTC[i]; /* Get CRTC from file */
+ SiS_SetReg1 (SiS_P3d4, i, CRTCdata); /* Set CRTC(3d4) */
+ }
+ if ((HwDeviceExtension->jChipType == SIS_630) &&
+ (HwDeviceExtension->jChipRevision == 0x30)) { /* for 630S0 */


+ if (SiS_VBInfo & SetInSlaveMode) {

+ if (SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
+ SiS_SetReg1 (SiS_P3d4, 0x18, 0xFE);


+ }
+ }
+ }
+}
+

+void
+SiS_SetATTRegs (ULONG ROMAddr, USHORT StandTableIndex)
+{
+ UCHAR ARdata;
+ USHORT i;
+
+ for (i = 0; i <= 0x13; i++) {
+ ARdata = SiS_StandTable[StandTableIndex].ATTR[i]; /* Get AR for file */


+ /*301b */
+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B)) {

+ if (SiS_VBInfo & SetCRT2ToLCDA) {

+ if (i == 0x13) {
+ ARdata = 0;
+ }
+ }
+ }
+ /*end 301b */
+ if (SiS_IF_DEF_LVDS == 1) { /*for LVDS */


+ if (SiS_IF_DEF_CH7005 == 1) {
+ if (SiS_VBInfo & SetCRT2ToTV) {

+ if (SiS_VBInfo & SetInSlaveMode) {

+ if (i == 0x13) {
+ ARdata = 0;
+ }
+ }
+ }
+ }


+ if (SiS_VBInfo & SetCRT2ToLCD) {

+ if (SiS_VBInfo & SetInSlaveMode) {

+ if (SiS_LCDInfo & LCDNonExpanding) {

+ if (i == 0x13) {
+ ARdata = 0;


+ }
+ }
+ }
+ }
+ }

+ SiS_GetReg2 (SiS_P3da); /* reset 3da */
+ SiS_SetReg3 (SiS_P3c0, i); /* set index */
+ SiS_SetReg3 (SiS_P3c0, ARdata); /* set data */
+ }
+ SiS_GetReg2 (SiS_P3da); /* reset 3da */
+ SiS_SetReg3 (SiS_P3c0, 0x14); /* set index */
+ SiS_SetReg3 (SiS_P3c0, 0x00); /* set data */
+
+ SiS_GetReg2 (SiS_P3da); /* Enable Attribute */
+ SiS_SetReg3 (SiS_P3c0, 0x20);
+}
+
+void
+SiS_SetGRCRegs (ULONG ROMAddr, USHORT StandTableIndex)
+{
+ UCHAR GRdata;
+ USHORT i;
+
+ for (i = 0; i <= 0x08; i++) {
+ GRdata = SiS_StandTable[StandTableIndex].GRC[i]; /* Get GR from file */
+ SiS_SetReg1 (SiS_P3ce, i, GRdata); /* Set GR(3ce) */
+ }
+
+ if (SiS_ModeType > ModeVGA) {
+ GRdata = (UCHAR) SiS_GetReg1 (SiS_P3ce, 0x05);
+ GRdata = GRdata & 0xBF; /* 256 color disable */
+ SiS_SetReg1 (SiS_P3ce, 0x05, GRdata);
+ }
+}
+
+void
+SiS_ClearExt1Regs ()
+{
+ USHORT i;
+
+ for (i = 0x0A; i <= 0x0E; i++)
+ SiS_SetReg1 (SiS_P3c4, i, 0x00); /* Clear SR0A-SR0E */
+}
+
+void
+SiS_SetSync (ULONG ROMAddr, USHORT RefreshRateTableIndex)
+{
+ USHORT sync;
+ USHORT temp;
+
+ sync = SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag >> 8; /* di+0x00 */
+
+ sync = sync & 0xC0;
+ temp = 0x2F;
+ temp = temp | sync;
+ SiS_SetReg3 (SiS_P3c2, temp); /* Set Misc(3c2) */
+}
+
+void
+SiS_SetCRT1CRTC (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex)
+{
+ UCHAR index;
+ UCHAR data;
+ USHORT temp, tempah, i, modeflag, j;
+ USHORT ResInfo, DisplayType;
+ SiS_LCDACRT1DataStruct *LCDACRT1Ptr = NULL;
+ if ((SiS_VBType & VB_SIS302B) && (SiS_VBInfo & SetCRT2ToLCDA)) {
+ /*add crt1ptr */


+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */

+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+ }

+ temp =
+ SiS_GetLCDACRT1Ptr (ROMAddr, ModeNo, ModeIdIndex,


+ RefreshRateTableIndex, &ResInfo,
+ &DisplayType);
+

+ switch (DisplayType) {
+ case 0:

+ LCDACRT1Ptr = SiS_LCDACRT1800x600_1;


+ break;
+ case 1:

+ LCDACRT1Ptr = SiS_LCDACRT11024x768_1;


+ break;
+ case 2:

+ LCDACRT1Ptr = SiS_LCDACRT11280x1024_1;


+ break;
+ case 3:

+ LCDACRT1Ptr = SiS_LCDACRT1800x600_1_H;


+ break;
+ case 4:

+ LCDACRT1Ptr = SiS_LCDACRT11024x768_1_H;


+ break;
+ case 5:

+ LCDACRT1Ptr = SiS_LCDACRT11280x1024_1_H;


+ break;
+ case 6:

+ LCDACRT1Ptr = SiS_LCDACRT1800x600_2;


+ break;
+ case 7:

+ LCDACRT1Ptr = SiS_LCDACRT11024x768_2;


+ break;
+ case 8:

+ LCDACRT1Ptr = SiS_LCDACRT11280x1024_2;


+ break;
+ case 9:

+ LCDACRT1Ptr = SiS_LCDACRT1800x600_2_H;


+ break;
+ case 10:

+ LCDACRT1Ptr = SiS_LCDACRT11024x768_2_H;


+ break;
+ case 11:

+ LCDACRT1Ptr = SiS_LCDACRT11280x1024_2_H;
+ break;
+ /*case 12: LCDACRT1Ptr = SiS_CHTVCRT1UNTSC; break;
+ case 13: LCDACRT1Ptr = SiS_CHTVCRT1ONTSC; break;
+ case 14: LCDACRT1Ptr = SiS_CHTVCRT1UPAL; break;
+ case 15: LCDACRT1Ptr = SiS_CHTVCRT1OPAL; break; */
+ }
+
+ tempah = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x11); /*unlock cr0-7 */
+ tempah = tempah & 0x7F;
+ SiS_SetReg1 (SiS_P3d4, 0x11, tempah);
+ tempah = (LCDACRT1Ptr + ResInfo)->CR[0];
+ SiS_SetReg1 (SiS_P3d4, 0x0, tempah);
+ for (i = 0x01, j = 1; i <= 0x07; i++, j++) {
+ tempah = (LCDACRT1Ptr + ResInfo)->CR[j];
+ SiS_SetReg1 (SiS_P3d4, i, tempah);
+ }
+/* for(i=0x06,j=5;i<=0x07;i++,j++){
+ tempah = (LCDACRT1Ptr+ResInfo)->CR[j];
+ SiS_SetReg1(SiS_P3d4,i,tempah);
+ }*/
+ for (i = 0x10, j = 8; i <= 0x12; i++, j++) {
+ tempah = (LCDACRT1Ptr + ResInfo)->CR[j];
+ SiS_SetReg1 (SiS_P3d4, i, tempah);
+ }
+ for (i = 0x15, j = 11; i <= 0x16; i++, j++) {
+ tempah = (LCDACRT1Ptr + ResInfo)->CR[j];
+ SiS_SetReg1 (SiS_P3d4, i, tempah);
+ }
+
+ for (i = 0x0A, j = 13; i <= 0x0C; i++, j++) {
+ tempah = (LCDACRT1Ptr + ResInfo)->CR[j];
+ SiS_SetReg1 (SiS_P3c4, i, tempah);
+ }
+
+ tempah = (LCDACRT1Ptr + ResInfo)->CR[16];
+ tempah = tempah & 0x0E0;
+ SiS_SetReg1 (SiS_P3c4, 0x0E, tempah);
+
+ tempah = (LCDACRT1Ptr + ResInfo)->CR[16];
+ tempah = tempah & 0x01;


+ tempah = tempah << 5;

+ if (modeflag & DoubleScanMode) {

+ tempah = tempah | 0x080;
+ }

+ SiS_SetRegANDOR (SiS_P3d4, 0x09, ~0x020, tempah);
+ if (SiS_ModeType > 0x03)
+ SiS_SetReg1 (SiS_P3d4, 0x14, 0x4F);
+/*end 301b*/
+ } else {
+ index = SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; /* Get index */


+ index = index & 0x3F;
+

+ data = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x11);
+ data = data & 0x7F;
+ SiS_SetReg1 (SiS_P3d4, 0x11, data); /* Unlock CRTC */
+
+ for (i = 0, j = 0; i <= 07; i++, j++) {
+ data = SiS_CRT1Table[index].CR[i];
+ SiS_SetReg1 (SiS_P3d4, j, data);
+ }
+ for (j = 0x10; i <= 10; i++, j++) {
+ data = SiS_CRT1Table[index].CR[i];
+ SiS_SetReg1 (SiS_P3d4, j, data);
+ }
+ for (j = 0x15; i <= 12; i++, j++) {
+ data = SiS_CRT1Table[index].CR[i];
+ SiS_SetReg1 (SiS_P3d4, j, data);
+ }
+ for (j = 0x0A; i <= 15; i++, j++) {
+ data = SiS_CRT1Table[index].CR[i];
+ SiS_SetReg1 (SiS_P3c4, j, data);
+ }
+
+ data = SiS_CRT1Table[index].CR[16];
+ data = data & 0xE0;
+ SiS_SetReg1 (SiS_P3c4, 0x0E, data);
+
+ data = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x09);
+ data = data & 0xDF; /* clear CR9 D[5] */
+ i = SiS_CRT1Table[index].CR[16];
+ i = i & 0x01;
+ i = i << 5;
+ data = data | i;


+
+ if (ModeNo <= 0x13)

+ i = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ else
+ i = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+
+ i = i & DoubleScanMode;
+ if (i)
+ data = data | 0x80;
+ SiS_SetReg1 (SiS_P3d4, 0x09, data);
+
+ if (SiS_ModeType > 0x03)
+ SiS_SetReg1 (SiS_P3d4, 0x14, 0x4F);
+ }
+}
+void
+SiS_SetCRT1Offset (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,


+ USHORT RefreshRateTableIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{

+ USHORT temp, ah, al;
+ USHORT temp2, i;
+ USHORT DisplayUnit;
+
+ /* Alan */
+ temp = SiS_EModeIDTable[ModeIdIndex].Ext_ModeInfo;


+ if (HwDeviceExtension->jChipType >= SIS_315H) {

+ temp = temp >> 8; /* sis310 *//* index */
+ } else {
+ temp = temp >> 4; /* sis300 *//* index */
+ }
+ temp = SiS_ScreenOffset[temp];


+ if ((ModeNo >= 0x7C) && (ModeNo <= 0x7E)) {

+ temp = 0x6B;
+ temp2 = ModeNo - 0x7C;
+ } else {
+ temp2 = SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+ temp2 = temp2 & InterlaceMode;
+ if (temp2)


+ temp = temp << 1;

+ temp2 = SiS_ModeType - ModeEGA;
+ }
+ switch (temp2) {
+ case 0:
+ temp2 = 1;


+ break;
+ case 1:

+ temp2 = 2;
+ break;
+ case 2:
+ temp2 = 4;
+ break;
+ case 3:
+ temp2 = 4;


+ break;
+ case 4:

+ temp2 = 6;


+ break;
+ case 5:

+ temp2 = 8;
+ break;
+ }
+ temp = temp * temp2;
+ DisplayUnit = temp;
+
+ temp2 = temp;
+ temp = temp >> 8; /* ah */


+ temp = temp & 0x0F;

+ i = SiS_GetReg1 (SiS_P3c4, 0x0E);
+ i = i & 0xF0;
+ i = i | temp;
+ SiS_SetReg1 (SiS_P3c4, 0x0E, i);
+
+ temp = (UCHAR) temp2;
+ temp = temp & 0xFF; /* al */
+ SiS_SetReg1 (SiS_P3d4, 0x13, temp);
+
+ temp2 = SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+ temp2 = temp2 & InterlaceMode;
+ if (temp2)
+ DisplayUnit >>= 1;
+
+ DisplayUnit = DisplayUnit << 5;
+ ah = (DisplayUnit & 0xff00) >> 8;
+ al = DisplayUnit & 0x00ff;
+ if (al == 0)
+ ah = ah + 1;
+ else
+ ah = ah + 2;
+ SiS_SetReg1 (SiS_P3c4, 0x10, ah);
+}
+
+void
+SiS_SetCRT1VCLK (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT RefreshRateTableIndex)
+{
+ UCHAR index, data;
+ USHORT vclkindex;


+ if (SiS_IF_DEF_LVDS == 1) {

+ vclkindex =
+ SiS_GetVCLK2Ptr (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, HwDeviceExtension);
+ data = SiS_GetReg1 (SiS_P3c4, 0x31) & 0xCF;
+ SiS_SetReg1 (SiS_P3c4, 0x31, data);
+
+ data = SiS_VCLKData[vclkindex].SR2B;
+ SiS_SetReg1 (SiS_P3c4, 0x2B, data);
+ data = SiS_VCLKData[vclkindex].SR2C;
+ SiS_SetReg1 (SiS_P3c4, 0x2C, data);


+
+ if (HwDeviceExtension->jChipType < SIS_315H)

+ SiS_SetReg1 (SiS_P3c4, 0x2D, 0x80);
+ else
+ SiS_SetReg1 (SiS_P3c4, 0x2D, 0x01);
+
+ }
+ else


+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))

+ && (SiS_VBInfo & SetCRT2ToLCDA) && (SiS_IF_DEF_LVDS == 0)) {
+ vclkindex =
+ SiS_GetVCLK2Ptr (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, HwDeviceExtension);
+ data = SiS_GetReg1 (SiS_P3c4, 0x31) & 0xCF;
+ SiS_SetReg1 (SiS_P3c4, 0x31, data);
+
+ data = SiS_VBVCLKData[vclkindex].Part4_A;
+ SiS_SetReg1 (SiS_P3c4, 0x2B, data);
+ data = SiS_VBVCLKData[vclkindex].Part4_B;
+ SiS_SetReg1 (SiS_P3c4, 0x2C, data);


+
+ if (HwDeviceExtension->jChipType < SIS_315H)

+ SiS_SetReg1 (SiS_P3c4, 0x2D, 0x80); /* for300 series */
+ else
+ SiS_SetReg1 (SiS_P3c4, 0x2D, 0x01);
+
+ } else {
+ index = SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;


+ /*if(HwDeviceExtension->jChipType < SIS_315H) { */

+ index = index & 0x3F;

+ /*} */
+ data = SiS_GetReg1 (SiS_P3c4, 0x31) & 0xCF;
+/*SiS_SetReg1(SiS_P3c4,0x31,0x00); *//* for300 */
+ SiS_SetReg1 (SiS_P3c4, 0x31, data);
+ SiS_SetReg1 (SiS_P3c4, 0x2B, SiS_VCLKData[index].SR2B);
+ SiS_SetReg1 (SiS_P3c4, 0x2C, SiS_VCLKData[index].SR2C);


+ if (HwDeviceExtension->jChipType < SIS_315H)

+ SiS_SetReg1 (SiS_P3c4, 0x2D, 0x80); /* for300 series */
+ else
+ SiS_SetReg1 (SiS_P3c4, 0x2D, 0x01); /* for310 series */
+ }
+}
+void
+SiS_IsLowResolution (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex)
+{
+ USHORT data;
+ USHORT ModeFlag;
+
+ data = SiS_GetReg1 (SiS_P3c4, 0x0F);
+ data = data & 0x7F;
+ SiS_SetReg1 (SiS_P3c4, 0x0F, data);


+
+ if (ModeNo > 0x13) {

+ ModeFlag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ if ((ModeFlag & HalfDCLK) && (ModeFlag & DoubleScanMode)) {
+ data = SiS_GetReg1 (SiS_P3c4, 0x0F);
+ data = data | 0x80;
+ SiS_SetReg1 (SiS_P3c4, 0x0F, data);
+ data = SiS_GetReg1 (SiS_P3c4, 0x01);
+ data = data & 0xF7;
+ SiS_SetReg1 (SiS_P3c4, 0x01, data);
+ }
+ }
+}
+
+void
+SiS_SetCRT1ModeRegs (ULONG ROMAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex)
+{
+ USHORT data, data2, data3;
+ USHORT infoflag = 0, modeflag;
+ USHORT resindex, xres;


+
+ if (ModeNo > 0x13) {

+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;

+ infoflag = SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;

+ } else {


+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ModeFlag */
+ }

+ SiS_SetRegANDOR (SiS_P3c4, 0x1F, 0x3F, 0x00);
+ if (ModeNo > 0x13)
+ data = infoflag;
+ else
+ data = 0;
+ data2 = 0;
+ if (ModeNo > 0x13) {
+ if (SiS_ModeType > 0x02) {
+ data2 = data2 | 0x02;
+ data3 = SiS_ModeType - ModeVGA;
+ data3 = data3 << 2;
+ data2 = data2 | data3;
+ }
+ }
+ data = data & InterlaceMode;
+ if (data)
+ data2 = data2 | 0x20;
+ SiS_SetReg1 (SiS_P3c4, 0x06, data2);
+ if ((HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_540) ||
+ (HwDeviceExtension->jChipType == SIS_730)) {


+ resindex = SiS_GetResInfo (ROMAddr, ModeNo, ModeIdIndex);
+ if (ModeNo <= 0x13) {
+ xres = SiS_StResInfo[resindex].HTotal;

+ } else {
+ xres = SiS_ModeResInfo[resindex].HTotal; /* xres->ax */
+ }

+ data = 0x0000;


+ if (infoflag & InterlaceMode) {

+ if (xres == 1024)
+ data = 0x0035;
+ if (xres == 1280)
+ data = 0x0048;
+ }
+ data2 = data & 0x00FF;
+ SiS_SetRegANDOR (SiS_P3d4, 0x19, 0xFF, data2);
+ data2 = (data & 0xFF00) >> 8;
+ SiS_SetRegANDOR (SiS_P3d4, 0x19, 0xFC, data2);
+ }
+ if (modeflag & HalfDCLK) {
+ SiS_SetRegANDOR (SiS_P3c4, 0x01, 0xFF, 0x01);
+ }
+
+ if ((HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_540) ||
+ (HwDeviceExtension->jChipType == SIS_730)) {
+ } else {
+ if (modeflag & LineCompareOff) {
+ SiS_SetRegANDOR (SiS_P3c4, 0x0F, 0xF7, 0x08);
+ } else {
+ SiS_SetRegANDOR (SiS_P3c4, 0x0F, 0xF7, 0x00);
+ }
+ }
+
+ data = 0x60;
+ if (SiS_ModeType != ModeText) {
+ data = data ^ 0x60;
+ if (SiS_ModeType != ModeEGA) {
+ data = data ^ 0xA0;
+ }
+ }
+ SiS_SetRegANDOR (SiS_P3c4, 0x21, 0x1F, data);
+}
+
+void
+SiS_SetVCLKState (ULONG ROMAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT ModeNo, USHORT RefreshRateTableIndex)
+{
+ USHORT data, data2 = 0;
+ USHORT VCLK;
+ UCHAR index;


+
+ if (ModeNo <= 0x13)

+ VCLK = 0;
+ else {
+ index = SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;


+ /*if(HwDeviceExtension->jChipType < SIS_315H) { */

+ index = index & 0x3F;

+ /*} */


+ VCLK = SiS_VCLKData[index].CLOCK;

+ }


+
+ if (HwDeviceExtension->jChipType < SIS_315H) {

+ data2 = 0x00;
+ if (VCLK > 150)
+ data2 = data2 | 0x80;
+ SiS_SetRegANDOR (SiS_P3c4, 0x07, 0x7B, data2);
+
+ data2 = 0x00;
+ if (VCLK >= 150)
+ data2 = data2 | 0x08; /* VCLK > 150 */
+ SiS_SetRegANDOR (SiS_P3c4, 0x32, 0xF7, data2);


+ } else { /* 310 series */
+

+ data = SiS_GetReg1 (SiS_P3c4, 0x32);
+ data = data & 0xf3;
+ if (VCLK >= 200)
+ data = data | 0x0c; /* VCLK > 200 */
+ SiS_SetReg1 (SiS_P3c4, 0x32, data);
+ data = SiS_GetReg1 (SiS_P3c4, 0x1F);
+ data &= 0xE7;
+ if (VCLK < 200)
+ data |= 0x10;
+ SiS_SetReg1 (SiS_P3c4, 0x1F, data);


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

echo 'End of part 076'
echo 'File patch-2.4.15 is continued in part 077'
echo "077" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:55 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part079

#!/bin/sh -x
# this is part 079 of a 115 - part archive


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

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

+ SiS_SetCH7005 (0x090E);
+ }
+ SiS_DisplayOff ();


+ SiS_SetRegANDOR (SiS_P3c4, 0x32, 0xDF, 0x00);

+ SiS_SetRegANDOR (SiS_P3c4, 0x1E, 0xDF, 0x00);

+ SiS_UnLockCRT2 (HwDeviceExtension, BaseAddr);
+ SiS_SetRegANDOR (SiS_Part1Port, 0x01, 0xFF, 0x80);
+ SiS_SetRegANDOR (SiS_Part1Port, 0x02, 0xFF, 0x40);
+ }
+/*SetPanelDelay(0); */
+ SiS_SetRegANDOR (SiS_P3c4, 0x11, 0xFB, 0x04);
+}
+
+void
+SiS_EnableBridge (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr)
+{
+ USHORT temp, tempah;
+
+ SiS_SetRegANDOR (SiS_P3c4, 0x11, 0xFB, 0x00);
+/*SetPanelDelay(0); */


+ if (SiS_IF_DEF_LVDS == 0) {

+ if ((!(SiS_IsVAMode (BaseAddr)))


+ && ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))) {

+ SiS_SetRegANDOR (SiS_Part2Port, 0x00, 0x1F, 0x20);
+ } else {
+ temp = SiS_GetReg1 (SiS_P3c4, 0x32);
+ temp = temp & 0xDF;
+ if (SiS_BridgeInSlave ()) {
+ tempah = SiS_GetReg1 (SiS_P3d4, 0x30);
+ if (!(tempah & SetCRT2ToRAMDAC)) {
+ temp = temp | 0x20;
+ }
+ }
+ SiS_SetReg1 (SiS_P3c4, 0x32, temp);


+ SiS_SetRegANDOR (SiS_P3c4, 0x1E, 0xFF, 0x20);

+ if (HwDeviceExtension->jChipType >= SIS_315H) { /* 310 series */

+ temp = SiS_GetReg1 (SiS_Part1Port, 0x2E);


+ if (!(temp & 0x80))

+ SiS_SetRegOR (SiS_Part1Port, 0x2E, 0x80); /* by alan,BVBDOENABLE=1 */
+
+ }
+ SiS_SetRegANDOR (SiS_Part2Port, 0x00, 0x1F, 0x20);
+
+ if (HwDeviceExtension->jChipType >= SIS_315H) { /* 310 series */
+ temp = SiS_GetReg1 (SiS_Part1Port, 0x2E);


+ if (!(temp & 0x80))

+ SiS_SetRegOR (SiS_Part1Port, 0x2E, 0x80); /* by alan,BVBDOENABLE=1 */
+ }
+
+ SiS_SetRegANDOR (SiS_Part2Port, 0x00, 0x1F, 0x20);
+ SiS_VBLongWait ();
+ SiS_DisplayOn ();
+ SiS_VBLongWait ();
+ }
+ /*add301b */


+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B)) {

+ if (!(SiS_Is301B (BaseAddr))) {
+ temp = SiS_GetReg1 (SiS_Part1Port, 0x2E);


+ if (!(temp & 0x80))

+ SiS_SetRegOR (SiS_Part1Port, 0x2E,
+ 0x80);


+ if ((!(SiS_IsDualEdge (BaseAddr)))
+ && (!(SiS_IsVAMode (BaseAddr))))

+ tempah = 0x80;


+ else if ((!(SiS_IsDualEdge (BaseAddr)))
+ && (SiS_IsVAMode (BaseAddr)))

+ tempah = 0x40;
+ else
+ tempah = 0xC0;
+ SiS_SetRegOR (SiS_Part4Port, 0x1F, tempah);


+ }
+ }
+ /*end 301b */

+ } else {
+ /*LVDS*/ SiS_EnableCRT2 ();
+ SiS_DisplayOn ();
+ SiS_UnLockCRT2 (HwDeviceExtension, BaseAddr);
+ SiS_SetRegANDOR (SiS_Part1Port, 0x02, 0xBF, 0x00);
+ if (SiS_BridgeInSlave ()) {
+ SiS_SetRegANDOR (SiS_Part1Port, 0x01, 0x1F, 0x00);
+ } else {
+ SiS_SetRegANDOR (SiS_Part1Port, 0x01, 0x1F, 0x40);
+ }
+ if (SiS_IF_DEF_CH7005) {
+ SiS_SetCH7005 (0x0B0E);
+ }
+ }
+/*SetPanelDelay(1); */
+ SiS_SetRegANDOR (SiS_P3c4, 0x11, 0xF7, 0x00);
+}
+
+void
+SiS_SetPanelDelay (USHORT DelayTime)
+{
+ USHORT PanelID;
+
+ PanelID = SiS_GetReg1 (SiS_P3d4, 0x36);
+ PanelID = PanelID >> 4;
+
+ if (DelayTime == 0)
+ SiS_LCD_Wait_Time (SiS_PanelDelayTbl[PanelID].timer[0]);
+ else
+ SiS_LCD_Wait_Time (SiS_PanelDelayTbl[PanelID].timer[1]);
+}
+
+void
+SiS_LCD_Wait_Time (UCHAR DelayTime)


+{
+ USHORT i, j;

+ ULONG temp, flag;


+
+ flag = 0;

+ for (i = 0; i < DelayTime; i++) {
+ for (j = 0; j < 66; j++) {
+ temp = SiS_GetReg3 (0x61);
+ temp = temp & 0x10;
+ if (temp == flag)
+ continue;
+ flag = temp;
+ }
+ }
+}
+
+/*301b*/
+
+BOOLEAN
+SiS_Is301B (USHORT BaseAddr)
+{
+ USHORT flag;


+ flag = SiS_GetReg1 (SiS_Part4Port, 0x01);

+ if (flag > (0x0B0))
+ return (0); /*301b */
+ else
+ return (1);
+}
+
+BOOLEAN
+SiS_IsDualEdge (USHORT BaseAddr)
+{
+#ifdef CONFIG_FB_SIS_315
+ USHORT flag;
+ flag = SiS_GetReg1 (SiS_P3d4, 0x38);
+ if (flag & EnableDualEdge)
+ return (0);
+ else
+ return (1);
+#endif


+ return (1);
+}
+

+BOOLEAN
+SiS_IsVAMode (USHORT BaseAddr)
+{
+ USHORT flag;
+ flag = SiS_GetReg1 (SiS_P3d4, 0x38);
+#ifdef CONFIG_FB_SIS_315
+ if ((flag & EnableDualEdge) && (flag & SetToLCDA))
+ return (0);
+ else
+ return (1);
+#endif


+ return (1);
+}
+

+BOOLEAN
+SiS_IsDisableCRT2 (USHORT BaseAddr)
+{
+ USHORT flag;
+ flag = SiS_GetReg1 (SiS_P3d4, 0x30);
+ if (flag & 0x20)
+ return (0); /*301b */
+ else
+ return (1);


+}
+
+/*end 301b*/
+

+BOOLEAN
+SiS_BridgeIsOn (USHORT BaseAddr)
+{
+ USHORT flag;
+
+ if (SiS_IF_DEF_LVDS == 1) {
+ return (1);
+ } else {
+ flag = SiS_GetReg1 (SiS_Part4Port, 0x00);
+ if ((flag == 1) || (flag == 2))
+ return (1); /*301b */
+ else


+ return (0);
+ }
+}
+

+BOOLEAN
+SiS_BridgeIsEnable (USHORT BaseAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+ USHORT flag;
+
+ if (SiS_BridgeIsOn (BaseAddr) == 0) {
+ flag = SiS_GetReg1 (SiS_Part1Port, 0x0);


+ if (HwDeviceExtension->jChipType < SIS_315H) { /* 300 series */

+ if (flag & 0x0a0) {
+ return 1;
+ } else {
+ return 0;
+ }


+ } else { /* 310 series */
+

+ if (flag & 0x050) {
+ return 1;
+ } else {


+ return 0;
+ }
+
+ }
+ }

+ return 0;
+}
+
+BOOLEAN
+SiS_BridgeInSlave ()
+{
+ USHORT flag1;
+
+ flag1 = SiS_GetReg1 (SiS_P3d4, 0x31);
+ if (flag1 & (SetInSlaveMode >> 8)) {
+ return 1;
+ } else {


+ return 0;
+ }
+}
+

+BOOLEAN
+SiS_GetLCDResInfo301 (ULONG ROMAddr, USHORT SiS_P3d4, USHORT ModeNo,
+ USHORT ModeIdIndex)
+{
+ USHORT temp, modeflag, resinfo = 0;
+
+ SiS_LCDResInfo = 0;
+ SiS_LCDTypeInfo = 0;
+ SiS_LCDInfo = 0;


+
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ModeFlag */
+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;

+ resinfo = SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; /*si+Ext_ResInfo */
+ }
+
+ if (!(SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) {
+ return 0;
+ }
+ if (!(SiS_VBInfo & (SetSimuScanMode | SwitchToCRT2))) {
+ return 0;
+ }
+ temp = SiS_GetReg1 (SiS_P3d4, 0x36);
+ SiS_LCDTypeInfo = temp >> 4;
+ SiS_LCDResInfo = temp & 0x0F;


+ if (SiS_IF_DEF_LVDS == 0) {

+ if (SiS_LCDResInfo < Panel1024x768)
+ SiS_LCDResInfo = Panel1024x768;
+ } else {
+ if (SiS_LCDResInfo < Panel800x600)
+ SiS_LCDResInfo = Panel800x600;
+ }
+ if (SiS_LCDResInfo > Panel640x480)
+ SiS_LCDResInfo = Panel1024x768;
+
+ temp = SiS_GetReg1 (SiS_P3d4, 0x37);
+ SiS_LCDInfo = temp;
+
+ if (SiS_IF_DEF_LVDS == 1) {


+ if (modeflag & HalfDCLK) {

+ if (SiS_IF_DEF_TRUMPION == 0) {

+ if (!(SiS_LCDInfo & LCDNonExpanding)) {

+ if (ModeNo > 0x13) {
+ if (SiS_LCDResInfo ==
+ Panel1024x768) {
+ if (resinfo == 4) { /* 512x384 */


+ SiS_SetFlag =
+ SiS_SetFlag
+ |

+ EnableLVDSDDA;
+ }
+ } else {
+ if (SiS_LCDResInfo ==
+ Panel800x600) {
+ if (resinfo == 3) { /*400x300 */
+ SiS_SetFlag
+ =
+ SiS_SetFlag
+ |
+ EnableLVDSDDA;


+ }
+ }
+ }
+ }
+ } else {

+ SiS_SetFlag =
+ SiS_SetFlag | EnableLVDSDDA;
+ }
+ } else {
+ SiS_SetFlag = SiS_SetFlag | EnableLVDSDDA;
+ }
+ }
+ }
+


+ if (SiS_VBInfo & SetInSlaveMode) {

+ if (SiS_VBInfo & SetNotSimuMode) {
+ SiS_SetFlag = SiS_SetFlag | LCDVESATiming;
+ }
+ } else {
+ SiS_SetFlag = SiS_SetFlag | LCDVESATiming;


+ }
+ return 1;
+}
+

+void
+SiS_PresetScratchregister (USHORT SiS_P3d4,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+ /*SiS_SetReg1(SiS_P3d4,0x30,0x21); */
+ /*SiS_SetReg1(SiS_P3d4,0x31,0x41); */
+ /*SiS_SetReg1(SiS_P3d4,0x32,0x28); */
+ /*SiS_SetReg1(SiS_P3d4,0x33,0x22); */
+ /*SiS_SetReg1(SiS_P3d4,0x35,0x43); */
+ /*SiS_SetReg1(SiS_P3d4,0x36,0x01); */
+ /*SiS_SetReg1(SiS_P3d4,0x37,0x00); */
+}
+
+void
+SiS_LongWait ()


+{
+ USHORT i;
+

+ i = SiS_GetReg1 (SiS_P3c4, 0x1F);
+ if (!(i & 0xC0)) {
+
+ for (i = 0; i < 0xFFFF; i++) {
+ if (!(SiS_GetReg2 (SiS_P3da) & 0x08))
+ break;
+ }
+ for (i = 0; i < 0xFFFF; i++) {
+ if ((SiS_GetReg2 (SiS_P3da) & 0x08))


+ break;
+ }
+ }
+}

+
+void
+SiS_VBLongWait ()
+{
+ USHORT tempal, temp, i, j;
+
+ if (!(SiS_VBInfo & SetCRT2ToTV)) {
+ temp = 0;
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 100; j++) {
+ tempal = SiS_GetReg2 (SiS_P3da);
+ if (temp & 0x01) { /* VBWaitMode2 */
+ if ((tempal & 0x08)) {
+ continue;
+ }
+ if (!(tempal & 0x08)) {
+ break;
+ }
+ } else { /* VBWaitMode1 */
+ if (!(tempal & 0x08)) {
+ continue;
+ }
+ if ((tempal & 0x08)) {


+ break;
+ }
+ }
+ }

+ temp = temp ^ 0x01;
+ }
+ } else {
+ SiS_LongWait ();


+ }
+ return;
+}
+

+BOOLEAN
+SiS_WaitVBRetrace (USHORT BaseAddr)
+{
+ USHORT temp;
+
+ return 0;
+
+ temp = SiS_GetReg1 (SiS_Part1Port, 0x00);


+ if (!(temp & 0x80)) {

+ return 0;
+ }
+

+ for (temp = 0; temp == 0;) {
+ temp = SiS_GetReg1 (SiS_Part1Port, 0x25);
+ temp = temp & 0x01;
+ }
+ for (; temp > 0;) {
+ temp = SiS_GetReg1 (SiS_Part1Port, 0x25);
+ temp = temp & 0x01;


+ }
+ return 1;
+}
+

+void
+SiS_SetRegANDOR (USHORT Port, USHORT Index, USHORT DataAND, USHORT DataOR)
+{
+ USHORT temp;
+
+ temp = SiS_GetReg1 (Port, Index); /* SiS_Part1Port index 02 */
+ temp = (temp & (DataAND)) | DataOR;
+ SiS_SetReg1 (Port, Index, temp);
+}
+
+void
+SiS_SetRegAND (USHORT Port, USHORT Index, USHORT DataAND)
+{
+ USHORT temp;
+
+ temp = SiS_GetReg1 (Port, Index); /* SiS_Part1Port index 02 */
+ temp = temp & DataAND;
+ SiS_SetReg1 (Port, Index, temp);
+}
+
+void
+SiS_SetRegOR (USHORT Port, USHORT Index, USHORT DataOR)
+{
+ USHORT temp;
+
+ temp = SiS_GetReg1 (Port, Index); /* SiS_Part1Port index 02 */
+ temp = temp | DataOR;
+ SiS_SetReg1 (Port, Index, temp);
+}
+
+void
+SiS_SetGroup2 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,


+ USHORT ModeIdIndex, USHORT RefreshRateTableIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{

+ USHORT i, j, tempax, tempbx, tempcx, temp, temp3;
+ USHORT push1, push2, temp1;
+ UCHAR *PhasePoint;
+ UCHAR *TimingPoint;
+ USHORT modeflag, resinfo, crt2crtc, resindex, xres;
+ ULONG longtemp, tempeax, tempebx, temp2, tempecx;
+ USHORT SiS_RY1COE = 0, SiS_RY2COE = 0, SiS_RY3COE = 0, SiS_RY4COE =
+ 0, SiS_RY5COE = 0, SiS_RY6COE = 0, SiS_RY7COE = 0;


+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+ resinfo = SiS_SModeIDTable[ModeIdIndex].St_ResInfo;

+ crt2crtc = SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {


+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+ resinfo = SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;

+ crt2crtc = SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ }
+
+ tempcx = SiS_VBInfo;
+ tempax = (tempcx & 0x00FF) << 8;
+ tempbx = (tempcx & 0x00FF) | ((tempcx & 0x00FF) << 8);
+ tempbx = tempbx & 0x0410;
+ temp = (tempax & 0x0800) >> 8;
+ temp = temp >> 1;
+ temp = temp | (((tempbx & 0xFF00) >> 8) << 1);
+ temp = temp | ((tempbx & 0x00FF) >> 3);
+ temp = temp ^ 0x0C;
+
+ PhasePoint = SiS_PALPhase;
+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) { /* PALPhase */
+ temp = temp ^ 0x01;


+ if (SiS_VBInfo & SetInSlaveMode) {

+ TimingPoint = SiS_HiTVSt2Timing;


+ if (SiS_SetFlag & TVSimuMode) {

+ if (modeflag & Charx8Dot)

+ TimingPoint = SiS_HiTVSt1Timing;
+ else
+ TimingPoint = SiS_HiTVTextTiming;
+ }
+ } else
+ TimingPoint = SiS_HiTVExtTiming;


+ } else {
+ if (SiS_VBInfo & SetPALTV) {

+ if ((SiS_VBType & VB_SIS301B)

+ || (SiS_VBType & VB_SIS302B)) PhasePoint = SiS_PALPhase2; /* PALPhase */
+ else
+ PhasePoint = SiS_PALPhase;
+
+ TimingPoint = SiS_PALTiming;
+ } else {
+ temp = temp | 0x10;


+ if ((SiS_VBType & VB_SIS301B)

+ || (SiS_VBType & VB_SIS302B)) PhasePoint = SiS_NTSCPhase2; /* PALPhase */
+ else
+ PhasePoint = SiS_NTSCPhase;
+
+ TimingPoint = SiS_NTSCTiming;
+ }
+ }
+ SiS_SetReg1 (SiS_Part2Port, 0x0, temp);


+
+#ifdef CONFIG_FB_SIS_300
+ /*add PALMN */

+ if ((HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_730)) {

+ if (SiS_VBInfo & SetCRT2ToTV) {


+ temp = SiS_GetReg1 (SiS_P3d4, 0x31);

+ temp = temp & 0x01;
+ if (temp) {
+ temp1 = SiS_GetReg1 (SiS_P3d4, 0x35);
+ temp1 = temp1 & 0x40;
+ if (temp1)
+ PhasePoint = SiS_PALMPhase;
+ temp1 = SiS_GetReg1 (SiS_P3d4, 0x35);
+ temp1 = temp1 & 0x80;
+ if (temp1)
+ PhasePoint = SiS_PALNPhase;
+ }
+ }
+ }
+/*end add*/


+#endif
+#ifdef CONFIG_FB_SIS_315
+ /*add PALMN */

+ if (SiS_VBInfo & SetCRT2ToTV) {


+ temp = SiS_GetReg1 (SiS_P3d4, 0x31);

+ temp = temp & 0x01;
+ if (temp) {
+ temp1 = SiS_GetReg1 (SiS_P3d4, 0x38);
+ temp1 = temp1 & 0x40;
+ if (temp1)
+ PhasePoint = SiS_PALMPhase;
+ temp1 = SiS_GetReg1 (SiS_P3d4, 0x38);
+ temp1 = temp1 & 0x80;
+ if (temp1)
+ PhasePoint = SiS_PALNPhase;


+ }
+ }
+ /*end add */
+#endif

+ for (i = 0x31, j = 0; i <= 0x34; i++, j++) {
+ SiS_SetReg1 (SiS_Part2Port, i, PhasePoint[j]);
+ }
+ for (i = 0x01, j = 0; i <= 0x2D; i++, j++) {
+ SiS_SetReg1 (SiS_Part2Port, i, TimingPoint[j]);
+ }
+ for (i = 0x39; i <= 0x45; i++, j++) {
+ SiS_SetReg1 (SiS_Part2Port, i, TimingPoint[j]); /* di->temp2[j] */
+ }
+ if (SiS_VBInfo & SetCRT2ToTV) {
+ SiS_SetRegANDOR (SiS_Part2Port, 0x3A, 0x1F, 0x00);
+ }
+ temp = SiS_NewFlickerMode;
+ SiS_SetRegANDOR (SiS_Part2Port, 0x0A, 0xFF, temp);
+
+ SiS_SetReg1 (SiS_Part2Port, 0x35, 0x00); /*301b */
+ SiS_SetReg1 (SiS_Part2Port, 0x36, 0x00);
+ SiS_SetReg1 (SiS_Part2Port, 0x37, 0x00);
+ SiS_SetReg1 (SiS_Part2Port, 0x38, SiS_RY1COE);
+ SiS_SetReg1 (SiS_Part2Port, 0x48, SiS_RY2COE);
+ SiS_SetReg1 (SiS_Part2Port, 0x49, SiS_RY3COE);
+ SiS_SetReg1 (SiS_Part2Port, 0x4a, SiS_RY4COE);
+/*add to change 630+301b filter*/


+
+ resindex = SiS_GetResInfo (ROMAddr, ModeNo, ModeIdIndex);
+ if (ModeNo <= 0x13) {
+ xres = SiS_StResInfo[resindex].HTotal;

+ } else {
+ xres = SiS_ModeResInfo[resindex].HTotal; /* xres->ax */
+ }

+ if (xres == 640) {
+ SiS_RY1COE = 0xFF;
+ SiS_RY2COE = 0x03;
+ SiS_RY3COE = 0x02;
+ SiS_RY4COE = 0xF6;
+ SiS_RY5COE = 0xFC;
+ SiS_RY6COE = 0x27;
+ SiS_RY7COE = 0x46;
+ }
+ if (xres == 800) {
+ SiS_RY1COE = 0x01;
+ SiS_RY2COE = 0x01;
+ SiS_RY3COE = 0xFC;
+ SiS_RY4COE = 0xF8;
+ SiS_RY5COE = 0x08;
+ SiS_RY6COE = 0x26;
+ SiS_RY7COE = 0x38;
+ }
+ if (xres == 1024) {
+ SiS_RY1COE = 0xFF;
+ SiS_RY2COE = 0xFF;
+ SiS_RY3COE = 0xFC;
+ SiS_RY4COE = 0x00;
+ SiS_RY5COE = 0x0F;
+ SiS_RY6COE = 0x22;
+ SiS_RY7COE = 0x28;
+ }


+ if (xres == 720) {

+ SiS_RY1COE = 0x01;
+ SiS_RY2COE = 0x02;
+ SiS_RY3COE = 0xFE;
+ SiS_RY4COE = 0xF7;
+ SiS_RY5COE = 0x03;
+ SiS_RY6COE = 0x27;
+ SiS_RY7COE = 0x3c;
+ }
+ SiS_SetReg1 (SiS_Part2Port, 0x35, SiS_RY1COE); /*301b */
+ SiS_SetReg1 (SiS_Part2Port, 0x36, SiS_RY2COE);
+ SiS_SetReg1 (SiS_Part2Port, 0x37, SiS_RY3COE);
+ SiS_SetReg1 (SiS_Part2Port, 0x38, SiS_RY4COE);
+ SiS_SetReg1 (SiS_Part2Port, 0x48, SiS_RY5COE);
+ SiS_SetReg1 (SiS_Part2Port, 0x49, SiS_RY6COE);
+ SiS_SetReg1 (SiS_Part2Port, 0x4a, SiS_RY7COE);
+
+/*end add*/


+
+ if (SiS_VBInfo & SetCRT2ToHiVisionTV)

+ tempax = 950;


+ else {
+ if (SiS_VBInfo & SetPALTV)

+ tempax = 520;
+ else
+ tempax = 440;
+ }
+ if (SiS_VDE <= tempax) {
+ tempax = tempax - SiS_VDE;
+ tempax = tempax >> 2;
+ tempax = (tempax & 0x00FF) | ((tempax & 0x00FF) << 8);
+ push1 = tempax;
+ temp = (tempax & 0xFF00) >> 8;
+ temp = temp + (USHORT) TimingPoint[0];
+ SiS_SetReg1 (SiS_Part2Port, 0x01, temp);
+ tempax = push1;
+ temp = (tempax & 0xFF00) >> 8;
+ temp = temp + TimingPoint[1];
+ SiS_SetReg1 (SiS_Part2Port, 0x02, temp);
+ }


+ /*301b */
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))

+ && (SiS_VBInfo & SetCRT2ToTV) && (SiS_VGAHDE == 1024)) {


+ if (SiS_VBInfo & SetPALTV) {

+ SiS_SetReg1 (SiS_Part2Port, 0x01, 0x19);
+ SiS_SetReg1 (SiS_Part2Port, 0x02, 0x52);
+ } else {
+ SiS_SetReg1 (SiS_Part2Port, 0x01, 0x0B);
+ SiS_SetReg1 (SiS_Part2Port, 0x02, 0x11);
+ }
+ }
+
+ tempcx = SiS_HT - 1;
+ /*301b */
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))) {
+ tempcx = tempcx - 1;
+ }


+ temp = tempcx & 0x00FF;

+ SiS_SetReg1 (SiS_Part2Port, 0x1B, temp);
+ temp = (tempcx & 0xFF00) >> 8;
+ SiS_SetRegANDOR (SiS_Part2Port, 0x1D, ~0x0F, temp);
+
+ tempcx = SiS_HT >> 1;
+ push1 = tempcx; /* push cx */
+ tempcx = tempcx + 7;
+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) {
+ tempcx = tempcx - 4;
+ }


+ temp = (tempcx & 0x00FF);

+ temp = temp << 4;
+ SiS_SetRegANDOR (SiS_Part2Port, 0x22, 0x0F, temp);
+
+ tempbx = TimingPoint[j] | ((TimingPoint[j + 1]) << 8);


+ tempbx = tempbx + tempcx;

+ push2 = tempbx;


+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part2Port, 0x24, temp);


+ temp = (tempbx & 0xFF00) >> 8;

+ temp = temp << 4;
+ SiS_SetRegANDOR (SiS_Part2Port, 0x25, 0x0F, temp);


+
+ tempbx = push2;

+ tempbx = tempbx + 8;

+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) {

+ tempbx = tempbx - 4;
+ tempcx = tempbx;
+ }
+ temp = (tempbx & 0x00FF) << 4;
+ SiS_SetRegANDOR (SiS_Part2Port, 0x29, 0x0F, temp);
+
+ j = j + 2;
+ tempcx = tempcx + (TimingPoint[j] | ((TimingPoint[j + 1]) << 8));


+ temp = tempcx & 0x00FF;

+ SiS_SetReg1 (SiS_Part2Port, 0x27, temp);
+ temp = ((tempcx & 0xFF00) >> 8) << 4;
+ SiS_SetRegANDOR (SiS_Part2Port, 0x28, 0x0F, temp);
+
+ tempcx = tempcx + 8;


+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) {

+ tempcx = tempcx - 4;
+ }
+ temp = tempcx & 0xFF;


+ temp = temp << 4;

+ SiS_SetRegANDOR (SiS_Part2Port, 0x2A, 0x0F, temp);
+
+ tempcx = push1; /* pop cx */
+ j = j + 2;
+ temp = TimingPoint[j] | ((TimingPoint[j + 1]) << 8);
+ tempcx = tempcx - temp;


+ temp = tempcx & 0x00FF;

+ temp = temp << 4;
+ SiS_SetRegANDOR (SiS_Part2Port, 0x2D, 0x0F, temp);
+
+ tempcx = tempcx - 11;
+ if (!(SiS_VBInfo & SetCRT2ToTV)) {
+ tempax = SiS_GetVGAHT2 ();
+ tempcx = tempax - 1;
+ }


+ temp = tempcx & 0x00FF;

+ SiS_SetReg1 (SiS_Part2Port, 0x2E, temp);
+
+ tempbx = SiS_VDE;


+ if (SiS_VGAVDE == 360)

+ tempbx = 746;
+ if (SiS_VGAVDE == 375)
+ tempbx = 746;
+ if (SiS_VGAVDE == 405)
+ tempbx = 853;


+ if (SiS_VBInfo & SetCRT2ToTV) {

+ tempbx = tempbx >> 1;
+ }
+ tempbx = tempbx - 2;


+ temp = tempbx & 0x00FF;

+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) {

+ if (SiS_VBInfo & SetInSlaveMode) {

+ if (ModeNo == 0x2f)
+ temp = temp + 1;
+ }
+ }
+ SiS_SetReg1 (SiS_Part2Port, 0x2F, temp);
+
+ temp = (tempcx & 0xFF00) >> 8;
+ temp = temp | (((tempbx & 0xFF00) >> 8) << 6);


+ if (!(SiS_VBInfo & SetCRT2ToHiVisionTV)) {

+ temp = temp | 0x10;
+ if (!(SiS_VBInfo & SetCRT2ToSVIDEO)) {
+ temp = temp | 0x20;
+ }
+ }
+ SiS_SetReg1 (SiS_Part2Port, 0x30, temp);
+ /*301b */
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))) { /*tv gatingno */
+ tempbx = SiS_VDE;


+ if (SiS_VBInfo & SetCRT2ToTV) {

+ tempbx = tempbx >> 1;
+ }
+ temp = (((tempbx - 3) & 0x0300) >> 8) << 5;
+ SiS_SetReg1 (SiS_Part2Port, 0x46, temp);
+ temp = (tempbx - 3) & 0x00FF;
+ SiS_SetReg1 (SiS_Part2Port, 0x47, temp);
+ }
+/*end 301b*/
+
+ tempbx = tempbx & 0x00FF;


+ if (!(modeflag & HalfDCLK)) {

+ tempcx = SiS_VGAHDE;
+ if (tempcx >= SiS_HDE) {
+ tempbx = tempbx | 0x2000;
+ tempax = tempax & 0x00FF;
+ }
+ }
+ tempcx = 0x0101;
+
+ if (SiS_VBInfo & (SetCRT2ToHiVisionTV | SetCRT2ToTV)) { /*301b */
+ if (SiS_VGAHDE >= 1024) {
+ tempcx = 0x1920;
+ if (SiS_VGAHDE >= 1280) {
+ tempcx = 0x1420;
+ tempbx = tempbx & 0xDFFF;
+ }
+ }
+ }
+ if (!(tempbx & 0x2000)) {


+ if (modeflag & HalfDCLK) {

+ tempcx = (tempcx & 0xFF00) | ((tempcx & 0x00FF) << 1);
+ }
+ push1 = tempbx;
+ tempeax = SiS_VGAHDE;
+ tempebx = (tempcx & 0xFF00) >> 8;
+ longtemp = tempeax * tempebx;
+ tempecx = tempcx & 0x00FF;
+ longtemp = longtemp / tempecx;
+ /*301b */
+ tempecx = 8 * 1024;
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))) {
+ tempecx = tempecx * 8;
+ }
+ longtemp = longtemp * tempecx;
+ tempecx = SiS_HDE;
+ temp2 = longtemp % tempecx;
+ tempeax = longtemp / tempecx;
+ if (temp2 != 0) {
+ tempeax = tempeax + 1;
+ }
+ tempax = (USHORT) tempeax;
+ /*301b */
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))) {
+ tempcx = ((tempax & 0xFF00) >> 5) >> 8;


+ }
+ /*end 301b */

+ tempbx = push1;
+ tempbx =
+ (USHORT) (((tempeax & 0x0000FF00) & 0x1F00) |
+ (tempbx & 0x00FF));
+ tempax =
+ (USHORT) (((tempeax & 0x000000FF) << 8) |
+ (tempax & 0x00FF));
+ temp = (tempax & 0xFF00) >> 8;
+ } else {
+ temp = (tempax & 0x00FF) >> 8;
+ }
+ SiS_SetReg1 (SiS_Part2Port, 0x44, temp);


+ temp = (tempbx & 0xFF00) >> 8;

+ SiS_SetRegANDOR (SiS_Part2Port, 0x45, ~0x03F, temp);
+ /*301b */
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))) {
+ if ((tempcx & 0x00FF) == 0x01)
+ tempcx = 0x00;
+ SiS_SetRegANDOR (SiS_Part2Port, 0x46, ~0x007, tempcx);
+ SiS_SetRegOR (SiS_Part2Port, 0x46, 0x18);


+ if (SiS_VBInfo & SetPALTV) {

+ tempbx = 0x0364;
+ tempcx = 0x009c;
+ } else {
+ tempbx = 0x0346;
+ tempcx = 0x0078;
+ }
+ temp = (tempbx & 0x00FF);
+ SiS_SetReg1 (SiS_Part2Port, 0x4B, temp);


+ temp = (tempcx & 0x00FF);

+ SiS_SetReg1 (SiS_Part2Port, 0x4C, temp);
+ tempbx = (tempbx & 0x0300);
+ temp = (tempcx & 0xFF00) >> 8;
+ temp = (temp & 0x0003) << 2;
+ temp = temp | (tempbx >> 8);
+ SiS_SetReg1 (SiS_Part2Port, 0x4D, temp);
+ temp = SiS_GetReg1 (SiS_Part2Port, 0x43);
+ SiS_SetReg1 (SiS_Part2Port, 0x43, temp - 3);
+ }
+/*end 301b*/
+
+#ifdef CONFIG_FB_SIS_300
+/*add PALMN*/


+ if ((HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_730)) {

+ if (SiS_VBInfo & SetCRT2ToTV) {


+ temp = SiS_GetReg1 (SiS_P3d4, 0x31);

+ temp = temp & 0x01;
+ if (temp) {
+ temp1 = SiS_GetReg1 (SiS_P3d4, 0x35);
+ temp1 = temp1 & 0x40;
+ if (temp1) {
+ SiS_SetRegANDOR (SiS_Part2Port, 0x00,
+ 0xEF, 0x00);
+ temp3 =
+ SiS_GetReg1 (SiS_Part2Port, 0x01);
+ temp3 = temp3 - 1;
+ SiS_SetReg1 (SiS_Part2Port, 0x01,
+ temp3);


+ }
+ }
+ }
+ }
+ /*end add */
+#endif
+

+#ifdef CONFIG_FB_SIS_315
+/*add PALMN*/


+ if (SiS_VBInfo & SetCRT2ToTV) {

+ temp = SiS_GetReg1 (SiS_P3d4, 0x31);

+ temp = temp & 0x01;
+ if (temp) {
+ temp1 = SiS_GetReg1 (SiS_P3d4, 0x38);
+ temp1 = temp1 & 0x40;
+ if (temp1) {
+ SiS_SetRegANDOR (SiS_Part2Port, 0x00, 0xEF,
+ 0x00);
+ temp3 = SiS_GetReg1 (SiS_Part2Port, 0x01);
+ temp3 = temp3 - 1;
+ SiS_SetReg1 (SiS_Part2Port, 0x01, temp3);


+ }
+ }
+ }
+ /*end add */
+#endif
+

+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) {

+ if (!(SiS_VBInfo & SetInSlaveMode)) {
+ SiS_SetReg1 (SiS_Part2Port, 0x0B, 0x00);


+ }
+ }
+ if (SiS_VBInfo & SetCRT2ToTV) {

+ return;
+ }
+
+ tempbx = SiS_HDE - 1; /* RHACTE=HDE-1 */


+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part2Port, 0x2C, temp);


+ temp = (tempbx & 0xFF00) >> 8;

+ temp = temp << 4;
+ SiS_SetRegANDOR (SiS_Part2Port, 0x2B, 0x0F, temp);
+ temp = 0x01;


+ if (SiS_LCDResInfo == Panel1280x1024) {

+ if (SiS_ModeType == ModeEGA) {
+ if (SiS_VGAHDE >= 1024) {
+ temp = 0x02;


+ if (SiS_SetFlag & LCDVESATiming)

+ temp = 0x01;
+ }
+ }
+ }
+ SiS_SetReg1 (SiS_Part2Port, 0x0B, temp);
+
+ tempbx = SiS_VDE; /* RTVACTEO=(VDE-1)&0xFF */
+ push1 = tempbx;
+ tempbx--;


+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part2Port, 0x03, temp);
+ temp = ((tempbx & 0xFF00) >> 8) & 0x07;
+ SiS_SetRegANDOR (SiS_Part2Port, 0x0C, ~0x07, temp);
+
+ tempcx = SiS_VT - 1;
+ push2 = tempcx + 1;
+ temp = tempcx & 0x00FF; /* RVTVT=VT-1 */
+ SiS_SetReg1 (SiS_Part2Port, 0x19, temp);
+ temp = (tempcx & 0xFF00) >> 8;
+ temp = temp << 5;


+ if (SiS_LCDInfo & LCDRGB18Bit) {

+ temp = temp | 0x10;


+ }
+ if (SiS_VBInfo & SetCRT2ToLCD) {

+ tempbx = (tempbx & 0xFF00) | (SiS_LCDInfo & 0x0FF);
+ if (tempbx & LCDSync) {
+ tempbx = tempbx & LCDSyncBit;
+ tempbx =
+ (tempbx & 0xFF00) | ((tempbx & 0x00FF) >>
+ LCDSyncShift);
+ temp = temp | (tempbx & 0x00FF);
+ }
+ }
+ SiS_SetReg1 (SiS_Part2Port, 0x1A, temp);
+
+ tempcx++;
+ tempbx = 768;
+ if (SiS_LCDResInfo != Panel1024x768) {
+ tempbx = 1024;


+ if (SiS_LCDResInfo != Panel1280x1024) {

+ tempbx = 1200; /*301b */
+ if (SiS_LCDResInfo != Panel1600x1200) {


+ if (tempbx != SiS_VDE) {

+ tempbx = 960;
+ }
+ }

+ }


+ }
+ if (SiS_LCDInfo & LCDNonExpanding) {

+ tempbx = SiS_VDE;
+ tempbx--;
+ tempcx--;
+ }
+ tempax = 1;


+ if (!(SiS_LCDInfo & LCDNonExpanding)) {

+ if (tempbx != SiS_VDE) {
+ tempax = tempbx;
+ if (tempax < SiS_VDE) {
+ tempax = 0;
+ tempcx = 0;
+ } else {
+ tempax = tempax - SiS_VDE;
+ }
+ tempax = tempax >> 1;
+ }
+ tempcx = tempcx - tempax; /* lcdvdes */
+ tempbx = tempbx - tempax; /* lcdvdee */
+ } else {
+ tempax = tempax >> 1;
+ tempcx = tempcx - tempax; /* lcdvdes */
+ tempbx = tempbx - tempax; /* lcdvdee */
+ }
+
+ temp = tempcx & 0x00FF; /* RVEQ1EQ=lcdvdes */
+ SiS_SetReg1 (SiS_Part2Port, 0x05, temp);
+ temp = tempbx & 0x00FF; /* RVEQ2EQ=lcdvdee */
+ SiS_SetReg1 (SiS_Part2Port, 0x06, temp);


+
+ temp = (tempbx & 0xFF00) >> 8;

+ temp = temp << 3;
+ temp = temp | ((tempcx & 0xFF00) >> 8);
+ SiS_SetReg1 (SiS_Part2Port, 0x02, temp);


+
+ tempbx = push2;

+ tempax = push1;
+ tempcx = tempbx;
+ tempcx = tempcx - tempax;
+ tempcx = tempcx >> 4;


+ tempbx = tempbx + tempax;

+ tempbx = tempbx >> 1;


+ if (SiS_LCDInfo & LCDNonExpanding) {

+ tempbx = tempbx - 10;
+ }
+ temp = tempbx & 0x00FF; /* RTVACTEE=lcdvrs */
+ SiS_SetReg1 (SiS_Part2Port, 0x04, temp);


+
+ temp = (tempbx & 0xFF00) >> 8;

+ temp = temp << 4;
+ tempbx = tempbx + tempcx + 1;
+ temp = temp | (tempbx & 0x000F);
+ SiS_SetReg1 (SiS_Part2Port, 0x01, temp);


+
+ if (SiS_LCDResInfo == Panel1024x768) {
+ if (!(SiS_SetFlag & LCDVESATiming)) {
+ if (!(SiS_LCDInfo & LCDNonExpanding)) {

+ if (ModeNo == 0x13) {
+ SiS_SetReg1 (SiS_Part2Port, 0x04, 0xB9);
+ SiS_SetReg1 (SiS_Part2Port, 0x05, 0xCC);
+ SiS_SetReg1 (SiS_Part2Port, 0x06, 0xA6);
+ } else {
+ temp = crt2crtc & 0x3F;
+ if (temp == 4) {
+ SiS_SetReg1 (SiS_Part2Port,
+ 0x01, 0x2B);
+ SiS_SetReg1 (SiS_Part2Port,
+ 0x02, 0x13);
+ SiS_SetReg1 (SiS_Part2Port,
+ 0x04, 0xE5);
+ SiS_SetReg1 (SiS_Part2Port,
+ 0x05, 0x08);
+ SiS_SetReg1 (SiS_Part2Port,
+ 0x06, 0xE2);


+ }
+ }
+ }
+ }
+ }
+

+ SiS_SetRegANDOR (SiS_Part2Port, 0x09, 0xF0, 0x00);
+ SiS_SetRegANDOR (SiS_Part2Port, 0x0A, 0xF0, 0x00);
+
+ tempcx = (SiS_HT - SiS_HDE) >> 2; /* (HT-HDE)>>2 */
+ tempbx = (SiS_HDE + 7); /* lcdhdee */
+ /*301b */
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))) {


+ tempbx = tempbx + 2;
+ }

+ push1 = tempbx;
+ temp = tempbx & 0x00FF; /* RHEQPLE=lcdhdee */
+ SiS_SetReg1 (SiS_Part2Port, 0x23, temp);


+ temp = (tempbx & 0xFF00) >> 8;

+ SiS_SetRegANDOR (SiS_Part2Port, 0x25, ~0x0F, temp);
+ /*301b */
+ temp = 7;
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))) {
+ temp = temp + 2;
+ }
+ SiS_SetReg1 (SiS_Part2Port, 0x1F, temp); /* RHBLKE=lcdhdes */
+ SiS_SetRegANDOR (SiS_Part2Port, 0x20, 0x0F, 0x00);
+


+ tempbx = tempbx + tempcx;

+ push2 = tempbx;
+ temp = tempbx & 0xFF; /* RHBURSTS=lcdhrs */


+ if (SiS_LCDResInfo == Panel1280x1024) {

+ if (!(SiS_LCDInfo & LCDNonExpanding)) {

+ if (SiS_HDE == 1280) {
+ temp = 0x47;
+ }
+ }
+ }
+ SiS_SetReg1 (SiS_Part2Port, 0x1C, temp);


+ temp = (tempbx & 0xFF00) >> 8;

+ temp = temp << 4;
+ SiS_SetRegANDOR (SiS_Part2Port, 0x1D, ~0x0F0, temp);


+
+ tempbx = push2;

+ tempcx = tempcx << 1;
+ tempbx = tempbx + tempcx;

+ temp = tempbx & 0x00FF; /* RHSYEXP2S=lcdhre */
+ SiS_SetReg1 (SiS_Part2Port, 0x21, temp);
+
+ SiS_SetRegANDOR (SiS_Part2Port, 0x17, 0xFB, 0x00);
+ SiS_SetRegANDOR (SiS_Part2Port, 0x18, 0xDF, 0x00);
+


+ if (!(SiS_SetFlag & LCDVESATiming)) {

+ if (SiS_VGAVDE == 525) {
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))) { /*301b */
+ temp = 0xC6;
+ } else
+ temp = 0xC4;
+ SiS_SetReg1 (SiS_Part2Port, 0x2f, temp);
+ SiS_SetReg1 (SiS_Part2Port, 0x30, 0xB3);
+ }
+ if (SiS_VGAVDE == 420) {


+ if (
+ ((SiS_VBType & VB_SIS301B)
+ || (SiS_VBType & VB_SIS302B))) {

+ temp = 0x4F;
+ } else
+ temp = 0x4E;
+ SiS_SetReg1 (SiS_Part2Port, 0x2f, temp);
+ }
+ }
+}
+
+USHORT
+SiS_GetVGAHT2 ()
+{
+ ULONG tempax, tempbx;
+
+ tempbx = ((SiS_VGAVT - SiS_VGAVDE) * SiS_RVBHCMAX) & 0xFFFF;
+ tempax = (SiS_VT - SiS_VDE) * SiS_RVBHCFACT;
+ tempax = (tempax * SiS_HT) / tempbx;
+ return ((USHORT) tempax);
+}
+
+void
+SiS_SetGroup3 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,


+ USHORT ModeIdIndex, PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{

+ USHORT i;
+ UCHAR *tempdi;
+ USHORT modeflag, temp, temp1;


+
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */

+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+ }

+
+ SiS_SetReg1 (SiS_Part3Port, 0x00, 0x00);


+ if (SiS_VBInfo & SetPALTV) {

+ SiS_SetReg1 (SiS_Part3Port, 0x13, 0xFA);
+ SiS_SetReg1 (SiS_Part3Port, 0x14, 0xC8);
+ } else {
+ SiS_SetReg1 (SiS_Part3Port, 0x13, 0xF6);
+ SiS_SetReg1 (SiS_Part3Port, 0x14, 0xBF);


+ }
+#ifdef CONFIG_FB_SIS_300
+ /*add PALMN */

+ if ((HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_730)) {

+ if (SiS_VBInfo & SetCRT2ToTV) {


+ temp = SiS_GetReg1 (SiS_P3d4, 0x31);

+ temp = temp & 0x01;
+ if (temp) {
+ temp1 = SiS_GetReg1 (SiS_P3d4, 0x35);
+ temp1 = temp1 & 0x40;
+ if (temp1) {
+ SiS_SetReg1 (SiS_Part3Port, 0x13, 0xFA);
+ SiS_SetReg1 (SiS_Part3Port, 0x14, 0xC8);
+ SiS_SetReg1 (SiS_Part3Port, 0x3D, 0xA8);


+ }
+ }
+ }
+ }
+ /*end add */
+#endif
+#ifdef CONFIG_FB_SIS_315
+/*add PALMN*/

+ if (SiS_VBInfo & SetCRT2ToTV) {

+ temp = SiS_GetReg1 (SiS_P3d4, 0x31);

+ temp = temp & 0x01;
+ if (temp) {
+ temp1 = SiS_GetReg1 (SiS_P3d4, 0x38);
+ temp1 = temp1 & 0x40;
+ if (temp1) {
+ SiS_SetReg1 (SiS_Part3Port, 0x13, 0xFA);
+ SiS_SetReg1 (SiS_Part3Port, 0x14, 0xC8);
+ SiS_SetReg1 (SiS_Part3Port, 0x3D, 0xA8);


+ }
+ }
+ }
+ /*end add */
+#endif

+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) {

+ tempdi = SiS_HiTVGroup3Data;


+ if (SiS_SetFlag & TVSimuMode) {

+ tempdi = SiS_HiTVGroup3Simu;


+ if (!(modeflag & Charx8Dot)) {

+ tempdi = SiS_HiTVGroup3Text;
+ }
+ }
+ for (i = 0; i <= 0x3E; i++) {
+ SiS_SetReg1 (SiS_Part3Port, i, tempdi[i]);


+ }
+ }
+ return;
+}
+
+void

+SiS_SetGroup4 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,


+ USHORT ModeIdIndex, USHORT RefreshRateTableIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{

+ USHORT tempax, tempcx, tempbx, modeflag, temp, temp2, push1;
+ ULONG tempebx, tempeax, templong;


+
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */

+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+ }

+ temp = SiS_RVBHCFACT;
+ SiS_SetReg1 (SiS_Part4Port, 0x13, temp);
+
+ tempbx = SiS_RVBHCMAX;


+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part4Port, 0x14, temp);
+ temp2 = ((tempbx & 0xFF00) >> 8) << 7;
+
+ tempcx = SiS_VGAHT - 1;


+ temp = tempcx & 0x00FF;

+ SiS_SetReg1 (SiS_Part4Port, 0x16, temp);
+ temp = ((tempcx & 0xFF00) >> 8) << 3;
+ temp2 = temp | temp2;
+
+ tempcx = SiS_VGAVT - 1;
+ if (!(SiS_VBInfo & SetCRT2ToTV)) {
+ tempcx = tempcx - 5;
+ }


+ temp = tempcx & 0x00FF;

+ SiS_SetReg1 (SiS_Part4Port, 0x17, temp);
+ temp = temp2 | ((tempcx & 0xFF00) >> 8);
+ SiS_SetReg1 (SiS_Part4Port, 0x15, temp);
+
+ tempcx = SiS_VBInfo;
+ tempbx = SiS_VGAHDE;


+ if (modeflag & HalfDCLK) {

+ tempbx = tempbx >> 1;
+ }
+ if (tempcx & SetCRT2ToHiVisionTV) {
+ temp = 0xA0;
+ if (tempbx != 1024) {
+ temp = 0xC0;
+ if (tempbx != 1280)
+ temp = 0;
+ }
+ } else if ((tempcx & SetCRT2ToTV) && (SiS_VGAHDE == 1024)) { /*301b */
+ temp = 0xA0;
+ } else {
+ temp = 0x80;


+ if (SiS_VBInfo & SetCRT2ToLCD) {

+ temp = 0;
+ if (tempbx > 800)
+ temp = 0x60;
+ }
+ }
+ if (SiS_LCDResInfo != Panel1280x1024)
+ temp = temp | 0x0A;
+ SiS_SetRegANDOR (SiS_Part4Port, 0x0E, ~0xEF, temp);
+
+ tempebx = SiS_VDE;
+ if (tempcx & SetCRT2ToHiVisionTV) {
+ /* if(!(tempax&0xE000)) tempbx=tempbx>>1; */
+ if (!(temp & 0xE000))
+ tempbx = tempbx >> 1; /* alan ???? */
+
+ }
+
+ tempcx = SiS_RVBHRS;


+ temp = tempcx & 0x00FF;

+ SiS_SetReg1 (SiS_Part4Port, 0x18, temp);
+
+ tempebx = tempebx;
+ tempeax = SiS_VGAVDE;
+ tempcx = tempcx | 0x04000;
+/*tempeax=tempeax-tempebx; */
+ if (tempeax <= tempebx) {
+ tempcx = ((tempcx & 0xFF00) ^ 0x4000) | (tempcx & 0x00ff);


+ tempeax = SiS_VGAVDE;
+ }

+
+ else {
+ tempeax = tempeax - tempebx;
+ }
+
+ push1 = tempcx;
+ templong = (tempeax * 256 * 1024) % tempebx;
+ tempeax = (tempeax * 256 * 1024) / tempebx;
+ tempebx = tempeax;
+ if (templong != 0) {
+ tempebx++;
+ }
+ tempcx = push1;
+ temp = (USHORT) (tempebx & 0x000000FF);
+ SiS_SetReg1 (SiS_Part4Port, 0x1B, temp);


+ temp = (USHORT) ((tempebx & 0x0000FF00) >> 8);

+ SiS_SetReg1 (SiS_Part4Port, 0x1A, temp);
+ tempbx = (USHORT) (tempebx >> 16);


+ temp = tempbx & 0x00FF;

+ temp = temp << 4;
+ temp = temp | ((tempcx & 0xFF00) >> 8);
+ SiS_SetReg1 (SiS_Part4Port, 0x19, temp);
+ /*301b */
+
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))) {
+ temp = 0x0028;
+ SiS_SetReg1 (SiS_Part4Port, 0x1C, temp);
+ tempax = SiS_VGAHDE;


+ if (modeflag & HalfDCLK) {

+ tempax = tempax >> 1;
+ }
+ if (SiS_VBInfo & (SetCRT2ToLCD)) {
+ if (tempax > 800)
+ tempax = tempax - 800;
+ }
+ tempax = tempax - 1;
+
+ if (SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToHiVisionTV)) {
+ if (SiS_VGAHDE > 800) {
+ if (SiS_VGAHDE == 1024)
+ tempax = (tempax * 25 / 32) - 1;
+ else
+ tempax = (tempax * 20 / 32) - 1;
+ }
+ }
+ temp = (tempax & 0xFF00) >> 8;
+ temp = ((temp & 0x0003) << 4);
+ SiS_SetReg1 (SiS_Part4Port, 0x1E, temp);


+ temp = (tempax & 0x00FF);

+ SiS_SetReg1 (SiS_Part4Port, 0x1D, temp);
+
+ if (SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToHiVisionTV)) {
+ if (SiS_VGAHDE > 800) {
+ SiS_SetRegOR (SiS_Part4Port, 0x1E, 0x08);
+ }
+ }
+ temp = 0x0036;


+ if (SiS_VBInfo & SetCRT2ToTV) {

+ temp = temp | 0x0001;
+ }
+ SiS_SetRegANDOR (SiS_Part4Port, 0x1F, 0x00C0, temp);
+ tempbx = (SiS_HT / 2) - 2;
+ temp = ((tempbx & 0x0700) >> 8) << 3;
+ SiS_SetRegANDOR (SiS_Part4Port, 0x21, 0x00C0, temp);


+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part4Port, 0x22, temp);
+ }
+/*end 301b*/
+ SiS_SetCRT2VCLK (BaseAddr, ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, HwDeviceExtension);
+}
+
+void
+SiS_SetCRT2VCLK (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,


+ USHORT ModeIdIndex, USHORT RefreshRateTableIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{

+ USHORT vclkindex;
+ USHORT tempah, temp1;
+
+ vclkindex =
+ SiS_GetVCLK2Ptr (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, HwDeviceExtension);
+ /*301b */
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))) {
+ tempah = SiS_VBVCLKData[vclkindex].Part4_A;
+ SiS_SetReg1 (SiS_Part4Port, 0x0A, tempah);
+ tempah = SiS_VBVCLKData[vclkindex].Part4_B;
+ SiS_SetReg1 (SiS_Part4Port, 0x0B, tempah);
+ } else {
+ SiS_SetReg1 (SiS_Part4Port, 0x0A, 0x01);
+ tempah = SiS_VBVCLKData[vclkindex].Part4_B;
+ SiS_SetReg1 (SiS_Part4Port, 0x0B, tempah);
+ tempah = SiS_VBVCLKData[vclkindex].Part4_A;
+ SiS_SetReg1 (SiS_Part4Port, 0x0A, tempah);
+
+ }
+ SiS_SetReg1 (SiS_Part4Port, 0x12, 0x00);
+ tempah = 0x08;


+ if (SiS_VBInfo & SetCRT2ToRAMDAC) {

+ tempah = tempah | 0x020;
+ }

+ temp1 = SiS_GetReg1 (SiS_Part4Port, 0x12);
+ tempah = tempah | temp1;
+ SiS_SetReg1 (SiS_Part4Port, 0x12, tempah);
+}
+
+USHORT
+SiS_GetVCLK2Ptr (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,


+ USHORT RefreshRateTableIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{

+ USHORT tempbx;
+#ifdef CONFIG_FB_SIS_300
+ USHORT LCDXlat1VCLK[4] = { VCLK65, VCLK65, VCLK65, VCLK65 };
+ USHORT LCDXlat2VCLK[4] = { VCLK108_2, VCLK108_2, VCLK108_2, VCLK108_2 };
+ USHORT LVDSXlat2VCLK[4] = { VCLK65, VCLK65, VCLK65, VCLK65 };
+ USHORT LVDSXlat3VCLK[4] = { VCLK65, VCLK65, VCLK65, VCLK65 };
+#else /* SIS315H */
+ USHORT LCDXlat1VCLK[4] =
+ { VCLK65 + 2, VCLK65 + 2, VCLK65 + 2, VCLK65 + 2 };
+ USHORT LCDXlat2VCLK[4] =
+ { VCLK108_2 + 5, VCLK108_2 + 5, VCLK108_2 + 5, VCLK108_2 + 5 };
+ USHORT LVDSXlat2VCLK[4] =
+ { VCLK65 + 2, VCLK65 + 2, VCLK65 + 2, VCLK65 + 2 };
+ USHORT LVDSXlat3VCLK[4] =
+ { VCLK65 + 2, VCLK65 + 2, VCLK65 + 2, VCLK65 + 2 };
+#endif
+ USHORT LVDSXlat1VCLK[4] = { VCLK40, VCLK40, VCLK40, VCLK40 };
+ USHORT CRT2Index, VCLKIndex;
+ USHORT modeflag, resinfo;
+ UCHAR *CHTVVCLKPtr = NULL;


+
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+ resinfo = SiS_SModeIDTable[ModeIdIndex].St_ResInfo;

+ CRT2Index = SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {


+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+ resinfo = SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;

+ CRT2Index = SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ }
+


+ if (SiS_IF_DEF_LVDS == 0) {

+ CRT2Index = CRT2Index >> 6; /* for LCD */
+ if ((SiS_VBInfo & SetCRT2ToLCD) || (SiS_VBInfo & SetCRT2ToLCDA)) { /*301b */
+ if (SiS_LCDResInfo != Panel1024x768) {
+ VCLKIndex = LCDXlat2VCLK[CRT2Index];
+ } else {
+ VCLKIndex = LCDXlat1VCLK[CRT2Index];
+ }
+ } else { /* for TV */


+ if (SiS_VBInfo & SetCRT2ToTV) {

+ if (SiS_IF_DEF_HiVision == 1) {
+ if (SiS_SetFlag & RPLLDIV2XO) {
+ VCLKIndex = HiTVVCLKDIV2;
+ if (HwDeviceExtension->
+ jChipType >= SIS_315H) { /* 310 series */
+/* VCLKIndex += 11; for chip310 0x2E */
+ VCLKIndex += 25; /* for chip315 */
+ }
+ } else {
+ VCLKIndex = HiTVVCLK;
+ if (HwDeviceExtension->
+ jChipType >= SIS_315H) { /* 310 series */
+/* VCLKIndex += 11; for chip310 0x2E */
+ VCLKIndex += 25; /* for chip315 */
+ }
+ }
+ if (SiS_SetFlag & TVSimuMode) {


+ if (modeflag & Charx8Dot) {

+ VCLKIndex =
+ HiTVSimuVCLK;
+ if (HwDeviceExtension->
+ jChipType >= SIS_315H) { /* 310 series */
+/* VCLKIndex += 11; for chip310 0x2E */
+ VCLKIndex += 25; /* for chip315 */
+ }
+ } else {
+ VCLKIndex =
+ HiTVTextVCLK;
+ if (HwDeviceExtension->
+ jChipType >= SIS_315H) { /* 310 series */
+/* VCLKIndex += 11; for chip310 0x2E */
+ VCLKIndex += 25; /* for chip315 */


+ }
+ }
+ }
+ } else {

+ if (SiS_VBInfo & SetCRT2ToTV) {

+ if (SiS_SetFlag & RPLLDIV2XO) {
+ VCLKIndex = TVVCLKDIV2;
+ if (HwDeviceExtension->
+ jChipType >= SIS_315H) { /* 310 series */
+/* VCLKIndex += 11; for chip310 0x2E */
+ VCLKIndex += 25; /* for chip315 */
+ }
+ } else {
+ VCLKIndex = TVVCLK;
+ if (HwDeviceExtension->
+ jChipType >= SIS_315H) { /* 310 series */
+/* VCLKIndex += 11; for chip310 0x2E */
+ VCLKIndex += 25; /* for chip315 */
+ }
+ }
+ }
+ }
+ } else { /* for CRT2 */
+ VCLKIndex =
+ (UCHAR) SiS_GetReg2 ((USHORT) (SiS_P3ca + 0x02)); /* Port 3cch */
+ VCLKIndex = ((VCLKIndex >> 2) & 0x03);
+ if (ModeNo > 0x13) {
+ VCLKIndex =
+ SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; /* di+Ext_CRTVCLK */
+ VCLKIndex = VCLKIndex & 0x3f;
+ }
+ }
+ }
+ } else { /* LVDS */


+ if (ModeNo <= 0x13)

+ VCLKIndex = CRT2Index;
+ else
+ VCLKIndex = CRT2Index;


+ if (SiS_IF_DEF_CH7005 == 1) {
+ if (!(SiS_VBInfo & SetCRT2ToLCD)) {

+ VCLKIndex = VCLKIndex & 0x1f;
+ tempbx = 0;


+ if (SiS_VBInfo & SetPALTV)
+ tempbx = tempbx + 2;
+ if (SiS_VBInfo & SetCHTVOverScan)
+ tempbx = tempbx + 1;

+ switch (tempbx) {
+ case 0:
+ CHTVVCLKPtr = SiS_CHTVVCLKUNTSC;


+ break;
+ case 1:

+ CHTVVCLKPtr = SiS_CHTVVCLKONTSC;


+ break;
+ case 2:

+ CHTVVCLKPtr = SiS_CHTVVCLKUPAL;


+ break;
+ case 3:

+ CHTVVCLKPtr = SiS_CHTVVCLKOPAL;
+ break;
+ }
+ VCLKIndex = CHTVVCLKPtr[VCLKIndex];
+ }
+ } else {
+ VCLKIndex = VCLKIndex >> 6;


+ if (SiS_LCDResInfo == Panel800x600)

+ VCLKIndex = LVDSXlat1VCLK[VCLKIndex];
+ else if (SiS_LCDResInfo == Panel1024x768)
+ VCLKIndex = LVDSXlat2VCLK[VCLKIndex];
+ else
+ VCLKIndex = LVDSXlat3VCLK[VCLKIndex];
+ }
+ }
+/*VCLKIndex=VCLKIndex&0x3F; */
+ if (HwDeviceExtension->jChipType < SIS_315H) { /* for300 serial */
+ VCLKIndex = VCLKIndex & 0x3F;
+ }
+ return (VCLKIndex);
+}
+
+void
+SiS_SetGroup5 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex)
+{
+ USHORT Pindex, Pdata;
+
+ Pindex = SiS_Part5Port;
+ Pdata = SiS_Part5Port + 1;
+ if (SiS_ModeType == ModeVGA) {


+ if (!
+ (SiS_VBInfo &

+ (SetInSlaveMode | LoadDACFlag | CRT2DisplayFlag))) {
+ SiS_EnableCRT2 ();
+/* LoadDAC2(ROMAddr,SiS_Part5Port,ModeNo,ModeIdIndex); */


+ }
+ }
+ return;
+}
+
+void

+SiS_LoadDAC2 (ULONG ROMAddr, USHORT SiS_Part5Port, USHORT ModeNo,
+ USHORT ModeIdIndex)
+{
+ USHORT data, data2;
+ USHORT time, i, j, k;
+ USHORT m, n, o;
+ USHORT si, di, bx, dl;
+ USHORT al, ah, dh;
+ USHORT *table = 0;
+ USHORT Pindex, Pdata, modeflag;


+
+ if (ModeNo <= 0x13) {

+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+ } else {


+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+ }

+
+ Pindex = SiS_Part5Port;
+ Pdata = SiS_Part5Port + 1;
+ data = modeflag & DACInfoFlag;
+ time = 64;
+ if (data == 0x00)
+ table = SiS_MDA_DAC;
+ if (data == 0x08)
+ table = SiS_CGA_DAC;
+ if (data == 0x10)
+ table = SiS_EGA_DAC;
+ if (data == 0x18) {
+ time = 256;
+ table = SiS_VGA_DAC;
+ }
+ if (time == 256)
+ j = 16;
+ else
+ j = time;
+
+ SiS_SetReg3 (Pindex, 0x00);
+
+ for (i = 0; i < j; i++) {
+ data = table[i];
+ for (k = 0; k < 3; k++) {
+ data2 = 0;
+ if (data & 0x01)
+ data2 = 0x2A;
+ if (data & 0x02)
+ data2 = data2 + 0x15;
+ SiS_SetReg3 (Pdata, data2);
+ data = data >> 2;
+ }
+ }
+
+ if (time == 256) {
+ for (i = 16; i < 32; i++) {
+ data = table[i];
+ for (k = 0; k < 3; k++)
+ SiS_SetReg3 (Pdata, data);
+ }
+ si = 32;
+ for (m = 0; m < 9; m++) {
+ di = si;
+ bx = si + 0x04;
+ dl = 0;
+ for (n = 0; n < 3; n++) {
+ for (o = 0; o < 5; o++) {
+ dh = table[si];
+ ah = table[di];
+ al = table[bx];
+ si++;
+ SiS_WriteDAC2 (Pdata, dl, ah, al, dh);
+ } /* for 5 */
+ si = si - 2;
+ for (o = 0; o < 3; o++) {
+ dh = table[bx];
+ ah = table[di];
+ al = table[si];
+ si--;
+ SiS_WriteDAC2 (Pdata, dl, ah, al, dh);
+ } /* for 3 */
+ dl++;
+ } /* for 3 */
+ si = si + 5;
+ } /* for 9 */
+ }
+}
+
+void
+SiS_WriteDAC2 (USHORT Pdata, USHORT dl, USHORT ah, USHORT al, USHORT dh)
+{
+ USHORT temp;
+ USHORT bh, bl;
+
+ bh = ah;
+ bl = al;
+ if (dl != 0) {
+ temp = bh;
+ bh = dh;
+ dh = temp;
+ if (dl == 1) {
+ temp = bl;
+ bl = dh;
+ dh = temp;
+ } else {
+ temp = bl;
+ bl = bh;
+ bh = temp;
+ }
+ }
+ SiS_SetReg3 (Pdata, (USHORT) dh);
+ SiS_SetReg3 (Pdata, (USHORT) bh);
+ SiS_SetReg3 (Pdata, (USHORT) bl);
+}
+
+void
+SiS_SetCHTVReg (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex)
+{
+ USHORT temp, tempbx, tempcl;
+/* USHORT CRT2CRTC; */
+ USHORT TVType, resindex;
+ SiS_CHTVRegDataStruct *CHTVRegData = NULL;


+
+ if (ModeNo <= 0x13) {

+ tempcl = SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {
+ tempcl = SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ }
+ TVType = 0;
+ if (SiS_VBInfo & SetPALTV)
+ TVType = TVType + 2;


+ if (SiS_VBInfo & SetCHTVOverScan)

+ TVType = TVType + 1;
+ switch (TVType) {
+ case 0:
+ CHTVRegData = SiS_CHTVReg_UNTSC;


+ break;
+ case 1:

+ CHTVRegData = SiS_CHTVReg_ONTSC;


+ break;
+ case 2:

+ CHTVRegData = SiS_CHTVReg_UPAL;


+ break;
+ case 3:

+ CHTVRegData = SiS_CHTVReg_OPAL;
+ break;
+ }
+ resindex = tempcl & 0x3F;
+
+ if (SiS_VBInfo & SetPALTV) {
+ SiS_SetCH7005 (0x4304);
+ SiS_SetCH7005 (0x6909);
+ } else {
+ SiS_SetCH7005 (0x0304);
+ SiS_SetCH7005 (0x7109);
+ }
+
+ temp = CHTVRegData[resindex].Reg[0];
+ tempbx = ((temp & 0x00FF) << 8) | 0x00;
+ SiS_SetCH7005 (tempbx);
+ temp = CHTVRegData[resindex].Reg[1];
+ tempbx = ((temp & 0x00FF) << 8) | 0x07;
+ SiS_SetCH7005 (tempbx);
+ temp = CHTVRegData[resindex].Reg[2];
+ tempbx = ((temp & 0x00FF) << 8) | 0x08;
+ SiS_SetCH7005 (tempbx);
+ temp = CHTVRegData[resindex].Reg[3];
+ tempbx = ((temp & 0x00FF) << 8) | 0x0A;
+ SiS_SetCH7005 (tempbx);
+ temp = CHTVRegData[resindex].Reg[4];
+ tempbx = ((temp & 0x00FF) << 8) | 0x0B;
+ SiS_SetCH7005 (tempbx);
+
+ SiS_SetCH7005 (0x2801);
+ SiS_SetCH7005 (0x3103);
+ SiS_SetCH7005 (0x003D);
+ SiS_SetCHTVRegANDOR (0x0010, 0x1F);
+ SiS_SetCHTVRegANDOR (0x0211, 0xF8);
+ SiS_SetCHTVRegANDOR (0x001C, 0xEF);


+
+ if (!(SiS_VBInfo & SetPALTV)) {

+ /* tempcl=CRT2CRTC; */
+ tempcl = tempcl & 0x3F;


+ if (SiS_VBInfo & SetCHTVOverScan) {

+ if (tempcl == 0x04) { /* 640x480 underscan */
+ SiS_SetCHTVRegANDOR (0x0020, 0xEF);
+ SiS_SetCHTVRegANDOR (0x0121, 0xFE);
+ } else {
+ if (tempcl == 0x05) { /* 800x600 underscan */
+ SiS_SetCHTVRegANDOR (0x0118, 0xF0);
+ SiS_SetCHTVRegANDOR (0x0C19, 0xF0);
+ SiS_SetCHTVRegANDOR (0x001A, 0xF0);
+ SiS_SetCHTVRegANDOR (0x001B, 0xF0);
+ SiS_SetCHTVRegANDOR (0x001C, 0xF0);
+ SiS_SetCHTVRegANDOR (0x001D, 0xF0);
+ SiS_SetCHTVRegANDOR (0x001E, 0xF0);
+ SiS_SetCHTVRegANDOR (0x001F, 0xF0);
+ SiS_SetCHTVRegANDOR (0x0120, 0xEF);
+ SiS_SetCHTVRegANDOR (0x0021, 0xFE);
+ }
+ }
+ } else {
+ if (tempcl == 0x04) { /* 640x480 overscan */
+ SiS_SetCHTVRegANDOR (0x0020, 0xEF);
+ SiS_SetCHTVRegANDOR (0x0121, 0xFE);
+ } else {
+ if (tempcl == 0x05) { /* 800x600 overscan */
+ SiS_SetCHTVRegANDOR (0x0118, 0xF0);
+ SiS_SetCHTVRegANDOR (0x0F19, 0xF0);
+ SiS_SetCHTVRegANDOR (0x011A, 0xF0);
+ SiS_SetCHTVRegANDOR (0x0C1B, 0xF0);
+ SiS_SetCHTVRegANDOR (0x071C, 0xF0);
+ SiS_SetCHTVRegANDOR (0x011D, 0xF0);
+ SiS_SetCHTVRegANDOR (0x0C1E, 0xF0);
+ SiS_SetCHTVRegANDOR (0x071F, 0xF0);
+ SiS_SetCHTVRegANDOR (0x0120, 0xEF);
+ SiS_SetCHTVRegANDOR (0x0021, 0xFE);


+ }
+ }
+ }
+ }
+}
+

+void
+SiS_SetCHTVRegANDOR (USHORT tempax, USHORT tempbh)
+{
+ USHORT tempal, tempah, tempbl;
+
+ tempal = tempax & 0x00FF;
+ tempah = (tempax >> 8) & 0x00FF;
+ tempbl = SiS_GetCH7005 (tempal);
+ tempbl = (((tempbl & tempbh) | tempah) << 8 | tempal);
+ SiS_SetCH7005 (tempbl);
+}
+
+void
+SiS_SetCH7005 (USHORT tempbx)
+{
+ USHORT tempah, temp;
+
+ SiS_DDC_Port = 0x3c4;
+ SiS_DDC_Index = 0x11;
+ SiS_DDC_DataShift = 0x00;
+ SiS_DDC_DeviceAddr = 0xEA;
+
+ temp = 1;
+ for (; temp != 0;) {
+ SiS_SetSwitchDDC2 ();
+ SiS_SetStart ();
+ tempah = SiS_DDC_DeviceAddr;
+ temp = SiS_WriteDDC2Data (tempah);
+ if (temp)
+ continue;
+ tempah = tempbx & 0x00FF;
+ temp = SiS_WriteDDC2Data (tempah);
+ if (temp)
+ continue;
+ tempah = (tempbx & 0xFF00) >> 8;
+ temp = SiS_WriteDDC2Data (tempah);
+ if (temp)
+ continue;
+ SiS_SetStop ();
+ }
+}
+
+USHORT
+SiS_GetCH7005 (USHORT tempbx)
+{
+ USHORT tempah, temp;
+
+ SiS_DDC_Port = 0x3c4;
+ SiS_DDC_Index = 0x11;
+ SiS_DDC_DataShift = 0x00;
+ SiS_DDC_DeviceAddr = 0xEA;
+ SiS_DDC_ReadAddr = tempbx;
+
+ for (;;) {
+ SiS_SetSwitchDDC2 ();
+ SiS_SetStart ();
+ tempah = SiS_DDC_DeviceAddr;
+ temp = SiS_WriteDDC2Data (tempah);
+ if (temp)
+ continue;
+ tempah = SiS_DDC_ReadAddr;
+ temp = SiS_WriteDDC2Data (tempah);
+ if (temp)
+ continue;
+
+ SiS_SetStart ();
+ tempah = SiS_DDC_DeviceAddr;
+ tempah = tempah | 0x01;
+ temp = SiS_WriteDDC2Data (tempah);
+ if (temp)
+ continue;
+ tempah = SiS_ReadDDC2Data (tempah);
+ SiS_SetStop ();
+ return (tempah);
+ }
+}
+
+void
+SiS_SetSwitchDDC2 (void)


+{
+ USHORT i;
+

+ SiS_SetSCLKHigh ();
+ for (i = 0; i < 1000; i++) {
+ SiS_GetReg1 (SiS_DDC_Port, 0x05);
+ }
+ SiS_SetSCLKLow ();
+ for (i = 0; i < 1000; i++) {
+ SiS_GetReg1 (SiS_DDC_Port, 0x05);
+ }
+}
+
+void
+SiS_SetStart (void)
+{
+
+ SiS_SetSCLKLow ();
+ SiS_SetRegANDOR (SiS_DDC_Port, SiS_DDC_Index, 0xFD, 0x02); /* SetSDA(0x01); */
+ SiS_SetSCLKHigh ();
+ SiS_SetRegANDOR (SiS_DDC_Port, SiS_DDC_Index, 0xFD, 0x00); /* SetSDA(0x00); */
+ SiS_SetSCLKHigh ();
+}
+
+void
+SiS_SetStop (void)
+{
+ SiS_SetSCLKLow ();
+ SiS_SetRegANDOR (SiS_DDC_Port, SiS_DDC_Index, 0xFD, 0x00); /* SetSDA(0x00); */
+ SiS_SetSCLKHigh ();
+ SiS_SetRegANDOR (SiS_DDC_Port, SiS_DDC_Index, 0xFD, 0x02); /* SetSDA(0x01); */
+ SiS_SetSCLKHigh ();
+}
+
+USHORT
+SiS_WriteDDC2Data (USHORT tempax)
+{
+ USHORT i, flag, temp;
+
+ flag = 0x80;
+ for (i = 0; i < 8; i++) {
+ SiS_SetSCLKLow ();
+ if (tempax & flag) {
+ SiS_SetRegANDOR (SiS_DDC_Port, SiS_DDC_Index, 0xFD,
+ 0x02);
+ } else {
+ SiS_SetRegANDOR (SiS_DDC_Port, SiS_DDC_Index, 0xFD,
+ 0x00);
+ }
+ SiS_SetSCLKHigh ();
+ flag = flag >> 1;
+ }
+ temp = SiS_CheckACK ();
+ return (temp);
+}
+
+USHORT
+SiS_ReadDDC2Data (USHORT tempax)
+{
+ USHORT i, temp, getdata;
+
+ getdata = 0;


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

+ getdata = getdata << 1;
+ SiS_SetSCLKLow ();
+ SiS_SetRegANDOR (SiS_DDC_Port, SiS_DDC_Index, 0xFD, 0x02);
+ SiS_SetSCLKHigh ();
+ temp = SiS_GetReg1 (SiS_DDC_Port, SiS_DDC_Index);


+ if (temp & 0x02)

+ getdata = getdata | 0x01;
+ }
+ return (getdata);
+}
+
+void
+SiS_SetSCLKLow (void)


+{
+ USHORT temp;
+

+ SiS_SetRegANDOR (SiS_DDC_Port, SiS_DDC_Index, 0xFE, 0x00); /* SetSCLKLow() */
+ do {
+ temp = SiS_GetReg1 (SiS_DDC_Port, SiS_DDC_Index);
+ } while (temp & 0x01);
+ SiS_DDC2Delay ();
+}
+
+void
+SiS_SetSCLKHigh (void)


+{
+ USHORT temp;
+

+ SiS_SetRegANDOR (SiS_DDC_Port, SiS_DDC_Index, 0xFE, 0x01); /* SetSCLKHigh() */
+ do {
+ temp = SiS_GetReg1 (SiS_DDC_Port, SiS_DDC_Index);
+ } while (!(temp & 0x01));
+ SiS_DDC2Delay ();
+}
+
+void
+SiS_DDC2Delay (void)


+{
+ USHORT i;
+

+ for (i = 0; i < DDC2DelayTime; i++) {
+ SiS_GetReg1 (SiS_P3c4, 0x05);
+ }
+}
+
+USHORT
+SiS_CheckACK (void)
+{
+ USHORT tempah;
+
+ SiS_SetSCLKLow ();
+ SiS_SetRegANDOR (SiS_DDC_Port, SiS_DDC_Index, 0xFD, 0x02);
+ SiS_SetSCLKHigh ();
+ tempah = SiS_GetReg1 (SiS_DDC_Port, SiS_DDC_Index);
+ SiS_SetSCLKLow ();
+ if (tempah & 0x02)
+ return (1);
+ else


+ return (0);
+}
+

+void
+SiS_ModCRT1CRTC (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex)
+{


+ USHORT temp, tempah, i, modeflag, j;

+ USHORT ResInfo, DisplayType;
+ SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr = NULL;
+

+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */

+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+ }

+


+ temp =
+ SiS_GetLVDSCRT1Ptr (ROMAddr, ModeNo, ModeIdIndex,

+ RefreshRateTableIndex, &ResInfo, &DisplayType);

+ tempah = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x11); /*unlock cr0-7 */
+ tempah = tempah & 0x7F;
+ SiS_SetReg1 (SiS_P3d4, 0x11, tempah);

+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[0];


+ SiS_SetReg1 (SiS_P3d4, 0x0, tempah);

+ for (i = 0x02, j = 1; i <= 0x05; i++, j++) {
+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[j];


+ SiS_SetReg1 (SiS_P3d4, i, tempah);
+ }

+ for (i = 0x06, j = 5; i <= 0x07; i++, j++) {
+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[j];


+ SiS_SetReg1 (SiS_P3d4, i, tempah);
+ }

+ for (i = 0x10, j = 7; i <= 0x11; i++, j++) {
+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[j];


+ SiS_SetReg1 (SiS_P3d4, i, tempah);
+ }

+ for (i = 0x15, j = 9; i <= 0x16; i++, j++) {
+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[j];


+ SiS_SetReg1 (SiS_P3d4, i, tempah);
+ }
+

+ for (i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[j];


+ SiS_SetReg1 (SiS_P3c4, i, tempah);
+ }
+

+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[14];


+ tempah = tempah & 0x0E0;

+ SiS_SetReg1 (SiS_P3c4, 0x0E, tempah);
+
+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[14];


+ tempah = tempah & 0x01;

+ tempah = tempah << 5;

+ if (modeflag & DoubleScanMode) {

+ tempah = tempah | 0x080;
+ }

+ SiS_SetRegANDOR (SiS_P3d4, 0x09, ~0x020, tempah);

+ return;
+}
+
+/*301b*/
+void

+SiS_CHACRT1CRTC (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex)
+{


+ USHORT temp, tempah, i, modeflag, j;

+ USHORT ResInfo, DisplayType;
+ SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr = NULL;
+

+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */

+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+ }

+


+ temp =
+ SiS_GetLVDSCRT1Ptr (ROMAddr, ModeNo, ModeIdIndex,

+ RefreshRateTableIndex, &ResInfo, &DisplayType);

+ tempah = (UCHAR) SiS_GetReg1 (SiS_P3d4, 0x11); /*unlock cr0-7 */
+ tempah = tempah & 0x7F;
+ SiS_SetReg1 (SiS_P3d4, 0x11, tempah);

+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[0];


+ SiS_SetReg1 (SiS_P3d4, 0x0, tempah);

+ for (i = 0x02, j = 1; i <= 0x05; i++, j++) {
+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[j];


+ SiS_SetReg1 (SiS_P3d4, i, tempah);
+ }

+ for (i = 0x06, j = 5; i <= 0x07; i++, j++) {
+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[j];


+ SiS_SetReg1 (SiS_P3d4, i, tempah);
+ }

+ for (i = 0x10, j = 7; i <= 0x11; i++, j++) {
+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[j];


+ SiS_SetReg1 (SiS_P3d4, i, tempah);
+ }

+ for (i = 0x15, j = 9; i <= 0x16; i++, j++) {
+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[j];


+ SiS_SetReg1 (SiS_P3d4, i, tempah);
+ }
+

+ for (i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[j];


+ SiS_SetReg1 (SiS_P3c4, i, tempah);
+ }
+

+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[14];


+ tempah = tempah & 0x0E0;

+ SiS_SetReg1 (SiS_P3c4, 0x0E, tempah);
+
+ tempah = (LVDSCRT1Ptr + ResInfo)->CR[14];


+ tempah = tempah & 0x01;

+ tempah = tempah << 5;

+ if (modeflag & DoubleScanMode) {

+ tempah = tempah | 0x080;
+ }

+ SiS_SetRegANDOR (SiS_P3d4, 0x09, ~0x020, tempah);

+ return;


+}
+
+/*add for LCDA*/
+

+BOOLEAN
+SiS_GetLCDACRT1Ptr (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex, USHORT * ResInfo,
+ USHORT * DisplayType)
+{
+ USHORT tempbx = 0, modeflag = 0;
+ USHORT CRT2CRTC = 0;


+ /*301b */
+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))
+ && (SiS_VBInfo & SetCRT2ToLCDA)) {

+ tempbx = SiS_LCDResInfo;
+ tempbx -= Panel800x600;


+ if (SiS_LCDInfo & LCDNonExpanding)

+ tempbx += 6;


+ if (modeflag & HalfDCLK)

+ tempbx += +3;


+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */

+ CRT2CRTC = SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {


+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */

+ CRT2CRTC =


+ SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ }
+ }

+ *ResInfo = CRT2CRTC & 0x3F;
+ *DisplayType = tempbx;


+ return 1;
+}
+

+/*end for 301b*/
+
+BOOLEAN
+SiS_GetLVDSCRT1Ptr (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex, USHORT * ResInfo,
+ USHORT * DisplayType)
+{
+ USHORT tempbx, modeflag = 0;
+ USHORT Flag, CRT2CRTC;


+
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */

+ CRT2CRTC = SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {


+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */

+ CRT2CRTC = SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ }


+ if (!(SiS_VBInfo & SetInSlaveMode)) {

+ return 0;
+ }


+ Flag = 1;
+ tempbx = 0;
+ if (SiS_IF_DEF_CH7005 == 1) {
+ if (!(SiS_VBInfo & SetCRT2ToLCD)) {
+ Flag = 0;

+ tempbx = 12;


+ if (SiS_VBInfo & SetPALTV)

+ tempbx += 2;


+ if (SiS_VBInfo & SetCHTVOverScan)

+ tempbx += 1;
+ }
+ }
+ if (Flag) {
+ tempbx = SiS_LCDResInfo;
+ tempbx -= Panel800x600;


+ if (SiS_LCDInfo & LCDNonExpanding)

+ tempbx += 6;


+ if (modeflag & HalfDCLK)

+ tempbx += +3;
+ }
+
+ *ResInfo = CRT2CRTC & 0x3F;
+ *DisplayType = tempbx;


+ return 1;
+}
+

+void
+SiS_SetCRT2ECLK (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,


+ USHORT RefreshRateTableIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{

+ USHORT tempah, tempal;
+ USHORT P3cc = SiS_P3c9 + 3;
+ USHORT vclkindex = 0;
+
+ if (SiS_IF_DEF_TRUMPION == 0) { /*no trumpion */
+ tempal = SiS_GetReg2 (P3cc);
+ tempal = tempal & 0x0C;


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

echo 'End of part 079'
echo 'File patch-2.4.15 is continued in part 080'
echo "080" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:46 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part070

#!/bin/sh -x
# this is part 070 of a 115 - part archive


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

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

+ mark_bh(IMMEDIATE_BH);
X
- wake_up_interruptible(&port->write_wait);
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup)(tty);
-
- wake_up_interruptible(&tty->write_wait);
-
X return;
X } /* ftdi_sio_write_bulk_callback */
X
+


+static int ftdi_sio_write_room( struct usb_serial_port *port )

+{
+ struct ftdi_private *priv = (struct ftdi_private *)port->private;
+ int room;
+ if ( port->write_urb->status == -EINPROGRESS) {
+ /* There is a race here with the _write routines but it won't hurt */
+ room = 0;
+ } else {
+ room = port->bulk_out_size - priv->write_offset;
+ }
+ return(room);
+
+
+} /* ftdi_sio_write_room */
+
+


X static void ftdi_sio_read_bulk_callback (struct urb *urb)

X { /* ftdi_sio_serial_buld_callback */


X struct usb_serial_port *port = (struct usb_serial_port *)urb->context;

@@ -555,7 +555,7 @@
X int i;
X int result;
X
- dbg(__FUNCTION__);
+ dbg(__FUNCTION__ " - port %d", port->number);
X
X if (port_paranoia_check (port, "ftdi_sio_read_bulk_callback")) {
X return;
@@ -647,12 +647,12 @@
X #endif
X
X /* Continue trying to always read */
- FILL_BULK_URB(urb, serial->dev,
+ FILL_BULK_URB(port->read_urb, serial->dev,
X usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
- urb->transfer_buffer, urb->transfer_buffer_length,
+ port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
X ftdi_sio_read_bulk_callback, port);
X
- result = usb_submit_urb(urb);
+ result = usb_submit_urb(port->read_urb);
X if (result)
X err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
X
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/serial/io_edgeport.c linux/drivers/usb/serial/io_edgeport.c
--- v2.4.14/linux/drivers/usb/serial/io_edgeport.c Thu Oct 11 08:02:26 2001
+++ linux/drivers/usb/serial/io_edgeport.c Wed Nov 21 09:59:11 2001
@@ -25,6 +25,14 @@
X *
X * Version history:
X *
+ * 2.2 2001_11_14 greg kroah-hartman
+ * - fixed bug in edge_close that kept the port from being used more
+ * than once.
+ * - fixed memory leak on device removal.
+ * - fixed potential double free of memory when command urb submitting
+ * failed.
+ * - other small cleanups when the device is removed
+ *
X * 2.1 2001_07_09 greg kroah-hartman
X * - added support for TIOCMBIS and TIOCMBIC.
X *
@@ -263,7 +271,7 @@


X /*
X * Version Information
X */

-#define DRIVER_VERSION "v2.1"
+#define DRIVER_VERSION "v2.2"
X #define DRIVER_AUTHOR "Greg Kroah-Hartman <gr...@kroah.com> and David Iacovelli"
X #define DRIVER_DESC "Edgeport USB Serial Driver"
X
@@ -433,7 +441,7 @@
X
X /* function prototypes for all URB callbacks */
X static void edge_interrupt_callback (struct urb *urb);
-static void edge_bulk_in_callback (struct urb *urb);
+static void edge_bulk_in_callback (struct urb *urb);
X static void edge_bulk_out_data_callback (struct urb *urb);
X static void edge_bulk_out_cmd_callback (struct urb *urb);
X
@@ -646,12 +654,6 @@


X }
X #endif
X
-

-
-/************************************************************************
- * *
- * *
- ************************************************************************/
X static void get_product_info(struct edgeport_serial *edge_serial)
X {
X struct edgeport_product_info *product_info = &edge_serial->product_info;
@@ -933,7 +935,7 @@
X dbg(__FUNCTION__" - FREE URB %p (outstanding %d)", urb, CmdUrbs);
X
X
- /* if this urb had a transfer buffer already (old transfer) free it */
+ /* clean up the transfer buffer */
X if (urb->transfer_buffer != NULL) {
X kfree(urb->transfer_buffer);
X }
@@ -957,7 +959,6 @@
X /* tell the tty driver that something has changed */
X wake_up_interruptible(&tty->write_wait);
X
-
X /* we have completed the command */
X edge_port->commandPending = FALSE;
X wake_up_interruptible(&edge_port->wait_command);
@@ -987,6 +988,9 @@
X
X dbg(__FUNCTION__ " - port %d", port->number);
X
+ if (edge_port == NULL)
+ return -ENODEV;
+
X ++port->open_count;
X MOD_INC_USE_COUNT;
X
@@ -1002,6 +1006,12 @@
X as the structures were not set up at that time.) */


X serial = port->serial;

X edge_serial = (struct edgeport_serial *)serial->private;
+ if (edge_serial == NULL) {
+ port->active = 0;
+ port->open_count = 0;
+ MOD_DEC_USE_COUNT;
+ return -ENODEV;
+ }
X if (edge_serial->interrupt_in_buffer == NULL) {
X struct usb_serial_port *port0 = &serial->port[0];
X
@@ -1015,25 +1025,22 @@
X edge_serial->bulk_out_endpoint = port0->bulk_out_endpointAddress;
X
X /* set up our interrupt urb */
- /* Like to use FILL_INT_URB, but we don't know wMaxPacketSize or bInterval, something to change for 2.5... */
- edge_serial->interrupt_read_urb->complete = edge_interrupt_callback;
- edge_serial->interrupt_read_urb->context = edge_serial;
- /* FILL_INT_URB(edge_serial->interrupt_read_urb, serial->dev,
- usb_rcvintpipe (serial->dev, edge_serial->interrupt_in_endpoint),
- edge_serial->interrupt_in_buffer, edge_serial->interrupt_in_endpoint.wMaxPacketSize,
- edge_interrupt_callback, edge_serial, edge_serial->interrupt_in_endpoint.bInterval);
- */
+ FILL_INT_URB(edge_serial->interrupt_read_urb,
+ serial->dev,
+ usb_rcvintpipe(serial->dev,
+ port0->interrupt_in_endpointAddress),
+ port0->interrupt_in_buffer,
+ edge_serial->interrupt_read_urb->transfer_buffer_length,
+ edge_interrupt_callback, edge_serial,
+ edge_serial->interrupt_read_urb->interval);
X
X /* set up our bulk in urb */
- /* Like to use FILL_BULK_URB, but we don't know wMaxPacketSize or bInterval, something to change for 2.5... */
- edge_serial->read_urb->complete = edge_bulk_in_callback;
- edge_serial->read_urb->context = edge_serial;
- /* FILL_BULK_URB(edge_serial->read_urb, serial->dev,
- usb_rcvbulkpipe (serial->dev, edge_serial->bulk_in_endpoint),
- edge_serial->bulk_in_buffer, edge_serial->bulk_in_endpoint->wMaxPacketSize,
+ FILL_BULK_URB(edge_serial->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev, port0->bulk_in_endpointAddress),
+ port0->bulk_in_buffer,
+ edge_serial->read_urb->transfer_buffer_length,
X edge_bulk_in_callback, edge_serial);
- */
-
+
X /* start interrupt read for this edgeport
X * this interrupt will continue as long as the edgeport is connected */
X response = usb_submit_urb (edge_serial->interrupt_read_urb);


@@ -1237,7 +1244,9 @@
X

X edge_serial = (struct edgeport_serial *)serial->private;
X edge_port = (struct edgeport_port *)port->private;
-
+ if ((edge_serial == NULL) || (edge_port == NULL))
+ return;
+
X --port->open_count;
X
X if (port->open_count <= 0) {
@@ -1283,15 +1292,14 @@
X if (edge_port->txfifo.fifo) {
X kfree(edge_port->txfifo.fifo);
X }
+ port->active = 0;
+ port->open_count = 0;
X }
X
X MOD_DEC_USE_COUNT;
X dbg(__FUNCTION__" exited");
X }
X
-
-
-
X /*****************************************************************************
X * SerialWrite
X * this function is called by the tty driver when data should be written to
@@ -1310,6 +1318,9 @@
X
X dbg(__FUNCTION__ " - port %d", port->number);
X
+ if (edge_port == NULL)
+ return -ENODEV;
+
X // get a pointer to the Tx fifo
X fifo = &edge_port->txfifo;
X
@@ -1399,7 +1410,6 @@
X struct urb *urb;
X unsigned char *buffer;
X int status;
- unsigned long flags;
X int count;
X int bytesleft;
X int firsthalf;
@@ -1407,13 +1417,9 @@
X
X dbg(__FUNCTION__"(%d)", edge_port->port->number);
X
- /* find our next free urb */ // ICK!!! FIXME!!!
- save_flags(flags); cli();
-
X if (edge_port->write_in_progress ||
X !edge_port->open ||
X (fifo->count == 0)) {
- restore_flags(flags);
X dbg(__FUNCTION__"(%d) EXIT - fifo %d, PendingWrite = %d", edge_port->port->number, fifo->count, edge_port->write_in_progress);
X return;
X }
@@ -1426,14 +1432,12 @@
X // it's better to wait for more credits so we can do a larger
X // write.
X if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits)) {
- restore_flags(flags);
X dbg(__FUNCTION__"(%d) Not enough credit - fifo %d TxCredit %d", edge_port->port->number, fifo->count, edge_port->txCredits );
X return;
X }
X
X // lock this write
X edge_port->write_in_progress = TRUE;
- restore_flags(flags);
X
X // get a pointer to the write_urb
X urb = edge_port->write_urb;
@@ -1514,9 +1518,10 @@
X
X dbg(__FUNCTION__);
X
- if (edge_port->closePending == TRUE) {
+ if (edge_port == NULL)
+ return -ENODEV;
+ if (edge_port->closePending == TRUE)
X return -ENODEV;
- }
X
X dbg(__FUNCTION__" - port %d", port->number);
X
@@ -1549,6 +1554,11 @@
X
X dbg(__FUNCTION__);
X
+ if (edge_port == NULL)
+ return -ENODEV;
+ if (edge_port->closePending == TRUE)
+ return -ENODEV;
+
X if (!edge_port->open) {
X dbg (__FUNCTION__" - port not opened");
X return -EINVAL;
@@ -1576,6 +1586,9 @@
X
X dbg(__FUNCTION__" - port %d", port->number);
X
+ if (edge_port == NULL)
+ return;
+
X if (!edge_port->open) {
X dbg (__FUNCTION__" - port not opened");
X return;
@@ -1618,6 +1631,9 @@
X
X dbg(__FUNCTION__" - port %d", port->number);
X
+ if (edge_port == NULL)
+ return;
+
X if (!edge_port->open) {
X dbg (__FUNCTION__" - port not opened");
X return;
@@ -1675,6 +1691,9 @@
X
X dbg(__FUNCTION__" - port %d", port->number);
X
+ if (edge_port == NULL)
+ return;
+
X if (!edge_port->open) {
X dbg (__FUNCTION__" - port not opened");
X return;
@@ -1833,7 +1852,6 @@
X struct async_icount cnow;
X struct async_icount cprev;
X struct serial_icounter_struct icount;


- unsigned long flags;
X

X
X dbg(__FUNCTION__" - port %d, cmd = 0x%x", port->number, cmd);
@@ -1845,14 +1863,6 @@
X return get_number_bytes_avail(edge_port, (unsigned int *) arg);
X break;
X
-// case TCGETS:
-// dbg(__FUNCTION__" (%d) TCGETS", port->number);
-// break;
-
-// case TCSETS:
-// dbg(__FUNCTION__" (%d) TCSETS", port->number);
-// break;
-
X case TIOCSERGETLSR:
X dbg(__FUNCTION__" (%d) TIOCSERGETLSR", port->number);
X return get_lsr_info(edge_port, (unsigned int *) arg);
@@ -1878,17 +1888,13 @@
X
X case TIOCMIWAIT:
X dbg(__FUNCTION__" (%d) TIOCMIWAIT", port->number);
- save_flags(flags); cli();
X cprev = edge_port->icount;
- restore_flags(flags);
X while (1) {
X interruptible_sleep_on(&edge_port->delta_msr_wait);
X /* see if a signal did it */
X if (signal_pending(current))
X return -ERESTARTSYS;
- save_flags(flags); cli();
- cnow = edge_port->icount; /* atomic copy */
- restore_flags(flags);
+ cnow = edge_port->icount;
X if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
X cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
X return -EIO; /* no change => error */
@@ -1904,9 +1910,7 @@
X break;
X
X case TIOCGICOUNT:
- save_flags(flags); cli();
X cnow = edge_port->icount;
- restore_flags(flags);
X icount.cts = cnow.cts;
X icount.dsr = cnow.dsr;
X icount.rng = cnow.rng;
@@ -2477,15 +2481,12 @@
X
X /* Allocate our next urb */
X urb = usb_alloc_urb (0);
+ if (!urb)
+ return -ENOMEM;
X
X CmdUrbs++;
-
X dbg(__FUNCTION__" - ALLOCATE URB %p (outstanding %d)", urb, CmdUrbs);
X
- if (!urb) {


- return -ENOMEM;
- }
-

X FILL_BULK_URB (urb, edge_serial->serial->dev,
X usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
X buffer, length, edge_bulk_out_cmd_callback, edge_port);
@@ -2494,17 +2495,11 @@
X urb->transfer_flags |= USB_QUEUE_BULK;
X
X edge_port->commandPending = TRUE;
- urb->dev = edge_serial->serial->dev;
X status = usb_submit_urb(urb);
X
X if (status) {
X /* something went wrong */
X dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed");
-
- /* if this urb had a transfer buffer already (old transfer) free it */
- if (urb->transfer_buffer != NULL) {
- kfree(urb->transfer_buffer);
- }
X usb_unlink_urb (urb);
X usb_free_urb (urb);
X return status;
@@ -2568,6 +2563,10 @@
X MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, edge_port->shadowLCR);
X
X status = write_cmd_usb(edge_port, cmdBuffer, cmdLen );
+ if (status) {
+ /* something bad happened, let's free up the memory */
+ kfree (cmdBuffer);
+ }
X
X return status;
X }
@@ -2643,6 +2642,10 @@
X MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, edge_port->port->number, regNum, regValue);
X
X status = write_cmd_usb(edge_port, cmdBuffer, cmdLen);
+ if (status) {
+ /* something bad happened, let's free up the memory */
+ kfree (cmdBuffer);
+ }
X
X return status;
X }
@@ -2727,10 +2730,8 @@
X unsigned char stop_char = STOP_CHAR(tty);
X unsigned char start_char = START_CHAR(tty);
X
- {
- send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XON_CHAR, start_char);
- send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char);
- }
+ send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XON_CHAR, start_char);
+ send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char);
X
X /* if we are implementing INBOUND XON/XOFF */
X if (I_IXOFF(tty)) {
@@ -2982,10 +2983,11 @@
X get_product_info(edge_serial);
X
X /* set the number of ports from the manufacturing description */
- // FIXME should we override this???
- //serial->num_ports = serial->product_info.NumPorts;
+ /* serial->num_ports = serial->product_info.NumPorts; */
X if (edge_serial->product_info.NumPorts != serial->num_ports) {
- warn(__FUNCTION__ " - Device Reported %d serial ports vs core thinking we have %d ports, email gr...@kroah.com this info.", edge_serial->product_info.NumPorts, serial->num_ports);
+ warn(__FUNCTION__ " - Device Reported %d serial ports vs core "
+ "thinking we have %d ports, email gr...@kroah.com this info.",
+ edge_serial->product_info.NumPorts, serial->num_ports);
X }
X
X dbg(__FUNCTION__ " - time 1 %ld", jiffies);
@@ -3025,10 +3027,9 @@
X
X
X /****************************************************************************
- * usb_edgeport_disconnect
+ * edge_shutdown
X * This function is called whenever the device is removed from the usb bus.
X ****************************************************************************/
-//static void usb_edgeport_disconnect (struct usb_device *dev, void *ptr)
X static void edge_shutdown (struct usb_serial *serial)
X {
X int i;
@@ -3040,11 +3041,11 @@
X while (serial->port[i].open_count > 0) {
X edge_close (&serial->port[i], NULL);
X }
+ kfree (serial->port[i].private);
+ serial->port[i].private = NULL;
X }
-
- /* free up any memory that we allocated */
- // FIXME
-
+ kfree (serial->private);
+ serial->private = NULL;
X }
X
X
@@ -3054,22 +3055,10 @@
X ****************************************************************************/
X int __init edgeport_init(void)
X {
- usb_serial_register (&edgeport_4_device);
- usb_serial_register (&rapidport_4_device);
- usb_serial_register (&edgeport_4t_device);
- usb_serial_register (&edgeport_2_device);
- usb_serial_register (&edgeport_4i_device);
- usb_serial_register (&edgeport_2i_device);
- usb_serial_register (&edgeport_prl_device);
- usb_serial_register (&edgeport_421_device);
- usb_serial_register (&edgeport_21_device);
- usb_serial_register (&edgeport_8dual_device);
- usb_serial_register (&edgeport_8_device);
- usb_serial_register (&edgeport_2din_device);
- usb_serial_register (&edgeport_4din_device);
- usb_serial_register (&edgeport_16dual_device);
- usb_serial_register (&edgeport_compat_id_device);
- usb_serial_register (&edgeport_8i_device);
+ usb_serial_register (&edgeport_1port_device);
+ usb_serial_register (&edgeport_2port_device);
+ usb_serial_register (&edgeport_4port_device);
+ usb_serial_register (&edgeport_8port_device);
X info(DRIVER_DESC " " DRIVER_VERSION);
X return 0;
X }
@@ -3082,22 +3071,10 @@
X ****************************************************************************/
X void __exit edgeport_exit (void)
X {
- usb_serial_deregister (&edgeport_4_device);
- usb_serial_deregister (&rapidport_4_device);
- usb_serial_deregister (&edgeport_4t_device);
- usb_serial_deregister (&edgeport_2_device);
- usb_serial_deregister (&edgeport_4i_device);
- usb_serial_deregister (&edgeport_2i_device);
- usb_serial_deregister (&edgeport_prl_device);
- usb_serial_deregister (&edgeport_421_device);
- usb_serial_deregister (&edgeport_21_device);
- usb_serial_deregister (&edgeport_8dual_device);
- usb_serial_deregister (&edgeport_8_device);
- usb_serial_deregister (&edgeport_2din_device);
- usb_serial_deregister (&edgeport_4din_device);
- usb_serial_deregister (&edgeport_16dual_device);
- usb_serial_deregister (&edgeport_compat_id_device);
- usb_serial_deregister (&edgeport_8i_device);
+ usb_serial_deregister (&edgeport_1port_device);
+ usb_serial_deregister (&edgeport_2port_device);
+ usb_serial_deregister (&edgeport_4port_device);
+ usb_serial_deregister (&edgeport_8port_device);
X }
X
X module_init(edgeport_init);
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/serial/io_tables.h linux/drivers/usb/serial/io_tables.h
--- v2.4.14/linux/drivers/usb/serial/io_tables.h Mon Mar 19 17:21:54 2001
+++ linux/drivers/usb/serial/io_tables.h Tue Nov 13 17:45:27 2001
@@ -11,29 +11,48 @@


X *
X */
X

-static __devinitdata struct usb_device_id edgeport_4_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4)}, {} };
-static __devinitdata struct usb_device_id rapidport_4_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_RAPIDPORT_4) }, {} };
-static __devinitdata struct usb_device_id edgeport_4t_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4T) }, {} };
-static __devinitdata struct usb_device_id edgeport_2_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2) }, {} };
-static __devinitdata struct usb_device_id edgeport_4i_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4I) }, {} };
-static __devinitdata struct usb_device_id edgeport_2i_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2I) }, {} };
-static __devinitdata struct usb_device_id edgeport_prl_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT) }, {} };
-static __devinitdata struct usb_device_id edgeport_421_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_421) }, {} };
-static __devinitdata struct usb_device_id edgeport_21_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_21) }, {} };
-static __devinitdata struct usb_device_id edgeport_8dual_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU) }, {} };
-static __devinitdata struct usb_device_id edgeport_8_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8) }, {} };
-static __devinitdata struct usb_device_id edgeport_2din_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2_DIN) }, {} };
-static __devinitdata struct usb_device_id edgeport_4din_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4_DIN) }, {} };
-static __devinitdata struct usb_device_id edgeport_16dual_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU) }, {} };
-static __devinitdata struct usb_device_id edgeport_compat_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_COMPATIBLE) }, {} };
-static __devinitdata struct usb_device_id edgeport_8i_id_table [] = {{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8I) }, {} };
+#ifndef IO_TABLES_H
+#define IO_TABLES_H
X
+static __devinitdata struct usb_device_id edgeport_1port_id_table [] = {
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT) },
+ { }
+};
+
+static __devinitdata struct usb_device_id edgeport_2port_id_table [] = {
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2I) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_421) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_21) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2_DIN) },
+ { }
+};
+
+static __devinitdata struct usb_device_id edgeport_4port_id_table [] = {
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_RAPIDPORT_4) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4T) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_MT4X56USB) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4I) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4_DIN) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_COMPATIBLE) },
+ { }
+};
+
+static __devinitdata struct usb_device_id edgeport_8port_id_table [] = {
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8I) },
+ { }
+};
X
X /* Devices that this driver supports */
X static __devinitdata struct usb_device_id id_table_combined [] = {
X { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4) },
X { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_RAPIDPORT_4) },
X { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4T) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_MT4X56USB) },
X { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2) },
X { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4I) },
X { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2I) },
@@ -52,155 +71,9 @@
X
X MODULE_DEVICE_TABLE (usb, id_table_combined);
X
-
-/* build up the list of devices that this driver supports */
-struct usb_serial_device_type edgeport_4_device = {
- name: "Edgeport 4",
- id_table: edgeport_4_id_table,
- needs_interrupt_in: MUST_HAVE,
- needs_bulk_in: MUST_HAVE,
- needs_bulk_out: MUST_HAVE,
- num_interrupt_in: 1,
- num_bulk_in: 1,
- num_bulk_out: 1,
- num_ports: 4,
- open: edge_open,
- close: edge_close,
- throttle: edge_throttle,
- unthrottle: edge_unthrottle,
- startup: edge_startup,
- shutdown: edge_shutdown,
- ioctl: edge_ioctl,
- set_termios: edge_set_termios,
- write: edge_write,
- write_room: edge_write_room,
- chars_in_buffer: edge_chars_in_buffer,
- break_ctl: edge_break,
-};
-
-struct usb_serial_device_type rapidport_4_device = {
- name: "Rapidport 4",
- id_table: rapidport_4_id_table,
- needs_interrupt_in: MUST_HAVE,
- needs_bulk_in: MUST_HAVE,
- needs_bulk_out: MUST_HAVE,
- num_interrupt_in: 1,
- num_bulk_in: 1,
- num_bulk_out: 1,
- num_ports: 4,
- open: edge_open,
- close: edge_close,
- throttle: edge_throttle,
- unthrottle: edge_unthrottle,
- startup: edge_startup,
- shutdown: edge_shutdown,
- ioctl: edge_ioctl,
- set_termios: edge_set_termios,
- write: edge_write,
- write_room: edge_write_room,
- chars_in_buffer: edge_chars_in_buffer,
- break_ctl: edge_break,
-};
-
-struct usb_serial_device_type edgeport_4t_device = {
- name: "Edgeport 4t",
- id_table: edgeport_4t_id_table,
- needs_interrupt_in: MUST_HAVE,
- needs_bulk_in: MUST_HAVE,
- needs_bulk_out: MUST_HAVE,
- num_interrupt_in: 1,
- num_bulk_in: 1,
- num_bulk_out: 1,
- num_ports: 4,
- open: edge_open,
- close: edge_close,
- throttle: edge_throttle,
- unthrottle: edge_unthrottle,
- startup: edge_startup,
- shutdown: edge_shutdown,
- ioctl: edge_ioctl,
- set_termios: edge_set_termios,
- write: edge_write,
- write_room: edge_write_room,
- chars_in_buffer: edge_chars_in_buffer,
- break_ctl: edge_break,
-};
-
-struct usb_serial_device_type edgeport_2_device = {
- name: "Edgeport 2",
- id_table: edgeport_2_id_table,
- needs_interrupt_in: MUST_HAVE,
- needs_bulk_in: MUST_HAVE,
- needs_bulk_out: MUST_HAVE,
- num_interrupt_in: 1,
- num_bulk_in: 1,
- num_bulk_out: 1,
- num_ports: 2,
- open: edge_open,
- close: edge_close,
- throttle: edge_throttle,
- unthrottle: edge_unthrottle,
- startup: edge_startup,
- shutdown: edge_shutdown,
- ioctl: edge_ioctl,
- set_termios: edge_set_termios,
- write: edge_write,
- write_room: edge_write_room,
- chars_in_buffer: edge_chars_in_buffer,
- break_ctl: edge_break,
-};
-
-struct usb_serial_device_type edgeport_4i_device = {
- name: "Edgeport 4i",
- id_table: edgeport_4i_id_table,
- needs_interrupt_in: MUST_HAVE,
- needs_bulk_in: MUST_HAVE,
- needs_bulk_out: MUST_HAVE,
- num_interrupt_in: 1,
- num_bulk_in: 1,
- num_bulk_out: 1,
- num_ports: 4,
- open: edge_open,
- close: edge_close,
- throttle: edge_throttle,
- unthrottle: edge_unthrottle,
- startup: edge_startup,
- shutdown: edge_shutdown,
- ioctl: edge_ioctl,
- set_termios: edge_set_termios,
- write: edge_write,
- write_room: edge_write_room,
- chars_in_buffer: edge_chars_in_buffer,
- break_ctl: edge_break,
-};
-
-struct usb_serial_device_type edgeport_2i_device = {
- name: "Edgeport 2i",
- id_table: edgeport_2i_id_table,
- needs_interrupt_in: MUST_HAVE,
- needs_bulk_in: MUST_HAVE,
- needs_bulk_out: MUST_HAVE,
- num_interrupt_in: 1,
- num_bulk_in: 1,
- num_bulk_out: 1,
- num_ports: 2,
- open: edge_open,
- close: edge_close,
- throttle: edge_throttle,
- unthrottle: edge_unthrottle,
- startup: edge_startup,
- shutdown: edge_shutdown,
- ioctl: edge_ioctl,
- set_termios: edge_set_termios,
- write: edge_write,
- write_room: edge_write_room,
- chars_in_buffer: edge_chars_in_buffer,
- break_ctl: edge_break,
-};
-
-struct usb_serial_device_type edgeport_prl_device = {
- name: "Edgeport Parallel",
- id_table: edgeport_prl_id_table,
+static struct usb_serial_device_type edgeport_1port_device = {
+ name: "Edgeport 1 port adapter",
+ id_table: edgeport_1port_id_table,
X needs_interrupt_in: MUST_HAVE,
X needs_bulk_in: MUST_HAVE,
X needs_bulk_out: MUST_HAVE,
@@ -222,9 +95,9 @@
X break_ctl: edge_break,
X };
X
-struct usb_serial_device_type edgeport_421_device = {
- name: "Edgeport 421",
- id_table: edgeport_421_id_table,
+static struct usb_serial_device_type edgeport_2port_device = {
+ name: "Edgeport 2 port adapter",
+ id_table: edgeport_2port_id_table,
X needs_interrupt_in: MUST_HAVE,
X needs_bulk_in: MUST_HAVE,
X needs_bulk_out: MUST_HAVE,
@@ -246,153 +119,9 @@
X break_ctl: edge_break,
X };
X
-struct usb_serial_device_type edgeport_21_device = {
- name: "Edgeport 21",
- id_table: edgeport_21_id_table,
- needs_interrupt_in: MUST_HAVE,
- needs_bulk_in: MUST_HAVE,
- needs_bulk_out: MUST_HAVE,
- num_interrupt_in: 1,
- num_bulk_in: 1,
- num_bulk_out: 1,
- num_ports: 2,
- open: edge_open,
- close: edge_close,
- throttle: edge_throttle,
- unthrottle: edge_unthrottle,
- startup: edge_startup,
- shutdown: edge_shutdown,
- ioctl: edge_ioctl,
- set_termios: edge_set_termios,
- write: edge_write,
- write_room: edge_write_room,
- chars_in_buffer: edge_chars_in_buffer,
- break_ctl: edge_break,
-};
-
-struct usb_serial_device_type edgeport_8dual_device = {
- name: "Edgeport 8 dual cpu",
- id_table: edgeport_8dual_id_table,
- needs_interrupt_in: MUST_HAVE,
- needs_bulk_in: MUST_HAVE,
- needs_bulk_out: MUST_HAVE,
- num_interrupt_in: 1,
- num_bulk_in: 1,
- num_bulk_out: 1,
- num_ports: 4,
- open: edge_open,
- close: edge_close,
- throttle: edge_throttle,
- unthrottle: edge_unthrottle,
- startup: edge_startup,
- shutdown: edge_shutdown,
- ioctl: edge_ioctl,
- set_termios: edge_set_termios,
- write: edge_write,
- write_room: edge_write_room,
- chars_in_buffer: edge_chars_in_buffer,
- break_ctl: edge_break,
-};
-
-struct usb_serial_device_type edgeport_8_device = {
- name: "Edgeport 8",
- id_table: edgeport_8_id_table,
- needs_interrupt_in: MUST_HAVE,
- needs_bulk_in: MUST_HAVE,
- needs_bulk_out: MUST_HAVE,
- num_interrupt_in: 1,
- num_bulk_in: 1,
- num_bulk_out: 1,
- num_ports: 8,
- open: edge_open,
- close: edge_close,
- throttle: edge_throttle,
- unthrottle: edge_unthrottle,
- startup: edge_startup,
- shutdown: edge_shutdown,
- ioctl: edge_ioctl,
- set_termios: edge_set_termios,
- write: edge_write,
- write_room: edge_write_room,
- chars_in_buffer: edge_chars_in_buffer,
- break_ctl: edge_break,
-};
-
-struct usb_serial_device_type edgeport_2din_device = {
- name: "Edgeport 2din",
- id_table: edgeport_2din_id_table,
- needs_interrupt_in: MUST_HAVE,
- needs_bulk_in: MUST_HAVE,
- needs_bulk_out: MUST_HAVE,
- num_interrupt_in: 1,
- num_bulk_in: 1,
- num_bulk_out: 1,
- num_ports: 2,
- open: edge_open,
- close: edge_close,
- throttle: edge_throttle,
- unthrottle: edge_unthrottle,
- startup: edge_startup,
- shutdown: edge_shutdown,
- ioctl: edge_ioctl,
- set_termios: edge_set_termios,
- write: edge_write,
- write_room: edge_write_room,
- chars_in_buffer: edge_chars_in_buffer,
- break_ctl: edge_break,
-};
-
-struct usb_serial_device_type edgeport_4din_device = {
- name: "Edgeport 4din",
- id_table: edgeport_4din_id_table,
- needs_interrupt_in: MUST_HAVE,
- needs_bulk_in: MUST_HAVE,
- needs_bulk_out: MUST_HAVE,
- num_interrupt_in: 1,
- num_bulk_in: 1,
- num_bulk_out: 1,
- num_ports: 4,
- open: edge_open,
- close: edge_close,
- throttle: edge_throttle,
- unthrottle: edge_unthrottle,
- startup: edge_startup,
- shutdown: edge_shutdown,
- ioctl: edge_ioctl,
- set_termios: edge_set_termios,
- write: edge_write,
- write_room: edge_write_room,
- chars_in_buffer: edge_chars_in_buffer,
- break_ctl: edge_break,
-};
-
-struct usb_serial_device_type edgeport_16dual_device = {
- name: "Edgeport 16 dual cpu",
- id_table: edgeport_16dual_id_table,
- needs_interrupt_in: MUST_HAVE,
- needs_bulk_in: MUST_HAVE,
- needs_bulk_out: MUST_HAVE,
- num_interrupt_in: 1,
- num_bulk_in: 1,
- num_bulk_out: 1,
- num_ports: 8,
- open: edge_open,
- close: edge_close,
- throttle: edge_throttle,
- unthrottle: edge_unthrottle,
- startup: edge_startup,
- shutdown: edge_shutdown,
- ioctl: edge_ioctl,
- set_termios: edge_set_termios,
- write: edge_write,
- write_room: edge_write_room,
- chars_in_buffer: edge_chars_in_buffer,
- break_ctl: edge_break,
-};
-
-struct usb_serial_device_type edgeport_compat_id_device = {
- name: "Edgeport Compatible",
- id_table: edgeport_compat_id_table,
+static struct usb_serial_device_type edgeport_4port_device = {
+ name: "Edgeport 4 port adapter",
+ id_table: edgeport_4port_id_table,
X needs_interrupt_in: MUST_HAVE,
X needs_bulk_in: MUST_HAVE,
X needs_bulk_out: MUST_HAVE,
@@ -414,10 +143,9 @@
X break_ctl: edge_break,
X };
X
-
-struct usb_serial_device_type edgeport_8i_device = {
- name: "Edgeport 8i",
- id_table: edgeport_8i_id_table,
+static struct usb_serial_device_type edgeport_8port_device = {
+ name: "Edgeport 8 port adapter",
+ id_table: edgeport_8port_id_table,
X needs_interrupt_in: MUST_HAVE,
X needs_bulk_in: MUST_HAVE,
X needs_bulk_out: MUST_HAVE,
@@ -439,6 +167,5 @@
X break_ctl: edge_break,
X };
X
-
-
+#endif
X
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/serial/io_usbvend.h linux/drivers/usb/serial/io_usbvend.h
--- v2.4.14/linux/drivers/usb/serial/io_usbvend.h Sun Sep 23 11:41:00 2001
+++ linux/drivers/usb/serial/io_usbvend.h Tue Nov 13 17:45:27 2001
@@ -90,6 +90,7 @@
X #define ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU 0x012 // Half of an Edgeport/16 (the kind with 2 EP/8s)
X #define ION_DEVICE_ID_EDGEPORT_COMPATIBLE 0x013 // Edgeport Compatible, for NCR, Axiohm etc. testing
X #define ION_DEVICE_ID_EDGEPORT_8I 0x014 // Edgeport/8 RS422 (single-CPU)
+#define ION_DEVICE_ID_MT4X56USB 0x1403 // OEM device
X
X // These IDs are used by the Edgeport.exe program for uninstalling.
X //
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/serial/ir-usb.c linux/drivers/usb/serial/ir-usb.c
--- v2.4.14/linux/drivers/usb/serial/ir-usb.c Mon Nov 5 15:55:32 2001
+++ linux/drivers/usb/serial/ir-usb.c Mon Nov 12 09:53:56 2001
@@ -17,9 +17,13 @@
X * Portions of this driver were taken from drivers/net/irda/irda-usb.c, which
X * was written by Roman Weissgaerber <wei...@vienna.at>, Dag Brattli
X * <d...@brattli.net>, and Jean Tourrilhes <j...@hpl.hp.com>
-
+ *


X * See Documentation/usb/usb-serial.txt for more information on using this driver
X *

+ * 2001_Nov_08 greg kh
+ * Changed the irda_usb_find_class_desc() function based on comments and
+ * code from Martin Diehl.
+ *
X * 2001_Nov_01 greg kh
X * Added support for more IrDA USB devices.
X * Added support for zero packet. Added buffer override paramater, so
@@ -58,7 +62,7 @@


X /*
X * Version Information
X */

-#define DRIVER_VERSION "v0.2"
+#define DRIVER_VERSION "v0.3"


X #define DRIVER_AUTHOR "Greg Kroah-Hartman <gr...@kroah.com>"

X #define DRIVER_DESC "USB IR Dongle driver"
X
@@ -128,12 +132,12 @@
X * The class descriptor is some extra info that IrDA USB devices will
X * offer to us, describing their IrDA characteristics. We will use that in
X * irda_usb_init_qos()
+ *
+ * Based on the same function in drivers/net/irda/irda-usb.c
X */
X static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum)
X {
- struct usb_interface_descriptor *interface;
X struct irda_class_desc *desc;
- struct irda_class_desc *ptr;
X int ret;
X
X desc = kmalloc(sizeof (struct irda_class_desc), GFP_KERNEL);
@@ -141,28 +145,27 @@
X return NULL;
X memset(desc, 0, sizeof(struct irda_class_desc));
X

- ret = usb_get_class_descriptor(dev, ifnum, USB_DT_IRDA, 0, (void *) desc, sizeof(struct irda_class_desc));

- dbg(__FUNCTION__ " - ret=%d", ret);
- if (ret)
- dbg(__FUNCTION__ " - usb_get_class_descriptor failed (0x%x)", ret);
-


- /* Check if we found it? */
- if (desc->bDescriptorType == USB_DT_IRDA)

- goto exit;
-
- dbg(__FUNCTION__ " - parsing extra descriptors...");


+ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
+ IU_REQ_GET_CLASS_DESC,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0, ifnum, desc, sizeof(*desc), MSECS_TO_JIFFIES(500));
X
- /* Check if the class descriptor is interleaved with standard descriptors */
- interface = &dev->actconfig->interface[ifnum].altsetting[0];
- ret = usb_get_extra_descriptor(interface, USB_DT_IRDA, &ptr);
- if (ret) {
- kfree(desc);
- return NULL;

+ dbg(__FUNCTION__ " - ret=%d", ret);
+ if (ret < sizeof(*desc)) {
+ dbg(__FUNCTION__ " - class descriptor read %s (%d)",


+ (ret<0) ? "failed" : "too short", ret);

+ goto error;


X }
- *desc = *ptr;

-exit:
+ if (desc->bDescriptorType != USB_DT_IRDA) {
+ dbg(__FUNCTION__ " - bad class descriptor type");
+ goto error;
+ }
+
X irda_usb_dump_class_desc(desc);
X return desc;
+error:


+ kfree(desc);
+ return NULL;

X }
X
X static int ir_startup (struct usb_serial *serial)
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/serial/mct_u232.c linux/drivers/usb/serial/mct_u232.c
--- v2.4.14/linux/drivers/usb/serial/mct_u232.c Thu Oct 11 08:02:26 2001
+++ linux/drivers/usb/serial/mct_u232.c Mon Nov 12 09:53:56 2001
@@ -24,6 +24,9 @@
X * Basic tests have been performed with minicom/zmodem transfers and
X * modem dialing under Linux 2.4.0-test10 (for me it works fine).
X *
+ * 10-Nov-2001 Wolfgang Grandegger
+ * - Fixed an endianess problem with the baudrate selection for PowerPC.
+ *
X * 30-May-2001 Greg Kroah-Hartman


X * switched from using spinlock to a semaphore, which fixes lots of problems.
X *

@@ -263,7 +266,7 @@
X {
X unsigned int divisor;
X int rc;
- divisor = mct_u232_calculate_baud_rate(serial, value);
+ divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
X rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
X MCT_U232_SET_BAUD_RATE_REQUEST,
X MCT_U232_SET_REQUEST_TYPE,
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c
--- v2.4.14/linux/drivers/usb/serial/visor.c Thu Oct 11 08:02:26 2001
+++ linux/drivers/usb/serial/visor.c Mon Nov 12 09:53:56 2001
@@ -12,6 +12,10 @@


X *
X * See Documentation/usb/usb-serial.txt for more information on using this driver
X *

+ * (11/11/2001) gkh
+ * Added support for the m125 devices, and added check to prevent oopses
+ * for Clié devices that lie about the number of ports they have.
+ *
X * (08/30/2001) gkh
X * Added support for the Clie devices, both the 3.5 and 4.0 os versions.
X * Many thanks to Daniel Burke, and Bryan Payne for helping with this.
@@ -123,9 +127,9 @@


X /*
X * Version Information
X */

-#define DRIVER_VERSION "v1.4"
+#define DRIVER_VERSION "v1.5"


X #define DRIVER_AUTHOR "Greg Kroah-Hartman <gr...@kroah.com>"

-#define DRIVER_DESC "USB HandSpring Visor, Palm m50x, Sony Clie driver"
+#define DRIVER_DESC "USB HandSpring Visor, Palm m50x, Sony Clié driver"
X
X /* function prototypes for a handspring visor */
X static int visor_open (struct usb_serial_port *port, struct file *filp);
@@ -148,13 +152,10 @@
X { } /* Terminating entry */
X };
X
-static __devinitdata struct usb_device_id palm_m500_id_table [] = {
+static __devinitdata struct usb_device_id palm_4_0_id_table [] = {
X { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
- { } /* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id palm_m505_id_table [] = {
X { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
+ { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
X { } /* Terminating entry */
X };
X
@@ -172,6 +173,7 @@
X { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
X { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
X { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
+ { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
X { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) },
X { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
X { } /* Terminating entry */
@@ -207,10 +209,10 @@
X read_bulk_callback: visor_read_bulk_callback,
X };
X
-/* device info for the Palm M500 */
-struct usb_serial_device_type palm_m500_device = {
- name: "Palm M500",
- id_table: palm_m500_id_table,
+/* device info for the Palm 4.0 devices */
+struct usb_serial_device_type palm_4_0_device = {
+ name: "Palm 4.0",
+ id_table: palm_4_0_id_table,
X needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */
X needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
X needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
@@ -233,35 +235,10 @@
X read_bulk_callback: visor_read_bulk_callback,
X };
X
-/* device info for the Palm M505 */
-struct usb_serial_device_type palm_m505_device = {
- name: "Palm M505",
- id_table: palm_m505_id_table,
- needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */
- needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
- needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
- num_interrupt_in: 0,
- num_bulk_in: 2,
- num_bulk_out: 2,
- num_ports: 2,
- open: visor_open,
- close: visor_close,
- throttle: visor_throttle,
- unthrottle: visor_unthrottle,
- startup: visor_startup,
- shutdown: visor_shutdown,
- ioctl: visor_ioctl,
- set_termios: visor_set_termios,
- write: visor_write,
- write_room: visor_write_room,
- chars_in_buffer: visor_chars_in_buffer,
- write_bulk_callback: visor_write_bulk_callback,
- read_bulk_callback: visor_read_bulk_callback,
-};
X
X /* device info for the Sony Clie OS version 3.5 */
X static struct usb_serial_device_type clie_3_5_device = {
- name: "Sony Clie 3.5",
+ name: "Sony Clié 3.5",
X id_table: clie_id_3_5_table,
X needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */
X needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
@@ -285,7 +262,7 @@
X
X /* device info for the Sony Clie OS version 4.0 */
X static struct usb_serial_device_type clie_4_0_device = {
- name: "Sony Clie 4.0",
+ name: "Sony Clié 4.0",
X id_table: clie_id_4_0_table,
X needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */
X needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
@@ -330,6 +307,11 @@
X
X dbg(__FUNCTION__ " - port %d", port->number);
X
+ if (!port->read_urb) {
+ err ("Device lied about number of ports, please use a lower one.");


+ return -ENODEV;
+ }
+

X down (&port->sem);
X
X ++port->open_count;
@@ -819,8 +801,7 @@
X int i;
X
X usb_serial_register (&handspring_device);
- usb_serial_register (&palm_m500_device);
- usb_serial_register (&palm_m505_device);
+ usb_serial_register (&palm_4_0_device);
X usb_serial_register (&clie_3_5_device);
X usb_serial_register (&clie_4_0_device);
X
@@ -854,8 +835,7 @@


X unsigned long flags;
X

X usb_serial_deregister (&handspring_device);
- usb_serial_deregister (&palm_m500_device);
- usb_serial_deregister (&palm_m505_device);
+ usb_serial_deregister (&palm_4_0_device);
X usb_serial_deregister (&clie_3_5_device);
X usb_serial_deregister (&clie_4_0_device);
X
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/serial/visor.h linux/drivers/usb/serial/visor.h
--- v2.4.14/linux/drivers/usb/serial/visor.h Sun Sep 23 11:41:00 2001
+++ linux/drivers/usb/serial/visor.h Mon Nov 12 09:53:56 2001
@@ -23,6 +23,7 @@
X #define PALM_VENDOR_ID 0x0830
X #define PALM_M500_ID 0x0001
X #define PALM_M505_ID 0x0002
+#define PALM_M125_ID 0x0040
X
X #define SONY_VENDOR_ID 0x054C
X #define SONY_CLIE_3_5_ID 0x0038
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/storage/freecom.c linux/drivers/usb/storage/freecom.c
--- v2.4.14/linux/drivers/usb/storage/freecom.c Sun Aug 12 13:28:00 2001
+++ linux/drivers/usb/storage/freecom.c Tue Nov 13 09:19:41 2001
@@ -1,6 +1,6 @@
X /* Driver for Freecom USB/IDE adaptor
X *
- * $Id: freecom.c,v 1.15 2001/06/27 23:50:28 mdharm Exp $
+ * $Id: freecom.c,v 1.19 2001/11/11 05:42:34 mdharm Exp $
X *
X * Freecom v0.1:
X *


@@ -81,27 +81,28 @@
X

X /* Freecom stuffs the interrupt status in the INDEX_STAT bit of the ide
X * register. */
-#define FCM_INT_STATUS INDEX_STAT
+#define FCM_INT_STATUS 0x02 /* INDEX_STAT */
+#define FCM_STATUS_BUSY 0x80
X
X /* These are the packet types. The low bit indicates that this command
X * should wait for an interrupt. */
-#define FCM_PACKET_ATAPI 0x21
-#define FCM_PACKET_STATUS 0x20
+#define FCM_PACKET_ATAPI 0x21
+#define FCM_PACKET_STATUS 0x20
X
X /* Receive data from the IDE interface. The ATAPI packet has already
X * waited, so the data should be immediately available. */
-#define FCM_PACKET_INPUT 0x81
+#define FCM_PACKET_INPUT 0x81
X
X /* Send data to the IDE interface. */
-#define FCM_PACKET_OUTPUT 0x01
+#define FCM_PACKET_OUTPUT 0x01
X
X /* Write a value to an ide register. Or the ide register to write after
X * munging the address a bit. */
-#define FCM_PACKET_IDE_WRITE 0x40
-#define FCM_PACKET_IDE_READ 0xC0
+#define FCM_PACKET_IDE_WRITE 0x40
+#define FCM_PACKET_IDE_READ 0xC0
X
X /* All packets (except for status) are 64 bytes long. */
-#define FCM_PACKET_LENGTH 64
+#define FCM_PACKET_LENGTH 64
X
X /*
X * Transfer an entire SCSI command's worth of data payload over the bulk
@@ -132,6 +133,12 @@
X sg = (struct scatterlist *) srb->request_buffer;
X for (i = 0; i < srb->use_sg; i++) {
X
+ US_DEBUGP("transfer_amount: %d and total_transferred: %d\n", transfer_amount, total_transferred);
+
+ /* End this if we're done */
+ if (transfer_amount == total_transferred)
+ break;
+
X /* transfer the lesser of the next buffer or the
X * remaining data */
X if (transfer_amount - total_transferred >=
@@ -139,10 +146,12 @@
X result = usb_stor_transfer_partial(us,
X sg[i].address, sg[i].length);
X total_transferred += sg[i].length;
- } else
+ } else {
X result = usb_stor_transfer_partial(us,
X sg[i].address,
X transfer_amount - total_transferred);
+ total_transferred += transfer_amount - total_transferred;
+ }
X
X /* if we get an error, end the loop here */
X if (result)
@@ -158,7 +167,7 @@
X srb->result = result;
X }
X
-
+#if 0
X /* Write a value to an ide register. */
X static int
X freecom_ide_write (struct us_data *us, int reg, int value)
@@ -197,7 +206,9 @@
X
X return USB_STOR_TRANSPORT_GOOD;
X }
+#endif
X
+#if 0 /* Unused at this time */
X /* Read a value from an ide register. */
X static int
X freecom_ide_read (struct us_data *us, int reg, int *value)
@@ -221,6 +232,8 @@
X else
X reg = 0x0e;
X
+ US_DEBUGP("IDE in request for register 0x%02x\n", reg);
+
X idein->Type = FCM_PACKET_IDE_READ | reg;
X memset (idein->Pad, 0, sizeof (idein->Pad));
X
@@ -245,16 +258,18 @@
X else
X return USB_STOR_TRANSPORT_ERROR;
X }
+ US_DEBUGP("IDE in partial is %d\n", partial);
X
X if (desired_length == 1)
X *value = buffer[0];
X else
X *value = le16_to_cpu (*(__u16 *) buffer);
X
- US_DEBUGP("IDE in 0x%02x -> 0x%02x\n", reg, *value);
+ US_DEBUGP("IDE in 0x%02x -> 0x%02x\n", reg, *value);
X
X return USB_STOR_TRANSPORT_GOOD;
X }
+#endif
X
X static int
X freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
@@ -364,13 +379,6 @@
X opipe = usb_sndbulkpipe (us->pusb_dev, us->ep_out);
X ipipe = usb_rcvbulkpipe (us->pusb_dev, us->ep_in);
X
-#if 0
- /* Yuck, let's see if this helps us. Artificially increase the
- * length on this. */
- if (srb->cmnd[0] == 0x03 && srb->cmnd[4] == 0x12)
- srb->cmnd[4] = 0x0E;
-#endif
-
X /* The ATAPI Command always goes out first. */
X fcb->Type = FCM_PACKET_ATAPI | 0x00;
X fcb->Timeout = 0;
@@ -412,17 +420,25 @@
X
X US_DEBUG(pdump ((void *) fst, partial));
X
- /* while we haven't received the IRQ */
- while (!(fst->Status & 0x2)) {
- /* send a command to re-fetch the status */
- US_DEBUGP("Re-attempting to get status...\n");
+ /* The firmware will time-out commands after 20 seconds. Some commands
+ * can legitimately take longer than this, so we use a different
+ * command that only waits for the interrupt and then sends status,
+ * without having to send a new ATAPI command to the device.
+ *
+ * NOTE: There is some indication that a data transfer after a timeout
+ * may not work, but that is a condition that should never happen.
+ */
+ while (fst->Status & FCM_STATUS_BUSY) {
+ US_DEBUGP("20 second USB/ATAPI bridge TIMEOUT occured!\n");
+ US_DEBUGP("fst->Status is %x\n", fst->Status);
X
+ /* Get the status again */
X fcb->Type = FCM_PACKET_STATUS;
X fcb->Timeout = 0;
- memset (fcb->Atapi, 0, 12);
+ memset (fcb->Atapi, 0, sizeof(fcb->Filler));
X memset (fcb->Filler, 0, sizeof (fcb->Filler));
X
- /* Send it out. */
+ /* Send it out. */
X result = usb_stor_bulk_msg (us, fcb, opipe,
X FCM_PACKET_LENGTH, &partial);
X
@@ -443,10 +459,12 @@
X return USB_STOR_TRANSPORT_ERROR;
X }
X
- /* actually get the status info */
- result = usb_stor_bulk_msg (us, fst, ipipe,
+ /* get the data */
+ result = usb_stor_bulk_msg (us, fst, ipipe,
X FCM_PACKET_LENGTH, &partial);
+
X US_DEBUGP("bar Status result %d %d\n", result, partial);
+
X /* -ENOENT -- we canceled this transfer */
X if (result == -ENOENT) {
X US_DEBUGP("freecom_transport(): transfer aborted\n");
@@ -470,13 +488,15 @@
X US_DEBUGP("Device indicates that it has %d bytes available\n",
X le16_to_cpu (fst->Count));
X
- /* Find the length we desire to read. It is the lesser of the SCSI
- * layer's requested length, and the length the device claims to
- * have available. */
+ /* Find the length we desire to read. */
X length = usb_stor_transfer_length (srb);
X US_DEBUGP("SCSI requested %d\n", length);
- if (length > le16_to_cpu (fst->Count))
- length = le16_to_cpu (fst->Count);
+
+ /* verify that this amount is legal */
+ if (length > srb->request_bufflen) {
+ length = srb->request_bufflen;
+ US_DEBUGP("Truncating request to match buffer length: %d\n", length);
+ }
X
X /* What we do now depends on what direction the data is supposed to
X * move in. */
@@ -522,7 +542,6 @@
X if (result != USB_STOR_TRANSPORT_GOOD)
X return result;
X
-#if 1
X US_DEBUGP("FCM: Waiting for status\n");
X result = usb_stor_bulk_msg (us, fst, ipipe,
X FCM_PACKET_LENGTH, &partial);
@@ -540,7 +559,7 @@
X US_DEBUGP("Drive seems still hungry\n");
X return USB_STOR_TRANSPORT_FAILED;
X }
-#endif
+
X US_DEBUGP("Transfer happy\n");
X break;
X
@@ -570,8 +589,7 @@
X int
X freecom_init (struct us_data *us)
X {
- int result, value;
- int counter;
+ int result;
X char buffer[33];
X
X /* Allocate a buffer for us. The upper usb transport code will
@@ -591,42 +609,29 @@
X buffer[32] = '\0';
X US_DEBUGP("String returned from FC init is: %s\n", buffer);
X
- result = freecom_ide_write (us, 0x06, 0xA0);
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
- result = freecom_ide_write (us, 0x01, 0x00);
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- counter = 50;
- do {
- result = freecom_ide_read (us, 0x07, &value);
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
- if (counter-- < 0) {
- US_DEBUGP("Timeout in freecom");
- return USB_STOR_TRANSPORT_ERROR;
- }
- } while ((value & 0x80) != 0);
+ /* Special thanks to the people at Freecom for providing me with
+ * this "magic sequence", which they use in their Windows and MacOS
+ * drivers to make sure that all the attached perhiperals are
+ * properly reset.
+ */
X
- result = freecom_ide_write (us, 0x07, 0x08);
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- counter = 50;
- do {
- result = freecom_ide_read (us, 0x07, &value);
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
- if (counter-- < 0) {
- US_DEBUGP("Timeout in freecom");
- return USB_STOR_TRANSPORT_ERROR;
- }
- } while ((value & 0x80) != 0);
+ /* send reset */
+ result = usb_control_msg(us->pusb_dev,
+ usb_sndctrlpipe(us->pusb_dev, 0),
+ 0x4d, 0x40, 0x24d8, 0x0, NULL, 0x0, 3*HZ);
+ US_DEBUGP("result from activate reset is %d\n", result);
+
+ /* wait 250ms */
+ mdelay(250);
+
+ /* clear reset */
+ result = usb_control_msg(us->pusb_dev,
+ usb_sndctrlpipe(us->pusb_dev, 0),
+ 0x4d, 0x40, 0x24f8, 0x0, NULL, 0x0, 3*HZ);
+ US_DEBUGP("result from clear reset is %d\n", result);
X
- result = freecom_ide_write (us, 0x08, 0x08);
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
+ /* wait 3 seconds */
+ mdelay(3 * 1000);
X
X return USB_STOR_TRANSPORT_GOOD;
X }
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/storage/isd200.c linux/drivers/usb/storage/isd200.c
--- v2.4.14/linux/drivers/usb/storage/isd200.c Sun Sep 23 11:41:00 2001
+++ linux/drivers/usb/storage/isd200.c Tue Nov 13 09:19:41 2001
@@ -1112,8 +1112,10 @@
X
X /* loop until we detect !BSY or timeout */
X while(TRUE) {
+#ifdef CONFIG_USB_STORAGE_DEBUG
X char* mstr = master_slave == ATA_ADDRESS_DEVHEAD_STD ?
X "Master" : "Slave";
+#endif
X
X status = isd200_action( us, ACTION_ENUM, NULL, master_slave );
X if ( status != ISD200_GOOD )
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/storage/scsiglue.c linux/drivers/usb/storage/scsiglue.c
--- v2.4.14/linux/drivers/usb/storage/scsiglue.c Sun Sep 23 11:41:00 2001
+++ linux/drivers/usb/storage/scsiglue.c Sun Nov 11 10:01:32 2001
@@ -1,7 +1,7 @@
X /* Driver for USB Mass Storage compliant devices
X * SCSI layer glue code
X *
- * $Id: scsiglue.c,v 1.22 2001/09/02 04:29:27 mdharm Exp $
+ * $Id: scsiglue.c,v 1.24 2001/11/11 03:33:58 mdharm Exp $
X *
X * Current development and maintenance by:
X * (c) 1999, 2000 Matthew Dharm (mdhar...@one-eyed-alien.net)
@@ -346,7 +346,7 @@
X
X /* show the GUID of the device */
X SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid));
- SPRINTF(" Attached: %d\n", us->pusb_dev != NULL);
+ SPRINTF(" Attached: %s\n", us->pusb_dev ? "Yes" : "No");
X
X /*
X * Calculate start of next buffer, and return value.
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/storage/sddr09.c linux/drivers/usb/storage/sddr09.c
--- v2.4.14/linux/drivers/usb/storage/sddr09.c Mon Nov 5 15:55:32 2001
+++ linux/drivers/usb/storage/sddr09.c Fri Nov 9 14:37:14 2001
@@ -1,6 +1,6 @@
X /* Driver for SanDisk SDDR-09 SmartMedia reader
X *
- * $Id: sddr09.c,v 1.19 2001/09/02 06:07:20 mdharm Exp $
+ * $Id: sddr09.c,v 1.21 2001/11/06 03:18:36 mdharm Exp $
X *
X * SDDR09 driver v0.1:
X *
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/storage/transport.c linux/drivers/usb/storage/transport.c
--- v2.4.14/linux/drivers/usb/storage/transport.c Sun Sep 23 11:41:00 2001
+++ linux/drivers/usb/storage/transport.c Fri Nov 9 14:37:14 2001
@@ -1,6 +1,6 @@
X /* Driver for USB Mass Storage compliant devices
X *
- * $Id: transport.c,v 1.40 2001/08/18 08:37:46 mdharm Exp $
+ * $Id: transport.c,v 1.41 2001/10/15 07:02:32 mdharm Exp $
X *
X * Current development and maintenance by:
X * (c) 1999, 2000 Matthew Dharm (mdhar...@one-eyed-alien.net)
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/storage/usb.c linux/drivers/usb/storage/usb.c
--- v2.4.14/linux/drivers/usb/storage/usb.c Sun Sep 23 11:41:00 2001
+++ linux/drivers/usb/storage/usb.c Sun Nov 11 10:01:32 2001
@@ -1,6 +1,6 @@
X /* Driver for USB Mass Storage compliant devices
X *
- * $Id: usb.c,v 1.67 2001/07/29 23:41:52 mdharm Exp $
+ * $Id: usb.c,v 1.69 2001/11/11 03:33:03 mdharm Exp $
X *
X * Current development and maintenance by:
X * (c) 1999, 2000 Matthew Dharm (mdhar...@one-eyed-alien.net)
@@ -262,16 +262,28 @@
X if (data_len<36) // You lose.
X return;
X
- memcpy(data+8, us->unusual_dev->vendorName,
- strlen(us->unusual_dev->vendorName) > 8 ? 8 :
- strlen(us->unusual_dev->vendorName));
- memcpy(data+16, us->unusual_dev->productName,
- strlen(us->unusual_dev->productName) > 16 ? 16 :
- strlen(us->unusual_dev->productName));
- data[32] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>12) & 0x0F);
- data[33] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>8) & 0x0F);
- data[34] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>4) & 0x0F);
- data[35] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice) & 0x0F);
+ if(data[0]&0x20) { /* USB device currently not connected. Return
+ peripheral qualifier 001b ("...however, the
+ physical device is not currently connected
+ to this logical unit") and leave vendor and
+ product identification empty. ("If the target
+ does store some of the INQUIRY data on the
+ device, it may return zeros or ASCII spaces
+ (20h) in those fields until the data is
+ available from the device."). */
+ memset(data+8,0,28);
+ } else {
+ memcpy(data+8, us->unusual_dev->vendorName,
+ strlen(us->unusual_dev->vendorName) > 8 ? 8 :
+ strlen(us->unusual_dev->vendorName));
+ memcpy(data+16, us->unusual_dev->productName,
+ strlen(us->unusual_dev->productName) > 16 ? 16 :
+ strlen(us->unusual_dev->productName));
+ data[32] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>12) & 0x0F);
+ data[33] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>8) & 0x0F);
+ data[34] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>4) & 0x0F);
+ data[35] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice) & 0x0F);
+ }
X
X if (us->srb->use_sg) {
X sg = (struct scatterlist *)us->srb->request_buffer;
@@ -389,24 +401,6 @@
X break;
X }
X
- /* Handle those devices which need us to fake their
- * inquiry data */
- if ((us->srb->cmnd[0] == INQUIRY) &&
- (us->flags & US_FL_FIX_INQUIRY)) {
- unsigned char data_ptr[36] = {
- 0x00, 0x80, 0x02, 0x02,
- 0x1F, 0x00, 0x00, 0x00};
-
- US_DEBUGP("Faking INQUIRY command\n");
- fill_inquiry_response(us, data_ptr, 36);
- us->srb->result = GOOD << 1;
-
- set_current_state(TASK_INTERRUPTIBLE);
- us->srb->scsi_done(us->srb);
- us->srb = NULL;
- break;
- }
-
X /* lock the device pointers */
X down(&(us->dev_semaphore));
X
@@ -422,6 +416,13 @@
X usb_stor_sense_notready,
X sizeof(usb_stor_sense_notready));
X us->srb->result = GOOD << 1;
+ } else if(us->srb->cmnd[0] == INQUIRY) {
+ unsigned char data_ptr[36] = {
+ 0x20, 0x80, 0x02, 0x02,
+ 0x1F, 0x00, 0x00, 0x00};
+ US_DEBUGP("Faking INQUIRY command for disconnected device\n");
+ fill_inquiry_response(us, data_ptr, 36);
+ us->srb->result = GOOD << 1;
X } else {
X memcpy(us->srb->sense_buffer,
X usb_stor_sense_notready,
@@ -429,9 +430,23 @@
X us->srb->result = CHECK_CONDITION << 1;
X }
X } else { /* !us->pusb_dev */
- /* we've got a command, let's do it! */
- US_DEBUG(usb_stor_show_command(us->srb));
- us->proto_handler(us->srb, us);
+
+ /* Handle those devices which need us to fake
+ * their inquiry data */
+ if ((us->srb->cmnd[0] == INQUIRY) &&
+ (us->flags & US_FL_FIX_INQUIRY)) {
+ unsigned char data_ptr[36] = {
+ 0x00, 0x80, 0x02, 0x02,
+ 0x1F, 0x00, 0x00, 0x00};
+
+ US_DEBUGP("Faking INQUIRY command\n");
+ fill_inquiry_response(us, data_ptr, 36);
+ us->srb->result = GOOD << 1;


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

echo 'End of part 070'
echo 'File patch-2.4.15 is continued in part 071'
echo "071" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:57 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part081

#!/bin/sh -x
# this is part 081 of a 115 - part archive


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

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

+};
+
+UCHAR SiS310_PALNFilter2[9][7] = {
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0x01, 0x01, 0xFC, 0xF8, 0x08, 0x26, 0x38},
+ {0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0x22, 0x28}
+};
+
+/*end PALMN*/
+UCHAR SiS310_TVPhaseIncr1[3][2][4] = {
+ {
+ {0x21, 0xed, 0x8a, 0x8},
+ {0x21, 0xed, 0x8a, 0x8}
+ }
+ ,
+ {
+ {0x2a, 0x5, 0xd3, 0x0},
+ {0x2a, 0x5, 0xd3, 0x0}
+ }
+ ,
+ {
+ {0x2a, 0x5, 0xd3, 0x0},
+ {0x2a, 0x5, 0xd3, 0x0}
+ }
+};
+
+UCHAR SiS310_TVPhaseIncr2[3][2][4] = {
+ {
+ {0x21, 0xF0, 0x7b, 0xd6},
+ {0x21, 0xF0, 0x7b, 0xd6}
+ }
+ ,
+ {
+ {0x2a, 0x09, 0x86, 0xe9},
+ {0x2a, 0x09, 0x86, 0xe9}
+ }
+ ,
+ {
+ {0x2a, 0x5, 0xd3, 0x0},
+ {0x2a, 0x5, 0xd3, 0x0}
+ }
+};
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/osdef.h linux/drivers/video/sis/osdef.h
--- v2.4.14/linux/drivers/video/sis/osdef.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/sis/osdef.h Fri Nov 9 14:11:14 2001
@@ -0,0 +1,37 @@
+#define LINUX_KERNEL
+
+#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
+#define SiS_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
+
+/**********************************************************************/
+
+#ifdef OutPortByte
+#undef OutPortByte
+#endif /* OutPortByte */
+
+#ifdef OutPortWord
+#undef OutPortWord
+#endif /* OutPortWord */
+
+#ifdef OutPortLong
+#undef OutPortLong
+#endif /* OutPortLong */
+
+#ifdef InPortByte
+#undef InPortByte
+#endif /* InPortByte */
+
+#ifdef InPortWord
+#undef InPortWord
+#endif /* InPortWord */
+
+#ifdef InPortLong
+#undef InPortLong
+#endif /* InPortLong */
+
+#define OutPortByte(p,v) outb((u8)(v),(u16)(p))
+#define OutPortWord(p,v) outw((u16)(v),(u16)(p))
+#define OutPortLong(p,v) outl((u32)(v),(u16)(p))
+#define InPortByte(p) inb((u16)(p))
+#define InPortWord(p) inw((u16)(p))
+#define InPortLong(p) inl((u16)(p))
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/sis.h linux/drivers/video/sis/sis.h
--- v2.4.14/linux/drivers/video/sis/sis.h Wed Nov 8 17:15:04 2000
+++ linux/drivers/video/sis/sis.h Wed Dec 31 16:00:00 1969
@@ -1,64 +0,0 @@
-#ifndef _SISFB_LOCAL
-#define _SISFB_LOCAL
-#include <linux/types.h>
-
-#undef NOBIOS
-#undef CONFIG_FB_SIS_LINUXBIOS
-
-#ifdef NOBIOS
-#undef CONFIG_FB_SIS_LINUXBIOS
-#endif
-
-#define TRUE 1
-#define FALSE 0
-#define NO_ERROR 0
-
-/* Data type conversion */
-#define UCHAR unsigned char
-#define USHORT unsigned short
-#define ULONG unsigned long
-#define SHORT short
-#define BOOLEAN int
-#define VOID void
-
-#define IND_SIS_CRT2_PORT_04 0x04 - 0x30
-#define IND_SIS_CRT2_PORT_10 0x10 - 0x30
-#define IND_SIS_CRT2_PORT_12 0x12 - 0x30
-#define IND_SIS_CRT2_PORT_14 0x14 - 0x30
-
-#define ClearALLBuffer(x) ClearBuffer(x)
-
-/* Data struct for setmode codes */
-typedef enum _CHIP_TYPE {
- SIS_GENERIC = 0,
- SIS_Glamour, //300
- SIS_Trojan, //630
- SIS_Spartan, //540
- SIS_730,
- MAX_SIS_CHIP
-} CHIP_TYPE;
-
-typedef enum _LCD_TYPE {
- LCD1024 = 1,
- LCD1280,
- LCD2048,
- LCD1920,
- LCD1600,
- LCD800,
- LCD640
-} LCD_TYPE;
-
-
-typedef struct _HW_DEVICE_EXTENSION
-{
- unsigned long VirtualRomBase;
- char *VirtualVideoMemoryAddress;
- unsigned short IOAddress;
- CHIP_TYPE jChipID;
- int bIntegratedMMEnabled;
- LCD_TYPE usLCDType;
- u8 revision_id;
- u8 uVBChipID;
-} HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION;
-
-#endif
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/sis_300.c linux/drivers/video/sis/sis_300.c
--- v2.4.14/linux/drivers/video/sis/sis_300.c Sun Nov 12 20:40:42 2000
+++ linux/drivers/video/sis/sis_300.c Wed Dec 31 16:00:00 1969
@@ -1,1524 +0,0 @@
-/* Recently Update by v1.09.50 */
-#include <linux/config.h>
-#include "sis_300.h"
-
-#if defined(ALLOC_PRAGMA)
-#pragma alloc_text(PAGE,SiSSetMode)
-#pragma alloc_text(PAGE,SiSInit300)
-#endif
-
-
-#ifdef NOBIOS
-BOOLEAN SiSInit300(PHW_DEVICE_EXTENSION HwDeviceExtension)
-{
- ULONG ROMAddr = (ULONG)HwDeviceExtension->VirtualRomBase;
- ULONG FBAddr = (ULONG)HwDeviceExtension->VirtualVideoMemoryAddress;
- USHORT BaseAddr = (USHORT)HwDeviceExtension->IOAddress;
- UCHAR i,temp,AGP;
- ULONG j,k,ulTemp;
- UCHAR SR07,SR11,SR19,SR1A,SR1F,SR21,SR22,SR23,SR24,SR25,SR32;
- UCHAR SR14;
- ULONG Temp;
-
- if(ROMAddr==0) return (FALSE);
- if(FBAddr==0) return (FALSE);
- if(BaseAddr==0) return (FALSE);
- if(HwDeviceExtension->jChipID >= SIS_Trojan)
- if(!HwDeviceExtension->bIntegratedMMEnabled) return (FALSE);
-
- P3c4=BaseAddr+0x14;
- P3d4=BaseAddr+0x24;
- P3c0=BaseAddr+0x10;
- P3ce=BaseAddr+0x1e;
- P3c2=BaseAddr+0x12;
- P3ca=BaseAddr+0x1a;
- P3c6=BaseAddr+0x16;
- P3c7=BaseAddr+0x17;
- P3c8=BaseAddr+0x18;
- P3c9=BaseAddr+0x19;
- P3da=BaseAddr+0x2A;
- Set_LVDS_TRUMPION();
-
- SetReg1(P3c4,0x05,0x86); // 1.Openkey
- SR14 = (UCHAR)GetReg1(P3c4,0x14);
- SR19 = (UCHAR)GetReg1(P3c4,0x19);
- SR1A = (UCHAR)GetReg1(P3c4,0x1A);
- for(i=0x06;i< 0x20;i++) SetReg1(P3c4,i,0); // 2.Reset Extended register
- for(i=0x21;i<=0x27;i++) SetReg1(P3c4,i,0); // Reset Extended register
- for(i=0x31;i<=0x3D;i++) SetReg1(P3c4,i,0);
- for(i=0x30;i<=0x37;i++) SetReg1(P3d4,i,0);
-
- if(HwDeviceExtension->jChipID >= SIS_Trojan)
- temp=(UCHAR)SR1A; // 3.Set Define Extended register
- else
- {
- temp=*((UCHAR *)(ROMAddr+SoftSettingAddr));
- if((temp&SoftDRAMType)==0){
- temp=(UCHAR)GetReg1(P3c4,0x3A); // 3.Set Define Extended register
- }
- }
- RAMType=temp&0x07;
- SetMemoryClock(ROMAddr);
- for(k=0; k<5; k++)
- {
- for(j=0; j<0xffff; j++)
- {
- ulTemp = (ULONG)GetReg1(P3c4, 0x05);
- }
- }
- Temp = (ULONG)GetReg1(P3c4, 0x3C);
- Temp = Temp | 0x01;
- SetReg1(P3c4, 0x3C, (USHORT)Temp);
- for(k=0; k<5; k++)
- {
- for(j=0; j<0xffff; j++)
- {
- Temp = (ULONG)GetReg1(P3c4, 0x05);
- }
- }
- Temp = (ULONG)GetReg1(P3c4, 0x3C);
- Temp = Temp & 0xFE;
- SetReg1(P3c4, 0x3C, (USHORT)Temp);
- for(k=0; k<5; k++)
- {
- for(j=0; j<0xffff; j++)
- {
- Temp = (ULONG)GetReg1(P3c4, 0x05);
- }
- }
-
- SR07=*((UCHAR *)(ROMAddr+0xA4));
- SetReg1(P3c4,0x07,SR07);
- if (HwDeviceExtension->jChipID == SIS_Glamour )
- {
- for(i=0x15;i<=0x1C;i++)
- {
- temp=*((UCHAR *)(ROMAddr+0xA5+((i-0x15)*8)+RAMType));
- SetReg1(P3c4,i,temp);
- }
- }
-
- SR1F=*((UCHAR *)(ROMAddr+0xE5));
- SetReg1(P3c4,0x1F,SR1F);
-
- AGP=1; // Get AGP
- temp=(UCHAR)GetReg1(P3c4,0x3A);
- temp=temp&0x30;
- if(temp==0x30) AGP=0; // PCI
-
- SR21=*((UCHAR *)(ROMAddr+0xE6));
- if(AGP==0) SR21=SR21&0xEF; // PCI
- SetReg1(P3c4,0x21,SR21);
-
- SR22=*((UCHAR *)(ROMAddr+0xE7));
- if(AGP==1) SR22=SR22&0x20; // AGP
- SetReg1(P3c4,0x22,SR22);
-
- SR23=*((UCHAR *)(ROMAddr+0xE8));
- SetReg1(P3c4,0x23,SR23);
-
- SR24=*((UCHAR *)(ROMAddr+0xE9));
- SetReg1(P3c4,0x24,SR24);
-
- SR25=*((UCHAR *)(ROMAddr+0xEA));
- SetReg1(P3c4,0x25,SR25);
-
- SR32=*((UCHAR *)(ROMAddr+0xEB));
- SetReg1(P3c4,0x32,SR32);
-
- SR11=0x0F;
- SetReg1(P3c4,0x11,SR11);
-
- if(IF_DEF_LVDS==1){ //LVDS
- temp=ExtChipLVDS;
- }else if(IF_DEF_TRUMPION==1){ //Trumpion
- temp=ExtChipTrumpion;
- }else{ //301
- temp=ExtChip301;
- }
- SetReg1(P3d4,0x37,temp);
-
- //For SiS 630/540 Chip
- //Restore SR14, SR19 and SR1A
- SetReg1(P3c4,0x14,SR14);
- SetReg1(P3c4,0x19,SR19);
- SetReg1(P3c4,0x1A,SR1A);
-
- SetReg3(P3c6,0xff); // Reset register
- ClearDAC(P3c8); // Reset register
- DetectMonitor(HwDeviceExtension); //sense CRT1
- GetSenseStatus(HwDeviceExtension,BaseAddr,ROMAddr);//sense CRT2
-
- return(TRUE);
-}
-
-VOID Set_LVDS_TRUMPION(VOID)
-{
- IF_DEF_LVDS=0;
- IF_DEF_TRUMPION=0;
-}
-
-VOID SetMemoryClock(ULONG ROMAddr)
-{
- UCHAR data,i;
-
- MCLKData=*((USHORT *)(ROMAddr+0x20C)); // MCLKData Table
- MCLKData=MCLKData+RAMType*5;
- ECLKData=MCLKData+0x28;
-
- for(i=0x28;i<=0x2A;i++) { // Set MCLK
- data=*((UCHAR *)(ROMAddr+MCLKData));
- SetReg1(P3c4,i,data);
- MCLKData++;
- }
-
- for(i=0x2E;i<=0x30;i++) { // Set ECLK
- data=*((UCHAR *)(ROMAddr+ECLKData));
- SetReg1(P3c4,i,data);
- ECLKData++;
- }
-}
-#endif /* NOBIOS */
-
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-BOOLEAN SiSInit300(PHW_DEVICE_EXTENSION HwDeviceExtension)
-{
- ULONG ROMAddr = 0;
- USHORT BaseAddr = (USHORT)HwDeviceExtension->IOAddress;
- UCHAR i,temp,AGP;
- ULONG j,k,ulTemp;
- UCHAR SR07,SR11,SR19,SR1A,SR1F,SR21,SR22,SR23,SR24,SR25,SR32;
- UCHAR SR14;
- ULONG Temp;
-
- if(BaseAddr==0) return (FALSE);
- if(HwDeviceExtension->jChipID >= SIS_Trojan)
- if(!HwDeviceExtension->bIntegratedMMEnabled) return (FALSE);
-
- P3c4=BaseAddr+0x14;
- P3d4=BaseAddr+0x24;
- P3c0=BaseAddr+0x10;
- P3ce=BaseAddr+0x1e;
- P3c2=BaseAddr+0x12;
- P3ca=BaseAddr+0x1a;
- P3c6=BaseAddr+0x16;
- P3c7=BaseAddr+0x17;
- P3c8=BaseAddr+0x18;
- P3c9=BaseAddr+0x19;
- P3da=BaseAddr+0x2A;
-
- SetReg1(P3c4,0x05,0x86); // 1.Openkey
-
- SR14 = (UCHAR)GetReg1(P3c4,0x14);
- SR19 = (UCHAR)GetReg1(P3c4,0x19);
- SR1A = (UCHAR)GetReg1(P3c4,0x1A);
-
- for(i=0x06;i< 0x20;i++) SetReg1(P3c4,i,0); // 2.Reset Extended register
- for(i=0x21;i<=0x27;i++) SetReg1(P3c4,i,0); // Reset Extended register
- for(i=0x31;i<=0x3D;i++) SetReg1(P3c4,i,0);
- for(i=0x30;i<=0x37;i++) SetReg1(P3d4,i,0);
-
- temp=(UCHAR)SR1A; // 3.Set Define Extended register
-
- RAMType=temp&0x07;
- SetMemoryClock(ROMAddr);
- for(k=0; k<5; k++)
- for(j=0; j<0xffff; j++)
- ulTemp = (ULONG)GetReg1(P3c4, 0x05);
-
- Temp = (ULONG)GetReg1(P3c4, 0x3C);
- Temp = Temp | 0x01;
- SetReg1(P3c4, 0x3C, (USHORT)Temp);
-
- for(k=0; k<5; k++)
- for(j=0; j<0xffff; j++)
- Temp = (ULONG)GetReg1(P3c4, 0x05);
-
- Temp = (ULONG)GetReg1(P3c4, 0x3C);
- Temp = Temp & 0xFE;
- SetReg1(P3c4, 0x3C, (USHORT)Temp);
-
- for(k=0; k<5; k++)
- for(j=0; j<0xffff; j++)
- Temp = (ULONG)GetReg1(P3c4, 0x05);
-
- SR07=SRegsInit[0x07];
- SetReg1(P3c4,0x07,SR07);
-
- SR1F=SRegsInit[0x1F];
- SetReg1(P3c4,0x1F,SR1F);
-
- AGP=1; // Get AGP
- temp=(UCHAR)GetReg1(P3c4,0x3A);
- temp=temp&0x30;
- if(temp==0x30) AGP=0; // PCI
-
- SR21=SRegsInit[0x21];
- if(AGP==0) SR21=SR21&0xEF; // PCI
- SetReg1(P3c4,0x21,SR21);
-
- SR22=SRegsInit[0x22];
- if(AGP==1) SR22=SR22&0x20; // AGP
- SetReg1(P3c4,0x22,SR22);
-
- SR23=SRegsInit[0x23];
- SetReg1(P3c4,0x23,SR23);
-
- SR24=SRegsInit[0x24];
- SetReg1(P3c4,0x24,SR24);
-
- SR25=SRegsInit[0x25];
- SetReg1(P3c4,0x25,SR25);
-
- SR32=SRegsInit[0x32];
- SetReg1(P3c4,0x32,SR32);
-
- SR11=0x0F;
- SetReg1(P3c4,0x11,SR11);
-
- temp=ExtChip301;
- SetReg1(P3d4,0x37,temp);
-
- SetReg1(P3c4,0x14,SR14);
- SetReg1(P3c4,0x19,SR19);
- SetReg1(P3c4,0x1A,SR1A);
-
- SetReg3(P3c6,0xff); // Reset register
- ClearDAC(P3c8); // Reset register
- DetectMonitor(HwDeviceExtension); //sense CRT1
-
- return(TRUE);
-}
-
-VOID SetMemoryClock(ULONG ROMAddr)
-{
- UCHAR i;
- USHORT idx;
-
- u8 MCLK[] = {
- 0x5A, 0x64, 0x80, 0x66, 0x00, // SDRAM
- 0xB3, 0x45, 0x80, 0x83, 0x00, // SGRAM
- 0x37, 0x61, 0x80, 0x00, 0x01, // ESDRAM
- 0x37, 0x22, 0x80, 0x33, 0x01,
- 0x37, 0x61, 0x80, 0x00, 0x01,
- 0x37, 0x61, 0x80, 0x00, 0x01,
- 0x37, 0x61, 0x80, 0x00, 0x01,
- 0x37, 0x61, 0x80, 0x00, 0x01
- };
-
- u8 ECLK[] = {
- 0x54, 0x43, 0x80, 0x00, 0x01,
- 0x53, 0x43, 0x80, 0x00, 0x01,
- 0x55, 0x43, 0x80, 0x00, 0x01,
- 0x52, 0x43, 0x80, 0x00, 0x01,
- 0x3f, 0x42, 0x80, 0x00, 0x01,
- 0x54, 0x43, 0x80, 0x00, 0x01,
- 0x54, 0x43, 0x80, 0x00, 0x01,
- 0x54, 0x43, 0x80, 0x00, 0x01
- };
-
- idx = RAMType * 5;
-
- for (i = 0x28; i <= 0x2A; i++) { // Set MCLK
- SetReg1(P3c4, i, MCLK[idx]);
- idx++;
- }
-
- idx = RAMType * 5;
- for (i = 0x2E; i <= 0x30; i++) { // Set ECLK
- SetReg1(P3c4, i, ECLK[idx]);
- idx++;
- }
-
-}
-
-#endif /* CONFIG_FB_SIS_LINUXBIOS */
-
-// =========================================
-// ======== SiS SetMode Function ==========
-// =========================================
-
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-BOOLEAN SiSSetMode(PHW_DEVICE_EXTENSION HwDeviceExtension,
- USHORT ModeNo)
-{
- ULONG i;
- USHORT cr30flag,cr31flag;
- ULONG ROMAddr = (ULONG)HwDeviceExtension->VirtualRomBase;
- USHORT BaseAddr = (USHORT)HwDeviceExtension->IOAddress;
-
- P3c4=BaseAddr+0x14;
- P3d4=BaseAddr+0x24;
- P3c0=BaseAddr+0x10;
- P3ce=BaseAddr+0x1e;
- P3c2=BaseAddr+0x12;
- P3ca=BaseAddr+0x1a;
- P3c6=BaseAddr+0x16;
- P3c7=BaseAddr+0x17;
- P3c8=BaseAddr+0x18;
- P3c9=BaseAddr+0x19;
- P3da=BaseAddr+0x2A;
-
- cr30flag=(UCHAR)GetReg1(P3d4,0x30);
-
- if(((cr30flag&0x01)==1)||((cr30flag&0x02)==0)){
- SetReg1(P3d4,0x34,ModeNo);
- //SetSeqRegs(ROMAddr);
- {
- UCHAR SRdata;
- SRdata = SRegs[0x01] | 0x20;
- SetReg1(P3c4, 0x01, SRdata);
-
- for (i = 02; i <= 04; i++)
- SetReg1(P3c4, i, SRegs[i]);
- }
-
- //SetMiscRegs(ROMAddr);
- {
- SetReg3(P3c2, 0x23);
- }
-
- //SetCRTCRegs(ROMAddr);
- {
- UCHAR CRTCdata;
-
- CRTCdata = (UCHAR) GetReg1(P3d4, 0x11);
- SetReg1(P3d4, 0x11, CRTCdata);
-
- for (i = 0; i <= 0x18; i++)
- SetReg1(P3d4, i, CRegs[i]);
- }
-
- //SetATTRegs(ROMAddr);
- {
- for (i = 0; i <= 0x13; i++) {
- GetReg2(P3da);
- SetReg3(P3c0, i);
- SetReg3(P3c0, ARegs[i]);
- }
- GetReg2(P3da);
- SetReg3(P3c0, 0x14);
- SetReg3(P3c0, 0x00);
- GetReg2(P3da);
- SetReg3(P3c0, 0x20);
- }
-
- //SetGRCRegs(ROMAddr);
- {
- for (i = 0; i <= 0x08; i++)
- SetReg1(P3ce, i, GRegs[i]);
- }
-
- //ClearExt1Regs();
- {
- for (i = 0x0A; i <= 0x0E; i++)
- SetReg1(P3c4, i, 0x00);
- }
-
-
- //SetSync(ROMAddr);
- {
- SetReg3(P3c2, MReg);
- }
-
- //SetCRT1CRTC(ROMAddr);
- {
- UCHAR data;
-
- data = (UCHAR) GetReg1(P3d4, 0x11);
- data = data & 0x7F;
- SetReg1(P3d4, 0x11, data);
-
- for (i = 0; i <= 0x07; i++)
- SetReg1(P3d4, i, CRegs[i]);
- for (i = 0x10; i <= 0x12; i++)
- SetReg1(P3d4, i, CRegs[i]);
- for (i = 0x15; i <= 0x16; i++)
- SetReg1(P3d4, i, CRegs[i]);
- for (i = 0x0A; i <= 0x0C; i++)
- SetReg1(P3c4, i, SRegs[i]);
-
- data = SRegs[0x0E] & 0xE0;
- SetReg1(P3c4, 0x0E, data);
-
- SetReg1(P3d4, 0x09, CRegs[0x09]);
- }
-
- //SetCRT1Offset(ROMAddr);
- {
- SetReg1(P3c4, 0x0E, SRegs[0x0E]);
- SetReg1(P3c4, 0x10, SRegs[0x10]);
- }
-
- //SetCRT1VCLK(HwDeviceExtension, ROMAddr);
- {
- SetReg1(P3c4, 0x31, 0);
-
- for (i = 0x2B; i <= 0x2C; i++)
- SetReg1(P3c4, i, SRegs[i]);
- SetReg1(P3c4, 0x2D, 0x80);
- }
-
- //SetVCLKState(HwDeviceExtension, ROMAddr, ModeNo);
- {
- SetReg1(P3c4, 0x32, SRegs[0x32]);
- SetReg1(P3c4, 0x07, SRegs[0x07]);
- }
-
- //SetCRT1FIFO2(ROMAddr);
- {
- SetReg1(P3c4, 0x15, SRegs[0x15]);
-
- SetReg4(0xcf8, 0x80000050);
- SetReg4(0xcfc, 0xc5041e04);
-
- SetReg1(P3c4, 0x08, SRegs[0x08]);
- SetReg1(P3c4, 0x0F, SRegs[0x0F]);
- SetReg1(P3c4, 0x3b, 0x00);
- SetReg1(P3c4, 0x09, SRegs[0x09]);
- }
-
- //SetCRT1ModeRegs(ROMAddr, ModeNo);
- {
- SetReg1(P3c4, 0x06, SRegs[0x06]);
- SetReg1(P3c4, 0x01, SRegs[0x01]);
- SetReg1(P3c4, 0x0F, SRegs[0x0F]);
- SetReg1(P3c4, 0x21, SRegs[0x21]);
- }
-
- if(HwDeviceExtension->jChipID >= SIS_Trojan)
- {
- //SetInterlace(ROMAddr,ModeNo);
- SetReg1(P3d4, 0x19, CRegs[0x19]);
- SetReg1(P3d4, 0x1A, CRegs[0x1A]);
- }
-
- LoadDAC(ROMAddr);
-
- ClearBuffer(HwDeviceExtension);
- }
-
- cr31flag=(UCHAR)GetReg1(P3d4,0x31);
- DisplayOn(); // 16.DisplayOn
- return(NO_ERROR);
-}
-
-VOID LoadDAC(ULONG ROMAddr)
-{
- USHORT data,data2;
- USHORT time,i,j,k;
- USHORT m,n,o;
- USHORT si,di,bx,dl;
- USHORT al,ah,dh;
- USHORT *table=VGA_DAC;
-
- time=256;
- table=VGA_DAC;
- j=16;
-
- SetReg3(P3c6,0xFF);
- SetReg3(P3c8,0x00);
-
- for(i=0;i<j;i++) {
- data=table[i];
- for(k=0;k<3;k++) {
- data2=0;
- if(data&0x01) data2=0x2A;
- if(data&0x02) data2=data2+0x15;
- SetReg3(P3c9,data2);
- data=data>>2;
- }
- }
-
- if(time==256) {
- for(i=16;i<32;i++) {
- data=table[i];
- for(k=0;k<3;k++) SetReg3(P3c9,data);
- }
- si=32;
- for(m=0;m<9;m++) {
- di=si;
- bx=si+0x04;
- dl=0;
- for(n=0;n<3;n++) {
- for(o=0;o<5;o++) {
- dh=table[si];
- ah=table[di];
- al=table[bx];
- si++;
- WriteDAC(dl,ah,al,dh);
- }
- si=si-2;
- for(o=0;o<3;o++) {
- dh=table[bx];
- ah=table[di];
- al=table[si];
- si--;
- WriteDAC(dl,ah,al,dh);
- }
- dl++;
- }
- si=si+5;
- }
- }
-}
-
-VOID WriteDAC(USHORT dl, USHORT ah, USHORT al, USHORT dh)
-{
- USHORT temp;
- USHORT bh,bl;
-
- bh=ah;
- bl=al;
- if(dl!=0) {
- temp=bh;
- bh=dh;
- dh=temp;
- if(dl==1) {
- temp=bl;
- bl=dh;
- dh=temp;
- }
- else {
- temp=bl;
- bl=bh;
- bh=temp;
- }
- }
- SetReg3(P3c9,(USHORT)dh);
- SetReg3(P3c9,(USHORT)bh);
- SetReg3(P3c9,(USHORT)bl);
-}
-
-
-VOID DisplayOn()
-{
- USHORT data;
-
- data=GetReg1(P3c4,0x01);
- data=data&0xDF;
- SetReg1(P3c4,0x01,data);
-}
-
-
-#else
-BOOLEAN SiSSetMode(PHW_DEVICE_EXTENSION HwDeviceExtension,
- USHORT ModeNo)
-{
- ULONG temp;
- USHORT cr30flag,cr31flag;
- ULONG ROMAddr = (ULONG)HwDeviceExtension->VirtualRomBase;
- USHORT BaseAddr = (USHORT)HwDeviceExtension->IOAddress;
-
- P3c4=BaseAddr+0x14;
- P3d4=BaseAddr+0x24;
- P3c0=BaseAddr+0x10;
- P3ce=BaseAddr+0x1e;
- P3c2=BaseAddr+0x12;
- P3ca=BaseAddr+0x1a;
- P3c6=BaseAddr+0x16;
- P3c7=BaseAddr+0x17;
- P3c8=BaseAddr+0x18;
- P3c9=BaseAddr+0x19;
- P3da=BaseAddr+0x2A;
- if(ModeNo&0x80){
- ModeNo=ModeNo&0x7F;
- flag_clearbuffer=0;
- }else{
- flag_clearbuffer=1;
- }
-
- PresetScratchregister(P3d4,HwDeviceExtension); //add for CRT2
-
- SetReg1(P3c4,0x05,0x86); // 1.Openkey
- temp=SearchModeID(ROMAddr,ModeNo); // 2.Get ModeID Table
- if(temp==0) return(0);
-
- SetTVSystem(HwDeviceExtension,ROMAddr); //add for CRT2
- GetLCDDDCInfo(HwDeviceExtension); //add for CRT2
- GetVBInfo(BaseAddr,ROMAddr); //add for CRT2
- GetLCDResInfo(ROMAddr,P3d4); //add for CRT2
-
- temp=CheckMemorySize(ROMAddr); // 3.Check memory size
- if(temp==0) return(0);
- cr30flag=(UCHAR)GetReg1(P3d4,0x30);
- if(((cr30flag&0x01)==1)||((cr30flag&0x02)==0)){
- // if cr30 d[0]=1 or d[1]=0 set crt1
- SetReg1(P3d4,0x34,ModeNo);
- // set CR34->CRT1 ModeNofor CRT2 FIFO
- GetModePtr(ROMAddr,ModeNo); // 4.GetModePtr
- SetSeqRegs(ROMAddr); // 5.SetSeqRegs
- SetMiscRegs(ROMAddr); // 6.SetMiscRegs
- SetCRTCRegs(ROMAddr); // 7.SetCRTCRegs
- SetATTRegs(ROMAddr); // 8.SetATTRegs
- SetGRCRegs(ROMAddr); // 9.SetGRCRegs
- ClearExt1Regs(); // 10.Clear Ext1Regs
- temp=GetRatePtr(ROMAddr,ModeNo); // 11.GetRatePtr
- if(temp) {
- SetSync(ROMAddr); // 12.SetSync
- SetCRT1CRTC(ROMAddr); // 13.SetCRT1CRTC
- SetCRT1Offset(ROMAddr); // 14.SetCRT1Offset
- SetCRT1VCLK(HwDeviceExtension, ROMAddr); // 15.SetCRT1VCLK
- SetVCLKState(HwDeviceExtension, ROMAddr, ModeNo);
- if(HwDeviceExtension->jChipID >= SIS_Trojan)
- SetCRT1FIFO2(ROMAddr);
- else
- SetCRT1FIFO(ROMAddr);
- }
- SetCRT1ModeRegs(ROMAddr, ModeNo);
- if(HwDeviceExtension->jChipID >= SIS_Trojan)
- SetInterlace(ROMAddr,ModeNo);
- LoadDAC(ROMAddr);
- if(flag_clearbuffer) ClearBuffer(HwDeviceExtension);
- }
-
- cr31flag=(UCHAR)GetReg1(P3d4,0x31);
- if(((cr30flag&0x01)==1)||((cr30flag&0x03)==0x02)
- ||(((cr30flag&0x03)==0x00)&&((cr31flag&0x20)==0x20))){
- //if CR30 d[0]=1 or d[1:0]=10, set CRT2 or cr30 cr31== 0x00 0x20
- SetCRT2Group(BaseAddr,ROMAddr,ModeNo, HwDeviceExtension); //CRT2
- }
- DisplayOn(); // 16.DisplayOn
- return(NO_ERROR);
-}
-
-BOOLEAN SearchModeID(ULONG ROMAddr, USHORT ModeNo)
-{
- UCHAR ModeID;
- USHORT usIDLength;
-
- ModeIDOffset=*((USHORT *)(ROMAddr+0x20A)); // Get EModeIDTable
- ModeID=*((UCHAR *)(ROMAddr+ModeIDOffset)); // Offset 0x20A
- usIDLength = GetModeIDLength(ROMAddr, ModeNo);
- while(ModeID!=0xff && ModeID!=ModeNo) {
- ModeIDOffset=ModeIDOffset+usIDLength;
- ModeID=*((UCHAR *)(ROMAddr+ModeIDOffset));
- }
- if(ModeID==0xff) return(FALSE);
- else return(TRUE);
-}
-
-BOOLEAN CheckMemorySize(ULONG ROMAddr)
-{
- USHORT memorysize;
- USHORT modeflag;
- USHORT temp;
-
- modeflag=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
- ModeType=modeflag&ModeInfoFlag; // Get mode type
-
- memorysize=modeflag&MemoryInfoFlag;
- memorysize=memorysize>MemorySizeShift;
- memorysize++; // Get memory size
-
- temp=GetReg1(P3c4,0x14); // Get DRAM Size
- temp=temp&0x3F;
- temp++;
-
- if(temp<memorysize) return(FALSE);
- else return(TRUE);
-}
-
-VOID GetModePtr(ULONG ROMAddr, USHORT ModeNo)
-{
- UCHAR index;
-
- StandTable=*((USHORT *)(ROMAddr+0x202)); // Get First 0x202
- // StandTable Offset
- if(ModeNo<=13) {
- index=*((UCHAR *)(ROMAddr+ModeIDOffset+0x03)); // si+St_ModeFlag
- }
- else {
- if(ModeType <= 0x02) index=0x1B; // 02 -> ModeEGA
- else index=0x0F;
- }
-
- StandTable=StandTable+64*index; // Get ModeNo StandTable
-
-}
-
-VOID SetSeqRegs(ULONG ROMAddr)
-{
- UCHAR SRdata;
- USHORT i;
-
- SetReg1(P3c4,0x00,0x03); // Set SR0
- StandTable=StandTable+0x05;
- SRdata=*((UCHAR *)(ROMAddr+StandTable)); // Get SR01 from file
- if(IF_DEF_LVDS==1){
- if(VBInfo&SetCRT2ToLCD){
- if(VBInfo&SetInSlaveMode){
- if(LCDInfo&LCDNonExpanding){
- SRdata=SRdata|0x01;
- }
- }
- }
- }
-
- SRdata=SRdata|0x20;
- SetReg1(P3c4,0x01,SRdata); // Set SR1
- for(i=02;i<=04;i++) {
- StandTable++;
- SRdata=*((UCHAR *)(ROMAddr+StandTable)); // Get SR2,3,4 from file
- SetReg1(P3c4,i,SRdata); // Set SR2 3 4
- }
-}
-
-VOID SetMiscRegs(ULONG ROMAddr)
-{
- UCHAR Miscdata;
-
- StandTable++;
- Miscdata=*((UCHAR *)(ROMAddr+StandTable)); // Get Misc from file
- SetReg3(P3c2,Miscdata); // Set Misc(3c2)
-}
-
-VOID SetCRTCRegs(ULONG ROMAddr)
-{
- UCHAR CRTCdata;
- USHORT i;
-
- CRTCdata=(UCHAR)GetReg1(P3d4,0x11);
- CRTCdata=CRTCdata&0x7f;
- SetReg1(P3d4,0x11,CRTCdata); // Unlock CRTC
-
- for(i=0;i<=0x18;i++) {
- StandTable++;
- CRTCdata=*((UCHAR *)(ROMAddr+StandTable)); // Get CRTC from file
- SetReg1(P3d4,i,CRTCdata); // Set CRTC(3d4)
- }
-}
-
-VOID SetATTRegs(ULONG ROMAddr)
-{
- UCHAR ARdata;
- USHORT i;
-
- for(i=0;i<=0x13;i++) {
- StandTable++;
- ARdata=*((UCHAR *)(ROMAddr+StandTable)); // Get AR for file
- if(IF_DEF_LVDS==1){ //for LVDS
- if(VBInfo&SetCRT2ToLCD){
- if(VBInfo&SetInSlaveMode){
- if(LCDInfo&LCDNonExpanding){
- if(i==0x13){
- ARdata=0;
- }
- }
- }
- }
- }
- GetReg2(P3da); // reset 3da
- SetReg3(P3c0,i); // set index
- SetReg3(P3c0,ARdata); // set data
- }
- if(IF_DEF_LVDS==1){ //for LVDS
- if(VBInfo&SetCRT2ToLCD){
- if(VBInfo&SetInSlaveMode){
- if(LCDInfo&LCDNonExpanding){
-
- }
- }
- }
- }
- GetReg2(P3da); // reset 3da
- SetReg3(P3c0,0x14); // set index
- SetReg3(P3c0,0x00); // set data
-
- GetReg2(P3da); // Enable Attribute
- SetReg3(P3c0,0x20);
-}
-
-VOID SetGRCRegs(ULONG ROMAddr)
-{
- UCHAR GRdata;
- USHORT i;
-
- for(i=0;i<=0x08;i++) {
- StandTable++;
- GRdata=*((UCHAR *)(ROMAddr+StandTable)); // Get GR from file
- SetReg1(P3ce,i,GRdata); // Set GR(3ce)
- }
- if(ModeType>ModeVGA){
- GRdata=(UCHAR)GetReg1(P3ce,0x05);
- GRdata=GRdata&0xBF;
- SetReg1(P3ce,0x05,GRdata);
- }
-}
-
-VOID ClearExt1Regs()
-{
- USHORT i;
-
- for(i=0x0A;i<=0x0E;i++) SetReg1(P3c4,i,0x00); // Clear SR0A-SR0E
-}
-
-
-BOOLEAN GetRatePtr(ULONG ROMAddr, USHORT ModeNo)
-{
- SHORT index;
- USHORT temp;
- USHORT ulRefIndexLength;
-
- if(ModeNo<0x14) return(FALSE); // Mode No <= 13h then return
-
- index=GetReg1(P3d4,0x33); // Get 3d4 CRTC33
- index=index&0x0F; // Frame rate index
- if(index!=0) index--;
- REFIndex=*((USHORT *)(ROMAddr+ModeIDOffset+0x04)); // si+Ext_point
-
- ulRefIndexLength = GetRefindexLength(ROMAddr, ModeNo);
- do {
- temp=*((USHORT *)(ROMAddr+REFIndex)); // di => REFIndex
- if(temp==0xFFFF) break;
- temp=temp&ModeInfoFlag;
- if(temp<ModeType) break;
-
- REFIndex=REFIndex+ulRefIndexLength; // rate size
- index--;
- } while(index>=0);
-
- REFIndex=REFIndex-ulRefIndexLength; // rate size
- return(TRUE);
-}
-
-VOID SetSync(ULONG ROMAddr)
-{
- USHORT sync;
- USHORT temp;
-
- sync=*((USHORT *)(ROMAddr+REFIndex)); // di+0x00
- sync=sync&0xC0;
- temp=0x2F;
- temp=temp|sync;
- SetReg3(P3c2,temp); // Set Misc(3c2)
-}
-
-VOID SetCRT1CRTC(ULONG ROMAddr)
-{
- UCHAR index;
- UCHAR data;
- USHORT i;
-
- index=*((UCHAR *)(ROMAddr+REFIndex+0x02)); // Get index
- index=index&0x03F;
- CRT1Table=*((USHORT *)(ROMAddr+0x204)); // Get CRT1Table
- CRT1Table=CRT1Table+index*CRT1Len;
-
- data=(UCHAR)GetReg1(P3d4,0x11);
- data=data&0x7F;
- SetReg1(P3d4,0x11,data); // Unlock CRTC
-
- CRT1Table--;
- for(i=0;i<=0x05;i++) {
- CRT1Table++;
- data=*((UCHAR *)(ROMAddr+CRT1Table));
- SetReg1(P3d4,i,data);
- }
- for(i=0x06;i<=0x07;i++) {
- CRT1Table++;
- data=*((UCHAR *)(ROMAddr+CRT1Table));
- SetReg1(P3d4,i,data);
- }
- for(i=0x10;i<=0x12;i++) {
- CRT1Table++;
- data=*((UCHAR *)(ROMAddr+CRT1Table));
- SetReg1(P3d4,i,data);
- }
- for(i=0x15;i<=0x16;i++) {
- CRT1Table++;
- data=*((UCHAR *)(ROMAddr+CRT1Table));
- SetReg1(P3d4,i,data);
- }
- for(i=0x0A;i<=0x0C;i++) {
- CRT1Table++;
- data=*((UCHAR *)(ROMAddr+CRT1Table));
- SetReg1(P3c4,i,data);
- }
-
- CRT1Table++;
- data=*((UCHAR *)(ROMAddr+CRT1Table));
- data=data&0xE0;
- SetReg1(P3c4,0x0E,data);
-
- data=(UCHAR)GetReg1(P3d4,0x09);
- data=data&0xDF;
- i=*((UCHAR *)(ROMAddr+CRT1Table));
- i=i&0x01;
- i=i<<5;
- data=data|i;
- i=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));
- i=i&DoubleScanMode;
- if(i) data=data|0x80;
- SetReg1(P3d4,0x09,data);
-
- if(ModeType>0x03) SetReg1(P3d4,0x14,0x4F);
-}
-
-VOID SetCRT1Offset(ULONG ROMAddr)
-{
- USHORT temp,ah,al;
- USHORT temp2,i;
- USHORT DisplayUnit;
-
- temp=*((UCHAR *)(ROMAddr+ModeIDOffset+0x03)); // si+Ext_ModeInfo
- temp=temp>>4; // index
- ScreenOffset=*((USHORT *)(ROMAddr+0x206)); // ScreenOffset
- temp=*((UCHAR *)(ROMAddr+ScreenOffset+temp)); // data
-
- temp2=*((USHORT *)(ROMAddr+REFIndex+0x00));
- temp2=temp2&InterlaceMode;
- if(temp2) temp=temp<<1;
- temp2=ModeType-ModeEGA;
- switch (temp2) {
- case 0 : temp2=1; break;
- case 1 : temp2=2; break;
- case 2 : temp2=4; break;
- case 3 : temp2=4; break;
- case 4 : temp2=6; break;
- case 5 : temp2=8; break;
- }
- temp=temp*temp2;
- DisplayUnit=temp;
-
- temp2=temp;
- temp=temp>>8;
- temp=temp&0x0F;
- i=GetReg1(P3c4,0x0E);
- i=i&0xF0;
- i=i|temp;
- SetReg1(P3c4,0x0E,i);
-
- temp=(UCHAR)temp2;
- temp=temp&0xFF;
- SetReg1(P3d4,0x13,temp);
-
- temp2=*((USHORT *)(ROMAddr+REFIndex+0x00));
- temp2=temp2&InterlaceMode;
- if(temp2) DisplayUnit>>=1;
-
- DisplayUnit=DisplayUnit<<5;
- ah=(DisplayUnit&0xff00)>>8;
- al=DisplayUnit&0x00ff;
- if(al==0) ah=ah+1;
- else ah=ah+2;
- SetReg1(P3c4,0x10,ah);
-}
-
-
-VOID SetCRT1VCLK(PHW_DEVICE_EXTENSION HwDeviceExtension, ULONG ROMAddr)
-{
- USHORT i;
- UCHAR index,data;
-
- index=*((UCHAR *)(ROMAddr+REFIndex+0x03));
- index=index&0x03F;
- CRT1VCLKLen=GetVCLKLen(ROMAddr);
- data=index*CRT1VCLKLen;
- VCLKData=*((USHORT *)(ROMAddr+0x208));
- VCLKData=VCLKData+data;
-
- SetReg1(P3c4,0x31,0);
- for(i=0x2B;i<=0x2C;i++) {
- data=*((UCHAR *)(ROMAddr+VCLKData));
- SetReg1(P3c4,i,data);
- VCLKData++;
- }
- SetReg1(P3c4,0x2D,0x80);
-}
-
-
-VOID SetCRT1ModeRegs(ULONG ROMAddr, USHORT ModeNo)
-{
-
- USHORT data,data2,data3;
-
- if(ModeNo>0x13) data=*((USHORT *)(ROMAddr+REFIndex+0x00));
- else data=0;
-
- data2=0;
- if(ModeNo>0x13)
- if(ModeType>0x02) {
- data2=data2|0x02;
- data3=ModeType-ModeVGA;
- data3=data3<<2;
- data2=data2|data3;
- }
-
- data=data&InterlaceMode;
- if(data) data2=data2|0x20;
- SetReg1(P3c4,0x06,data2);
-
- data=GetReg1(P3c4,0x01);
- data=data&0xF7;
- data2=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));
- data2=data2&HalfDCLK;
- if(data2) data=data|0x08;
- SetReg1(P3c4,0x01,data);
-
- data=GetReg1(P3c4,0x0F);
- data=data&0xF7;
- data2=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));
- data2=data2&LineCompareOff;
- if(data2) data=data|0x08;
- SetReg1(P3c4,0x0F,data);
-
- data=GetReg1(P3c4,0x21);
- data=data&0x1F;
- if(ModeType==0x00) data=data|0x60; // Text Mode
- else if(ModeType<=0x02) data=data|0x00; // EGA Mode
- else data=data|0xA0; // VGA Mode
- SetReg1(P3c4,0x21,data);
-}
-
-VOID SetVCLKState(PHW_DEVICE_EXTENSION HwDeviceExtension, ULONG ROMAddr, USHORT ModeNo)
-{
- USHORT data,data2;
- USHORT VCLK;
- UCHAR index;
-
- index=*((UCHAR *)(ROMAddr+REFIndex+0x03));
- index=index&0x03F;
- CRT1VCLKLen=GetVCLKLen(ROMAddr);
- data=index*CRT1VCLKLen;
- VCLKData=*((USHORT *)(ROMAddr+0x208));
- VCLKData=VCLKData+data+(CRT1VCLKLen-2);
- VCLK=*((USHORT *)(ROMAddr+VCLKData));
- if(ModeNo<=0x13) VCLK=0;
-
- data=GetReg1(P3c4,0x07);
- data=data&0x7B;
- if(VCLK>=150) data=data|0x80; // VCLK > 150
- SetReg1(P3c4,0x07,data);
-
- data=GetReg1(P3c4,0x32);
- data=data&0xD7;
- if(VCLK>=150) data=data|0x08; // VCLK > 150
- SetReg1(P3c4,0x32,data);
-
- data2=0x03;
- if(VCLK>135) data2=0x02;
- if(VCLK>160) data2=0x01;
- if(VCLK>260) data2=0x00;
- data=GetReg1(P3c4,0x07);
- data=data&0xFC;
- data=data|data2;
- SetReg1(P3c4,0x07,data);
-}
-
-VOID LoadDAC(ULONG ROMAddr)
-{
- USHORT data,data2;
- USHORT time,i,j,k;
- USHORT m,n,o;
- USHORT si,di,bx,dl;
- USHORT al,ah,dh;
- USHORT *table=VGA_DAC;
-
- data=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));
- data=data&DACInfoFlag;
- time=64;
- if(data==0x00) table=MDA_DAC;
- if(data==0x08) table=CGA_DAC;
- if(data==0x10) table=EGA_DAC;
- if(data==0x18) {
- time=256;
- table=VGA_DAC;
- }
- if(time==256) j=16;
- else j=time;
-
- SetReg3(P3c6,0xFF);
- SetReg3(P3c8,0x00);
-
- for(i=0;i<j;i++) {
- data=table[i];
- for(k=0;k<3;k++) {
- data2=0;
- if(data&0x01) data2=0x2A;
- if(data&0x02) data2=data2+0x15;
- SetReg3(P3c9,data2);
- data=data>>2;
- }
- }
-
- if(time==256) {
- for(i=16;i<32;i++) {
- data=table[i];
- for(k=0;k<3;k++) SetReg3(P3c9,data);
- }
- si=32;
- for(m=0;m<9;m++) {
- di=si;
- bx=si+0x04;
- dl=0;
- for(n=0;n<3;n++) {
- for(o=0;o<5;o++) {
- dh=table[si];
- ah=table[di];
- al=table[bx];
- si++;
- WriteDAC(dl,ah,al,dh);
- }
- si=si-2;
- for(o=0;o<3;o++) {
- dh=table[bx];
- ah=table[di];
- al=table[si];
- si--;
- WriteDAC(dl,ah,al,dh);
- }
- dl++;
- }
- si=si+5;
- }
- }
-}
-
-VOID WriteDAC(USHORT dl, USHORT ah, USHORT al, USHORT dh)
-{
- USHORT temp;
- USHORT bh,bl;
-
- bh=ah;
- bl=al;
- if(dl!=0) {
- temp=bh;
- bh=dh;
- dh=temp;
- if(dl==1) {
- temp=bl;
- bl=dh;
- dh=temp;
- }
- else {
- temp=bl;
- bl=bh;
- bh=temp;
- }
- }
- SetReg3(P3c9,(USHORT)dh);
- SetReg3(P3c9,(USHORT)bh);
- SetReg3(P3c9,(USHORT)bl);
-}
-
-
-VOID DisplayOn()
-{
- USHORT data;
-
- data=GetReg1(P3c4,0x01);
- data=data&0xDF;
- SetReg1(P3c4,0x01,data);
-}
-
-USHORT GetModeIDLength(ULONG ROMAddr, USHORT ModeNo)
-{
- USHORT modeidlength;
- USHORT usModeIDOffset;
- USHORT PreviousWord,CurrentWord;
-
- modeidlength=0;
- usModeIDOffset=*((USHORT *)(ROMAddr+0x20A)); // Get EModeIDTable
- // maybe = 2Exx or xx2E
- CurrentWord=*((USHORT *)(ROMAddr+usModeIDOffset)); // Offset 0x20A
- PreviousWord=*((USHORT *)(ROMAddr+usModeIDOffset-2)); // Offset 0x20A
- while((CurrentWord!=0x2E07)||(PreviousWord!=0x0801)) {
- modeidlength++;
- usModeIDOffset=usModeIDOffset+1; // 10 <= ExtStructSize
- CurrentWord=*((USHORT *)(ROMAddr+usModeIDOffset));
- PreviousWord=*((USHORT *)(ROMAddr+usModeIDOffset-2));
- }
- modeidlength++;
- return(modeidlength);
-}
-
-USHORT GetRefindexLength(ULONG ROMAddr, USHORT ModeNo)
-{
- UCHAR ModeID;
- UCHAR temp;
- USHORT refindexlength;
- USHORT usModeIDOffset;
- USHORT usREFIndex;
- USHORT usIDLength;
-
- usModeIDOffset=*((USHORT *)(ROMAddr+0x20A)); // Get EModeIDTable
- ModeID=*((UCHAR *)(ROMAddr+usModeIDOffset)); // Offset 0x20A
- usIDLength = GetModeIDLength(ROMAddr, ModeNo);
- while(ModeID!=0x40) {
- usModeIDOffset=usModeIDOffset+usIDLength; // 10 <= ExtStructSize
- ModeID=*((UCHAR *)(ROMAddr+usModeIDOffset));
- }
-
- refindexlength=1;
- usREFIndex=*((USHORT *)(ROMAddr+usModeIDOffset+0x04)); // si+Ext_point
- usREFIndex++;
- temp=*((UCHAR *)(ROMAddr+usREFIndex)); // di => REFIndex
- while(temp!=0xFF) {
- refindexlength++;
- usREFIndex++;
- temp=*((UCHAR *)(ROMAddr+usREFIndex)); // di => REFIndex
- }
- return(refindexlength);
-}
-
-VOID SetInterlace(ULONG ROMAddr, USHORT ModeNo)
-{
- ULONG Temp;
- USHORT data,Temp2;
-
- Temp = (ULONG)GetReg1(P3d4, 0x01);
- Temp++;
- Temp=Temp*8;
-
- if(Temp==1024) data=0x0035;
- else if(Temp==1280) data=0x0048;
- else data=0x0000;
-
- Temp2=*((USHORT *)(ROMAddr+REFIndex+0x00));
- Temp2 &= InterlaceMode;
- if(Temp2 == 0) data=0x0000;
-
- SetReg1(P3d4,0x19,data);
-
- Temp = (ULONG)GetReg1(P3d4, 0x1A);
- Temp2= (USHORT)(Temp & 0xFC);
- SetReg1(P3d4,0x1A,(USHORT)Temp);
-
- Temp = (ULONG)GetReg1(P3c4, 0x0f);
- Temp2= (USHORT)Temp & 0xBF;
- if(ModeNo==0x37) Temp2=Temp2|0x40;
- SetReg1(P3d4,0x1A,(USHORT)Temp2);
-}
-
-VOID SetCRT1FIFO(ULONG ROMAddr)
-{
- USHORT colorth=0,index,data,VCLK,data2,MCLKOffset,MCLK;
- USHORT ah,bl,A,B;
-
- index=*((UCHAR *)(ROMAddr+REFIndex+0x03));
- index=index&0x03F;
- CRT1VCLKLen=GetVCLKLen(ROMAddr);
- data=index*CRT1VCLKLen;
- VCLKData=*((USHORT *)(ROMAddr+0x208));
- VCLKData=VCLKData+data+(CRT1VCLKLen-2);
- VCLK=*((USHORT *)(ROMAddr+VCLKData)); // Get VCLK
-
- MCLKOffset=*((USHORT *)(ROMAddr+0x20C));
- index=GetReg1(P3c4,0x3A);
- index=index&07;
- MCLKOffset=MCLKOffset+index*5;
- MCLK=*((UCHAR *)(ROMAddr+MCLKOffset+0x03)); // Get MCLK
-
- data2=ModeType-0x02;
- switch (data2) {
- case 0 : colorth=1; break;
- case 1 : colorth=2; break;
- case 2 : colorth=4; break;
- case 3 : colorth=4; break;
- case 4 : colorth=6; break;
- case 5 : colorth=8; break;
- }
-
- do{
- B=(CalcDelay(ROMAddr,0)*VCLK*colorth);
- B=B/(16*MCLK);
- B++;
-
- A=(CalcDelay(ROMAddr,1)*VCLK*colorth);
- A=A/(16*MCLK);
- A++;
-
- if(A<4) A=0;
- else A=A-4;
-
- if(A>B) bl=A;
- else bl=B;
-
- bl++;
- if(bl>0x13) {
- data=GetReg1(P3c4,0x16);
- data=data>>6;
- if(data!=0) {
- data--;
- data=data<<6;
- data2=GetReg1(P3c4,0x16);
- data2=(data2&0x3f)|data;
- SetReg1(P3c4,0x16,data2);
- }
- else bl=0x13;
- }
- } while(bl>0x13);
-
- ah=bl;
- ah=ah<<4;
- ah=ah|0x0f;
- SetReg1(P3c4,0x08,ah);
-
- data=bl;
- data=data&0x10;
- data=data<<1;
- data2=GetReg1(P3c4,0x0F);
- data2=data2&0x9f;
- data2=data2|data;
- SetReg1(P3c4,0x0F,data2);
-
- data=bl+3;
- if(data>0x0f) data=0x0f;
- SetReg1(P3c4,0x3b,0x00);
- data2=GetReg1(P3c4,0x09);
- data2=data2&0xF0;
- data2=data2|data;
- SetReg1(P3c4,0x09,data2);
-}
-
-static USHORT CalcDelay(ULONG ROMAddr,USHORT key)
-{
- USHORT data,data2,temp0,temp1;
- UCHAR ThLowA[]={61,3,52,5,68,7,100,11,
- 43,3,42,5,54,7, 78,11,
- 34,3,37,5,47,7, 67,11};
- UCHAR ThLowB[]={81,4,72,6,88,8,120,12,
- 55,4,54,6,66,8, 90,12,
- 42,4,45,6,55,8, 75,12};
- UCHAR ThTiming[]= {1,2,2,3,0,1,1,2};
-
- data=GetReg1(P3c4,0x16);
- data=data>>6;
- data2=GetReg1(P3c4,0x14);
- data2=(data2>>4)&0x0C;
- data=data|data2;
- data=data<1;
- if(key==0) {
- temp0=(USHORT)ThLowA[data];
- temp1=(USHORT)ThLowA[data+1];
- }
- else {
- temp0=(USHORT)ThLowB[data];
- temp1=(USHORT)ThLowB[data+1];
- }
-
- data2=0;
- data=GetReg1(P3c4,0x18);
- if(data&0x02) data2=data2|0x01;
- if(data&0x20) data2=data2|0x02;
- if(data&0x40) data2=data2|0x04;
-
- data=temp1*ThTiming[data2]+temp0;
- return(data);
-}
-
-VOID SetCRT1FIFO2(ULONG ROMAddr)
-{
- USHORT colorth=0,index,data,VCLK,data2,MCLKOffset,MCLK;
- USHORT ah,bl,B;
- ULONG eax;
-
- index=*((UCHAR *)(ROMAddr+REFIndex+0x03));
- index=index&0x03F;
- CRT1VCLKLen=GetVCLKLen(ROMAddr);
- data=index*CRT1VCLKLen;
- VCLKData=*((USHORT *)(ROMAddr+0x208));
- VCLKData=VCLKData+data+(CRT1VCLKLen-2);
- VCLK=*((USHORT *)(ROMAddr+VCLKData)); // Get VCLK
-
- MCLKOffset=*((USHORT *)(ROMAddr+0x20C));
- index=GetReg1(P3c4,0x1A);
- index=index&07;
- MCLKOffset=MCLKOffset+index*5;
- MCLK=*((USHORT *)(ROMAddr+MCLKOffset+0x03)); // Get MCLK
-
- data2=ModeType-0x02;
- switch (data2) {
- case 0 : colorth=1; break;
- case 1 : colorth=1; break;
- case 2 : colorth=2; break;
- case 3 : colorth=2; break;
- case 4 : colorth=3; break;
- case 5 : colorth=4; break;
- }
-
- do{
- B=(CalcDelay2(ROMAddr,0)*VCLK*colorth);
- if (B%(16*MCLK) == 0)
- {
- B=B/(16*MCLK);
- bl=B+1;
- }
- else
- {
- B=B/(16*MCLK);
- bl=B+2;
- }
-
- if(bl>0x13) {
- data=GetReg1(P3c4,0x15);
- data=data&0xf0;
- if(data!=0xb0) {
- data=data+0x20;
- if(data==0xa0) data=0x30;
-
- data2=GetReg1(P3c4,0x15);
- data2=(data2&0x0f)|data;
- SetReg1(P3c4,0x15,data2);
- }
- else bl=0x13;
- }
- } while(bl>0x13);
-
- data2=GetReg1(P3c4,0x15);
- data2=(data2&0xf0)>>4;
- data2=data2<<24;
-
- SetReg4(0xcf8,0x80000050);
- eax=GetReg3(0xcfc);
- eax=eax&0x0f0ffffff;
- eax=eax|data2;
- SetReg4(0xcfc,eax);
-
- ah=bl;
- ah=ah<<4;
- ah=ah|0x0f;
- SetReg1(P3c4,0x08,ah);
-
- data=bl;
- data=data&0x10;
- data=data<<1;
- data2=GetReg1(P3c4,0x0F);
- data2=data2&0x9f;
- data2=data2|data;
- SetReg1(P3c4,0x0F,data2);
-
- data=bl+3;
- if(data>0x0f) data=0x0f;
- SetReg1(P3c4,0x3b,0x00);
- data2=GetReg1(P3c4,0x09);
- data2=data2&0xF0;
- data2=data2|data;
- SetReg1(P3c4,0x09,data2);
-}
-
-USHORT CalcDelay2(ULONG ROMAddr,USHORT key)
-{
- USHORT data,index;
- UCHAR LatencyFactor[]={88,80,78,72,70,00,
- 00,79,77,71,69,49,
- 88,80,78,72,70,00,
- 00,72,70,64,62,44};
-
- index=0;
- data=GetReg1(P3c4,0x14);
- if(data&0x80) index=index+12;
-
- data=GetReg1(P3c4,0x15);
- data=(data&0xf0)>>4;
- if(data&0x01) index=index+6;
-
- data=data>>1;
- index=index+data;
- data=LatencyFactor[index];
-
- return(data);
-}
-
-#endif /* CONFIG_FB_SIS_LINUXBIOS */
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/sis_300.h linux/drivers/video/sis/sis_300.h
--- v2.4.14/linux/drivers/video/sis/sis_300.h Sun Nov 12 20:40:42 2000
+++ linux/drivers/video/sis/sis_300.h Wed Dec 31 16:00:00 1969
@@ -1,163 +0,0 @@
-#include <linux/config.h>
-#include "initdef.h"
-
-USHORT DRAMType[17][5]={{0x0C,0x0A,0x02,0x40,0x39},{0x0D,0x0A,0x01,0x40,0x48},
- {0x0C,0x09,0x02,0x20,0x35},{0x0D,0x09,0x01,0x20,0x44},
- {0x0C,0x08,0x02,0x10,0x31},{0x0D,0x08,0x01,0x10,0x40},
- {0x0C,0x0A,0x01,0x20,0x34},{0x0C,0x09,0x01,0x08,0x32},
- {0x0B,0x08,0x02,0x08,0x21},{0x0C,0x08,0x01,0x08,0x30},
- {0x0A,0x08,0x02,0x04,0x11},{0x0B,0x0A,0x01,0x10,0x28},
- {0x09,0x08,0x02,0x02,0x01},{0x0B,0x09,0x01,0x08,0x24},
- {0x0B,0x08,0x01,0x04,0x20},{0x0A,0x08,0x01,0x02,0x10},
- {0x09,0x08,0x01,0x01,0x00}};
-
-USHORT MDA_DAC[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
- 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
- 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
- 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
- 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F};
-
-USHORT CGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
- 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
- 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
- 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
- 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
- 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
- 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
- 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F};
-
-USHORT EGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
- 0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
- 0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D,
- 0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D,
- 0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17,
- 0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37,
- 0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F,
- 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F};
-
-USHORT VGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
- 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
- 0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18,
- 0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F,
-
- 0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F,
- 0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00,
- 0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18,
- 0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04,
- 0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10,
- 0x0B,0x0C,0x0D,0x0F,0x10};
-
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-unsigned char SRegsInit[] = {
- 0x03, 0x00, 0x03, 0x00, 0x02, 0xa1, 0x00, 0x13,
- 0x2f, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0f, 0x00, 0x00, 0x4f, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xa1, 0x76, 0xb2, 0xf6, 0x0d, 0x00, 0x00, 0x00,
- 0x37, 0x61, 0x80, 0x1b, 0xe1, 0x01, 0x55, 0x43,
- 0x80, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff,
- 0x8e, 0x40, 0x00, 0x00, 0x08, 0x00, 0xff, 0xff
-};
-
-unsigned char SRegs[] = {
- 0x03, 0x01, 0x0F, 0x00, 0x0E, 0xA1, 0x02, 0x13,
- 0x3F, 0x86, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x0B, 0x0F, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x40, 0x00,
- 0xA1, 0xB6, 0xB2, 0xF6, 0x0D, 0x00, 0xF8, 0xF0,
- 0x37, 0x61, 0x80, 0x1B, 0xE1, 0x80, 0x55, 0x43,
- 0x80, 0x00, 0x11, 0xFF, 0x00, 0x00, 0x00, 0xFF,
- 0x8E, 0x40, 0x00, 0x00, 0x08, 0x00, 0xFF, 0xFF
-};
-
-unsigned char CRegs[] = {
- 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0x0b, 0x3e,
- 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xe9, 0x0b, 0xdf, 0x50, 0x40, 0xe7, 0x04, 0xa3,
- 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff
-}; // clear CR11[7]
-
-unsigned char GRegs[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, 0x00
-};
-
-unsigned char ARegs[] = {
- 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
-};
-
-unsigned char MReg = 0x6f;
-
-#endif
-
-USHORT P3c4,P3d4,P3c0,P3ce,P3c2,P3ca,P3c6,P3c7,P3c8,P3c9,P3da;
-USHORT CRT1VCLKLen; //VCLKData table length of bytes of each entry
-USHORT flag_clearbuffer; //0: no clear frame buffer 1:clear frame buffer
-int RAMType;
-int ModeIDOffset,StandTable,CRT1Table,ScreenOffset,VCLKData,MCLKData, ECLKData;
-int REFIndex,ModeType;
-USHORT IF_DEF_LVDS,IF_DEF_TRUMPION;
-USHORT VBInfo,LCDResInfo,LCDTypeInfo,LCDInfo;
-
-//int init300(int,int,int);
-VOID SetMemoryClock(ULONG);
-VOID SetDRAMSize(PHW_DEVICE_EXTENSION);
-//extern "C" int ChkBUSWidth(int);
-
-//int setmode(int,int,int,int);
-BOOLEAN SearchModeID(ULONG, USHORT);
-BOOLEAN CheckMemorySize(ULONG);
-VOID GetModePtr(ULONG, USHORT);
-BOOLEAN GetRatePtr(ULONG, USHORT);
-VOID SetSeqRegs(ULONG);
-VOID SetMiscRegs(ULONG);
-VOID SetCRTCRegs(ULONG);
-VOID SetATTRegs(ULONG);
-VOID SetGRCRegs(ULONG);
-VOID ClearExt1Regs(VOID);
-VOID SetSync(ULONG);
-VOID SetCRT1CRTC(ULONG);
-VOID SetCRT1Offset(ULONG);
-VOID SetCRT1FIFO(ULONG);
-VOID SetCRT1FIFO2(ULONG);
-VOID SetCRT1VCLK(PHW_DEVICE_EXTENSION, ULONG);
-VOID LoadDAC(ULONG);
-VOID DisplayOn(VOID);
-VOID SetCRT1ModeRegs(ULONG, USHORT);
-VOID SetVCLKState(PHW_DEVICE_EXTENSION, ULONG, USHORT);
-VOID WriteDAC(USHORT, USHORT, USHORT, USHORT);
-VOID ClearBuffer(PHW_DEVICE_EXTENSION);
-USHORT ChkBUSWidth(ULONG);
-USHORT GetModeIDLength(ULONG, USHORT);
-USHORT GetRefindexLength(ULONG, USHORT);
-VOID SetInterlace(ULONG, USHORT);
-USHORT CalcDelay2(ULONG ,USHORT);
-void Set_LVDS_TRUMPION(VOID);
-BOOLEAN SiSSetMode(PHW_DEVICE_EXTENSION HwDeviceExtension,
- USHORT ModeNo);
-#ifndef CONFIG_FB_SIS_LINUXBIOS
-static USHORT CalcDelay(ULONG ,USHORT);
-#endif
-
-extern BOOLEAN SetCRT2Group(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo,
- PHW_DEVICE_EXTENSION HwDeviceExtension);
-extern VOID GetVBInfo(USHORT BaseAddr,ULONG ROMAddr);
-extern VOID PresetScratchregister(USHORT P3d4,PHW_DEVICE_EXTENSION HwDeviceExtension);
-extern BOOLEAN GetLCDResInfo(ULONG ROMAddr,USHORT P3d4);
-extern VOID SetTVSystem(PHW_DEVICE_EXTENSION HwDeviceExtension,ULONG ROMAddr);
-extern BOOLEAN GetLCDDDCInfo(PHW_DEVICE_EXTENSION HwDeviceExtension);
-extern BOOLEAN GetSenseStatus(PHW_DEVICE_EXTENSION HwDeviceExtension,USHORT BaseAddr,ULONG ROMAddr);
-extern BOOLEAN DetectMonitor(PHW_DEVICE_EXTENSION HwDeviceExtension);
-extern USHORT GetVCLKLen(ULONG ROMAddr);
-extern void SetReg1(u16 port, u16 index, u16 data);
-extern void SetReg3(u16 port, u16 data);
-extern void SetReg4(u16 port, unsigned long data);
-extern u8 GetReg1(u16 port, u16 index);
-extern u8 GetReg2(u16 port);
-extern u32 GetReg3(u16 port);
-extern void ClearDAC(u16 port);
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/sis_301.c linux/drivers/video/sis/sis_301.c
--- v2.4.14/linux/drivers/video/sis/sis_301.c Sun Nov 12 20:40:42 2000
+++ linux/drivers/video/sis/sis_301.c Wed Dec 31 16:00:00 1969
@@ -1,2868 +0,0 @@
-/* Recently Update by v1.09.50 */
-
-#include <linux/config.h>
-#include "sis_301.h"
-
-#ifndef CONFIG_FB_SIS_LINUXBIOS
-
-BOOLEAN SetCRT2Group(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo,
- PHW_DEVICE_EXTENSION HwDeviceExtension)
-{
- USHORT temp;
-
- SetFlag=SetFlag|ProgrammingCRT2;
- SearchModeID(ROMAddr,ModeNo);
-
- temp=GetRatePtrCRT2(ROMAddr,ModeNo);
- if(((temp&0x02)==0) && ((VBInfo&CRT2DisplayFlag)==0))
- return(FALSE);
- SaveCRT2Info(ModeNo);
- DisableBridge(BaseAddr);
- UnLockCRT2(BaseAddr);
- SetDefCRT2ExtRegs(BaseAddr);
- SetCRT2ModeRegs(BaseAddr,ModeNo);
- if(VBInfo&CRT2DisplayFlag){
- LockCRT2(BaseAddr);
- return 0;
- }
- GetCRT2Data(ROMAddr,ModeNo);
- if(IF_DEF_LVDS==1){ //LVDS
- GetLVDSDesData(ROMAddr,ModeNo);
- }
- SetGroup1(BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
- if(IF_DEF_LVDS==0){
- SetGroup2(BaseAddr,ROMAddr);
- SetGroup3(BaseAddr);
- SetGroup4(BaseAddr,ROMAddr,ModeNo);
- SetGroup5(BaseAddr,ROMAddr);
- }else{ //LVDS
- if(IF_DEF_TRUMPION==0){
- ModCRT1CRTC(ROMAddr,ModeNo);
- }
- SetCRT2ECLK(ROMAddr,ModeNo);
- }
-
- EnableCRT2();
- EnableBridge(BaseAddr);
- SetLockRegs();
- LockCRT2(BaseAddr);
-

- return 1;
-}
-

-VOID overwriteregs(ULONG ROMAddr,USHORT BaseAddr)
-{
- int i;
- USHORT Part1Port; //reg data is for 1024x768 16bit 85hz
- int p1reg[0x29]={0x84,0x76,0x4B,0x21,0x00,0x00,0x00,0x00,0x1F,0x51,
- 0x0C,0x10,0x44,0x90,0x1E,0xFF,0x00,0x34,0x13,0x10,
- 0x00,0x00,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x97,0x16,
- 0xA3};
- Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
- for(i=0;i<29;i++){
- SetReg1(Part1Port,(USHORT)i,(USHORT)p1reg[i]);
- }
-}
-
-VOID SetDefCRT2ExtRegs(USHORT BaseAddr)
-{
- USHORT Part1Port,Part2Port,Part4Port;
- USHORT temp;
- Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
- Part2Port=BaseAddr+IND_SIS_CRT2_PORT_10;
- Part4Port=BaseAddr+IND_SIS_CRT2_PORT_14;
- SetReg1(Part1Port,0x02,0x40);
- SetReg1(Part4Port,0x10,0x80);
- temp=(UCHAR)GetReg1(P3c4,0x16);
- temp=temp&0xC3;
- SetReg1(P3d4,0x35,temp);
-}
-
-USHORT GetRatePtrCRT2(ULONG ROMAddr, USHORT ModeNo)
-{ //return bit0=>0:standard mode 1:extended mode
- SHORT index; // bit1=>0:crt2 no support this mode
- USHORT temp; // 1:crt2 support this mode
- USHORT ulRefIndexLength;
- USHORT temp1;
- SHORT LCDRefreshIndex[4]={0x0,0x0,0x03,0x01};
- // LCDPanel:no lcd,800x600,1024x768,1280x1024
- if(ModeNo<0x14) return(0); // Mode No <= 13h then return
-
- index=GetReg1(P3d4,0x33); // Get 3d4 CRTC33
- index=index>>SelectCRT2Rate; //For CRT2,cl=SelectCRT2Rate=4, shr ah,cl
- index=index&0x0F; // Frame rate index
- if(index!=0) index--;
-
- if(IF_DEF_TRUMPION==1){
- if(VBInfo&SetSimuScanMode){
- index=0;
- }
- }
- if(SetFlag&ProgrammingCRT2){
- if(VBInfo&SetCRT2ToLCD){
- if(IF_DEF_LVDS==0){
- temp=LCDResInfo;
- temp1=LCDRefreshIndex[temp];
- if(index>temp1){
- index=temp1;
- }
- }else{
- index=0;
- }
- }
- }
-
- REFIndex=*((USHORT *)(ROMAddr+ModeIDOffset+0x04)); // si+Ext_point
-
- ulRefIndexLength =Ext2StructSize;
- do {
- temp=*((USHORT *)(ROMAddr+REFIndex)); // di => REFIndex
- if(temp==0xFFFF) break;
- temp=temp&ModeInfoFlag;
- if(temp<ModeType) break;
-
- REFIndex=REFIndex+ulRefIndexLength; // rate size
- index--;
- if(index<0){
- if(!(VBInfo&SetCRT2ToRAMDAC)){
- if(VBInfo&SetInSlaveMode){
- temp1=*((USHORT *)(ROMAddr+REFIndex+0-Ext2StructSize));
- if(temp1&InterlaceMode){
- index=0;
- }
- }
- }
- }
- } while(index>=0);
-
- REFIndex=REFIndex-ulRefIndexLength; // rate size
-
- if((SetFlag&ProgrammingCRT2)){
- temp1=AjustCRT2Rate(ROMAddr);
- }else{
- temp1=0;
- }
-
- return(0x01|(temp1<<1));
-}
-
-BOOLEAN AjustCRT2Rate(ULONG ROMAddr)
-{
- USHORT tempbx=0,tempax,temp;
- USHORT tempextinfoflag;
- tempax=0;
-
- if(IF_DEF_LVDS==0){
- if(VBInfo&SetCRT2ToRAMDAC){
- tempax=tempax|SupportRAMDAC2;
- }
- if(VBInfo&SetCRT2ToLCD){
- tempax=tempax|SupportLCD;
- if(LCDResInfo!=Panel1280x1024){
- temp=*((UCHAR *)(ROMAddr+ModeIDOffset+0x09)); //si+Ext_ResInfo
- if(temp>=9){
- tempax=0;
- }
- }
- }
- if(VBInfo&(SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)){
- tempax=tempax|SupportTV;
- if(!(VBInfo&SetPALTV)){
- tempextinfoflag=*((USHORT *)(ROMAddr+REFIndex+0x0)); //di+Ext_InfoFlag
- if(tempextinfoflag&NoSupportSimuTV){
- if(VBInfo&SetInSlaveMode){
- if(!(VBInfo&SetNotSimuTVMode)){


- return 0;
- }
- }
- }

- }
- }
- tempbx=*((USHORT *)(ROMAddr+ModeIDOffset+0x04)); // si+Ext_point
- }else{ //for LVDS
- if(VBInfo&SetCRT2ToLCD){
- tempax=tempax|SupportLCD;
- temp=*((UCHAR *)(ROMAddr+ModeIDOffset+0x09)); //si+Ext_ResInfo
- if(temp>0x08){ //1024x768
- return 0;
- }
- if(LCDResInfo<Panel1024x768){
- if(temp>0x07){ //800x600
- return 0;
- }
- if(temp==0x04){ //512x384


- return 0;
- }
- }
- }

- }
-
- for(;REFIndex>tempbx;REFIndex-=Ext2StructSize){
- tempextinfoflag=*((USHORT *)(ROMAddr+REFIndex+0x0)); //di+Ext_InfoFlag
- if(tempextinfoflag&tempax){


- return 1;
- }
- }

- for(REFIndex=tempbx;;REFIndex+=Ext2StructSize){
- tempextinfoflag=*((USHORT *)(ROMAddr+REFIndex+0x0)); //di+Ext_InfoFlag
- if(tempextinfoflag==0x0FFFF){
- return 0;
- }
- if(tempextinfoflag&tempax){


- return 1;
- }
- }

- return(FALSE);
-}
-
-VOID SaveCRT2Info(USHORT ModeNo){
- USHORT temp1,temp2,temp3;
- temp1=(VBInfo&SetInSlaveMode)>>8;
- temp2=~(SetInSlaveMode>>8);
- temp3=(UCHAR)GetReg1(P3d4,0x31);
- temp3=((temp3&temp2)|temp1);
- SetReg1(P3d4,0x31,(USHORT)temp3);
- temp3=(UCHAR)GetReg1(P3d4,0x35);
- temp3=temp3&0xF3;
- SetReg1(P3d4,0x35,(USHORT)temp3);
-}
-
-VOID DisableLockRegs(){
- UCHAR temp3;
- temp3=(UCHAR)GetReg1(P3c4,0x32);
- temp3=temp3&0xDF;
- SetReg1(P3c4,0x32,(USHORT)temp3);
-}
-
-VOID DisableCRT2(){
- UCHAR temp3;
- temp3=(UCHAR)GetReg1(P3c4,0x1E);
- temp3=temp3&0xDF;
- SetReg1(P3c4,0x1E,(USHORT)temp3);
-}
-
-void DisableBridge(USHORT BaseAddr)
-{
- USHORT Part2Port,Part1Port;
- Part2Port=BaseAddr+IND_SIS_CRT2_PORT_10;
- Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
-
- if(IF_DEF_LVDS==0){
- SetRegANDOR(Part2Port,0x00,0xDF,0x00); //Set Part2 Index0 D[5]=0
- DisableLockRegs(); // SR 32
- DisableCRT2(); // SR 1E
- }else{
- DisableLockRegs();
- DisableCRT2();
- if(IF_DEF_TRUMPION==0){
- UnLockCRT2(BaseAddr);
- SetRegANDOR(Part1Port,0x02,0xFF,0x40); //set Part1Port ,index 2, D6=1,
- }
- }
-}
-
-VOID GetCRT2Data(ULONG ROMAddr,USHORT ModeNo)
-{
- if(IF_DEF_LVDS==0){ //301
- GetCRT2Data301(ROMAddr,ModeNo);
- return;
- }else{ //LVDS
- GetCRT2DataLVDS(ROMAddr,ModeNo);


- return;
- }
-}
-

-VOID GetCRT2DataLVDS(ULONG ROMAddr,USHORT ModeNo)
-{
- USHORT tempax,tempbx,OldREFIndex;
-
- OldREFIndex=(USHORT)REFIndex; //push di
- GetResInfo(ROMAddr,ModeNo);
- GetCRT2Ptr(ROMAddr,ModeNo);
-
- tempax=*((USHORT *)(ROMAddr+REFIndex));
- tempax=tempax&0x0FFF;
- VGAHT=tempax;
-
- tempax=*((USHORT *)(ROMAddr+REFIndex+1));
- tempax=tempax>>4;
- tempax=tempax&0x07FF;
- VGAVT=tempax;
-
- tempax=*((USHORT *)(ROMAddr+REFIndex+3));
- tempax=tempax&0x0FFF;
- tempbx=*((USHORT *)(ROMAddr+REFIndex+4));
- tempbx=tempbx>>4;
- tempbx=tempbx&0x07FF;
-
- HT=tempax;
- VT=tempbx;
-
- if(IF_DEF_TRUMPION==0){
- if(VBInfo&SetCRT2ToLCD){
- if(!(LCDInfo&LCDNonExpanding)){
- if(LCDResInfo==Panel800x600){
- tempax=800;
- tempbx=600;
- }else if(LCDResInfo==Panel1024x768){
- tempax=1024;
- tempbx=768;
- }else{
- tempax=1280;
- tempbx=1024;
- }
- HDE=tempax;
- VDE=tempbx;
- }
- }
- }
- REFIndex=OldREFIndex; //pop di
- return;
-}
-
-VOID GetCRT2Data301(ULONG ROMAddr,USHORT ModeNo)
-{
- USHORT tempax,tempbx,modeflag1,OldREFIndex;
- USHORT tempal,tempah,tempbl;
-
- OldREFIndex=(USHORT)REFIndex; //push di
- RVBHRS=50;NewFlickerMode=0;RY1COE=0;
- RY2COE=0;RY3COE=0;RY4COE=0;
-
- GetResInfo(ROMAddr,ModeNo);
- if(VBInfo&SetCRT2ToRAMDAC){
- GetRAMDAC2DATA(ROMAddr,ModeNo);
- REFIndex=OldREFIndex; //pop di
- return;
- }
- GetCRT2Ptr(ROMAddr,ModeNo);
-
- tempal=*((UCHAR *)(ROMAddr+REFIndex));
- tempah=*((UCHAR *)(ROMAddr+REFIndex+4));
- tempax=tempal|(((tempah<<8)>>7)&0xFF00);
- RVBHCMAX=tempax;
-
- tempal=*((UCHAR *)(ROMAddr+REFIndex+1));
- RVBHCFACT=tempal;
-
- tempax=*((USHORT *)(ROMAddr+REFIndex+2));
- VGAHT=(tempax&0x0FFF);
-
- tempax=*((USHORT *)(ROMAddr+REFIndex+3));
- VGAVT=((tempax>>4)&0x07FF);
-
- tempax=*((USHORT *)(ROMAddr+REFIndex+5));
- tempax=(tempax&0x0FFF);
- tempbx=*((USHORT *)(ROMAddr+REFIndex+6));
- tempbx=((tempbx>>4)&0x07FF);
- tempbl=tempbx&0x00FF;
-
- if(VBInfo&SetCRT2ToTV){
- tempax=*((USHORT *)(ROMAddr+REFIndex+5));
- tempax=(tempax&0x0FFF);
- HDE=tempax;
- tempax=*((USHORT *)(ROMAddr+REFIndex+6));
- tempax=((tempax>>4)&0x07FF);
- VDE=tempax;
- //skipp something about hivisiontv
- tempax=*((USHORT *)(ROMAddr+REFIndex+8));
- tempbl=(tempax>>8);
- tempax=tempax&0x0FFF;
- modeflag1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
- if(modeflag1&HalfDCLK){
- tempax=*((USHORT *)(ROMAddr+REFIndex+10));
- }
- RVBHRS=tempax;
- NewFlickerMode=(tempbl&0x080);
-
- tempax=*((USHORT *)(ROMAddr+REFIndex+12));
- RY1COE=(tempax&0x00FF);
- RY2COE=((tempax&0xFF00)>>8);
- tempax=*((USHORT *)(ROMAddr+REFIndex+14));
- RY3COE=(tempax&0x00FF);
- RY4COE=((tempax&0xFF00)>>8);
- if(!(VBInfo&SetPALTV)){
- tempax=NTSCHT;
- tempbx=NTSCVT;
- }else{
- tempax=PALHT;
- tempbx=PALVT;
- }
- }
- HT=tempax;
- VT=tempbx;
- if(!(VBInfo&SetCRT2ToLCD)){
- REFIndex=OldREFIndex; //pop di
- return;
- }
-
- tempax=1024;
- if(VGAVDE==350){ //cx->VGAVDE
- tempbx=560;
- }else if(VGAVDE==400){
- tempbx=640;
- }else{
- tempbx=768;
- }
-
- if(LCDResInfo==Panel1280x1024){
- tempax=1280;
- if(VGAVDE==360){
- tempbx=768;
- }else if(VGAVDE==375){
- tempbx=800;
- }else if(VGAVDE==405){
- tempbx=864;
- }else{
- tempbx=1024;
- }
- }
-
- HDE=tempax;
- VDE=tempbx;
- REFIndex=OldREFIndex; //pop di
- return;
-}
-
-VOID GetResInfo(ULONG ROMAddr,USHORT ModeNo)
-{
- USHORT temp,xres,yres,modeflag1;
- if(ModeNo<=0x13){
- temp=(USHORT)*((UCHAR *)(ROMAddr+ModeIDOffset+0x05)); // si+St_ResInfo
- xres=StResInfo[temp][0];
- yres=StResInfo[temp][1];
- }else{
- temp=(USHORT)*((UCHAR *)(ROMAddr+ModeIDOffset+0x09)); // si+Ext_ResInfo
- xres=ModeResInfo[temp][0]; //xres->ax
- yres=ModeResInfo[temp][1]; //yres->bx
- modeflag1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
- if(modeflag1&HalfDCLK){ xres=xres*2;}
- if(modeflag1&DoubleScanMode){yres=yres*2;}
- }
- if(!(LCDResInfo==Panel1024x768)){
- if(yres==400) yres=405;
- if(yres==350) yres=360;
- if(SetFlag&LCDVESATiming){
- if(yres==360) yres=375;
- }
- }
- VGAHDE=xres;
- HDE=xres;
- VGAVDE=yres;
- VDE=yres;
-}
-
-VOID GetLVDSDesData(ULONG ROMAddr,USHORT ModeNo)
-{
- USHORT old_REFIndex,tempax;
-
- old_REFIndex=(USHORT)REFIndex; //push di
- REFIndex=GetLVDSDesPtr(ROMAddr,ModeNo);
-
- tempax=*((USHORT *)(ROMAddr+REFIndex));
- tempax=tempax&0x0FFF;
- LCDHDES=tempax;
-
- if(LCDInfo&LCDNonExpanding){ //hw walk-a-round
- if(LCDResInfo>=Panel1024x768){
- if(ModeNo<=0x13){
- LCDHDES=320;
- }
- }
- }
-
- tempax=*((USHORT *)(ROMAddr+REFIndex+1));
- tempax=tempax>>4;
- tempax=tempax&0x07FF;
- LCDVDES=tempax;
-
- REFIndex=old_REFIndex; //pop di


- return;
-}
-
-

-VOID GetRAMDAC2DATA(ULONG ROMAddr,USHORT ModeNo)
-{
- USHORT tempax,tempbx,tempbh,modeflag1,t1=0,t2;
- RVBHCMAX=1;RVBHCFACT=1;
- if(ModeNo<=0x13){
- tempax=*((UCHAR *)(ROMAddr+REFIndex+10));
- tempbx=*((USHORT *)(ROMAddr+REFIndex+16));
- }else{
- t1=*((UCHAR *)(ROMAddr+REFIndex+0x2)); //Ext_CRT1CRTC=2
- t1=t1&0x03F; //[06/29/2000] fix bug for vbios >=v1.07.00
- t1=t1*CRT1Len;
- REFIndex=*((USHORT *)(ROMAddr+0x204)); // Get CRT1Table
- REFIndex=REFIndex+t1;
- t1=*((UCHAR *)(ROMAddr+REFIndex+0));
- t2=*((UCHAR *)(ROMAddr+REFIndex+14));
- tempax=(t1&0xFF)|((t2&0x03)<<8);
- tempbx=*((USHORT *)(ROMAddr+REFIndex+6));
- t1=*((UCHAR *)(ROMAddr+REFIndex+13));
- t1=(t1&0x01)<<2;
- }
-
- tempbh=tempbx>>8;
- tempbh=((tempbh&0x20)>>4)|(tempbh&0x01);
- tempbh=tempbh|t1;
- tempbx=(tempbx&0xFF)|(tempbh<<8);
- tempax=tempax+5;
- modeflag1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
- if(modeflag1&Charx8Dot){
- tempax=tempax*8;
- }else{
- tempax=tempax*9;
- }
-
- VGAHT=tempax;
- HT=tempax;
- tempbx++;
- VGAVT=tempbx;
- VT=tempbx;
-
-}
-
-VOID GetCRT2Ptr(ULONG ROMAddr,USHORT ModeNo)
-{
- USHORT tempcl,tempbx,tempal,tempax,CRT2PtrData;
-
- if(IF_DEF_LVDS==0){
- if(VBInfo&SetCRT2ToLCD){ //LCD
- tempbx=0; //default tempbx=0 -> ExtLCD1Data
- tempcl=LCDDataLen;
- if(LCDResInfo==Panel1024x768){
- tempbx=0;
- }else if(LCDResInfo==Panel1280x1024){
- tempbx=1;
- }
- if(!(SetFlag&LCDVESATiming)) tempbx+=5;
- }else if(VBInfo&SetPALTV){
- tempcl=TVDataLen;
- tempbx=3;


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

echo 'End of part 081'
echo 'File patch-2.4.15 is continued in part 082'
echo "082" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:56 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part080

#!/bin/sh -x
# this is part 080 of a 115 - part archive


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

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

+ vclkindex =
+ SiS_GetVCLK2Ptr (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, HwDeviceExtension);

+ } else { /*trumpion */
+ SiS_SetFlag = SiS_SetFlag & (~ProgrammingCRT2);
+/* tempal=*((UCHAR *)(ROMAddr+SiS_RefIndex+0x03)); &di+Ext_CRTVCLK */
+ tempal = tempal & 0x03F;
+ if (tempal == 0x02) { /*31.5MHz */
+/* SiS_RefIndex=SiS_RefIndex-Ext2StructSize; */
+ }
+/* SiS_RefIndex=GetVCLKPtr(ROMAddr,ModeNo); */
+ SiS_SetFlag = SiS_SetFlag | ProgrammingCRT2;
+ }
+ tempal = 0x02B;


+ if (!(SiS_VBInfo & SetInSlaveMode)) {

+ tempal = tempal + 3;
+ }


+ SiS_SetReg1 (SiS_P3c4, 0x05, 0x86);

+ tempah = SiS_VCLKData[vclkindex].SR2B;
+ SiS_SetReg1 (SiS_P3c4, tempal, tempah);
+ tempal++;
+ tempah = SiS_VCLKData[vclkindex].SR2C;
+ SiS_SetReg1 (SiS_P3c4, tempal, tempah);
+ tempal++;
+ SiS_SetReg1 (SiS_P3c4, tempal, 0x80);


+ return;
+}
+
+void

+SiS_SetDefCRT2ExtRegs (USHORT BaseAddr)


+{
+ USHORT temp;
+

+ if (SiS_IF_DEF_LVDS == 0) {

+ SiS_SetReg1 (SiS_Part1Port, 0x02, 0x40);
+ SiS_SetReg1 (SiS_Part4Port, 0x10, 0x80);
+ temp = (UCHAR) SiS_GetReg1 (SiS_P3c4, 0x16);
+ temp = temp & 0xC3;
+ SiS_SetReg1 (SiS_P3d4, 0x35, temp);
+ } else {
+ SiS_SetReg1 (SiS_P3d4, 0x32, 0x02);
+ SiS_SetReg1 (SiS_Part1Port, 0x02, 0x00);
+ }
+}
+
+#ifdef CONFIG_FB_SIS_315
+/*
+ for SIS310 O.E.M.
+*/
+/*
+---------------------------------------------------------
+ LCDResInfo 1 : 800x600
+ 2 : 1024x768
+ 3 : 1280x1024
+ 4 : 1280x960
+ 5 : 640x480
+ 6 : 1600x1200
+ 7 : 1920x1440
+ VESA
+ non-VESA
+ non-Expanding
+---------------------------------------------------------
+*/
+USHORT
+GetLCDPtrIndex (void)
+{
+ USHORT index;
+
+ index = (SiS_LCDResInfo & 0x0F) - 1;
+ index *= 3;


+ if (SiS_LCDInfo & LCDNonExpanding)

+ index += 2;
+ else {
+ if (!(SiS_LCDInfo & LCDVESATiming))
+ index++;


+ }
+
+ return index;

+}
+
+/*
+---------------------------------------------------------
+ GetTVPtrIndex()
+ return 0 : NTSC Enhanced/Standard
+ 1 : NTSC Standard TVSimuMode
+ 2 : PAL Enhanced/Standard
+ 3 : PAL Standard TVSimuMode
+ 4 : HiVision Enhanced/Standard
+ 5 : HiVision Standard TVSimuMode
+---------------------------------------------------------
+*/
+USHORT
+GetTVPtrIndex (void)
+{
+ USHORT index;
+
+ index = 0;


+ if (SiS_VBInfo & SetPALTV)

+ index++;
+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) /* Hivision TV use PAL */
+ index++;
+ index *= 2;
+
+ if ((SiS_VBInfo & SetInSlaveMode) && (SiS_SetFlag & TVSimuMode))
+ index++;
+
+ return index;
+}
+
+void
+SetDelayComp (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ ULONG ROMAddr, USHORT ModeNo)
+{
+ USHORT Part1Port;
+ USHORT delay, index;
+
+ if (SiS_VBInfo & SetCRT2ToRAMDAC) {
+ delay = SiS310_CRT2DelayCompensation1;


+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))

+ delay = SiS310_CRT2DelayCompensation2;
+ } else if (SiS_VBInfo & SetCRT2ToLCD) {
+ index = GetLCDPtrIndex ();
+ delay = SiS310_LCDDelayCompensation1[index];


+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))

+ delay = SiS310_LCDDelayCompensation2[index];
+ } else {
+ index = GetTVPtrIndex ();
+ delay = SiS310_TVDelayCompensation1[index];


+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))

+ delay = SiS310_TVDelayCompensation2[index];
+ }
+
+ Part1Port = BaseAddr + SIS_CRT2_PORT_04;
+ SiS_SetRegANDOR (Part1Port, 0x2D, ~0x0F, delay); /* index 2D D[3:0] */
+
+}
+
+/*
+*/
+void
+SetAntiFlicker (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex)
+{
+ USHORT Part2Port;
+ USHORT index, temp;
+
+ Part2Port = BaseAddr + SIS_CRT2_PORT_10;
+ temp = GetTVPtrIndex ();
+ temp = (temp >> 1); /* 0: NTSC, 1 :PAL, 2:HiTV */


+ if (ModeNo <= 0x13) {

+ index = SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
+ } else {
+ index = SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
+ }
+ temp = SiS310_TVAntiFlick1[temp][index];
+ temp <<= 4;
+
+ SiS_SetRegANDOR (Part2Port, 0x0A, ~0x70, temp); /* index 0A D[6:4] */
+
+}
+
+void
+SetEdgeEnhance (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex)
+{
+ USHORT Part2Port;
+ USHORT index, temp;
+
+ Part2Port = BaseAddr + SIS_CRT2_PORT_10;
+ temp = GetTVPtrIndex ();
+ temp = (temp >> 1); /* 0: NTSC, 1 :PAL, 2:HiTV */


+ if (ModeNo <= 0x13) {

+ index = SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex; /* si+VB_StTVEdgeIndex */
+ } else {
+ index = SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex; /* si+VB_ExtTVEdgeIndex */
+ }
+ temp = SiS310_TVEdge1[temp][index];
+ temp <<= 5;
+
+ SiS_SetRegANDOR (Part2Port, 0x3A, ~0xE0, temp); /* index 0A D[7:5] */
+
+}
+
+void
+SetYFilter (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex)
+{
+ USHORT Part2Port, temp1, temp2;
+ USHORT index, temp, i, index1;


+ UCHAR OutputSelect = *pSiS_OutputSelect;

+ Part2Port = BaseAddr + SIS_CRT2_PORT_10;
+ temp = GetTVPtrIndex ();
+ temp >>= 1; /* 0: NTSC, 1 :PAL, 2:HiTV */


+
+ if (ModeNo <= 0x13) {

+ index = SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
+ } else {
+ index = SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
+ }
+
+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) /* Hivision TV use PAL */


+ temp = 0;
+

+ /*301b */


+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B)) {

+ for (i = 0x35; i <= 0x38; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS310_TVYFilter2[temp][index][i - 0x35]);
+ }
+ for (i = 0x48; i <= 0x4A; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS310_TVYFilter2[temp][index][(i - 0x48) +
+ 0x04]);


+ }
+ }
+ /*end 301b */
+ else {

+ for (i = 0x35; i <= 0x38; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS310_TVYFilter1[temp][index][i - 0x35]);
+ }
+ }
+/*add PALMN*/
+ if (OutputSelect & EnablePALMN) {
+ index1 = SiS_GetReg1 (SiS_P3d4, 0x31);
+ temp1 = index1 & 0x01;
+ index1 = SiS_GetReg1 (SiS_P3d4, 0x38);
+ temp2 = index1 & 0xC0;
+ if (temp1) {
+ if (temp2 == 0x40) {


+ if ((SiS_VBType & VB_SIS301B)

+ || (SiS_VBType & VB_SIS302B)) {
+ for (i = 0x35; i <= 0x38; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS310_PALMFilter2
+ [index][i - 0x35]);
+ }
+ for (i = 0x48; i <= 0x4A; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS310_PALMFilter2
+ [index][(i - 0x48)
+ + 0x04]);
+ }
+ } else {
+ for (i = 0x35; i <= 0x38; i++)
+ SiS_SetReg1 (Part2Port, i,
+ SiS310_PALMFilter
+ [index][i - 0x35]);
+ }
+ }
+ if (temp2 == 0x80) {


+ if ((SiS_VBType & VB_SIS301B)

+ || (SiS_VBType & VB_SIS302B)) {
+ for (i = 0x35; i <= 0x38; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS310_PALNFilter2
+ [index][i - 0x35]);
+ }
+ for (i = 0x48; i <= 0x4A; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS310_PALNFilter2
+ [index][(i - 0x48)
+ + 0x04]);
+ }
+ } else {
+ for (i = 0x35; i <= 0x38; i++)
+ SiS_SetReg1 (Part2Port, i,
+ SiS310_PALNFilter
+ [index][i - 0x35]);
+ }
+ }
+ }
+ }
+ /*end PALMN */
+}
+
+void
+SetPhaseIncr (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ ULONG ROMAddr, USHORT ModeNo)
+{
+ USHORT Part2Port;
+ USHORT index, temp, temp1, i;
+
+ Part2Port = BaseAddr + SIS_CRT2_PORT_10;
+ temp = GetTVPtrIndex ();
+ /* 0: NTSC Graphics, 1: NTSC Text, 2 :PAL Graphics, 3 :PAL Text, 4:HiTV Graphics 5:HiTV Text */
+ index = temp % 2;
+ temp >>= 1; /* 0: NTSC, 1 :PAL, 2:HiTV */
+ temp1 = SiS_GetReg1 (SiS_P3d4, 0x38); /*if PALMN Not Set */
+ temp1 = temp1 & 0xC0;
+ if (!temp1) {
+ for (i = 0x31; i <= 0x34; i++) {


+ if ((SiS_VBType & VB_SIS301B)
+ || (SiS_VBType & VB_SIS302B))

+ SiS_SetReg1 (Part2Port, i,
+ SiS310_TVPhaseIncr2[temp]
+ [index][i - 0x31]);
+ else
+ SiS_SetReg1 (Part2Port, i,
+ SiS310_TVPhaseIncr1[temp][index][i
+ -
+ 0x31]);
+ }
+ }
+}
+void
+SiS_OEM310Setting (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex)
+{
+ SetDelayComp (HwDeviceExtension, BaseAddr, ROMAddr, ModeNo);


+ if (SiS_VBInfo & SetCRT2ToTV) {

+ SetAntiFlicker (HwDeviceExtension, BaseAddr, ROMAddr, ModeNo,
+ ModeIdIndex);
+ SetPhaseIncr (HwDeviceExtension, BaseAddr, ROMAddr, ModeNo);
+ SetYFilter (HwDeviceExtension, BaseAddr, ROMAddr, ModeNo,
+ ModeIdIndex);
+ SetEdgeEnhance (HwDeviceExtension, BaseAddr, ROMAddr, ModeNo,


+ ModeIdIndex);
+ }
+}
+

+#endif
+
+#ifdef CONFIG_FB_SIS_300
+/*
+ for SIS300 O.E.M.
+*/
+
+USHORT
+GetRevisionID (PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+#ifdef CONFIG_FB_SIS_300
+ ULONG temp1, base;
+ USHORT temp2 = 0;
+ /* add to set SR14 */
+ if ((HwDeviceExtension->jChipType == SIS_540) ||
+ (HwDeviceExtension->jChipType == SIS_630) ||


+ (HwDeviceExtension->jChipType == SIS_730)) {

+ base = 0x80000008;


+ OutPortLong (base, 0xcf8);
+ temp1 = InPortLong (0xcfc);

+ temp1 = temp1 & 0x000000FF;
+ temp2 = (USHORT) (temp1);
+ return temp2;
+ }
+#endif
+}
+
+USHORT
+GetOEMLCDPtr (PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+ USHORT temp, tempbx = 0, tempax;


+
+ if (SiS_IF_DEF_LVDS == 0) {

+ if (SiS_VBInfo & SetCRT2ToLCD) { /* LCD */

+ tempax = SiS_LCDResInfo;
+ tempbx = SiS_LCDResInfo;
+ tempbx = tempbx - Panel1024x768;


+ if (!(SiS_SetFlag & LCDVESATiming)) {

+ tempbx += 4;
+ temp = GetRevisionID (HwDeviceExtension);
+ if ((HwDeviceExtension->jChipType == SIS_540)
+ && (temp < 1))
+ tempbx += 4;


+ if ((HwDeviceExtension->jChipType == SIS_630)

+ && (temp < 3))
+ tempbx += 4;
+ }
+ if ((tempax == Panel1024x768)
+ && (SiS_LCDInfo == LCDNonExpanding)) {
+ tempbx = tempbx + 3;
+ }
+ /*add OEMLCDPanelIDSupport */
+ tempbx = SiS_LCDTypeInfo;


+ tempbx = tempbx << 1;

+ if (!(SiS_SetFlag & LCDVESATiming))


+ tempbx = tempbx + 1;
+ }

+ }
+ tempbx *= 2;
+ return tempbx;
+}
+
+USHORT
+GetOEMTVPtr (void)
+{
+ USHORT index;


+
+ index = 0;

+ if (!(SiS_VBInfo & SetInSlaveMode))

+ index = index + 4;
+
+ if (SiS_VBInfo & SetCRT2ToSCART) {
+ index = index + 2;
+ } else {
+ if (SiS_VBInfo & SetCRT2ToHiVisionTV)
+ index = index + 3;


+ else {
+ if (SiS_VBInfo & SetPALTV)

+ index = index + 1;
+ }
+ }
+ return index;
+}
+
+void
+SetOEMTVDelay (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ ULONG ROMAddr, USHORT ModeNo)
+{
+ USHORT Part1Port;
+ USHORT index, temp, ModeIdIndex;
+ Part1Port = BaseAddr + SIS_CRT2_PORT_04;
+ ModeIdIndex = SiS_SearchVBModeID (ROMAddr, ModeNo);
+ temp = GetOEMTVPtr ();
+ index = SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex;
+ temp = SiS300_OEMTVDelay[temp][index];
+ temp = temp & 0x3c;
+ SiS_SetRegANDOR (Part1Port, 0x13, ~0x3C, temp); /* index 0A D[6:4] */
+}
+
+void
+SetOEMLCDDelay (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ ULONG ROMAddr, USHORT ModeNo)
+{
+ USHORT Part2Port;
+ USHORT index, temp, ModeIdIndex;
+ Part2Port = BaseAddr + SIS_CRT2_PORT_10;
+ ModeIdIndex = SiS_SearchVBModeID (ROMAddr, ModeNo);
+ temp = GetOEMLCDPtr (HwDeviceExtension);
+ index = SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
+ temp = SiS300_OEMLCDDelay1[temp][index];
+ /*add OEMLCDPanelIDSupport */
+ temp = SiS300_OEMLCDDelay2[temp][index];
+ temp = temp & 0x3c;
+ SiS_SetRegANDOR (Part2Port, 0x13, ~0x3C, temp); /* index 0A D[6:4] */
+}
+
+/*
+*/
+void
+SetOEMAntiFlicker (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ ULONG ROMAddr, USHORT ModeNo)
+{
+ USHORT Part2Port;
+ USHORT index, temp;
+ USHORT ModeIdIndex;
+ Part2Port = BaseAddr + SIS_CRT2_PORT_10;
+ ModeIdIndex = SiS_SearchVBModeID (ROMAddr, ModeNo);
+ temp = GetOEMTVPtr ();
+ index = SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex;
+ temp = SiS300_OEMTVFlicker[temp][index];
+ temp = temp & 0x70;
+ SiS_SetRegANDOR (Part2Port, 0x0A, ~0x70, temp); /* index 0A D[6:4] */
+
+}
+
+void
+SetOEMPhaseIncr (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ ULONG ROMAddr, USHORT ModeNo)
+{
+ USHORT Part2Port;
+ USHORT index, i, ModeIdIndex;
+
+ Part2Port = BaseAddr + SIS_CRT2_PORT_10;
+ // temp = GetTVPtrIndex();
+ /* 0: NTSC Graphics, 1: NTSC Text, 2 :PAL Graphics, 3 :PAL Text, 4:HiTV Graphics 5:HiTV Text */
+ // index = temp % 2;
+ // temp >>= 1; /* 0: NTSC, 1 :PAL, 2:HiTV */
+ ModeIdIndex = SiS_SearchVBModeID (ROMAddr, ModeNo);
+ index = SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;


+ if (SiS_VBInfo & SetInSlaveMode) {

+ if (SiS_VBInfo & SetPALTV) {
+ for (i = 0x31; i <= 0x34; i++)
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_StPALPhase[index][i -
+ 0x31]);
+ } else {
+ for (i = 0x31; i <= 0x34; i++)
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_StNTSCPhase[index][i -
+ 0x31]);
+ }
+ if (SiS_VBInfo & SetCRT2ToSCART) {
+ for (i = 0x31; i <= 0x34; i++)
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_StSCARTPhase[index][i -
+ 0x31]);
+ }
+ } else {
+ if (SiS_VBInfo & SetPALTV) {
+ for (i = 0x31; i <= 0x34; i++)
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_ExtPALPhase[index][i -
+ 0x31]);
+ } else {
+ for (i = 0x31; i <= 0x34; i++)
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_ExtNTSCPhase[index][i -
+ 0x31]);
+ }
+ if (SiS_VBInfo & SetCRT2ToSCART) {
+ for (i = 0x31; i <= 0x34; i++)
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_ExtSCARTPhase[index][i -
+ 0x31]);


+ }
+ }
+}
+
+void

+SetOEMYFilter (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ ULONG ROMAddr, USHORT ModeNo)
+{
+ USHORT Part2Port;
+ USHORT index, temp1, temp2, i, ModeIdIndex, index1;
+ Part2Port = BaseAddr + SIS_CRT2_PORT_10;
+ /*301b */
+ ModeIdIndex = SiS_SearchVBModeID (ROMAddr, ModeNo);
+ index = SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;


+ if (SiS_VBInfo & SetInSlaveMode) {

+ if (SiS_VBInfo & SetPALTV) {
+ for (i = 0x35; i <= 0x38; i++)
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_StPALFilter[index][i -
+ 0x35]);
+ } else {
+ for (i = 0x35; i <= 0x38; i++)
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_StNTSCFilter[index][i -
+ 0x35]);
+ }
+ } else {
+ if (SiS_VBInfo & SetPALTV) {
+ for (i = 0x35; i <= 0x38; i++)
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_ExtPALFilter[index][i -
+ 0x35]);
+ } else {
+ for (i = 0x35; i <= 0x38; i++)
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_ExtNTSCFilter[index][i -
+ 0x35]);
+ }
+ }
+


+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B)) {

+ if (SiS_VBInfo & SetPALTV) {
+ for (i = 0x35; i <= 0x38; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_PALFilter2[index][i -
+ 0x35]);
+ }
+ for (i = 0x48; i <= 0x4A; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_PALFilter2[index][(i - 0x48)
+ + 0x04]);
+ }
+ } else {
+ for (i = 0x35; i <= 0x38; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_NTSCFilter2[index][i -
+ 0x35]);
+ }
+ for (i = 0x48; i <= 0x4A; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_NTSCFilter2[index][
+ (i -
+ 0x48) +
+ 0x04]);
+ }
+ }
+ }
+


+/*add PALMN*/
+ if ((HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_730)) {

+ index1 = SiS_GetReg1 (SiS_P3d4, 0x31);
+ temp1 = index1 & 0x01;
+ index1 = SiS_GetReg1 (SiS_P3d4, 0x35);
+ temp2 = index1 & 0xC0;
+ if (temp1) {
+ if (temp2 == 0x40) {


+ if ((SiS_VBType & VB_SIS301B)

+ || (SiS_VBType & VB_SIS302B)) {
+ for (i = 0x35; i <= 0x38; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_PALMFilter2
+ [index][i - 0x35]);
+ }
+ for (i = 0x48; i <= 0x4A; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_PALMFilter2
+ [index][(i - 0x48)
+ + 0x04]);
+ }
+ } else {
+ for (i = 0x35; i <= 0x38; i++)
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_PALMFilter
+ [index][i - 0x35]);
+ }
+ }
+ if (temp2 == 0x80) {


+ if ((SiS_VBType & VB_SIS301B)

+ || (SiS_VBType & VB_SIS302B)) {
+ for (i = 0x35; i <= 0x38; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_PALNFilter2
+ [index][i - 0x35]);
+ }
+ for (i = 0x48; i <= 0x4A; i++) {
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_PALNFilter2
+ [index][(i - 0x48)
+ + 0x04]);
+ }
+ } else {
+ for (i = 0x35; i <= 0x38; i++)
+ SiS_SetReg1 (Part2Port, i,
+ SiS300_PALNFilter
+ [index][i - 0x35]);
+ }
+ }
+ }
+ }
+ /*end PALMN */
+}
+
+void
+SiS_OEM300Setting (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ ULONG ROMAddr, USHORT ModeNo)


+{
+ if (SiS_VBInfo & SetCRT2ToLCD) {

+ SetOEMLCDDelay (HwDeviceExtension, BaseAddr, ROMAddr, ModeNo);


+ }
+ if (SiS_VBInfo & SetCRT2ToTV) {

+ SetOEMTVDelay (HwDeviceExtension, BaseAddr, ROMAddr, ModeNo);
+ SetOEMAntiFlicker (HwDeviceExtension, BaseAddr, ROMAddr,
+ ModeNo);
+ /* SetOEMPhaseIncr(HwDeviceExtension,BaseAddr,ROMAddr,ModeNo); */
+ SetOEMYFilter (HwDeviceExtension, BaseAddr, ROMAddr, ModeNo);
+ }
+}
+#endif
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/init301.h linux/drivers/video/sis/init301.h
--- v2.4.14/linux/drivers/video/sis/init301.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/sis/init301.h Fri Nov 9 14:11:14 2001
@@ -0,0 +1,223 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/init301.h,v 1.4 2000/12/02 01:16:17 dawes Exp $ */
+#ifndef _INIT301_
+#define _INIT301_
+
+#include "osdef.h"
+#include "initdef.h"
+#include "vgatypes.h"
+#include "vstruct.h"
+
+#include <asm/io.h>
+#include <linux/types.h>
+#include <linux/sisfb.h>
+
+USHORT SiS_SetFlag;
+USHORT SiS_RVBHCFACT, SiS_RVBHCMAX, SiS_RVBHRS;
+USHORT SiS_VGAVT, SiS_VGAHT;
+USHORT SiS_VT, SiS_HT;
+USHORT SiS_VGAVDE, SiS_VGAHDE;
+USHORT SiS_VDE, SiS_HDE;
+USHORT SiS_NewFlickerMode, SiS_RY1COE, SiS_RY2COE, SiS_RY3COE, SiS_RY4COE;
+USHORT SiS_LCDHDES, SiS_LCDVDES;
+USHORT SiS_DDC_Port;
+USHORT SiS_DDC_Index;
+USHORT SiS_DDC_DataShift;
+USHORT SiS_DDC_DeviceAddr;
+USHORT SiS_DDC_Flag;
+USHORT SiS_DDC_ReadAddr;
+USHORT SiS_DDC_Buffer;
+
+extern USHORT SiS_CRT1Mode;
+extern USHORT SiS_P3c4, SiS_P3d4;
+/*extern USHORT SiS_P3c0,SiS_P3ce,SiS_P3c2;*/
+extern USHORT SiS_P3ca;
+/*extern USHORT SiS_P3c6,SiS_P3c7,SiS_P3c8;*/
+extern USHORT SiS_P3c9;
+extern USHORT SiS_P3da;
+extern USHORT SiS_Part1Port, SiS_Part2Port;
+extern USHORT SiS_Part3Port, SiS_Part4Port, SiS_Part5Port;
+extern USHORT SiS_MDA_DAC[];
+extern USHORT SiS_CGA_DAC[];
+extern USHORT SiS_EGA_DAC[];
+extern USHORT SiS_VGA_DAC[];
+extern USHORT SiS_ModeType;
+extern USHORT SiS_SelectCRT2Rate;
+extern USHORT SiS_IF_DEF_LVDS;
+extern USHORT SiS_IF_DEF_TRUMPION;
+extern USHORT SiS_IF_DEF_CH7005;
+extern USHORT SiS_IF_DEF_HiVision;
+extern USHORT SiS_IF_DEF_DSTN; /*add for dstn */
+extern USHORT SiS_VBInfo;
+extern USHORT SiS_VBType; /*301b */
+extern USHORT SiS_LCDResInfo;
+extern USHORT SiS_LCDTypeInfo;
+extern USHORT SiS_LCDInfo;
+extern BOOLEAN SiS_SearchVBModeID (ULONG, USHORT);
+extern BOOLEAN SiS_Is301B (USHORT BaseAddr); /*301b */
+extern BOOLEAN SiS_IsDisableCRT2 (USHORT BaseAddr);
+extern BOOLEAN SiS_IsVAMode (USHORT BaseAddr);
+extern BOOLEAN SiS_IsDualEdge (USHORT BaseAddr);
+/*end 301b*/
+
+void SiS_SetDefCRT2ExtRegs (USHORT BaseAddr);
+USHORT SiS_GetRatePtrCRT2 (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex);
+BOOLEAN SiS_AjustCRT2Rate (ULONG ROMAddr, USHORT ModeNo, USHORT MODEIdIndex,
+ USHORT RefreshRateTableIndex, USHORT * i);
+void SiS_SaveCRT2Info (USHORT ModeNo);
+void SiS_GetCRT2Data (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex);
+void SiS_GetCRT2DataLVDS (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex);
+void SiS_GetCRT2PtrA (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex, USHORT * CRT2Index, USHORT * ResIndex); /*301b */
+void SiS_GetCRT2Data301 (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex);
+USHORT SiS_GetResInfo (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex);
+void SiS_GetCRT2ResInfo (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex);
+void SiS_GetRAMDAC2DATA (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex);
+void SiS_GetCRT2Ptr (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,


+ USHORT RefreshRateTableIndex, USHORT * CRT2Index,

+ USHORT * ResIndex);
+void SiS_SetCRT2ModeRegs (USHORT BaseAddr, USHORT ModeNo, PSIS_HW_DEVICE_INFO);
+
+void SiS_GetLVDSDesData (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex);
+void SiS_SetCRT2Offset (USHORT Part1Port, ULONG ROMAddr, USHORT ModeNo,


+ USHORT ModeIdIndex, USHORT RefreshRateTableIndex,

+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+USHORT SiS_GetOffset (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+USHORT SiS_GetColorDepth (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex);
+USHORT SiS_GetVCLK (ULONG ROMAddr, USHORT ModeNo);
+USHORT SiS_GetVCLKPtr (ULONG ROMAddr, USHORT ModeNo);
+USHORT SiS_GetColorTh (ULONG ROMAddr);
+USHORT SiS_GetMCLK (ULONG ROMAddr);
+USHORT SiS_GetMCLKPtr (ULONG ROMAddr);
+USHORT SiS_GetDRAMType (ULONG ROMAddr);
+USHORT SiS_CalcDelayVB (void);
+extern USHORT SiS_GetVCLK2Ptr (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+void SiS_SetCRT2Sync (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT RefreshRateTableIndex);
+void SiS_SetRegANDOR (USHORT Port, USHORT Index, USHORT DataAND, USHORT DataOR);
+void SiS_SetRegOR (USHORT Port, USHORT Index, USHORT DataOR);
+void SiS_SetRegAND (USHORT Port, USHORT Index, USHORT DataAND);
+USHORT SiS_GetVGAHT2 (void);
+void SiS_SetGroup2 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,


+ USHORT ModeIdIndex, USHORT RefreshRateTableIndex,

+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+void SiS_SetGroup3 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex, PSIS_HW_DEVICE_INFO HwDeviceExtension);
+void SiS_SetGroup4 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,


+ USHORT ModeIdIndex, USHORT RefreshRateTableIndex,

+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+void SiS_SetGroup5 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex);
+void SiS_SetCRT2VCLK (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,


+ USHORT ModeIdIndex, USHORT RefreshRateTableIndex,

+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+void SiS_EnableCRT2 (void);
+void SiS_LoadDAC2 (ULONG ROMAddr, USHORT Part5Port, USHORT ModeNo,
+ USHORT ModeIdIndex);
+void SiS_WriteDAC2 (USHORT Pdata, USHORT dl, USHORT ah, USHORT al, USHORT dh);
+void SiS_GetVBInfo301 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+BOOLEAN SiS_GetLCDResInfo (ULONG ROMAddr, USHORT P3d4, USHORT ModeNo,
+ USHORT ModeIdIndex);
+BOOLEAN SiS_BridgeIsOn (USHORT BaseAddr);
+BOOLEAN SiS_BridgeIsEnable (USHORT BaseAddr, PSIS_HW_DEVICE_INFO);
+BOOLEAN SiS_BridgeInSlave (void);
+/*void SiS_PresetScratchregister(USHORT P3d4);*/
+void SiS_PresetScratchregister (USHORT SiS_P3d4,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+void SiS_SetTVSystem (VOID);
+void SiS_LongWait (VOID);
+USHORT SiS_GetQueueConfig (VOID);
+void SiS_VBLongWait (VOID);
+USHORT SiS_GetVCLKLen (ULONG ROMAddr);
+BOOLEAN SiS_WaitVBRetrace (USHORT BaseAddr);
+void SiS_SetCRT2ECLK (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+void SiS_GetLVDSDesPtr (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,


+ USHORT RefreshRateTableIndex, USHORT * PanelIndex,

+ USHORT * ResIndex);
+void SiS_GetLVDSDesPtrA (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,


+ USHORT RefreshRateTableIndex, USHORT * PanelIndex,

+ USHORT * ResIndex); /*301b */
+void SiS_SetTPData (VOID);
+void SiS_ModCRT1CRTC (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex);
+extern BOOLEAN SiS_GetLVDSCRT1Ptr (ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex,
+ USHORT * ResInfo, USHORT * DisplayType);
+void SiS_SetCHTVReg (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex);
+void SiS_SetCHTVRegANDOR (USHORT tempax, USHORT tempbh);
+void SiS_GetCHTVRegPtr (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex);
+void SiS_SetCH7005 (USHORT tempax);
+USHORT SiS_GetCH7005 (USHORT tempax);
+void SiS_SetSwitchDDC2 (void);
+void SiS_SetStart (void);
+void SiS_SetStop (void);
+void SiS_DDC2Delay (void);
+void SiS_SetSCLKLow (void);
+void SiS_SetSCLKHigh (void);
+USHORT SiS_ReadDDC2Data (USHORT tempax);
+USHORT SiS_WriteDDC2Data (USHORT tempax);
+USHORT SiS_CheckACK (void);
+void SiS_OEM310Setting (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex);
+void SiS_OEM300Setting (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ ULONG ROMAddr, USHORT ModeNo);
+USHORT GetRevisionID (PSIS_HW_DEVICE_INFO HwDeviceExtension);
+extern void SiS_SetReg1 (USHORT, USHORT, USHORT);
+extern void SiS_SetReg3 (USHORT, USHORT);
+extern UCHAR SiS_GetReg1 (USHORT, USHORT);
+extern UCHAR SiS_GetReg2 (USHORT);
+extern BOOLEAN SiS_SearchModeID (ULONG ROMAddr, USHORT ModeNo,
+ USHORT * ModeIdIndex);
+extern BOOLEAN SiS_GetRatePtr (ULONG, USHORT);
+extern void SiS_SetReg4 (USHORT, ULONG);
+extern ULONG SiS_GetReg3 (USHORT);
+extern void SiS_DisplayOff (void);
+extern void SiS_CRT2AutoThreshold (USHORT BaseAddr);
+extern void SiS_DisplayOn (void);
+extern UCHAR SiS_GetModePtr (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex);
+extern UCHAR SiS_Get310DRAMType (ULONG ROMAddr);
+
+BOOLEAN SiS_SetCRT2Group301 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+void SiS_SetGroup1 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT RefreshRateTableIndex);
+void SiS_SetGroup1_LVDS (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT RefreshRateTableIndex);
+void SiS_SetGroup1_LCDA (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT RefreshRateTableIndex); /*301b */
+void SiS_SetGroup1_301 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT RefreshRateTableIndex);
+void SiS_SetCRT2FIFO (USHORT Part1Port, ULONG ROMAddr, USHORT ModeNo,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+void SiS_SetCRT2FIFO2 (USHORT Part1Port, ULONG ROMAddr, USHORT ModeNo,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+BOOLEAN SiS_GetLCDDDCInfo (PSIS_HW_DEVICE_INFO HwDeviceExtension);
+void SiS_UnLockCRT2 (PSIS_HW_DEVICE_INFO, USHORT BaseAddr);
+void SiS_LockCRT2 (PSIS_HW_DEVICE_INFO, USHORT BaseAddr);
+void SiS_DisableBridge (PSIS_HW_DEVICE_INFO, USHORT BaseAddr);
+void SiS_EnableBridge (PSIS_HW_DEVICE_INFO, USHORT BaseAddr);
+void SiS_SetPanelDelay (USHORT DelayTime);
+void SiS_LCD_Wait_Time (UCHAR DelayTime);
+
+#endif
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/initdef.h linux/drivers/video/sis/initdef.h
--- v2.4.14/linux/drivers/video/sis/initdef.h Wed Nov 8 17:15:04 2000
+++ linux/drivers/video/sis/initdef.h Fri Nov 9 14:11:14 2001
@@ -1,138 +1,312 @@
-#include "sis.h"
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/initdef.h,v 1.4 2000/12/02 01:16:17 dawes Exp $ */
+#ifndef _INITDEF_
+#define _INITDEF_
X
-#define PRIMARY_VGA 1 //1: SiS is primary vga 0:SiS is secondary vga
-#define ModeInfoFlag 0x07
-#define MemoryInfoFlag 0x1E0
-#define MemorySizeShift 0x05
-#define ModeText 0x00
-#define ModeCGA 0x01
-#define ModeEGA 0x02
-#define ModeVGA 0x03
-#define Mode15Bpp 0x04
-#define Mode16Bpp 0x05
-#define Mode24Bpp 0x06
-#define Mode32Bpp 0x07
-#define CRT1Len 17
-#define DoubleScanMode 0x8000
-#define ADR_CRT2PtrData 0x20E //address of CRT2PtrData in ROM image
-#define offset_Zurac 0x210
-#define ADR_LVDSDesPtrData 0x212
-#define ADR_LVDSCRT1DataPtr 0x214
+#define SiS300 0x0300
+#define SiS540 0x5300
+#define SiS630 0x6300
+#define SiS730 0x6300
+#define VB_SIS301 0x0001 /*301b */
+#define VB_SIS301B 0x0002
+#define VB_SIS302B 0x0004
+#define VB_NoLCD 0x8000
+
+/*end 301b*/
+#define CRT1Len 17
+#define LVDSCRT1Len 15
+#define CHTVRegDataLen 5
+
+#define ModeInfoFlag 0x07
+#define IsTextMode 0x07
+#define ModeText 0x00
+#define ModeCGA 0x01
+#define ModeEGA 0x02
+#define ModeVGA 0x03
+#define Mode15Bpp 0x04
+#define Mode16Bpp 0x05
+#define Mode24Bpp 0x06
+#define Mode32Bpp 0x07
+
+#define DACInfoFlag 0x18
+#define MemoryInfoFlag 0x1E0
+#define MemorySizeShift 0x05
X
-#define SoftDRAMType 0x80 //5/19/2000,Mars,for soft setting dram type
-#define SoftSettingAddr 0x52
-#define ModeSettingAddr 0x53
-
-#define InterlaceMode 0x80
-#define HalfDCLK 0x1000
-#define DACInfoFlag 0x18
-#define LineCompareOff 0x400
-#define ActivePAL 0x20
-#define ActivePALShift 5
-
-
-#define SelectCRT2Rate 0x4
-#define ProgrammingCRT2 0x1
-#define CRT2DisplayFlag 0x2000
-#define SetCRT2ToRAMDAC 0x0040
X #define Charx8Dot 0x0200
-#define LCDDataLen 8
+#define LineCompareOff 0x0400
+#define CRT2Mode 0x0800
+#define HalfDCLK 0x1000
+#define NoSupportSimuTV 0x2000
+#define DoubleScanMode 0x8000
+
+#define SupportAllCRT2 0x0078
+#define SupportTV 0x0008
+#define SupportHiVisionTV 0x0010
+#define SupportLCD 0x0020
+#define SupportRAMDAC2 0x0040
+#define NoSupportTV 0x0070
+#define NoSupportHiVisionTV 0x0060
+#define NoSupportLCD 0x0058
+#define SupportCHTV 0x0800
+#define SupportTV1024 0x0800 /*301b */
+#define InterlaceMode 0x0080
+#define SyncPP 0x0000
+#define SyncPN 0x4000
+#define SyncNP 0x8000
+#define SyncNN 0xc000
+#define ECLKindex0 0x0000
+#define ECLKindex1 0x0100
+#define ECLKindex2 0x0200
+#define ECLKindex3 0x0300
+#define ECLKindex4 0x0400
+
+#define SetSimuScanMode 0x0001
+#define SwitchToCRT2 0x0002
+#define SetCRT2ToTV 0x009C
+#define SetCRT2ToAVIDEO 0x0004
+#define SetCRT2ToSVIDEO 0x0008
+#define SetCRT2ToSCART 0x0010
X #define SetCRT2ToLCD 0x0020
+#define SetCRT2ToRAMDAC 0x0040
X #define SetCRT2ToHiVisionTV 0x0080
-#define HiTVDataLen 12
-#define TVDataLen 16
+#define SetNTSCTV 0x0000
X #define SetPALTV 0x0100
X #define SetInSlaveMode 0x0200
-#define SetCRT2ToTV 0x009C
+#define SetNotSimuMode 0x0400
X #define SetNotSimuTVMode 0x0400
-#define SetSimuScanMode 0x0001
+#define SetDispDevSwitch 0x0800
+#define LoadDACFlag 0x1000
+#define DisableCRT2Display 0x2000
X #define DriverMode 0x4000
-#define CRT2Mode 0x0800
-//#define ReIndexEnhLCD 4
+#define HotKeySwitch 0x8000
+#define SetCHTVOverScan 0x8000
+#define SetCRT2ToLCDA 0x8000 /*301b */
+#define PanelRGB18Bit 0x0100
+#define PanelRGB24Bit 0x0000
+
+#define TVOverScan 0x10
+#define TVOverScanShift 4
+#define ClearBufferFlag 0x20
+#define EnableDualEdge 0x01 /*301b */
+#define SetToLCDA 0x02
+
+#define SetSCARTOutput 0x01
+#define BoardTVType 0x02
+#define EnablePALMN 0x40
+#define ProgrammingCRT2 0x01
+#define TVSimuMode 0x02
+#define RPLLDIV2XO 0x04
+#define LCDVESATiming 0x08
+#define EnableLVDSDDA 0x10
+#define SetDispDevSwitchFlag 0x20
+#define CheckWinDos 0x40
+#define SetJDOSMode 0x80
+
+#define Panel800x600 0x01
+#define Panel1024x768 0x02
+#define Panel1280x1024 0x03
+#define Panel1280x960 0x04
+#define Panel640x480 0x05
+#define Panel1600x1200 0x06 /*301b */
+#define LCDRGB18Bit 0x01
+#define ExtChipType 0x0e
+#define ExtChip301 0x02
+#define ExtChipLVDS 0x04
+#define ExtChipTrumpion 0x06
+#define ExtChipCH7005 0x08
+#define ExtChipMitacTV 0x0a
+#define LCDNonExpanding 0x10
+#define LCDNonExpandingShift 4
+#define LCDSync 0x20
+#define LCDSyncBit 0xe0
+#define LCDSyncShift 6
+
+#define DDC2DelayTime 300
+
+#define CRT2DisplayFlag 0x2000
+#define LCDDataLen 8
+#define HiTVDataLen 12
+#define TVDataLen 16
+#define SetPALTV 0x0100
X #define HalfDCLK 0x1000
-//#define HiVisionTVHT 2100
-//#define HiVisionTVVT 2100
X #define NTSCHT 1716
X #define NTSCVT 525
X #define PALHT 1728
X #define PALVT 625
+#define StHiTVHT 892
+#define StHiTVVT 1126
+#define StHiTextTVHT 1000
+#define StHiTextTVVT 1126
+#define ExtHiTVHT 2100
+#define ExtHiTVVT 1125
X
-#define VCLKStartFreq 25
-//Freq of first item in VCLKTable
-
+#define VCLKStartFreq 25
X #define SoftDramType 0x80
+#define VCLK40 0x04
X #define VCLK65 0x09
X #define VCLK108_2 0x14
-//#define LCDIs1280x1024Panel 0x04
-//#define HiVisionVCLK 0x22
-#define TVSimuMode 0x02
-#define SetCRT2ToSVIDEO 0x08
-//#define LCDRGB18Bit 0x20
X #define LCDRGB18Bit 0x01
-#define Panel1280x1024 0x03
-#define Panel1024x768 0x02
-#define Panel800x600 0x01
-#define RPLLDIV2XO 0x04
X #define LoadDACFlag 0x1000
X #define AfterLockCRT2 0x4000
-#define SupportRAMDAC2 0x0040
-#define SupportLCD 0x0020
-//#define Support1024x768LCD 0x0020
-//#define Support1280x1024LCD 0x0040
X #define SetCRT2ToAVIDEO 0x0004
X #define SetCRT2ToSCART 0x0010
-//#define NoSupportSimuTV 0x0100
-#define NoSupportSimuTV 0x2000
X #define Ext2StructSize 5
-#define SupportTV 0x0008
-//#define TVVCLKDIV2 0x020
-//#define TVVCLK 0x021
+
X #define TVVCLKDIV2 0x021
X #define TVVCLK 0x022
+
+#define HiTVVCLKDIV2 0x023
+#define HiTVVCLK 0x024
+#define HiTVSimuVCLK 0x025
+#define HiTVTextVCLK 0x026
X #define SwitchToCRT2 0x0002
X #define LCDVESATiming 0x08
X #define SetSCARTOutput 0x01
+#define AVIDEOSense 0x01
+#define SVIDEOSense 0x02
X #define SCARTSense 0x04
+#define LCDSense 0x08
X #define Monitor1Sense 0x20
X #define Monitor2Sense 0x10
-#define SVIDEOSense 0x02
-#define AVIDEOSense 0x01
-#define LCDSense 0x08
+#define HiTVSense 0x40
X #define BoardTVType 0x02
X #define HotPlugFunction 0x08
X #define StStructSize 0x06
X
-#define ExtChip301 0x02
-#define ExtChipLVDS 0x04
-#define ExtChipTrumpion 0x06
+#define SIS_CRT2_PORT_04 0x04 - 0x030
+#define SIS_CRT2_PORT_10 0x10 - 0x30
+#define SIS_CRT2_PORT_12 0x12 - 0x30
+#define SIS_CRT2_PORT_14 0x14 - 0x30
+
X #define LCDNonExpanding 0x10
-#define LCDNonExpandingShift 4
+#define ADR_CRT2PtrData 0x20E
+#define offset_Zurac 0x210
+#define ADR_LVDSDesPtrData 0x212
+#define ADR_LVDSCRT1DataPtr 0x214
+#define ADR_CHTVVCLKPtr 0x216
+#define ADR_CHTVRegDataPtr 0x218
+
X #define LVDSDataLen 6
X #define EnableLVDSDDA 0x10
-#define LCDSync 0x20
-#define SyncPP 0x0000
-#define LCDSyncBit 0xE0
X #define LVDSDesDataLen 3
-#define LVDSCRT1Len 15
-#define ActiveNonExpanding 0x40
-#define ActiveNonExpandingShift 6
-#define ModeSwitchStatus 0x0F
-#define SoftTVType 0x40
-
-#define PanelType00 0x00
-#define PanelType01 0x08
-#define PanelType02 0x10
-#define PanelType03 0x18
-#define PanelType04 0x20
-#define PanelType05 0x28
-#define PanelType06 0x30
-#define PanelType07 0x38
-#define PanelType08 0x40
-#define PanelType09 0x48
-#define PanelType0A 0x50
-#define PanelType0B 0x58
-#define PanelType0C 0x60
-#define PanelType0D 0x68
-#define PanelType0E 0x70
-#define PanelType0F 0x78
+#define ActiveNonExpanding 0x40
+#define ActiveNonExpandingShift 6
+#define ActivePAL 0x20
+#define ActivePALShift 5
+#define ModeSwitchStatus 0x0F
+#define SoftTVType 0x40
+#define SoftSettingAddr 0x52
+#define ModeSettingAddr 0x53
+
+#define SelectCRT1Rate 0x4
+
+#define _PanelType00 0x00
+#define _PanelType01 0x08
+#define _PanelType02 0x10
+#define _PanelType03 0x18
+#define _PanelType04 0x20
+#define _PanelType05 0x28
+#define _PanelType06 0x30
+#define _PanelType07 0x38
+#define _PanelType08 0x40
+#define _PanelType09 0x48
+#define _PanelType0A 0x50
+#define _PanelType0B 0x58
+#define _PanelType0C 0x60
+#define _PanelType0D 0x68
+#define _PanelType0E 0x70
+#define _PanelType0F 0x78
+
+#define PRIMARY_VGA 0 /* 1: SiS is primary vga 0:SiS is secondary vga */
+#define BIOSIDCodeAddr 0x235
+#define OEMUtilIDCodeAddr 0x237
+#define VBModeIDTableAddr 0x239
+#define OEMTVPtrAddr 0x241
+#define PhaseTableAddr 0x243
+#define NTSCFilterTableAddr 0x245
+#define PALFilterTableAddr 0x247
+#define OEMLCDPtr_1Addr 0x249
+#define OEMLCDPtr_2Addr 0x24B
+#define LCDHPosTable_1Addr 0x24D
+#define LCDHPosTable_2Addr 0x24F
+#define LCDVPosTable_1Addr 0x251
+#define LCDVPosTable_2Addr 0x253
+#define OEMLCDPIDTableAddr 0x255
+
+#define VBModeStructSize 5
+#define PhaseTableSize 4
+#define FilterTableSize 4
+#define LCDHPosTableSize 7
+#define LCDVPosTableSize 5
+#define OEMLVDSPIDTableSize 4
+#define LVDSHPosTableSize 4
+#define LVDSVPosTableSize 6
+
+#define VB_ModeID 0
+#define VB_TVTableIndex 1
+#define VB_LCDTableIndex 2
+#define VB_LCDHIndex 3
+#define VB_LCDVIndex 4
+
+#define OEMLCDEnable 0x0001
+#define OEMLCDDelayEnable 0x0002
+#define OEMLCDPOSEnable 0x0004
+#define OEMTVEnable 0x0100
+#define OEMTVDelayEnable 0x0200
+#define OEMTVFlickerEnable 0x0400
+#define OEMTVPhaseEnable 0x0800
+#define OEMTVFilterEnable 0x1000
+
+#define OEMLCDPanelIDSupport 0x0080
+
+/* =============================================================
+ for 310
+============================================================== */
+#define SoftDRAMType 0x80
+#define SoftSetting_OFFSET 0x52
+#define SR07_OFFSET 0x7C
+#define SR15_OFFSET 0x7D
+#define SR16_OFFSET 0x81
+#define SR17_OFFSET 0x85
+#define SR19_OFFSET 0x8D
+#define SR1F_OFFSET 0x99
+#define SR21_OFFSET 0x9A
+#define SR22_OFFSET 0x9B
+#define SR23_OFFSET 0x9C
+#define SR24_OFFSET 0x9D
+#define SR25_OFFSET 0x9E
+#define SR31_OFFSET 0x9F
+#define SR32_OFFSET 0xA0
+#define SR33_OFFSET 0xA1
+
+#define CR40_OFFSET 0xA2
+#define SR25_1_OFFSET 0xF6
+#define CR49_OFFSET 0xF7
+
+#define VB310Data_1_2_Offset 0xB6
+#define VB310Data_4_D_Offset 0xB7
+#define VB310Data_4_E_Offset 0xB8
+#define VB310Data_4_10_Offset 0xBB
+
+#define RGBSenseDataOffset 0xBD
+#define YCSenseDataOffset 0xBF
+#define VideoSenseDataOffset 0xC1
+#define OutputSelectOffset 0xF3
+
+#define ECLK_MCLK_DISTANCE 0x14
+#define VBIOSTablePointerStart 0x100
+#define StandTablePtrOffset VBIOSTablePointerStart+0x02
+#define EModeIDTablePtrOffset VBIOSTablePointerStart+0x04
+#define CRT1TablePtrOffset VBIOSTablePointerStart+0x06
+#define ScreenOffsetPtrOffset VBIOSTablePointerStart+0x08
+#define VCLKDataPtrOffset VBIOSTablePointerStart+0x0A
+#define MCLKDataPtrOffset VBIOSTablePointerStart+0x0E
+#define CRT2PtrDataPtrOffset VBIOSTablePointerStart+0x10
+#define TVAntiFlickPtrOffset VBIOSTablePointerStart+0x12
+#define TVDelayPtr1Offset VBIOSTablePointerStart+0x14
+#define TVPhaseIncrPtr1Offset VBIOSTablePointerStart+0x16
+#define TVYFilterPtr1Offset VBIOSTablePointerStart+0x18
+#define LCDDelayPtr1Offset VBIOSTablePointerStart+0x20
+#define TVEdgePtr1Offset VBIOSTablePointerStart+0x24
+#define CRT2Delay1Offset VBIOSTablePointerStart+0x28
X
+#endif
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/oem300.h linux/drivers/video/sis/oem300.h
--- v2.4.14/linux/drivers/video/sis/oem300.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/sis/oem300.h Fri Nov 9 14:11:14 2001
@@ -0,0 +1,397 @@
+UCHAR SiS300_TVEdge1[3][2] = {
+ {0x0, 0x4},
+ {0x0, 0x4},
+ {0x0, 0x0}
+};
+
+UCHAR SiS300_OEMTVDelay[8][4] = {
+ {0x08, 0x08, 0x08, 0x08},
+ {0x08, 0x08, 0x08, 0x08},
+ {0x08, 0x08, 0x08, 0x08},
+ {0x2c, 0x2c, 0x2c, 0x2c},
+ {0x08, 0x08, 0x08, 0x08},
+ {0x08, 0x08, 0x08, 0x08},
+ {0x08, 0x08, 0x08, 0x08},
+ {0x20, 0x20, 0x20, 0x20}
+};
+
+UCHAR SiS300_OEMTVFlicker[8][4] = {
+ {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}
+};
+
+UCHAR SiS300_OEMLCDDelay1[12][4] = {
+ {0x2c, 0x2c, 0x2c, 0x2c},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x2c, 0x2c, 0x2c, 0x2c},
+ {0x2c, 0x2c, 0x2c, 0x2c},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x24, 0x24, 0x24, 0x24},
+ {0x24, 0x24, 0x24, 0x24},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x24, 0x24, 0x24, 0x24}
+};
+
+UCHAR SiS300_OEMLCDDelay2[32][4] = {
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20},
+ {0x20, 0x20, 0x20, 0x20}
+};
+
+UCHAR SiS300_StNTSCPhase[6][4] = {
+ {0x21, 0xed, 0x00, 0x08},
+ {0x21, 0xed, 0x8a, 0x08},
+ {0x21, 0xed, 0x8a, 0x08},
+ {0x21, 0xed, 0x8a, 0x08},
+ {0x21, 0xed, 0x8a, 0x08},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_StPALPhase[6][4] = {
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_StSCARTPhase[6][4] = {
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_StHiTVPhase[6][4] = {
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_ExtNTSCPhase[6][4] = {
+ {0x21, 0xed, 0x00, 0x08},
+ {0x21, 0xed, 0x8a, 0x08},
+ {0x21, 0xed, 0x8a, 0x08},
+ {0x21, 0xed, 0x8a, 0x08},
+ {0x21, 0xed, 0x8a, 0x08},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_ExtPALPhase[6][4] = {
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_ExtSCARTPhase[6][4] = {
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_ExtHiTVPhase[6][4] = {
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0x2a, 0x05, 0xd3, 0x00},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_StNTSCFilter[17][4] = {
+ {0x00, 0xf4, 0x10, 0x38},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xeb, 0x04, 0x10, 0x18},
+ {0xf7, 0x06, 0x19, 0x14},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x15, 0x25, 0xf6},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_StPALFilter[17][4] = {
+ {0x00, 0xf4, 0x10, 0x38},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xf1, 0xf7, 0x10, 0x32},
+ {0xf3, 0x00, 0x1d, 0x20},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xfc, 0xfb, 0x14, 0x2a},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_StSCARTFilter[17][4] = {
+ {0x00, 0xf4, 0x10, 0x38},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xf1, 0xf7, 0x10, 0x32},
+ {0xf3, 0x00, 0x1d, 0x20},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xfc, 0xfb, 0x14, 0x2a},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_StHiTVFilter[17][4] = {
+ {0x00, 0xf4, 0x10, 0x38},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xf1, 0xf7, 0x10, 0x32},
+ {0xf3, 0x00, 0x1d, 0x20},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xfc, 0xfb, 0x14, 0x2a},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_ExtNTSCFilter[17][4] = {
+ {0x00, 0xf4, 0x10, 0x38},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xeb, 0x04, 0x10, 0x18},
+ {0xf7, 0x06, 0x19, 0x14},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x15, 0x25, 0xf6},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_ExtPALFilter[17][4] = {
+ {0x00, 0xf4, 0x10, 0x38},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xf1, 0xf7, 0x10, 0x32},
+ {0xf3, 0x00, 0x1d, 0x20},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xfc, 0xfb, 0x14, 0x2a},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_ExtSCARTFilter[17][4] = {
+ {0x00, 0xf4, 0x10, 0x38},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xf1, 0xf7, 0x10, 0x32},
+ {0xf3, 0x00, 0x1d, 0x20},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xfc, 0xfb, 0x14, 0x2a},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_ExtHiTVFilter[17][4] = {
+ {0x00, 0xf4, 0x10, 0x38},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xf1, 0xf7, 0x10, 0x32},
+ {0xf3, 0x00, 0x1d, 0x20},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xfc, 0xfb, 0x14, 0x2a},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_NTSCFilter2[9][7] = {


+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0x01, 0x01, 0xFC, 0xF8, 0x08, 0x26, 0x38},
+ {0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0x22, 0x28}
+};
+

+UCHAR SiS300_PALFilter2[9][7] = {


+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0x01, 0x01, 0xFC, 0xF8, 0x08, 0x26, 0x38},
+ {0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0x22, 0x28}
+};
+

+UCHAR SiS300_PALMFilter[17][4] = {
+ {0x00, 0xf4, 0x10, 0x38},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xeb, 0x04, 0x10, 0x18},
+ {0xf7, 0x06, 0x19, 0x14},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x15, 0x25, 0xf6},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_PALNFilter[17][4] = {
+ {0x00, 0xf4, 0x10, 0x38},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xeb, 0x04, 0x10, 0x18},
+ {0xf7, 0x06, 0x19, 0x14},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x15, 0x25, 0xf6},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS300_PALMFilter2[9][7] = {


+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0x01, 0x01, 0xFC, 0xF8, 0x08, 0x26, 0x38},
+ {0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0x22, 0x28}
+};
+

+UCHAR SiS300_PALNFilter2[9][7] = {


+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0x01, 0x01, 0xFC, 0xF8, 0x08, 0x26, 0x38},
+ {0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0x22, 0x28}
+};

diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/oem310.h linux/drivers/video/sis/oem310.h
--- v2.4.14/linux/drivers/video/sis/oem310.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/sis/oem310.h Fri Nov 9 14:11:14 2001
@@ -0,0 +1,204 @@
+UCHAR SiS310_CRT2DelayCompensation1 = 0x4; /* 301A */
+
+UCHAR SiS310_LCDDelayCompensation1[] = {
+ 0x0, 0x0, 0x0, 0xb, 0xb, 0xb, 0x8, 0x8,
+ 0x8, 0x8, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0
+};
+
+UCHAR SiS310_TVDelayCompensation1[] = { 0x2, 0x2, 0x2, 0x2, 0x8, 0xb };
+UCHAR SiS310_CRT2DelayCompensation2 = 0xC; /* 301B */
+UCHAR SiS310_LCDDelayCompensation2[] = {
+ 0x0, 0x0, 0x0, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x8, 0x8, 0x8, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
+};
+
+UCHAR SiS310_TVDelayCompensation2[] = { 0x3, 0x3, 0x3, 0x3, 0x8, 0xb };
+
+UCHAR SiS310_TVAntiFlick1[3][2] = {
+ {0x4, 0x0},
+ {0x4, 0x8},
+ {0x0, 0x0}
+};
+
+UCHAR SiS310_TVEdge1[3][2] = {
+ {0x0, 0x4},
+ {0x0, 0x4},
+ {0x0, 0x0}
+};
+
+UCHAR SiS310_TVYFilter1[3][8][4] = {
+ {
+ {0x0, 0xf4, 0x10, 0x38},
+ {0x0, 0xf4, 0x10, 0x38},
+ {0xeb, 0x4, 0x25, 0x18},
+ {0xf7, 0x6, 0x19, 0x14},
+ {0x0, 0xf4, 0x10, 0x38},
+ {0xeb, 0x4, 0x25, 0x18},
+ {0xee, 0xc, 0x22, 0x8},
+ {0xeb, 0x15, 0x25, 0xf6}
+ }
+ ,
+ {
+ {0x0, 0xf4, 0x10, 0x38},
+ {0x0, 0xf4, 0x10, 0x38},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf3, 0x0, 0x1d, 0x20},
+ {0x0, 0xf4, 0x10, 0x38},
+ {0xf1, 0xf7, 0x1f, 0x32},
+ {0xf3, 0x0, 0x1d, 0x20},
+ {0xfc, 0xfb, 0x14, 0x2a}
+ }
+ ,
+ {


+ {0x0, 0x0, 0x0, 0x0},

+ {0x0, 0xf4, 0x10, 0x38},
+ {0x0, 0xf4, 0x10, 0x38},
+ {0xeb, 0x4, 0x25, 0x18},
+ {0xf7, 0x6, 0x19, 0x14},
+ {0x0, 0xf4, 0x10, 0x38},
+ {0xeb, 0x4, 0x25, 0x18},
+ {0xee, 0xc, 0x22, 0x8}
+ }
+};
+
+/*301b*/
+UCHAR SiS310_TVYFilter2[3][9][7] = {
+ {


+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0x01, 0x01, 0xFC, 0xF8, 0x08, 0x26, 0x38},
+ {0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0x22, 0x28}
+ }

+ ,
+ {


+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0x01, 0x01, 0xFC, 0xF8, 0x08, 0x26, 0x38},
+ {0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0x22, 0x28}
+ }

+ ,
+ {
+
+ {0x0, 0x0, 0x0, 0xF4, 0xFF, 0x1C, 0x22},
+ {0x0, 0x0, 0x0, 0xF4, 0xFF, 0x1C, 0x22},
+ {0x0, 0x0, 0x0, 0xF4, 0xFF, 0x1C, 0x22},
+ {0x0, 0x0, 0x0, 0xF4, 0xFF, 0x1C, 0x22},
+ {0x0, 0x0, 0x0, 0xF4, 0xFF, 0x1C, 0x22},
+ {0x0, 0x0, 0x0, 0xF4, 0xFF, 0x1C, 0x22},
+ {0x0, 0x0, 0x0, 0xF4, 0xFF, 0x1C, 0x22},
+ {0x0, 0x0, 0x0, 0xF4, 0xFF, 0x1C, 0x22}
+ }
+};
+/*end 301b*/
+/*add PALMN*/
+
+UCHAR SiS310_PALMFilter[17][4] = {
+ {0x00, 0xf4, 0x10, 0x38},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xeb, 0x04, 0x10, 0x18},
+ {0xf7, 0x06, 0x19, 0x14},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x15, 0x25, 0xf6},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS310_PALNFilter[17][4] = {
+ {0x00, 0xf4, 0x10, 0x38},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xeb, 0x04, 0x10, 0x18},
+ {0xf7, 0x06, 0x19, 0x14},
+ {0x00, 0xf4, 0x10, 0x38},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x15, 0x25, 0xf6},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xeb, 0x04, 0x25, 0x18},
+ {0xff, 0xff, 0xff, 0xff}
+};
+
+UCHAR SiS310_PALMFilter2[9][7] = {


+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46},
+ {0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C},
+ {0x01, 0x01, 0xFC, 0xF8, 0x08, 0x26, 0x38},
+ {0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0x22, 0x28}

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

echo 'End of part 080'
echo 'File patch-2.4.15 is continued in part 081'
echo "081" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:01 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part085

#!/bin/sh -x
# this is part 085 of a 115 - part archive


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

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

+ #ifdef CONFIG_FB_SIS_300
+ if (sisvga_engine == SIS_300_VGA) {
+ sisfb_get_VB_type_300 ();
+ if (ivideo.hasVB != HASVB_NONE) {
+ sisfb_detect_VB_connect_300 ();
X }
X }
+#endif
X
- if(uDispType == MASK_DISPTYPE_LCD) // LCD conntected
- {
- // TODO: set LCDType by EDID
- HwExt.usLCDType = LCD1024;
+#ifdef CONFIG_FB_SIS_315
+ if (sisvga_engine == SIS_315_VGA) {
+ sisfb_get_VB_type_315 ();
+ if (ivideo.hasVB != HASVB_NONE) {
+ sisfb_detect_VB_connect_315 ();
+ }
X }
+#endif
X
- if (HwExt.jChipID >= SIS_Trojan)
- {
- vgawb(SEQ_ADR, 0x1A);
- uSRData = vgarb(SEQ_DATA);
- if (uSRData & 0x10)
- HwExt.bIntegratedMMEnabled = TRUE;
+ // Eden Chen
+sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
+sishw_ext.usExternalChip = 0;
+
+ switch (ivideo.hasVB) {
+ case HASVB_301:
+ /*karl */
+ vgawb (VB_PART4_ADR, 0x01);
+ reg = vgarb (VB_PART4_DATA);
+ if ((reg != 0xB1) && (reg != 0xB0))
+ sishw_ext.ujVBChipID = VB_CHIP_301;
X else
- HwExt.bIntegratedMMEnabled = FALSE;
+ sishw_ext.ujVBChipID = VB_CHIP_301B;
+ break;
+ case HASVB_302:
+ sishw_ext.ujVBChipID = VB_CHIP_302;
+ break;
+ case HASVB_303:
+ sishw_ext.ujVBChipID = VB_CHIP_303;
+ break;
+ case HASVB_LVDS:
+ sishw_ext.usExternalChip = 0x1;
+ break;
+ case HASVB_TRUMPION:
+ sishw_ext.usExternalChip = 0x2;
+ break;
+ case HASVB_CHRONTEL:
+ sishw_ext.usExternalChip = 0x4;
+ break;
+ case HASVB_LVDS_CHRONTEL:
+ sishw_ext.usExternalChip = 0x5;


+ break;
+ default:
+ break;

X }
X
- if(mode_idx >= 0) /* mode found */
- {
- /* Filtering mode for VB */
- switch(uDispType & MASK_DISPTYPE_DISP2)
- {
- case MASK_DISPTYPE_LCD:
- switch(HwExt.usLCDType)
- {
- case LCD1024:
- if(sisbios_mode[mode_idx].xres > 1024)
- mode_idx = -1;
- break;
- case LCD1280:
- if(sisbios_mode[mode_idx].xres > 1280)
- mode_idx = -1;
- break;
- case LCD2048:
- if(sisbios_mode[mode_idx].xres > 2048)
- mode_idx = -1;
- break;
- case LCD1920:
- if(sisbios_mode[mode_idx].xres > 1920)
- mode_idx = -1;
- break;
- case LCD1600:
- if(sisbios_mode[mode_idx].xres > 1600)
- mode_idx = -1;
- break;
- case LCD800:
- if(sisbios_mode[mode_idx].xres > 800)
- mode_idx = -1;
- break;
- case LCD640:
- if(sisbios_mode[mode_idx].xres > 640)
- mode_idx = -1;
- break;
- default:
- mode_idx = -1;
- }
+ // ~Eden Chen
X
- if(sisbios_mode[mode_idx].xres == 720) /* only for TV */
- mode_idx = -1;
+ if (ivideo.disp_state & DISPTYPE_DISP2) {
+ if (sisfb_crt1off)
+ ivideo.disp_state |= DISPMODE_SINGLE;
+ else
+ ivideo.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
+ } else
+ ivideo.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
+
+ if (ivideo.disp_state & DISPTYPE_LCD) {
+ vgawb (CRTC_ADR, IND_SIS_LCD_PANEL);
+ reg = vgarb (CRTC_DATA);
+ // Eden Chen
+ switch (reg) {
+ case SIS_LCD_PANEL_800X600:
+ sishw_ext.ulCRT2LCDType = LCD_800x600;
X break;
- case MASK_DISPTYPE_TV:
- switch(sisbios_mode[mode_idx].xres)
- {
- case 800:
- case 640:
- break;
- case 720:
- if(ivideo.TV_type == TVMODE_NTSC)
- {
- if(sisbios_mode[mode_idx].yres != 480)
- mode_idx = -1;
- }
- else if(ivideo.TV_type == TVMODE_PAL)
- {
- if(sisbios_mode[mode_idx].yres != 576)
- mode_idx = -1;
- }
- break;
- default:
- /* illegal mode */
- mode_idx = -1;
- }
+ case SIS_LCD_PANEL_1024X768:
+ sishw_ext.ulCRT2LCDType = LCD_1024x768;
+ break;
+ case SIS_LCD_PANEL_1280X1024:
+ sishw_ext.ulCRT2LCDType = LCD_1280x1024;
+ break;
+ case SIS_LCD_PANEL_640X480:
+ sishw_ext.ulCRT2LCDType = LCD_640x480;
+ break;
+ case SIS_LCD_PANEL_1280X960:
+ sishw_ext.ulCRT2LCDType = LCD_1280x960;
+ break;
+ default:
+ sishw_ext.ulCRT2LCDType = LCD_1024x768;
X break;
X }
- }
+ // ~Eden Chen
+ }
+
+ if (sisfb_mode_idx >= 0)
+ sisfb_validate_mode ();
X
- if (mode_idx < 0)
- {
- switch(uDispType & MASK_DISPTYPE_DISP2)
- {
- case MASK_DISPTYPE_LCD:
- mode_idx = DEFAULT_LCDMODE;
+ if (sisfb_mode_idx < 0) {
+ switch (ivideo.disp_state & DISPTYPE_DISP2) {
+ case DISPTYPE_LCD:
+ sisfb_mode_idx = DEFAULT_LCDMODE;
X break;
- case MASK_DISPTYPE_TV:
- mode_idx = DEFAULT_TVMODE;
+ case DISPTYPE_TV:
+ sisfb_mode_idx = DEFAULT_TVMODE;
X break;
X default:
- mode_idx = DEFAULT_MODE;
+ sisfb_mode_idx = DEFAULT_MODE;
+ break;
X }
X }
-
-#ifdef CONFIG_FB_SIS_LINUXBIOS
- mode_idx = DEFAULT_MODE;
- rate_idx = sisbios_mode[mode_idx].rate_idx;
- /* set to default refresh rate 60MHz */
- ivideo.refresh_rate = 60;
-#endif
-
- mode_no = sisbios_mode[mode_idx].mode_no;
-
+
+ sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+
X if (ivideo.refresh_rate != 0)
- search_refresh_rate(ivideo.refresh_rate);
+ sisfb_search_refresh_rate (ivideo.refresh_rate);
X
- if (rate_idx == 0) {
- rate_idx = sisbios_mode[mode_idx].rate_idx;
- /* set to default refresh rate 60MHz */
+ if (sisfb_rate_idx == 0) {
+ sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
X ivideo.refresh_rate = 60;
X }
X
- ivideo.video_bpp = sisbios_mode[mode_idx].bpp;
- ivideo.video_vwidth = ivideo.video_width = sisbios_mode[mode_idx].xres;
- ivideo.video_vheight = ivideo.video_height = sisbios_mode[mode_idx].yres;
+ ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
+ ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres;
+ ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres;
X ivideo.org_x = ivideo.org_y = 0;
X video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
X
- printk(KERN_DEBUG "FB base: 0x%lx, size: 0x%dK\n",
- ivideo.video_base, (unsigned int)ivideo.video_size/1024);
- printk(KERN_DEBUG "MMIO base: 0x%lx, size: 0x%dK\n",
- ivideo.mmio_base, (unsigned int)MMIO_SIZE/1024);
-
-
- if (!request_mem_region(ivideo.video_base, ivideo.video_size, "sisfb FB"))
- {
- printk(KERN_ERR "sisfb: cannot reserve frame buffer memory\n");
- return -ENODEV;
- }
-
- if (!request_mem_region(ivideo.mmio_base, MMIO_SIZE, "sisfb MMIO"))
- {
- printk(KERN_ERR "sisfb: cannot reserve MMIO region\n");
- release_mem_region(ivideo.video_base, ivideo.video_size);
- return -ENODEV;
- }
-
- HwExt.VirtualVideoMemoryAddress = ivideo.video_vbase
- = ioremap(ivideo.video_base, ivideo.video_size);
- ivideo.mmio_vbase = ioremap(ivideo.mmio_base, MMIO_SIZE);
-
-#ifdef NOBIOS
- SiSInit300(&HwExt);
-#else
-#ifdef CONFIG_FB_SIS_LINUXBIOS
- SiSInit300(&HwExt);
-#endif
-#endif
- printk(KERN_INFO
- "sisfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
- ivideo.video_base, ivideo.video_vbase,
- ivideo.video_size / 1024);
- printk(KERN_INFO "sisfb: mode is %dx%dx%d, linelength=%d\n",
- ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
- video_linelength);
-
- /* enable 2D engine */
- vgawb(SEQ_ADR, IND_SIS_MODULE_ENABLE);
- jTemp = vgarb(SEQ_DATA);
- jTemp |= SIS_2D_ENABLE;
- vgawb(SEQ_DATA, jTemp);
+ printk (KERN_INFO "sisfb: mode is %dx%dx%d, linelength=%d\n",
+ ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
+ video_linelength);
+
+ // Eden Chen
+ // Check interface correction For Debug
+ DPRINTK ("VM Adr=0x%p\n", sishw_ext.pjVideoMemoryAddress);
+ DPRINTK ("VM Size=%ldK\n", sishw_ext.ulVideoMemorySize / 1024);
+ DPRINTK ("IO Adr=0x%lx\n", sishw_ext.ulIOAddress);
+ DPRINTK ("Chip=%d\n", sishw_ext.jChipType);
+ DPRINTK ("ChipRevision=%d\n", sishw_ext.jChipRevision);
+ DPRINTK ("VBChip=%d\n", sishw_ext.ujVBChipID);
+ DPRINTK ("ExtVB=%d\n", sishw_ext.usExternalChip);
+ DPRINTK ("LCD=%ld\n", sishw_ext.ulCRT2LCDType);
+ DPRINTK ("bIntegratedMMEnabled=%d\n", sishw_ext.bIntegratedMMEnabled);
+ // ~Eden Chen
X
- pre_setmode();
+ sisfb_pre_setmode ();
X
- if (SiSSetMode(&HwExt, mode_no)) {
- DPRINTK("sisfb: set mode[0x%x]: failed\n", mode_no);
+ if (SiSSetMode (&sishw_ext, sisfb_mode_no) == 0) {
+ DPRINTK ("set mode[0x%x]: failed\n", sisfb_mode_no);
X return -1;
X }
+ vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+ vgawb (SEQ_DATA, SIS_PASSWORD);
+ // Eden Chen
X
- post_setmode();
-
- /* Get VB functions */
- sis_get301info();
+ sisfb_post_setmode ();
X
- crtc_to_var(&default_var);
+ sisfb_crtc_to_var (&default_var);
X
X fb_info.changevar = NULL;
X fb_info.node = -1;
@@ -2315,20 +2774,22 @@
X fb_info.blank = &sisfb_blank;
X fb_info.flags = FBINFO_FLAG_DEFAULT;
X
- sisfb_set_disp(-1, &default_var);
+ sisfb_set_disp (-1, &default_var);
X
- if (sisfb_heap_init()) {
- DPRINTK("sisfb: Failed to enable offscreen heap\n");
+ if (sisfb_heap_init ()) {
+ DPRINTK ("sisfb: Failed to enable offscreen heap\n");
X }
+
+ /*H.C. */
+ nRes = mtrr_add ((unsigned int) ivideo.video_base, (unsigned int) ivideo.video_size, MTRR_TYPE_WRCOMB, 1);
+ vc_resize_con (1, 1, 0);
X
- /* to avoid the inversed bgcolor bug of the initial state */
- vc_resize_con(1, 1, 0);
-
- if (register_framebuffer(&fb_info) < 0)
+ if (register_framebuffer (&fb_info) < 0)
X return -EINVAL;
X
- printk(KERN_INFO "fb%d: %s frame buffer device\n",
- GET_FB_IDX(fb_info.node), fb_info.modename);
+ printk (KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
+ GET_FB_IDX (fb_info.node), fb_info.modename, VER_MAJOR, VER_MINOR,
+ VER_LEVEL);
X
X return 0;
X }
@@ -2339,35 +2800,36 @@
X static unsigned int rate = 0;
X static unsigned int crt1 = 1;
X
-MODULE_PARM(mode, "s");
-MODULE_PARM(rate, "i");
-MODULE_PARM(crt1, "i"); /* default: CRT1 enable */
+MODULE_PARM (mode, "s");
+MODULE_PARM (rate, "i");
+MODULE_PARM (crt1, "i");
+MODULE_PARM (filter, "i");
X
-int init_module(void)
+int init_module (void)
X {
X if (mode)
- search_mode(mode);
+ sisfb_search_mode (mode);
X
X ivideo.refresh_rate = rate;
X
- if(crt1 == 0)
- crt1off = 1;
+ if (crt1 == 0)
+ sisfb_crt1off = 1;
X else
- crt1off = 0;
-
- sisfb_init();
+ sisfb_crt1off = 0;
+
+ sisfb_init ();
X
X return 0;
X }
X
-void cleanup_module(void)
+void cleanup_module (void)
X {
- unregister_framebuffer(&fb_info);
+ unregister_framebuffer (&fb_info);
X }
-#endif /* MODULE */
-
+#endif
X
-EXPORT_SYMBOL(sis_malloc);
-EXPORT_SYMBOL(sis_free);
+EXPORT_SYMBOL (sis_malloc);
+EXPORT_SYMBOL (sis_free);
+EXPORT_SYMBOL (sis_dispinfo);
X
-EXPORT_SYMBOL(ivideo);
+EXPORT_SYMBOL (ivideo);
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/sis_main.h linux/drivers/video/sis/sis_main.h
--- v2.4.14/linux/drivers/video/sis/sis_main.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/sis/sis_main.h Fri Nov 9 14:11:14 2001
@@ -0,0 +1,693 @@
+#ifndef _SISFB_MAIN
+#define _SISFB_MAIN
+
+/* ------------------- Constant Definitions ------------------------- */
+
+#undef LINUXBIOS /* turn on when use LINUXBIOS */
+#define AGPOFF /* default is turn off AGP */
+
+#define VER_MAJOR 1
+#define VER_MINOR 3
+#define VER_LEVEL 9
+
+#define DEFAULT_MODE 0
+#define DEFAULT_LCDMODE 9
+#define DEFAULT_TVMODE 9
+
+#define MAX_ROM_SCAN 0x10000
+
+#define TURBO_QUEUE_CAP 0x80
+#define HW_CURSOR_CAP 0x40
+#define AGP_CMD_QUEUE_CAP 0x80
+#define VM_CMD_QUEUE_CAP 0x20
+
+/* For 300 series */
+#ifdef CONFIG_FB_SIS_300
+#define TURBO_QUEUE_AREA_SIZE 0x80000 /* 512K */
+#define HW_CURSOR_AREA_SIZE 0x1000 /* 4K */
+#endif
+
+/* For 315 series */
+#ifdef CONFIG_FB_SIS_315
+#define COMMAND_QUEUE_AREA_SIZE 0x80000 /* 512K */
+#define HW_CURSOR_AREA_SIZE 0x4000 /* 16K */
+#define COMMAND_QUEUE_THRESHOLD 0x1F
+#endif
+
+#define OH_ALLOC_SIZE 4000
+#define SENTINEL 0x7fffffff
+
+#define SEQ_ADR 0x14
+#define SEQ_DATA 0x15
+#define DAC_ADR 0x18
+#define DAC_DATA 0x19
+#define CRTC_ADR 0x24
+#define CRTC_DATA 0x25
+#define DAC2_ADR (0x16-0x30)
+#define DAC2_DATA (0x17-0x30)
+#define VB_PART1_ADR (0x04-0x30)
+#define VB_PART1_DATA (0x05-0x30)
+#define VB_PART2_ADR (0x10-0x30)
+#define VB_PART2_DATA (0x11-0x30)
+#define VB_PART3_ADR (0x12-0x30)
+#define VB_PART3_DATA (0x13-0x30)
+#define VB_PART4_ADR (0x14-0x30)
+#define VB_PART4_DATA (0x15-0x30)
+
+#define IND_SIS_PASSWORD 0x05 /* SRs */
+#define IND_SIS_COLOR_MODE 0x06
+#define IND_SIS_RAMDAC_CONTROL 0x07
+#define IND_SIS_DRAM_SIZE 0x14
+#define IND_SIS_SCRATCH_REG_16 0x16
+#define IND_SIS_SCRATCH_REG_17 0x17
+#define IND_SIS_SCRATCH_REG_1A 0x1A
+#define IND_SIS_MODULE_ENABLE 0x1E
+#define IND_SIS_PCI_ADDRESS_SET 0x20
+#define IND_SIS_TURBOQUEUE_ADR 0x26
+#define IND_SIS_TURBOQUEUE_SET 0x27
+#define IND_SIS_POWER_ON_TRAP 0x38
+#define IND_SIS_POWER_ON_TRAP2 0x39
+#define IND_SIS_CMDQUEUE_SET 0x26
+#define IND_SIS_CMDQUEUE_THRESHOLD 0x27
+
+#define IND_SIS_SCRATCH_REG_CR30 0x30 /* CRs */
+#define IND_SIS_SCRATCH_REG_CR31 0x31
+#define IND_SIS_SCRATCH_REG_CR32 0x32
+#define IND_SIS_SCRATCH_REG_CR33 0x33
+#define IND_SIS_LCD_PANEL 0x36
+#define IND_SIS_SCRATCH_REG_CR37 0x37
+#define IND_SIS_AGP_IO_PAD 0x48
+
+#define IND_BRI_DRAM_STATUS 0x63
+
+#define MMIO_QUEUE_PHYBASE 0x85C0
+#define MMIO_QUEUE_WRITEPORT 0x85C4
+#define MMIO_QUEUE_READPORT 0x85C8
+
+// Eden Chen
+#ifdef CONFIG_FB_SIS_300
+#define IND_SIS_CRT2_WRITE_ENABLE 0x24
+#endif
+#ifdef CONFIG_FB_SIS_315
+#define IND_SIS_CRT2_WRITE_ENABLE 0x2F
+#endif
+// ~Eden Chen
+
+#define SIS_PASSWORD 0x86 /* SR05 */
+#define SIS_INTERLACED_MODE 0x20 /* SR06 */
+#define SIS_8BPP_COLOR_MODE 0x0
+#define SIS_15BPP_COLOR_MODE 0x1
+#define SIS_16BPP_COLOR_MODE 0x2
+#define SIS_32BPP_COLOR_MODE 0x4
+#define SIS_DRAM_SIZE_MASK 0x3F /* SR14 */
+#define SIS_DRAM_SIZE_1MB 0x00
+#define SIS_DRAM_SIZE_2MB 0x01
+#define SIS_DRAM_SIZE_4MB 0x03
+#define SIS_DRAM_SIZE_8MB 0x07
+#define SIS_DRAM_SIZE_16MB 0x0F
+#define SIS_DRAM_SIZE_32MB 0x1F
+#define SIS_DRAM_SIZE_64MB 0x3F
+#define SIS_DATA_BUS_MASK 0xC0
+#define SIS_DATA_BUS_32 0x00
+#define SIS_DATA_BUS_64 0x01
+#define SIS_DATA_BUS_128 0x02
+#define SIS315_DRAM_SIZE_MASK 0xF0 /* 315 SR14 */
+#define SIS315_DRAM_SIZE_2MB 0x01
+#define SIS315_DRAM_SIZE_4MB 0x02
+#define SIS315_DRAM_SIZE_8MB 0x03
+#define SIS315_DRAM_SIZE_16MB 0x04
+#define SIS315_DRAM_SIZE_32MB 0x05
+#define SIS315_DRAM_SIZE_64MB 0x06
+#define SIS315_DRAM_SIZE_128MB 0x07
+#define SIS315_DATA_BUS_MASK 0x02
+#define SIS315_DATA_BUS_64 0x00
+#define SIS315_DATA_BUS_128 0x01
+#define SIS315_DUAL_CHANNEL_MASK 0x0C
+#define SIS315_SINGLE_CHANNEL_1_RANK 0x0
+#define SIS315_SINGLE_CHANNEL_2_RANK 0x1
+#define SIS315_DUAL_CHANNEL_1_RANK 0x3
+#define SIS550_DRAM_SIZE_MASK 0x3F /* 550 SR14 */
+#define SIS550_DRAM_SIZE_4MB 0x00
+#define SIS550_DRAM_SIZE_8MB 0x01
+#define SIS550_DRAM_SIZE_16MB 0x03
+#define SIS550_DRAM_SIZE_24MB 0x05
+#define SIS550_DRAM_SIZE_32MB 0x07
+#define SIS550_DRAM_SIZE_64MB 0x0F
+#define SIS550_DRAM_SIZE_96MB 0x17
+#define SIS550_DRAM_SIZE_128MB 0x1F
+#define SIS550_DRAM_SIZE_256MB 0x3F
+
+#define SIS_SCRATCH_REG_1A_MASK 0x10
+#define SIS_ENABLE_2D 0x40 /* SR1E */
+#define SIS_MEM_MAP_IO_ENABLE 0x01 /* SR20 */
+#define SIS_PCI_ADDR_ENABLE 0x80
+#define SIS_AGP_CMDQUEUE_ENABLE 0x80 /* 315 SR26 */
+#define SIS_VRAM_CMDQUEUE_ENABLE 0x40
+#define SIS_MMIO_CMD_ENABLE 0x20
+#define SIS_CMD_QUEUE_SIZE_512k 0x00
+#define SIS_CMD_QUEUE_SIZE_1M 0x04
+#define SIS_CMD_QUEUE_SIZE_2M 0x08
+#define SIS_CMD_QUEUE_SIZE_4M 0x0C
+#define SIS_CMD_QUEUE_RESET 0x01
+#define SIS_SIMULTANEOUS_VIEW_ENABLE 0x01 /* CR30 */
+#define SIS_MODE_SELECT_CRT2 0x02
+#define SIS_VB_OUTPUT_COMPOSITE 0x04
+#define SIS_VB_OUTPUT_SVIDEO 0x08
+#define SIS_VB_OUTPUT_SCART 0x10
+#define SIS_VB_OUTPUT_LCD 0x20
+#define SIS_VB_OUTPUT_CRT2 0x40
+#define SIS_VB_OUTPUT_HIVISION 0x80
+#define SIS_VB_OUTPUT_DISABLE 0x20 /* CR31 */
+#define SIS_DRIVER_MODE 0x40
+#define SIS_VB_COMPOSITE 0x01 /* CR32 */
+#define SIS_VB_SVIDEO 0x02
+#define SIS_VB_SCART 0x04
+#define SIS_VB_LCD 0x08
+#define SIS_VB_CRT2 0x10
+#define SIS_CRT1 0x20
+#define SIS_VB_HIVISION 0x40
+#define SIS_VB_DVI 0x80
+#define SIS_VB_TV (SIS_VB_COMPOSITE | SIS_VB_SVIDEO | SIS_VB_SCART | SIS_VB_HIVISION)
+#define SIS_LCD_PANEL_800X600 0x1 /* CR36 */
+#define SIS_LCD_PANEL_1024X768 0x2
+#define SIS_LCD_PANEL_1280X1024 0x3
+#define SIS_LCD_PANEL_1280X960 0x4
+#define SIS_LCD_PANEL_640X480 0x5
+#define SIS_EXTERNAL_CHIP_MASK 0x0E /* CR37 */
+#define SIS_EXTERNAL_CHIP_SIS301 0x01
+#define SIS_EXTERNAL_CHIP_LVDS 0x02
+#define SIS_EXTERNAL_CHIP_TRUMPION 0x03
+#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL 0x04
+#define SIS_EXTERNAL_CHIP_CHRONTEL 0x05
+#define SIS_AGP_2X 0x20 /* CR48 */
+
+#define BRI_DRAM_SIZE_MASK 0x70 /* PCI bridge */
+#define BRI_DRAM_SIZE_2MB 0x00
+#define BRI_DRAM_SIZE_4MB 0x01
+#define BRI_DRAM_SIZE_8MB 0x02
+#define BRI_DRAM_SIZE_16MB 0x03
+#define BRI_DRAM_SIZE_32MB 0x04
+#define BRI_DRAM_SIZE_64MB 0x05
+
+// Eden Chen
+#define HW_DEVICE_EXTENSION SIS_HW_DEVICE_INFO
+#define PHW_DEVICE_EXTENSION PSIS_HW_DEVICE_INFO
+
+#define SR_BUFFER_SIZE 5
+#define CR_BUFFER_SIZE 5
+// ~Eden Chen
+
+/* ------------------- Global Variables ----------------------------- */
+
+/* Fbcon variables */
+static struct fb_info fb_info;
+static struct display disp;
+static int video_type = FB_TYPE_PACKED_PIXELS;
+static int video_linelength;
+static int video_cmap_len;
+static struct display_switch sisfb_sw;
+static struct fb_var_screeninfo default_var = {
+ 0, 0, 0, 0,
+ 0, 0,
+ 0,
+ 0,
+ {0, 8, 0},
+ {0, 8, 0},
+ {0, 8, 0},
+ {0, 0, 0},
+ 0,
+ FB_ACTIVATE_NOW, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,
+ FB_VMODE_NONINTERLACED,
+ {0, 0, 0, 0, 0, 0}
+};
+
+static struct {
+ u16 blue, green, red, pad;
+} palette[256];
+static union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+ u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cfb32[16];
+#endif
+} fbcon_cmap;
+
+/* display status */
+static int sisfb_off = 0;
+static int sisfb_crt1off = 0;
+static int sisfb_inverse = 0;
+static int sisvga_enabled = 0;
+static int currcon = 0;
+/*karl*/
+static int sisfb_tvmode = 0;
+static int sisfb_mem = 0;
+
+static enum _VGA_ENGINE {
+ UNKNOWN_VGA = 0,
+ SIS_300_VGA,
+ SIS_315_VGA,
+} sisvga_engine = UNKNOWN_VGA;
+
+/* mode-related variables */
+int sisfb_mode_idx = -1;
+u8 sisfb_mode_no = 0;
+u8 sisfb_rate_idx = 0;
+
+/* data for sis components*/
+struct video_info ivideo;
+
+// Eden Chen
+HW_DEVICE_EXTENSION sishw_ext = {


+ NULL, NULL, NULL, NULL,

+ 0, 0, 0, 0, 0, 0, 0, 0, 0,


+ NULL, NULL, NULL, NULL,

+ {0, 0, 0, 0}
+};
+// ~Eden Chen
+
+/* card parameters */
+static unsigned long sisfb_mmio_size = 0;
+static u8 sisfb_caps = 0;
+
+typedef enum _SIS_CMDTYPE {
+ MMIO_CMD = 0,
+ AGP_CMD_QUEUE,
+ VM_CMD_QUEUE,
+} SIS_CMDTYPE;
+
+/* Supported SiS Chips list */
+static struct board {
+ u16 vendor, device;
+ const char *name;
+} sisdev_list[] = {
+ {
+ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300, "SIS 300"}, {
+ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, "SIS 540"}, {
+ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, "SIS 630"}, {
+ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315H, "SIS 315H"}, {
+ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315, "SIS 315"}, {
+ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315PRO, "SIS 315Pro"}, {
+ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550_VGA, "SIS 550"}, {
+ 0, 0, NULL}
+};
+
+/* mode table */
+static const struct _sisbios_mode {
+ char name[15];
+ u8 mode_no;
+ u16 xres;
+ u16 yres;
+ u16 bpp;
+ u16 rate_idx;
+ u16 cols;
+ u16 rows;
+} sisbios_mode[] = {
+ {
+ "640x480x8", 0x2E, 640, 480, 8, 1, 80, 30}, {
+ "640x480x16", 0x44, 640, 480, 16, 1, 80, 30}, {
+ "640x480x32", 0x62, 640, 480, 32, 1, 80, 30}, {
+ "720x480x8", 0x31, 720, 480, 8, 1, 90, 30}, {
+ "720x480x16", 0x33, 720, 480, 16, 1, 90, 30}, {
+ "720x480x32", 0x35, 720, 480, 32, 1, 90, 30}, {
+ "720x576x8", 0x32, 720, 576, 8, 1, 90, 36}, {
+ "720x576x16", 0x34, 720, 576, 16, 1, 90, 36}, {
+ "720x576x32", 0x36, 720, 576, 32, 1, 90, 36}, {
+ "800x600x8", 0x30, 800, 600, 8, 2, 100, 37}, {
+ "800x600x16", 0x47, 800, 600, 16, 2, 100, 37}, {
+ "800x600x32", 0x63, 800, 600, 32, 2, 100, 37}, {
+ "1024x768x8", 0x38, 1024, 768, 8, 2, 128, 48}, {
+ "1024x768x16", 0x4A, 1024, 768, 16, 2, 128, 48}, {
+ "1024x768x32", 0x64, 1024, 768, 32, 2, 128, 48}, {
+ "1280x1024x8", 0x3A, 1280, 1024, 8, 2, 160, 64}, {
+ "1280x1024x16", 0x4D, 1280, 1024, 16, 2, 160, 64}, {
+ "1280x1024x32", 0x65, 1280, 1024, 32, 2, 160, 64}, {
+ "1600x1200x8", 0x3C, 1600, 1200, 8, 1, 200, 75}, {
+ "1600x1200x16", 0x3D, 1600, 1200, 16, 1, 200, 75}, {
+ "1600x1200x32", 0x66, 1600, 1200, 32, 1, 200, 75}, {
+ "1920x1440x8", 0x68, 1920, 1440, 8, 1, 240, 75}, {
+ "1920x1440x16", 0x69, 1920, 1440, 16, 1, 240, 75}, {
+ "1920x1440x32", 0x6B, 1920, 1440, 32, 1, 240, 75}, {
+ "\0", 0x00, 0, 0, 0, 0, 0, 0}
+};
+
+static struct _sis_vrate {
+ u16 idx;
+ u16 xres;
+ u16 yres;
+ u16 refresh;
+} sisfb_vrate[] = {
+ {
+ 1, 640, 480, 60}, {
+ 2, 640, 480, 72}, {
+ 3, 640, 480, 75}, {
+ 4, 640, 480, 85}, {
+ 5, 640, 480, 100}, {
+ 6, 640, 480, 120}, {
+ 7, 640, 480, 160}, {
+ 8, 640, 480, 200}, {
+ 1, 720, 480, 60}, {
+ 1, 720, 576, 50}, {
+ 1, 800, 600, 56}, {
+ 2, 800, 600, 60}, {
+ 3, 800, 600, 72}, {
+ 4, 800, 600, 75}, {
+ 5, 800, 600, 85}, {
+ 6, 800, 600, 100}, {
+ 7, 800, 600, 120}, {
+ 8, 800, 600, 160}, {
+ 1, 1024, 768, 43}, {
+ 2, 1024, 768, 60}, {
+ 3, 1024, 768, 70}, {
+ 4, 1024, 768, 75}, {
+ 5, 1024, 768, 85}, {
+ 6, 1024, 768, 100}, {
+ 7, 1024, 768, 120}, {
+ 1, 1280, 1024, 43}, {
+ 2, 1280, 1024, 60}, {
+ 3, 1280, 1024, 75}, {
+ 4, 1280, 1024, 85}, {
+ 1, 1600, 1200, 60}, {
+ 2, 1600, 1200, 65}, {
+ 3, 1600, 1200, 70}, {
+ 4, 1600, 1200, 75}, {
+ 5, 1600, 1200, 85}, {
+ 1, 1920, 1440, 60}, {
+ 0, 0, 0, 0}
+};
+
+/* Offscreen layout */
+typedef struct _SIS_GLYINFO {
+ unsigned char ch;
+ int fontwidth;
+ int fontheight;
+ u8 gmask[72];
+ int ngmask;
+} SIS_GLYINFO;
+
+typedef struct _SIS_OH {
+ struct _SIS_OH *poh_next;
+ struct _SIS_OH *poh_prev;
+ unsigned long offset;
+ unsigned long size;
+} SIS_OH;
+
+typedef struct _SIS_OHALLOC {
+ struct _SIS_OHALLOC *poha_next;
+ SIS_OH aoh[1];
+} SIS_OHALLOC;
+
+typedef struct _SIS_HEAP {
+ SIS_OH oh_free;
+ SIS_OH oh_used;
+ SIS_OH *poh_freelist;
+ SIS_OHALLOC *poha_chain;
+ unsigned long max_freesize;
+} SIS_HEAP;
+
+static unsigned long sisfb_hwcursor_vbase;
+
+static unsigned long sisfb_heap_start;
+static unsigned long sisfb_heap_end;
+static unsigned long sisfb_heap_size;
+static SIS_HEAP sisfb_heap;
+
+// Eden Chen
+static struct _sis_TV_filter {
+ u8 filter[9][4];
+} sis_TV_filter[] = {
+ { { {
+ 0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_0 */
+ {
+ 0x00, 0xE0, 0x10, 0x60}, {
+ 0x00, 0xEE, 0x10, 0x44}, {
+ 0x00, 0xF4, 0x10, 0x38}, {
+ 0xF8, 0xF4, 0x18, 0x38}, {
+ 0xFC, 0xFB, 0x14, 0x2A}, {
+ 0x00, 0x00, 0x10, 0x20}, {
+ 0x00, 0x04, 0x10, 0x18}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_1 */
+ {
+ 0x00, 0xE0, 0x10, 0x60}, {
+ 0x00, 0xEE, 0x10, 0x44}, {
+ 0x00, 0xF4, 0x10, 0x38}, {
+ 0xF8, 0xF4, 0x18, 0x38}, {
+ 0xFC, 0xFB, 0x14, 0x2A}, {
+ 0x00, 0x00, 0x10, 0x20}, {
+ 0x00, 0x04, 0x10, 0x18}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_2 */
+ {
+ 0xF5, 0xEE, 0x1B, 0x44}, {
+ 0xF8, 0xF4, 0x18, 0x38}, {
+ 0xEB, 0x04, 0x25, 0x18}, {
+ 0xF1, 0x05, 0x1F, 0x16}, {
+ 0xF6, 0x06, 0x1A, 0x14}, {
+ 0xFA, 0x06, 0x16, 0x14}, {
+ 0x00, 0x04, 0x10, 0x18}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_3 */
+ {
+ 0xF1, 0x04, 0x1F, 0x18}, {
+ 0xEE, 0x0D, 0x22, 0x06}, {
+ 0xF7, 0x06, 0x19, 0x14}, {
+ 0xF4, 0x0B, 0x1C, 0x0A}, {
+ 0xFA, 0x07, 0x16, 0x12}, {
+ 0xF9, 0x0A, 0x17, 0x0C}, {
+ 0x00, 0x07, 0x10, 0x12}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_4 */
+ {
+ 0x00, 0xE0, 0x10, 0x60}, {
+ 0x00, 0xEE, 0x10, 0x44}, {
+ 0x00, 0xF4, 0x10, 0x38}, {
+ 0xF8, 0xF4, 0x18, 0x38}, {
+ 0xFC, 0xFB, 0x14, 0x2A}, {
+ 0x00, 0x00, 0x10, 0x20}, {
+ 0x00, 0x04, 0x10, 0x18}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_5 */
+ {
+ 0xF5, 0xEE, 0x1B, 0x44}, {
+ 0xF8, 0xF4, 0x18, 0x38}, {
+ 0xEB, 0x04, 0x25, 0x18}, {
+ 0xF1, 0x05, 0x1F, 0x16}, {
+ 0xF6, 0x06, 0x1A, 0x14}, {
+ 0xFA, 0x06, 0x16, 0x14}, {
+ 0x00, 0x04, 0x10, 0x18}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_6 */
+ {
+ 0xEB, 0x04, 0x25, 0x18}, {
+ 0xE7, 0x0E, 0x29, 0x04}, {
+ 0xEE, 0x0C, 0x22, 0x08}, {
+ 0xF6, 0x0B, 0x1A, 0x0A}, {
+ 0xF9, 0x0A, 0x17, 0x0C}, {
+ 0xFC, 0x0A, 0x14, 0x0C}, {
+ 0x00, 0x08, 0x10, 0x10}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_7 */
+ {
+ 0xEC, 0x02, 0x24, 0x1C}, {
+ 0xF2, 0x04, 0x1E, 0x18}, {
+ 0xEB, 0x15, 0x25, 0xF6}, {
+ 0xF4, 0x10, 0x1C, 0x00}, {
+ 0xF8, 0x0F, 0x18, 0x02}, {
+ 0x00, 0x04, 0x10, 0x18}, {
+ 0x01, 0x06, 0x0F, 0x14}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* PALFilter_0 */
+ {
+ 0x00, 0xE0, 0x10, 0x60}, {
+ 0x00, 0xEE, 0x10, 0x44}, {
+ 0x00, 0xF4, 0x10, 0x38}, {
+ 0xF8, 0xF4, 0x18, 0x38}, {
+ 0xFC, 0xFB, 0x14, 0x2A}, {
+ 0x00, 0x00, 0x10, 0x20}, {
+ 0x00, 0x04, 0x10, 0x18}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* PALFilter_1 */
+ {
+ 0x00, 0xE0, 0x10, 0x60}, {
+ 0x00, 0xEE, 0x10, 0x44}, {
+ 0x00, 0xF4, 0x10, 0x38}, {
+ 0xF8, 0xF4, 0x18, 0x38}, {
+ 0xFC, 0xFB, 0x14, 0x2A}, {
+ 0x00, 0x00, 0x10, 0x20}, {
+ 0x00, 0x04, 0x10, 0x18}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* PALFilter_2 */
+ {
+ 0xF5, 0xEE, 0x1B, 0x44}, {
+ 0xF8, 0xF4, 0x18, 0x38}, {
+ 0xF1, 0xF7, 0x01, 0x32}, {
+ 0xF5, 0xFB, 0x1B, 0x2A}, {
+ 0xF9, 0xFF, 0x17, 0x22}, {
+ 0xFB, 0x01, 0x15, 0x1E}, {
+ 0x00, 0x04, 0x10, 0x18}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* PALFilter_3 */
+ {
+ 0xF5, 0xFB, 0x1B, 0x2A}, {
+ 0xEE, 0xFE, 0x22, 0x24}, {
+ 0xF3, 0x00, 0x1D, 0x20}, {
+ 0xF9, 0x03, 0x17, 0x1A}, {
+ 0xFB, 0x02, 0x14, 0x1E}, {
+ 0xFB, 0x04, 0x15, 0x18}, {
+ 0x00, 0x06, 0x10, 0x14}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* PALFilter_4 */
+ {
+ 0x00, 0xE0, 0x10, 0x60}, {
+ 0x00, 0xEE, 0x10, 0x44}, {
+ 0x00, 0xF4, 0x10, 0x38}, {
+ 0xF8, 0xF4, 0x18, 0x38}, {
+ 0xFC, 0xFB, 0x14, 0x2A}, {
+ 0x00, 0x00, 0x10, 0x20}, {
+ 0x00, 0x04, 0x10, 0x18}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* PALFilter_5 */
+ {
+ 0xF5, 0xEE, 0x1B, 0x44}, {
+ 0xF8, 0xF4, 0x18, 0x38}, {
+ 0xF1, 0xF7, 0x1F, 0x32}, {
+ 0xF5, 0xFB, 0x1B, 0x2A}, {
+ 0xF9, 0xFF, 0x17, 0x22}, {
+ 0xFB, 0x01, 0x15, 0x1E}, {
+ 0x00, 0x04, 0x10, 0x18}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* PALFilter_6 */
+ {
+ 0xF5, 0xEE, 0x1B, 0x2A}, {
+ 0xEE, 0xFE, 0x22, 0x24}, {
+ 0xF3, 0x00, 0x1D, 0x20}, {
+ 0xF9, 0x03, 0x17, 0x1A}, {
+ 0xFB, 0x02, 0x14, 0x1E}, {
+ 0xFB, 0x04, 0x15, 0x18}, {
+ 0x00, 0x06, 0x10, 0x14}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}, { { {
+ 0x00, 0x00, 0x00, 0x40}, /* PALFilter_7 */
+ {
+ 0xF5, 0xEE, 0x1B, 0x44}, {
+ 0xF8, 0xF4, 0x18, 0x38}, {
+ 0xFC, 0xFB, 0x14, 0x2A}, {
+ 0xEB, 0x05, 0x25, 0x16}, {
+ 0xF1, 0x05, 0x1F, 0x16}, {
+ 0xFA, 0x07, 0x16, 0x12}, {
+ 0x00, 0x07, 0x10, 0x12}, {
+ 0xFF, 0xFF, 0xFF, 0xFF}}}
+};
+
+static int filter = -1;
+static unsigned char filter_tb;
+//~Eden Chen
+
+/* ---------------------- Routine Prototype ------------------------- */
+
+/* Interface used by the world */
+int sisfb_setup (char *options);
+static int sisfb_get_fix (struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
+static int sisfb_get_var (struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int sisfb_set_var (struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int sisfb_get_cmap (struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info);
+static int sisfb_set_cmap (struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info);
+static int sisfb_ioctl (struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con,
+ struct fb_info *info);
+
+/* Interface to the low level console driver */
+int sisfb_init (void);
+static int sisfb_update_var (int con, struct fb_info *info);
+static int sisfb_switch (int con, struct fb_info *info);
+static void sisfb_blank (int blank, struct fb_info *info);
+
+/* hardware access routines */
+void sisfb_set_reg1 (u16 port, u16 index, u16 data);
+void sisfb_set_reg3 (u16 port, u16 data);
+void sisfb_set_reg4 (u16 port, unsigned long data);
+u8 sisfb_get_reg1 (u16 port, u16 index);
+u8 sisfb_get_reg2 (u16 port);
+u32 sisfb_get_reg3 (u16 port);
+// Eden Chen
+//void sisfb_clear_DAC(u16 port);
+//void sisfb_clear_buffer(PHW_DEVICE_EXTENSION psishw_ext);
+// ~Eden Chen
+
+/* Internal routines */
+static void sisfb_search_mode (const char *name);
+static void sisfb_validate_mode (void);
+static u8 sisfb_search_refresh_rate (unsigned int rate);
+static int sis_getcolreg (unsigned regno, unsigned *red, unsigned *green,
+ unsigned *blue, unsigned *transp,
+ struct fb_info *fb_info);
+static int sis_setcolreg (unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *fb_info);
+static int sisfb_do_set_var (struct fb_var_screeninfo *var, int isactive,
+ struct fb_info *info);
+static void sisfb_set_disp (int con, struct fb_var_screeninfo *var);
+static void sisfb_do_install_cmap (int con, struct fb_info *info);
+
+/* Chip-dependent Routines */
+#ifdef CONFIG_FB_SIS_300
+static int sisfb_get_dram_size_300 (void);
+//extern BOOLEAN SiSInit300(PHW_DEVICE_EXTENSION HwDeviceExtension);
+static void sisfb_detect_VB_connect_300 (void);
+static void sisfb_get_VB_type_300 (void);
+static int sisfb_has_VB_300 (void);
+//extern BOOLEAN SiSSetMode(PHW_DEVICE_EXTENSION HwDeviceExtension,USHORT ModeNo);
+#endif
+#ifdef CONFIG_FB_SIS_315
+static int sisfb_get_dram_size_315 (void);
+//extern BOOLEAN SiSInit310(PHW_DEVICE_EXTENSION HwDeviceExtension);
+static void sisfb_detect_VB_connect_315 (void);
+static void sisfb_get_VB_type_315 (void);
+//extern BOOLEAN SiSSetMode310(PHW_DEVICE_EXTENSION HwDeviceExtension, USHORT ModeNo);
+#endif
+
+/* SetMode routines */
+
+// Eden Chen
+extern BOOLEAN SiSSetMode (PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT ModeNo);
+extern BOOLEAN SiSInit (PSIS_HW_DEVICE_INFO HwDeviceExtension);
+// ~Eden Chen
+
+static void sisfb_pre_setmode (void);
+static void sisfb_post_setmode (void);
+static void sisfb_crtc_to_var (struct fb_var_screeninfo *var);
+
+/* Export functions */
+static void sis_get_glyph (SIS_GLYINFO * gly);
+void sis_dispinfo (struct ap_data *rec);
+void sis_malloc (struct sis_memreq *req);
+void sis_free (unsigned long base);
+
+/* heap routines */
+static int sisfb_heap_init (void);
+static SIS_OH *sisfb_poh_new_node (void);
+static SIS_OH *sisfb_poh_allocate (unsigned long size);
+static void sisfb_delete_node (SIS_OH * poh);
+static void sisfb_insert_node (SIS_OH * pohList, SIS_OH * poh);
+static SIS_OH *sisfb_poh_free (unsigned long base);
+static void sisfb_free_node (SIS_OH * poh);
+
+/* routines to access PCI configuration space */
+BOOLEAN sisfb_query_VGA_config_space (PSIS_HW_DEVICE_INFO psishw_ext,
+ unsigned long offset, unsigned long set,
+ unsigned long *value);
+BOOLEAN sisfb_query_north_bridge_space (PSIS_HW_DEVICE_INFO psishw_ext,
+ unsigned long offset, unsigned long set,
+ unsigned long *value);
+
+#endif
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/vgatypes.h linux/drivers/video/sis/vgatypes.h
--- v2.4.14/linux/drivers/video/sis/vgatypes.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/sis/vgatypes.h Fri Nov 9 14:11:14 2001
@@ -0,0 +1,275 @@
+#ifndef _VGATYPES_
+#define _VGATYPES_
+
+#ifndef TC
+#define far
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef CHAR
+typedef char CHAR;
+#endif
+
+#ifndef SHORT
+typedef short SHORT;
+#endif
+
+#ifndef LONG
+typedef long LONG;
+#endif
+
+#ifndef UCHAR
+typedef unsigned char UCHAR;
+#endif
+
+#ifndef USHORT
+typedef unsigned short USHORT;
+#endif
+
+#ifndef ULONG
+typedef unsigned long ULONG;
+#endif
+
+#ifndef PUCHAR
+typedef UCHAR far *PUCHAR;
+#endif
+
+#ifndef PUSHORT
+typedef USHORT far *PUSHORT;
+#endif
+
+#ifndef PULONG
+typedef ULONG far *PULONG;
+#endif
+
+#ifndef PVOID
+typedef void far *PVOID;
+#endif
+#ifndef VOID
+typedef void VOID;
+#endif
+
+#ifndef BOOLEAN
+typedef UCHAR BOOLEAN;
+#endif
+
+#ifndef WINCE_HEADER
+#ifndef bool
+typedef UCHAR bool;
+#endif
+#endif /* WINCE_HEADER */
+
+#ifndef VBIOS_VER_MAX_LENGTH
+#define VBIOS_VER_MAX_LENGTH 4
+#endif
+
+#ifndef WIN2000
+#ifndef SIS_VB_CHIP_TYPE
+typedef enum _SIS_VB_CHIP_TYPE {
+ VB_CHIP_Legacy = 0,
+ VB_CHIP_301,
+ VB_CHIP_301B,
+ VB_CHIP_301BLCD,
+ VB_CHIP_301BTV,
+ VB_CHIP_302,
+ VB_CHIP_302B,
+ VB_CHIP_302BLCD,
+ VB_CHIP_302BTV,
+ VB_CHIP_303,
+ VB_CHIP_UNKNOWN, /* other video bridge or no video bridge */
+ MAX_VB_CHIP
+} SIS_VB_CHIP_TYPE;
+#endif
+#endif
+
+#ifndef WIN2000
+#ifndef SIS_LCD_TYPE
+typedef enum _SIS_LCD_TYPE {
+ LCD_INVALID = 0,
+ LCD_800x600,
+ LCD_1024x768,
+ LCD_1280x1024,
+ LCD_1280x960,
+ LCD_640x480,
+ LCD_1600x1200,
+ LCD_1920x1440,
+ LCD_2048x1536,
+ LCD_UNKNOWN
+} SIS_LCD_TYPE;
+#endif
+#endif
+
+#ifndef WIN2000 /* mark by Paul ,Move definition to sisv.h */
+#ifndef PSIS_DSReg
+typedef struct _SIS_DSReg {
+ UCHAR jIdx;
+ UCHAR jVal;
+} SIS_DSReg, *PSIS_DSReg;
+#endif
+
+#ifndef SIS_HW_DEVICE_INFO
+
+typedef struct _SIS_HW_DEVICE_INFO SIS_HW_DEVICE_INFO, *PSIS_HW_DEVICE_INFO;
+
+typedef BOOLEAN (*PSIS_QUERYSPACE) (PSIS_HW_DEVICE_INFO, ULONG, ULONG, ULONG *);
+
+struct _SIS_HW_DEVICE_INFO {
+ PVOID pDevice; /* The pointer to the physical device data structure
+ in each OS or NULL for unused. */
+ UCHAR *pjVirtualRomBase; /* Only for NT, NULL for WinCE & Linux. */
+ /* base virtual address of VBIOS ROM Space */
+ /* or base virtual address of ROM image file. */
+ /* if NULL, then read from pjROMImage; */
+ /* Note:ROM image file is the file of VBIOS ROM */
+
+ UCHAR *pjCustomizedROMImage; /* base virtual address of ROM image file. */
+ /* wincE:ROM image file is the file for OEM */
+ /* customized table */
+ /* Linux: not used */
+ /* NT : not used */
+ /* Note : pjCustomizedROMImage=NULL if no ROM image file */
+
+ UCHAR *pjVideoMemoryAddress; /* base virtual memory address */
+ /* of Linear VGA memory */
+
+ ULONG ulVideoMemorySize; /* size, in bytes, of the memory on the board */
+ ULONG ulIOAddress; /* base I/O address of VGA ports (0x3B0) */
+ UCHAR jChipType; /* Used to Identify SiS Graphics Chip */
+ /* defined in the data structure type */
+ /* "SIS_CHIP_TYPE" */
+
+ UCHAR jChipRevision; /* Used to Identify SiS Graphics Chip Revision */
+ UCHAR ujVBChipID; /* the ID of video bridge */
+ /* defined in the data structure type */
+ /* "SIS_VB_CHIP_TYPE" */
+
+ USHORT usExternalChip; /* NO VB or other video bridge(not */
+ /* SiS video bridge) */
+ /* if ujVBChipID = VB_CHIP_UNKNOWN, */
+ /* then bit0=1 : LVDS,bit1=1 : trumpion, */
+ /* bit2=1 : CH7005 & no video bridge if */
+ /* usExternalChip = 0. */
+ /* Note: CR37[3:1]: */
+ /* 001:SiS 301 */
+ /* 010:LVDS */
+ /* 011:Trumpion LVDS Scaling Chip */
+ /* 100:LVDS(LCD-out)+Chrontel 7005 */
+ /* 101:Single Chrontel 7005 */
+
+ ULONG ulCRT2LCDType; /* defined in the data structure type */
+ /* "SIS_LCD_TYPE" */
+
+ BOOLEAN bIntegratedMMEnabled; /* supporting integration MM enable */
+
+ BOOLEAN bSkipDramSizing; /* True: Skip video memory sizing. */
+ PSIS_DSReg pSR; /* restore SR registers in initial function. */
+ /* end data :(idx, val) = (FF, FF). */
+ /* Note : restore SR registers if */
+ /* bSkipDramSizing = TRUE */
+
+ PSIS_DSReg pCR; /* restore CR registers in initial function. */
+ /* end data :(idx, val) = (FF, FF) */
+ /* Note : restore cR registers if */
+ /* bSkipDramSizing = TRUE */
+
+ PSIS_QUERYSPACE pQueryVGAConfigSpace; /* Get/Set VGA Configuration */
+ /* space */
+
+ PSIS_QUERYSPACE pQueryNorthBridgeSpace; /* Get/Set North Bridge */
+ /* space */
+
+ UCHAR szVBIOSVer[VBIOS_VER_MAX_LENGTH];
+
+};
+#endif
+#endif /*~ mark by Paul ,Move definition to sisv.h */
+
+#ifndef WIN2000
+#ifndef WINCE_HEADER
+#ifndef BUS_DATA_TYPE
+typedef enum _BUS_DATA_TYPE {
+ ConfigurationSpaceUndefined = -1,
+ Cmos,
+ EisaConfiguration,
+ Pos,
+ CbusConfiguration,
+ PCIConfiguration,
+ VMEConfiguration,
+ NuBusConfiguration,
+ PCMCIAConfiguration,
+ MPIConfiguration,
+ MPSAConfiguration,
+ PNPISAConfiguration,
+ MaximumBusDataType
+} BUS_DATA_TYPE, *PBUS_DATA_TYPE;
+#endif
+#endif /* WINCE_HEADER */
+
+#ifndef PCI_TYPE0_ADDRESSES
+#define PCI_TYPE0_ADDRESSES 6
+#endif
+
+#ifndef PCI_TYPE1_ADDRESSES
+#define PCI_TYPE1_ADDRESSES 2
+#endif
+
+#ifndef WINCE_HEADER
+#ifndef PCI_COMMON_CONFIG
+typedef struct _PCI_COMMON_CONFIG {
+ USHORT VendorID; /* (ro) */
+ USHORT DeviceID; /* (ro) */
+ USHORT Command; /* Device control */
+ USHORT Status;
+ UCHAR RevisionID; /* (ro) */
+ UCHAR ProgIf; /* (ro) */
+ UCHAR SubClass; /* (ro) */
+ UCHAR BaseClass; /* (ro) */
+ UCHAR CacheLineSize; /* (ro+) */
+ UCHAR LatencyTimer; /* (ro+) */
+ UCHAR HeaderType; /* (ro) */
+ UCHAR BIST; /* Built in self test */
+
+ union {
+ struct _PCI_HEADER_TYPE_0 {
+ ULONG BaseAddresses[PCI_TYPE0_ADDRESSES];
+ ULONG CIS;
+ USHORT SubVendorID;
+ USHORT SubSystemID;
+ ULONG ROMBaseAddress;
+ ULONG Reserved2[2];
+
+ UCHAR InterruptLine; /* */
+ UCHAR InterruptPin; /* (ro) */
+ UCHAR MinimumGrant; /* (ro) */
+ UCHAR MaximumLatency; /* (ro) */
+ } type0;
+
+ } u;
+
+ UCHAR DeviceSpecific[192];
+
+} PCI_COMMON_CONFIG, *PPCI_COMMON_CONFIG;
+#endif
+#endif /* WINCE_HEADER */
+
+#ifndef FIELD_OFFSET
+#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field))
+#endif
+
+#ifndef PCI_COMMON_HDR_LENGTH
+#define PCI_COMMON_HDR_LENGTH (FIELD_OFFSET (PCI_COMMON_CONFIG, DeviceSpecific))
+#endif
+#endif
+
+#endif
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/vstruct.h linux/drivers/video/sis/vstruct.h
--- v2.4.14/linux/drivers/video/sis/vstruct.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/sis/vstruct.h Fri Nov 9 14:11:14 2001
@@ -0,0 +1,324 @@
+#ifdef _INIT_
+#define EXTERN
+#else
+#define EXTERN extern
+#endif /* _INIT_ */
+
+typedef struct _SiS_PanelDelayTblStruct {
+ UCHAR timer[2];
+} SiS_PanelDelayTblStruct;
+
+typedef struct _SiS_LCDDataStruct {


+ USHORT RVBHCMAX;
+ USHORT RVBHCFACT;
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;

+} SiS_LCDDataStruct;
+
+typedef struct _SiS_TVDataStruct {


+ USHORT RVBHCMAX;
+ USHORT RVBHCFACT;
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT TVHDE;
+ USHORT TVVDE;
+ USHORT RVBHRS;
+ UCHAR FlickerMode;
+ USHORT HALFRVBHRS;
+ UCHAR RY1COE;
+ UCHAR RY2COE;
+ UCHAR RY3COE;
+ UCHAR RY4COE;

+} SiS_TVDataStruct;
+
+typedef struct _SiS_LVDSDataStruct {


+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;

+} SiS_LVDSDataStruct;
+
+typedef struct _SiS_LVDSDesStruct {


+ USHORT LCDHDES;
+ USHORT LCDVDES;

+} SiS_LVDSDesStruct;
+
+typedef struct _SiS_LVDSCRT1DataStruct {
+ UCHAR CR[15];
+} SiS_LVDSCRT1DataStruct;
+
+/*add for LCDA*/
+typedef struct _SiS_LCDACRT1DataStruct {
+ UCHAR CR[17];
+} SiS_LCDACRT1DataStruct;
+
+typedef struct _SiS_CHTVRegDataStruct {
+ UCHAR Reg[5];
+} SiS_CHTVRegDataStruct;
+
+typedef struct _SiS_StStruct {


+ UCHAR St_ModeID;
+ USHORT St_ModeFlag;
+ UCHAR St_StTableIndex;
+ UCHAR St_CRT2CRTC;
+ UCHAR St_ResInfo;
+ UCHAR VB_StTVFlickerIndex;
+ UCHAR VB_StTVEdgeIndex;
+ UCHAR VB_StTVYFilterIndex;

+} SiS_StStruct;
+
+typedef struct _SiS_VBModeStruct {


+ UCHAR ModeID;
+ UCHAR VB_TVDelayIndex;
+ UCHAR VB_TVFlickerIndex;
+ UCHAR VB_TVPhaseIndex;
+ UCHAR VB_TVYFilterIndex;
+ UCHAR VB_LCDDelayIndex;
+ UCHAR _VB_LCDHIndex;
+ UCHAR _VB_LCDVIndex;

+} SiS_VBModeStruct;
+
+typedef struct _SiS_StandTableStruct {


+ UCHAR CRT_COLS;
+ UCHAR ROWS;
+ UCHAR CHAR_HEIGHT;
+ USHORT CRT_LEN;
+ UCHAR SR[4];
+ UCHAR MISC;
+ UCHAR CRTC[0x19];
+ UCHAR ATTR[0x14];
+ UCHAR GRC[9];

+} SiS_StandTableStruct;
+
+typedef struct _SiS_ExtStruct {


+ UCHAR Ext_ModeID;
+ USHORT Ext_ModeFlag;
+ USHORT Ext_ModeInfo;
+ USHORT Ext_Point;
+ USHORT Ext_VESAID;
+ UCHAR Ext_VESAMEMSize;
+ UCHAR Ext_RESINFO;
+ UCHAR VB_ExtTVFlickerIndex;
+ UCHAR VB_ExtTVEdgeIndex;
+ UCHAR VB_ExtTVYFilterIndex;
+ UCHAR REFindex;

+} SiS_ExtStruct;
+
+typedef struct _SiS_Ext2Struct {


+ USHORT Ext_InfoFlag;
+ UCHAR Ext_CRT1CRTC;
+ UCHAR Ext_CRTVCLK;
+ UCHAR Ext_CRT2CRTC;
+ UCHAR ModeID;
+ USHORT XRes;
+ USHORT YRes;
+ USHORT ROM_OFFSET;

+} SiS_Ext2Struct;
+
+typedef struct _SiS_CRT1TableStruct {
+ UCHAR CR[17];
+} SiS_CRT1TableStruct;
+
+typedef struct _SiS_MCLKDataStruct {


+ UCHAR SR28, SR29, SR2A;
+ USHORT CLOCK;

+} SiS_MCLKDataStruct;
+
+typedef struct _SiS_ECLKDataStruct {


+ UCHAR SR2E, SR2F, SR30;
+ USHORT CLOCK;

+} SiS_ECLKDataStruct;
+
+typedef struct _SiS_VCLKDataStruct {


+ UCHAR SR2B, SR2C;
+ USHORT CLOCK;

+} SiS_VCLKDataStruct;
+
+typedef struct _SiS_VBVCLKDataStruct {


+ UCHAR Part4_A, Part4_B;
+ USHORT CLOCK;

+} SiS_VBVCLKDataStruct;
+
+typedef struct _SiS_StResInfoStruct {


+ USHORT HTotal;
+ USHORT VTotal;

+} SiS_StResInfoStruct;
+
+typedef struct _SiS_ModeResInfoStruct {


+ USHORT HTotal;
+ USHORT VTotal;
+ UCHAR XChar;
+ UCHAR YChar;

+} SiS_ModeResInfoStruct;
+
+EXTERN SiS_StStruct *SiS_SModeIDTable;
+EXTERN SiS_StandTableStruct *SiS_StandTable;
+EXTERN SiS_ExtStruct *SiS_EModeIDTable;
+EXTERN SiS_Ext2Struct *SiS_RefIndex;
+EXTERN SiS_VBModeStruct *SiS_VBModeIDTable;
+EXTERN SiS_CRT1TableStruct *SiS_CRT1Table;
+EXTERN SiS_MCLKDataStruct *SiS_MCLKData;
+EXTERN SiS_ECLKDataStruct *SiS_ECLKData;
+EXTERN SiS_VCLKDataStruct *SiS_VCLKData;
+EXTERN SiS_VBVCLKDataStruct *SiS_VBVCLKData;
+EXTERN SiS_StResInfoStruct *SiS_StResInfo;
+EXTERN SiS_ModeResInfoStruct *SiS_ModeResInfo;
+EXTERN UCHAR *SiS_ScreenOffset;
+
+EXTERN UCHAR *pSiS_OutputSelect;
+EXTERN UCHAR *pSiS_SoftSetting;
+EXTERN UCHAR *pSiS_SR07;
+
+typedef UCHAR DRAM4Type[4];
+EXTERN DRAM4Type *SiS_SR15; /* pointer : point to array */
+EXTERN DRAM4Type *SiS_CR40; /* pointer : point to array */
+EXTERN UCHAR *SiS_CR49;
+EXTERN UCHAR *SiS_SR25;
+
+EXTERN UCHAR *pSiS_SR1F;
+EXTERN UCHAR *pSiS_SR21;
+EXTERN UCHAR *pSiS_SR22;
+EXTERN UCHAR *pSiS_SR23;
+EXTERN UCHAR *pSiS_SR24;
+EXTERN UCHAR *pSiS_SR31;
+EXTERN UCHAR *pSiS_SR32;
+EXTERN UCHAR *pSiS_SR33;
+EXTERN UCHAR *pSiS_CRT2Data_1_2;
+EXTERN UCHAR *pSiS_CRT2Data_4_D;
+EXTERN UCHAR *pSiS_CRT2Data_4_E;
+EXTERN UCHAR *pSiS_CRT2Data_4_10;
+EXTERN USHORT *pSiS_RGBSenseData;
+EXTERN USHORT *pSiS_VideoSenseData;
+EXTERN USHORT *pSiS_YCSenseData;
+EXTERN USHORT *pSiS_RGBSenseData2; /*301b */
+EXTERN USHORT *pSiS_VideoSenseData2;
+EXTERN USHORT *pSiS_YCSenseData2;
+
+EXTERN UCHAR *SiS_NTSCPhase;
+EXTERN UCHAR *SiS_PALPhase;
+EXTERN UCHAR *SiS_NTSCPhase2;
+EXTERN UCHAR *SiS_PALPhase2;
+EXTERN UCHAR *SiS_PALMPhase;
+EXTERN UCHAR *SiS_PALNPhase;
+EXTERN SiS_LCDDataStruct *SiS_StLCD1024x768Data;
+EXTERN SiS_LCDDataStruct *SiS_ExtLCD1024x768Data;
+EXTERN SiS_LCDDataStruct *SiS_St2LCD1024x768Data;
+EXTERN SiS_LCDDataStruct *SiS_StLCD1280x1024Data;
+EXTERN SiS_LCDDataStruct *SiS_ExtLCD1280x1024Data;
+EXTERN SiS_LCDDataStruct *SiS_St2LCD1280x1024Data;
+EXTERN SiS_LCDDataStruct *SiS_NoScaleData;
+EXTERN SiS_LCDDataStruct *SiS_LCD1280x960Data;
+EXTERN SiS_TVDataStruct *SiS_StPALData;
+EXTERN SiS_TVDataStruct *SiS_ExtPALData;
+EXTERN SiS_TVDataStruct *SiS_StNTSCData;
+EXTERN SiS_TVDataStruct *SiS_ExtNTSCData;
+EXTERN SiS_TVDataStruct *SiS_St1HiTVData;
+EXTERN SiS_TVDataStruct *SiS_St2HiTVData;
+EXTERN SiS_TVDataStruct *SiS_ExtHiTVData;
+EXTERN UCHAR *SiS_NTSCTiming;
+EXTERN UCHAR *SiS_PALTiming;
+EXTERN UCHAR *SiS_HiTVExtTiming;
+EXTERN UCHAR *SiS_HiTVSt1Timing;
+EXTERN UCHAR *SiS_HiTVSt2Timing;
+EXTERN UCHAR *SiS_HiTVTextTiming;
+EXTERN UCHAR *SiS_HiTVGroup3Data;
+EXTERN UCHAR *SiS_HiTVGroup3Simu;
+EXTERN UCHAR *SiS_HiTVGroup3Text;
+
+EXTERN SiS_PanelDelayTblStruct *SiS_PanelDelayTbl;
+EXTERN SiS_LVDSDataStruct *SiS_LVDS800x600Data_1;
+EXTERN SiS_LVDSDataStruct *SiS_LVDS800x600Data_2;
+EXTERN SiS_LVDSDataStruct *SiS_LVDS1024x768Data_1;
+EXTERN SiS_LVDSDataStruct *SiS_LVDS1024x768Data_2;
+EXTERN SiS_LVDSDataStruct *SiS_LVDS1280x1024Data_1;
+EXTERN SiS_LVDSDataStruct *SiS_LVDS1280x1024Data_2;
+EXTERN SiS_LVDSDataStruct *SiS_LVDS640x480Data_1;
+EXTERN SiS_LVDSDataStruct *SiS_CHTVUNTSCData;
+EXTERN SiS_LVDSDataStruct *SiS_CHTVONTSCData;
+EXTERN SiS_LVDSDataStruct *SiS_CHTVUPALData;
+EXTERN SiS_LVDSDataStruct *SiS_CHTVOPALData;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType00_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType01_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType02_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType03_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType04_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType05_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType06_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType07_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType08_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType09_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType0a_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType0b_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType0c_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType0d_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType0e_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType0f_1;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType00_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType01_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType02_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType03_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType04_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType05_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType06_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType07_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType08_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType09_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType0a_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType0b_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType0c_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType0d_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType0e_2;
+EXTERN SiS_LVDSDesStruct *SiS_PanelType0f_2;
+/*301b*/
+EXTERN SiS_LVDSDesStruct *LVDS1024x768Des_1;
+EXTERN SiS_LVDSDesStruct *LVDS1280x1024Des_1;
+EXTERN SiS_LVDSDesStruct *LVDS1280x960Des_1;
+EXTERN SiS_LVDSDesStruct *LVDS1024x768Des_2;
+EXTERN SiS_LVDSDesStruct *LVDS1280x1024Des_2;
+EXTERN SiS_LVDSDesStruct *LVDS1280x960Des_2;
+/*end 301b*/
+EXTERN SiS_LVDSDesStruct *SiS_CHTVUNTSCDesData;
+EXTERN SiS_LVDSDesStruct *SiS_CHTVONTSCDesData;
+EXTERN SiS_LVDSDesStruct *SiS_CHTVUPALDesData;
+EXTERN SiS_LVDSDesStruct *SiS_CHTVOPALDesData;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_1;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_1;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_1;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_1_H;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_1_H;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_1_H;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_2;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_2;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_2;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_2_H;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_2_H;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_2_H;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1UNTSC;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1ONTSC;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1UPAL;
+EXTERN SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1OPAL;
+/*add for LCDA*/
+EXTERN SiS_LCDACRT1DataStruct *SiS_LCDACRT1800x600_1;
+EXTERN SiS_LCDACRT1DataStruct *SiS_LCDACRT11024x768_1;
+EXTERN SiS_LCDACRT1DataStruct *SiS_LCDACRT11280x1024_1;
+EXTERN SiS_LCDACRT1DataStruct *SiS_LCDACRT1800x600_1_H;
+EXTERN SiS_LCDACRT1DataStruct *SiS_LCDACRT11024x768_1_H;
+EXTERN SiS_LCDACRT1DataStruct *SiS_LCDACRT11280x1024_1_H;
+EXTERN SiS_LCDACRT1DataStruct *SiS_LCDACRT1800x600_2;
+EXTERN SiS_LCDACRT1DataStruct *SiS_LCDACRT11024x768_2;
+EXTERN SiS_LCDACRT1DataStruct *SiS_LCDACRT11280x1024_2;
+EXTERN SiS_LCDACRT1DataStruct *SiS_LCDACRT1800x600_2_H;
+EXTERN SiS_LCDACRT1DataStruct *SiS_LCDACRT11024x768_2_H;
+EXTERN SiS_LCDACRT1DataStruct *SiS_LCDACRT11280x1024_2_H;
+/*end 301b*/
+
+EXTERN SiS_CHTVRegDataStruct *SiS_CHTVReg_UNTSC;
+EXTERN SiS_CHTVRegDataStruct *SiS_CHTVReg_ONTSC;
+EXTERN SiS_CHTVRegDataStruct *SiS_CHTVReg_UPAL;
+EXTERN SiS_CHTVRegDataStruct *SiS_CHTVReg_OPAL;
+EXTERN UCHAR *SiS_CHTVVCLKUNTSC;
+EXTERN UCHAR *SiS_CHTVVCLKONTSC;
+EXTERN UCHAR *SiS_CHTVVCLKUPAL;
+EXTERN UCHAR *SiS_CHTVVCLKOPAL;
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sstfb.c linux/drivers/video/sstfb.c
--- v2.4.14/linux/drivers/video/sstfb.c Tue Oct 23 22:48:53 2001
+++ linux/drivers/video/sstfb.c Wed Nov 14 14:52:20 2001
@@ -1697,7 +1697,7 @@


X if (!options || !*options)
X return 0;
X
- while (this_opt = strsep(&options, ",")) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {

X if (!*this_opt) continue;
X
X f_ddprintk("option %s\n", this_opt);
diff -u --recursive --new-file v2.4.14/linux/drivers/video/tdfxfb.c linux/drivers/video/tdfxfb.c
--- v2.4.14/linux/drivers/video/tdfxfb.c Tue Oct 23 22:48:53 2001
+++ linux/drivers/video/tdfxfb.c Wed Nov 14 14:52:20 2001
@@ -2086,7 +2086,9 @@
X if(!options || !*options)
X return;
X
- while(this_opt = strsep(&options, ",")) {
+ while((this_opt = strsep(&options, ",")) != NULL) {


+ if(!*this_opt)
+ continue;
X if(!strcmp(this_opt, "inverse")) {

X inverse = 1;
X fb_invert_cmaps();
diff -u --recursive --new-file v2.4.14/linux/drivers/video/tgafb.c linux/drivers/video/tgafb.c
--- v2.4.14/linux/drivers/video/tgafb.c Tue Oct 23 22:48:53 2001
+++ linux/drivers/video/tgafb.c Wed Nov 14 14:52:20 2001
@@ -889,7 +889,7 @@
X int i;
X
X if (options && *options) {


- while (this_opt = strsep(&options, ",")) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {

X if (!*this_opt) { continue; }
X

X if (!strncmp(this_opt, "font:", 5)) {

diff -u --recursive --new-file v2.4.14/linux/drivers/video/valkyriefb.c linux/drivers/video/valkyriefb.c
--- v2.4.14/linux/drivers/video/valkyriefb.c Tue Oct 23 22:48:53 2001
+++ linux/drivers/video/valkyriefb.c Wed Nov 14 14:52:20 2001
@@ -801,7 +801,7 @@


X if (!options || !*options)
X return 0;
X
- while (this_opt = strsep(&options, ",")) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {
X if (!strncmp(this_opt, "font:", 5)) {
X char *p;
X int i;

diff -u --recursive --new-file v2.4.14/linux/drivers/video/vesafb.c linux/drivers/video/vesafb.c
--- v2.4.14/linux/drivers/video/vesafb.c Tue Oct 23 22:48:53 2001
+++ linux/drivers/video/vesafb.c Wed Nov 14 14:52:20 2001
@@ -457,7 +457,7 @@


X if (!options || !*options)
X return 0;
X
- while (this_opt = strsep(&options, ",")) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {

X if (!*this_opt) continue;
X
X if (! strcmp(this_opt, "inverse"))
@@ -520,10 +520,11 @@
X FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
X
X if (!request_mem_region(video_base, video_size, "vesafb")) {
- printk(KERN_ERR
+ printk(KERN_WARNING
X "vesafb: abort, cannot reserve video memory at 0x%lx\n",
X video_base);
- return -EBUSY;
+ /* We cannot make this fatal. Sometimes this comes from magic
+ spaces our resource handlers simply don't know about */
X }
X
X video_vbase = ioremap(video_base, video_size);
@@ -635,7 +636,12 @@
X
X if (mtrr) {
X int temp_size = video_size;
- while (mtrr_add(video_base, temp_size, MTRR_TYPE_WRCOMB, 1)==-EINVAL) {
+ /* Find the largest power-of-two */
+ while (temp_size & (temp_size - 1))
+ temp_size &= (temp_size - 1);
+
+ /* Try and find a power of two to add */
+ while (temp_size && mtrr_add(video_base, temp_size, MTRR_TYPE_WRCOMB, 1)==-EINVAL) {
X temp_size >>= 1;
X }
X }
@@ -666,3 +672,5 @@
X * c-basic-offset: 8
X * End:
X */
+
+MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/drivers/video/vfb.c linux/drivers/video/vfb.c
--- v2.4.14/linux/drivers/video/vfb.c Tue Oct 23 22:48:53 2001
+++ linux/drivers/video/vfb.c Wed Nov 14 14:52:20 2001
@@ -382,7 +382,7 @@


X if (!options || !*options)
X return 0;
X
- while (this_opt = strsep(&options, ",")) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {
X if (!strncmp(this_opt, "font:", 5))
X strcpy(fb_info.fontname, this_opt+5);

X }
diff -u --recursive --new-file v2.4.14/linux/drivers/video/vga16fb.c linux/drivers/video/vga16fb.c
--- v2.4.14/linux/drivers/video/vga16fb.c Tue Oct 23 22:48:53 2001
+++ linux/drivers/video/vga16fb.c Wed Nov 14 14:52:20 2001
@@ -692,7 +692,7 @@


X if (!options || !*options)
X return 0;
X
- while (this_opt = strsep(&options, ",")) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {

X if (!*this_opt) continue;
X

X if (!strncmp(this_opt, "font:", 5))

diff -u --recursive --new-file v2.4.14/linux/drivers/video/virgefb.c linux/drivers/video/virgefb.c
--- v2.4.14/linux/drivers/video/virgefb.c Tue Oct 23 22:48:53 2001
+++ linux/drivers/video/virgefb.c Wed Nov 14 14:52:20 2001
@@ -1085,7 +1085,9 @@


X if (!options || !*options)
X return 0;
X
- while (this_opt = strsep(&options, ",")) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!*this_opt)
+ continue;
X if (!strcmp(this_opt, "inverse")) {

X Cyberfb_inverse = 1;
X fb_invert_cmaps();
@@ -1099,6 +1101,7 @@
X }
X else
X get_video_mode(this_opt);
+ }
X
X DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",virgefb_default.xres,
X virgefb_default.yres,
diff -u --recursive --new-file v2.4.14/linux/fs/Config.in linux/fs/Config.in
--- v2.4.14/linux/fs/Config.in Mon Nov 5 15:55:33 2001
+++ linux/fs/Config.in Mon Nov 12 09:34:16 2001
@@ -10,6 +10,7 @@
X
X dep_tristate 'Reiserfs support' CONFIG_REISERFS_FS $CONFIG_EXPERIMENTAL
X dep_mbool ' Have reiserfs do extra internal checking' CONFIG_REISERFS_CHECK $CONFIG_REISERFS_FS $CONFIG_EXPERIMENTAL
+dep_mbool ' Stats in /proc/fs/reiserfs' CONFIG_REISERFS_PROC_INFO $CONFIG_REISERFS_FS $CONFIG_EXPERIMENTAL
X
X dep_tristate 'ADFS file system support' CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
X dep_mbool ' ADFS write support (DANGEROUS)' CONFIG_ADFS_FS_RW $CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
@@ -20,6 +21,13 @@
X
X dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
X
+tristate 'Ext3 journalling file system support (EXPERIMENTAL)' CONFIG_EXT3_FS
+# CONFIG_JBD could be its own option (even modular), but until there are
+# other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
+# dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
+define_bool CONFIG_JBD $CONFIG_EXT3_FS
+dep_mbool ' JBD (ext3) debugging support' CONFIG_JBD_DEBUG $CONFIG_JBD
+
X # msdos file systems
X tristate 'DOS FAT fs support' CONFIG_FAT_FS
X dep_tristate ' MSDOS fs support' CONFIG_MSDOS_FS $CONFIG_FAT_FS
@@ -31,9 +39,9 @@
X int 'JFFS debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_JFFS_FS_VERBOSE 0
X bool 'JFFS stats available in /proc filesystem' CONFIG_JFFS_PROC_FS
X fi
-dep_tristate 'Journalling Flash File System v2 (JFFS2) support (EXPERIMENTAL)' CONFIG_JFFS2_FS $CONFIG_EXPERIMENTAL $CONFIG_MTD
-if [ "$CONFIG_JFFS2_FS" != "n" ] ; then
- int 'JFFS2 debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_JFFS2_FS_DEBUG 0
+dep_tristate 'Journalling Flash File System v2 (JFFS2) support' CONFIG_JFFS2_FS $CONFIG_MTD
+if [ "$CONFIG_JFFS2_FS" = "y" -o "$CONFIG_JFFS2_FS" = "m" ] ; then
+ int 'JFFS2 debugging verbosity (0 = quiet, 2 = noisy)' CONFIG_JFFS2_FS_DEBUG 0
X fi
X tristate 'Compressed ROM file system support' CONFIG_CRAMFS
X bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS
@@ -84,6 +92,7 @@
X comment 'Network File Systems'
X
X dep_tristate 'Coda file system support (advanced network fs)' CONFIG_CODA_FS $CONFIG_INET
+ dep_tristate 'InterMezzo file system support (experimental, replicating fs)' CONFIG_INTERMEZZO_FS $CONFIG_INET $CONFIG_EXPERIMENTAL
X dep_tristate 'NFS file system support' CONFIG_NFS_FS $CONFIG_INET
X dep_mbool ' Provide NFSv3 client support' CONFIG_NFS_V3 $CONFIG_NFS_FS
X dep_bool ' Root file system on NFS' CONFIG_ROOT_NFS $CONFIG_NFS_FS $CONFIG_IP_PNP
diff -u --recursive --new-file v2.4.14/linux/fs/Makefile linux/fs/Makefile
--- v2.4.14/linux/fs/Makefile Mon Nov 5 15:55:33 2001
+++ linux/fs/Makefile Mon Nov 12 09:34:16 2001
@@ -7,14 +7,14 @@
X
X O_TARGET := fs.o
X
-export-objs := filesystems.o open.o dcache.o
+export-objs := filesystems.o open.o dcache.o buffer.o
X mod-subdirs := nls
X
X obj-y := open.o read_write.o devices.o file_table.o buffer.o \
X super.o block_dev.o char_dev.o stat.o exec.o pipe.o namei.o \
X fcntl.o ioctl.o readdir.o select.o fifo.o locks.o \
X dcache.o inode.o attr.o bad_inode.o file.o iobuf.o dnotify.o \
- filesystems.o namespace.o
+ filesystems.o namespace.o seq_file.o
X
X ifeq ($(CONFIG_QUOTA),y)


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

echo 'End of part 085'
echo 'File patch-2.4.15 is continued in part 086'
echo "086" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:00 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part084

#!/bin/sh -x
# this is part 084 of a 115 - part archive


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

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

- ivideo.video_width * (ivideo.video_bpp >> 3);
+ vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_THRESHOLD);
+ vgawb (SEQ_DATA, COMMAND_QUEUE_THRESHOLD);
X
- DPRINTK("Current Mode: %dx%d-%d line_length=%d\n",
- ivideo.video_width, ivideo.video_height,
- ivideo.video_bpp, video_linelength);
- }
+ vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+ vgawb (SEQ_DATA, SIS_CMD_QUEUE_RESET);
X
- return 0;
-}
+ *write_port = *read_port;
X
-/* ---------------------- Draw Funtions ----------------------------- */
+ temp |= SIS_AGP_CMDQUEUE_ENABLE;
+ vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+ vgawb (SEQ_DATA, temp);
X
-static void sis_get_glyph(struct GlyInfo *gly)
-{
- struct display *p = &fb_display[currcon];
- u16 c;
- u8 *cdat;
- int widthb;
- u8 *gbuf = gly->gmask;
- int size;
+ *cmdq_baseport = agp_phys;
X
+ sisfb_caps |= AGP_CMD_QUEUE_CAP;
+#endif
+ break;
X
- gly->fontheight = fontheight(p);
- gly->fontwidth = fontwidth(p);
- widthb = (fontwidth(p) + 7) / 8;
+ case VM_CMD_QUEUE:
+ sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
+ sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
X
- c = gly->ch & p->charmask;
- if (fontwidth(p) <= 8)
- cdat = p->fontdata + c * fontheight(p);
- else
- cdat = p->fontdata + (c * fontheight(p) << 1);
+ vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_THRESHOLD);
+ vgawb (SEQ_DATA, COMMAND_QUEUE_THRESHOLD);
X
- size = fontheight(p) * widthb;
- memcpy(gbuf, cdat, size);
- gly->ngmask = size;
-}
+ vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+ vgawb (SEQ_DATA, SIS_CMD_QUEUE_RESET);
X
+ *write_port = *read_port;
X
-/* ---------------------- HEAP Routines ----------------------------- */
+ temp |= SIS_VRAM_CMDQUEUE_ENABLE;
+ vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+ vgawb (SEQ_DATA, temp);
X
-/*
- * Heap Initialization
- */
+ *cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
X
-static int sisfb_heap_init(void)
-{
- struct OH *poh;
- u8 jTemp, tq_state;
+ sisfb_caps |= VM_CMD_QUEUE_CAP;
X
- if(ivideo.video_size > 0x800000)
- /* video ram is large than 8M */
- heap_start = (unsigned long) ivideo.video_vbase + RESERVED_MEM_SIZE_8M;
- else
- heap_start = (unsigned long) ivideo.video_vbase + RESERVED_MEM_SIZE_4M;
+ DPRINTK ("VM Cmd Queue offset = 0x%lx, size is %dK\n",
+ *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE / 1024);
+ break;
+ default:
+ vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+ vgawb (SEQ_DATA, SIS_MMIO_CMD_ENABLE);
+ break;
+ }
X
- heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;
- heap_size = heap_end - heap_start;
+#endif
X
+#ifdef CONFIG_FB_SIS_300
+ if (sisfb_heap_size >= TURBO_QUEUE_AREA_SIZE) {
+ unsigned int tqueue_pos;
+ u8 tq_state;
X
- /* Setting for Turbo Queue */
- if (heap_size >= TURBO_QUEUE_AREA_SIZE) {
X tqueue_pos =
- (ivideo.video_size -
- TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
- jTemp = (u8) (tqueue_pos & 0xff);
- vgawb(SEQ_ADR, IND_SIS_TURBOQUEUE_SET);
- tq_state = vgarb(SEQ_DATA);
+ (ivideo.video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
+ temp = (u8) (tqueue_pos & 0xff);
+ vgawb (SEQ_ADR, IND_SIS_TURBOQUEUE_SET);
+ tq_state = vgarb (SEQ_DATA);
X tq_state |= 0xf0;
X tq_state &= 0xfc;
X tq_state |= (u8) (tqueue_pos >> 8);
- vgawb(SEQ_DATA, tq_state);
- vgawb(SEQ_ADR, IND_SIS_TURBOQUEUE_ADR);
- vgawb(SEQ_DATA, jTemp);
-
- caps |= TURBO_QUEUE_CAP;
-
- heap_end -= TURBO_QUEUE_AREA_SIZE;
- heap_size -= TURBO_QUEUE_AREA_SIZE;
+ vgawb (SEQ_DATA, tq_state);
+ vgawb (SEQ_ADR, IND_SIS_TURBOQUEUE_ADR);
+ vgawb (SEQ_DATA, temp);
+
+ sisfb_caps |= TURBO_QUEUE_CAP;
+
+ sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
+ sisfb_heap_size -= TURBO_QUEUE_AREA_SIZE;
+ DPRINTK ("Turbo Queue: start at 0x%lx, size is %dK\n",
+ sisfb_heap_end, TURBO_QUEUE_AREA_SIZE / 1024);
X }
+#endif
X
- /* Setting for HW cursor(4K) */
- if (heap_size >= HW_CURSOR_AREA_SIZE) {
- heap_end -= HW_CURSOR_AREA_SIZE;
- heap_size -= HW_CURSOR_AREA_SIZE;
- hwcursor_vbase = heap_end;
+ if (sisfb_heap_size >= HW_CURSOR_AREA_SIZE) {
+ sisfb_heap_end -= HW_CURSOR_AREA_SIZE;
+ sisfb_heap_size -= HW_CURSOR_AREA_SIZE;
+ sisfb_hwcursor_vbase = sisfb_heap_end;
X
- caps |= HW_CURSOR_CAP;
+ sisfb_caps |= HW_CURSOR_CAP;
+
+ DPRINTK ("Hardware Cursor: start at 0x%lx, size is %dK\n",
+ sisfb_heap_end, HW_CURSOR_AREA_SIZE / 1024);
X }
X
- heap.pohaChain = NULL;
- heap.pohFreeList = NULL;
+ sisfb_heap.poha_chain = NULL;
+ sisfb_heap.poh_freelist = NULL;
X
- poh = poh_new_node();
+ poh = sisfb_poh_new_node ();
X
X if (poh == NULL)
X return 1;
X
- /* The first node describles the entire heap size */
- poh->pohNext = &heap.ohFree;
- poh->pohPrev = &heap.ohFree;
- poh->ulSize = heap_end - heap_start + 1;
- poh->ulOffset = heap_start - (unsigned long) ivideo.video_vbase;
-
- DPRINTK("sisfb:Heap start:0x%p, end:0x%p, len=%dk\n",
- (char *) heap_start, (char *) heap_end,
- (unsigned int) poh->ulSize / 1024);
-
- DPRINTK("sisfb:First Node offset:0x%x, size:%dk\n",
- (unsigned int) poh->ulOffset, (unsigned int) poh->ulSize / 1024);
-
- /* The second node in our free list sentinel */
- heap.ohFree.pohNext = poh;
- heap.ohFree.pohPrev = poh;
- heap.ohFree.ulSize = 0;
- heap.ulMaxFreeSize = poh->ulSize;
-
- /* Initialize the discardable list */
- heap.ohUsed.pohNext = &heap.ohUsed;
- heap.ohUsed.pohPrev = &heap.ohUsed;
- heap.ohUsed.ulSize = SENTINEL;
+ poh->poh_next = &sisfb_heap.oh_free;
+ poh->poh_prev = &sisfb_heap.oh_free;
+ poh->size = sisfb_heap_end - sisfb_heap_start + 1;
+ poh->offset = sisfb_heap_start - (unsigned long) ivideo.video_vbase;
+
+ DPRINTK ("sisfb:Heap start:0x%p, end:0x%p, len=%dk\n",
+ (char *) sisfb_heap_start, (char *) sisfb_heap_end,
+ (unsigned int) poh->size / 1024);
+
+ DPRINTK ("sisfb:First Node offset:0x%x, size:%dk\n",
+ (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
+
+ sisfb_heap.oh_free.poh_next = poh;
+ sisfb_heap.oh_free.poh_prev = poh;
+ sisfb_heap.oh_free.size = 0;
+ sisfb_heap.max_freesize = poh->size;
+
+ sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
+ sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
+ sisfb_heap.oh_used.size = SENTINEL;


X
X return 0;
X }
X

-/*
- * Allocates a basic memory unit in which we'll pack our data structures.
- */
-
-static struct OH *poh_new_node(void)
+static SIS_OH *sisfb_poh_new_node (void)
X {
X int i;
X unsigned long cOhs;
- struct OHALLOC *poha;
- struct OH *poh;
+ SIS_OHALLOC *poha;
+ SIS_OH *poh;
X
- if (heap.pohFreeList == NULL) {
- poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
- if (!poha)
- return NULL;
+ if (sisfb_heap.poh_freelist == NULL) {
+ poha = kmalloc (OH_ALLOC_SIZE, GFP_KERNEL);
X
- poha->pohaNext = heap.pohaChain;
- heap.pohaChain = poha;
+ poha->poha_next = sisfb_heap.poha_chain;
+ sisfb_heap.poha_chain = poha;
X
X cOhs =
X (OH_ALLOC_SIZE -
- sizeof(struct OHALLOC)) / sizeof(struct OH) + 1;
+ sizeof (SIS_OHALLOC)) / sizeof (SIS_OH) + 1;
X
X poh = &poha->aoh[0];
X for (i = cOhs - 1; i != 0; i--) {
- poh->pohNext = poh + 1;
+ poh->poh_next = poh + 1;
X poh = poh + 1;
X }
X
- poh->pohNext = NULL;
- heap.pohFreeList = &poha->aoh[0];
+ poh->poh_next = NULL;
+ sisfb_heap.poh_freelist = &poha->aoh[0];
X }
X
- poh = heap.pohFreeList;
- heap.pohFreeList = poh->pohNext;
+ poh = sisfb_heap.poh_freelist;
+ sisfb_heap.poh_freelist = poh->poh_next;
X
X return (poh);
X }
X
-/*
- * Allocates space, return NULL when failed
- */
-
-static struct OH *poh_allocate(unsigned long size)


+static SIS_OH *sisfb_poh_allocate (unsigned long size)

X {
- struct OH *pohThis;
- struct OH *pohRoot;
+ SIS_OH *pohThis;
+ SIS_OH *pohRoot;
X int bAllocated = 0;
X
- if (size > heap.ulMaxFreeSize) {
- DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
- (unsigned int) size / 1024);
+ if (size > sisfb_heap.max_freesize) {
+ DPRINTK ("sisfb: Can't allocate %dk size on offscreen\n",
+ (unsigned int) size / 1024);


X return (NULL);
X }
X

- pohThis = heap.ohFree.pohNext;
+ pohThis = sisfb_heap.oh_free.poh_next;
X
- while (pohThis != &heap.ohFree) {
- if (size <= pohThis->ulSize) {
+ while (pohThis != &sisfb_heap.oh_free) {
+ if (size <= pohThis->size) {
X bAllocated = 1;
X break;
X }
- pohThis = pohThis->pohNext;
+ pohThis = pohThis->poh_next;
X }
X
X if (!bAllocated) {
- DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
- (unsigned int) size / 1024);
+ DPRINTK ("sisfb: Can't allocate %dk size on offscreen\n",
+ (unsigned int) size / 1024);


X return (NULL);
X }
X

- if (size == pohThis->ulSize) {
+ if (size == pohThis->size) {
X pohRoot = pohThis;
- delete_node(pohThis);
+ sisfb_delete_node (pohThis);
X } else {
- pohRoot = poh_new_node();
+ pohRoot = sisfb_poh_new_node ();
X
X if (pohRoot == NULL) {


X return (NULL);
X }
X

- pohRoot->ulOffset = pohThis->ulOffset;
- pohRoot->ulSize = size;
+ pohRoot->offset = pohThis->offset;
+ pohRoot->size = size;
X
- pohThis->ulOffset += size;
- pohThis->ulSize -= size;
+ pohThis->offset += size;
+ pohThis->size -= size;
X }
X
- heap.ulMaxFreeSize -= size;
+ sisfb_heap.max_freesize -= size;
X
- pohThis = &heap.ohUsed;
- insert_node(pohThis, pohRoot);
+ pohThis = &sisfb_heap.oh_used;
+ sisfb_insert_node (pohThis, pohRoot);
X
X return (pohRoot);
X }
X
-/*
- * To remove a node from a list.
- */
-
-static void delete_node(struct OH *poh)


+static void sisfb_delete_node (SIS_OH * poh)

X {
- struct OH *pohPrev;
- struct OH *pohNext;
+ SIS_OH *poh_prev;
+ SIS_OH *poh_next;
X
+ poh_prev = poh->poh_prev;
+ poh_next = poh->poh_next;
X
- pohPrev = poh->pohPrev;
- pohNext = poh->pohNext;
-
- pohPrev->pohNext = pohNext;
- pohNext->pohPrev = pohPrev;
+ poh_prev->poh_next = poh_next;
+ poh_next->poh_prev = poh_prev;
X
X return;
X }
X
-/*
- * To insert a node into a list.
- */
-
-static void insert_node(struct OH *pohList, struct OH *poh)


+static void sisfb_insert_node (SIS_OH * pohList, SIS_OH * poh)

X {
- struct OH *pohTemp;
+ SIS_OH *pohTemp;
X
- pohTemp = pohList->pohNext;
+ pohTemp = pohList->poh_next;
X
- pohList->pohNext = poh;
- pohTemp->pohPrev = poh;
+ pohList->poh_next = poh;
+ pohTemp->poh_prev = poh;
X
- poh->pohPrev = pohList;
- poh->pohNext = pohTemp;
+ poh->poh_prev = pohList;
+ poh->poh_next = pohTemp;
X }
X
-/*
- * Frees an off-screen heap allocation.
- */
-
-static struct OH *poh_free(unsigned long base)


+static SIS_OH *sisfb_poh_free (unsigned long base)

X {
X
- struct OH *pohThis;
- struct OH *pohFreed;
- struct OH *pohPrev;
- struct OH *pohNext;
+ SIS_OH *pohThis;
+ SIS_OH *poh_freed;
+ SIS_OH *poh_prev;
+ SIS_OH *poh_next;
X unsigned long ulUpper;
X unsigned long ulLower;
X int foundNode = 0;
X
- pohFreed = heap.ohUsed.pohNext;
+ poh_freed = sisfb_heap.oh_used.poh_next;
X
- while (pohFreed != &heap.ohUsed) {
- if (pohFreed->ulOffset == base) {
+ while (poh_freed != &sisfb_heap.oh_used) {
+ if (poh_freed->offset == base) {
X foundNode = 1;
X break;
X }
X
- pohFreed = pohFreed->pohNext;
+ poh_freed = poh_freed->poh_next;
X }
X
X if (!foundNode)
X return (NULL);
X
- heap.ulMaxFreeSize += pohFreed->ulSize;
+ sisfb_heap.max_freesize += poh_freed->size;
X
- pohPrev = pohNext = NULL;
- ulUpper = pohFreed->ulOffset + pohFreed->ulSize;
- ulLower = pohFreed->ulOffset;
+ poh_prev = poh_next = NULL;
+ ulUpper = poh_freed->offset + poh_freed->size;
+ ulLower = poh_freed->offset;
X
- pohThis = heap.ohFree.pohNext;
+ pohThis = sisfb_heap.oh_free.poh_next;
X
- while (pohThis != &heap.ohFree) {
- if (pohThis->ulOffset == ulUpper) {
- pohNext = pohThis;
+ while (pohThis != &sisfb_heap.oh_free) {
+ if (pohThis->offset == ulUpper) {
+ poh_next = pohThis;
+ } else if ((pohThis->offset + pohThis->size) == ulLower) {
+ poh_prev = pohThis;
X }
- else if ((pohThis->ulOffset + pohThis->ulSize) ==
- ulLower) {
- pohPrev = pohThis;
- }
- pohThis = pohThis->pohNext;
+ pohThis = pohThis->poh_next;
X }
X
- delete_node(pohFreed);
+ sisfb_delete_node (poh_freed);
X
- if (pohPrev && pohNext) {
- pohPrev->ulSize += (pohFreed->ulSize + pohNext->ulSize);
- delete_node(pohNext);
- free_node(pohFreed);
- free_node(pohNext);
- return (pohPrev);
+ if (poh_prev && poh_next) {
+ poh_prev->size += (poh_freed->size + poh_next->size);
+ sisfb_delete_node (poh_next);
+ sisfb_free_node (poh_freed);
+ sisfb_free_node (poh_next);
+ return (poh_prev);
X }
X
- if (pohPrev) {
- pohPrev->ulSize += pohFreed->ulSize;
- free_node(pohFreed);
- return (pohPrev);
+ if (poh_prev) {
+ poh_prev->size += poh_freed->size;
+ sisfb_free_node (poh_freed);
+ return (poh_prev);
X }
X
- if (pohNext) {
- pohNext->ulSize += pohFreed->ulSize;
- pohNext->ulOffset = pohFreed->ulOffset;
- free_node(pohFreed);
- return (pohNext);
+ if (poh_next) {
+ poh_next->size += poh_freed->size;
+ poh_next->offset = poh_freed->offset;
+ sisfb_free_node (poh_freed);
+ return (poh_next);
X }
X
- insert_node(&heap.ohFree, pohFreed);
+ sisfb_insert_node (&sisfb_heap.oh_free, poh_freed);
X
- return (pohFreed);
+ return (poh_freed);
X }
X
-/*
- * Frees our basic data structure allocation unit by adding it to a free
- * list.
- */
-
-static void free_node(struct OH *poh)


+static void sisfb_free_node (SIS_OH * poh)

X {
X if (poh == NULL) {
X return;
X }
X
- poh->pohNext = heap.pohFreeList;
- heap.pohFreeList = poh;
+ poh->poh_next = sisfb_heap.poh_freelist;
+ sisfb_heap.poh_freelist = poh;
X
X return;
X }
X
-void sis_malloc(struct sis_memreq *req)


+void sis_malloc (struct sis_memreq *req)

X {
- struct OH *poh;
+ SIS_OH *poh;
X
- poh = poh_allocate(req->size);
+ poh = sisfb_poh_allocate (req->size);
X
X if (poh == NULL) {
X req->offset = 0;
X req->size = 0;
- DPRINTK("sisfb: VMEM Allocation Failed\n");
+ DPRINTK ("sisfb: VMEM Allocation Failed\n");
X } else {
- DPRINTK("sisfb: VMEM Allocation Successed : 0x%p\n",
- (char *) (poh->ulOffset +
- (unsigned long) ivideo.video_vbase));
+ DPRINTK ("sisfb: VMEM Allocation Successed : 0x%p\n",
+ (char *) (poh->offset +
+ (unsigned long) ivideo.video_vbase));
X
- req->offset = poh->ulOffset;
- req->size = poh->ulSize;
+ req->offset = poh->offset;
+ req->size = poh->size;
X }
X
X }
X
-void sis_free(unsigned long base)


+void sis_free (unsigned long base)

X {
- struct OH *poh;
+ SIS_OH *poh;
X
- poh = poh_free(base);
+ poh = sisfb_poh_free (base);
X
X if (poh == NULL) {
- DPRINTK("sisfb: poh_free() failed at base 0x%x\n",
- (unsigned int) base);
+ DPRINTK ("sisfb: sisfb_poh_free() failed at base 0x%x\n",
+ (unsigned int) base);
X }
X }
X
-void sis_dispinfo(struct ap_data *rec)
+/* ------------------ SetMode Routines ------------------------------- */


+
+static void sisfb_pre_setmode (void)

X {
- rec->minfo.bpp = ivideo.video_bpp;
- rec->minfo.xres = ivideo.video_width;
- rec->minfo.yres = ivideo.video_height;
- rec->minfo.v_xres = ivideo.video_vwidth;
- rec->minfo.v_yres = ivideo.video_vheight;
- rec->minfo.org_x = ivideo.org_x;
- rec->minfo.org_y = ivideo.org_y;
- rec->minfo.vrate = ivideo.refresh_rate;
- rec->iobase = ivideo.vga_base - 0x30;
- rec->mem_size = ivideo.video_size;
- rec->disp_state = ivideo.disp_state;
- switch(HwExt.jChipID)
- {
- case SIS_Glamour:
- rec->chip = SiS_300;
- break;
- case SIS_Trojan:
- if((HwExt.revision_id & 0xf0) == 0x30)
- rec->chip = SiS_630S;
- else
- rec->chip = SiS_630;
- break;
- case SIS_Spartan:
- rec->chip = SiS_540;
- break;
- case SIS_730:
- rec->chip = SiS_730;
+ u8 cr30 = 0, cr31 = 0;
+
+ vgawb (CRTC_ADR, 0x31);
+ cr31 = vgarb (CRTC_DATA) & ~0x60;
+


+ switch (ivideo.disp_state & DISPTYPE_DISP2) {

+ case DISPTYPE_CRT2:
+ cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+ cr31 |= SIS_DRIVER_MODE;
+ break;
+ case DISPTYPE_LCD:
+ cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
+ cr31 |= SIS_DRIVER_MODE;
+ break;
+ case DISPTYPE_TV:
+ if (ivideo.TV_type == TVMODE_HIVISION)
+ cr30 =
+ (SIS_VB_OUTPUT_HIVISION |
+ SIS_SIMULTANEOUS_VIEW_ENABLE);
+ else if (ivideo.TV_plug == TVPLUG_SVIDEO)
+ cr30 =
+ (SIS_VB_OUTPUT_SVIDEO |
+ SIS_SIMULTANEOUS_VIEW_ENABLE);
+ else if (ivideo.TV_plug == TVPLUG_COMPOSITE)
+ cr30 =
+ (SIS_VB_OUTPUT_COMPOSITE |
+ SIS_SIMULTANEOUS_VIEW_ENABLE);
+ else if (ivideo.TV_plug == TVPLUG_SCART)
+ cr30 =
+ (SIS_VB_OUTPUT_SCART |
+ SIS_SIMULTANEOUS_VIEW_ENABLE);
+ cr31 |= SIS_DRIVER_MODE;
+
+ /*karl */
+ if (sisfb_tvmode == 1)
+ cr31 |= 0x1;
+ if (sisfb_tvmode == 2)
+ cr31 &= ~0x1;
+
X break;
X default:
- rec->chip = SiS_UNKNOWN;
- break;
+ cr30 = 0x00;
+ cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
X }
-}
-
-
-/* ---------------------- SetMode Routines -------------------------- */
X
-void SetReg1(u16 port, u16 index, u16 data)
-{
- outb((u8) (index & 0xff), port);
- port++;
- outb((u8) (data & 0xff), port);
+ vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR30);
+ vgawb (CRTC_DATA, cr30);
+ vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR31);
+ vgawb (CRTC_DATA, cr31);
+ vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR33);
+ vgawb (CRTC_DATA, sisfb_rate_idx & 0x0F);
X }
X
-void SetReg3(u16 port, u16 data)
+static void sisfb_post_setmode (void)
X {
- outb((u8) (data & 0xff), port);
-}
+ u8 reg;
X
-void SetReg4(u16 port, unsigned long data)
-{
- outl((u32) (data & 0xffffffff), port);
-}
+ vgawb (CRTC_ADR, 0x17);


+ reg = vgarb (CRTC_DATA);

X
-u8 GetReg1(u16 port, u16 index)
-{
- u8 data;
+ if ((ivideo.hasVB == HASVB_LVDS)
+ || (ivideo.hasVB == HASVB_LVDS_CHRONTEL)) if (ivideo.video_bpp == 8)
+ sisfb_crt1off = 0;
X
- outb((u8) (index & 0xff), port);
- port += 1;
- data = inb(port);
- return (data);
-}
+ if (sisfb_crt1off)
+ reg &= ~0x80;
+ else
+ reg |= 0x80;
+ vgawb (CRTC_DATA, reg);
X
-u8 GetReg2(u16 port)
-{
- u8 data;
+ vgawb (SEQ_ADR, IND_SIS_RAMDAC_CONTROL);
+ reg = vgarb (SEQ_DATA);
+ reg &= ~0x04;
+ vgawb (SEQ_DATA, reg);
+
+ if ((ivideo.disp_state & DISPTYPE_TV) && (ivideo.hasVB == HASVB_301)) {


+ /*karl */
+ vgawb (VB_PART4_ADR, 0x01);
+ reg = vgarb (VB_PART4_DATA);
+

+ if ((reg != 0xB1) && (reg != 0xB0)) { /*301B Revision ID */
+ // Eden Chen
+ switch (ivideo.video_width) {
+ case 320:
+ filter_tb =
+ (ivideo.TV_type == TVMODE_NTSC) ? 4 : 12;
+ break;
+ case 640:
+ filter_tb =
+ (ivideo.TV_type == TVMODE_NTSC) ? 5 : 13;
+ break;
+ case 720:
+ filter_tb =
+ (ivideo.TV_type == TVMODE_NTSC) ? 6 : 14;
+ break;
+ case 800:
+ filter_tb =
+ (ivideo.TV_type == TVMODE_NTSC) ? 7 : 15;
+ break;
+ default:
+ filter = -1;
+ break;
+ }


+ // ~Eden Chen
X

- data = inb(port);
+ // Eden Chen
+ //vgawb(VB_PART1_ADR, 0x24);
+ vgawb (VB_PART1_ADR, IND_SIS_CRT2_WRITE_ENABLE);
+ // ~Eden Chen
+ vgawb (VB_PART1_DATA, 0x1);
+
+ // Eden Chen for Debug


+ // ~Eden Chen
+

+ if (ivideo.TV_type == TVMODE_NTSC) {
+ vgawb (VB_PART2_ADR, 0x3A);
+ reg = vgarb (VB_PART2_DATA);
+ reg &= 0x1F;
+ vgawb (VB_PART2_DATA, reg);
+
+ if (ivideo.TV_plug == TVPLUG_SVIDEO) {
+ vgawb (VB_PART2_ADR, 0x30);
+ reg = vgarb (VB_PART2_DATA);
+ reg &= 0xDF;
+ vgawb (VB_PART2_DATA, reg);
+ } else if (ivideo.TV_plug == TVPLUG_COMPOSITE) {
+ vgawb (VB_PART2_ADR, 0x30);
+ reg = vgarb (VB_PART2_DATA);
+ reg |= 0x20;
+ vgawb (VB_PART2_DATA, reg);
+
+ switch (ivideo.video_width) {
+ case 640:
+ vgawb (VB_PART2_ADR, 0x35);
+ vgawb (VB_PART2_DATA, 0xEB);
+ vgawb (VB_PART2_ADR, 0x36);
+ vgawb (VB_PART2_DATA, 0x04);
+ vgawb (VB_PART2_ADR, 0x37);
+ vgawb (VB_PART2_DATA, 0x25);
+ vgawb (VB_PART2_ADR, 0x38);
+ vgawb (VB_PART2_DATA, 0x18);
+ break;
+ case 720:
+ vgawb (VB_PART2_ADR, 0x35);
+ vgawb (VB_PART2_DATA, 0xEE);
+ vgawb (VB_PART2_ADR, 0x36);
+ vgawb (VB_PART2_DATA, 0x0C);
+ vgawb (VB_PART2_ADR, 0x37);
+ vgawb (VB_PART2_DATA, 0x22);
+ vgawb (VB_PART2_ADR, 0x38);
+ vgawb (VB_PART2_DATA, 0x08);
+ break;
+ case 800:
+ vgawb (VB_PART2_ADR, 0x35);
+ vgawb (VB_PART2_DATA, 0xEB);
+ vgawb (VB_PART2_ADR, 0x36);
+ vgawb (VB_PART2_DATA, 0x15);
+ vgawb (VB_PART2_ADR, 0x37);
+ vgawb (VB_PART2_DATA, 0x25);
+ vgawb (VB_PART2_ADR, 0x38);
+ vgawb (VB_PART2_DATA, 0xF6);
+ break;
+ }
+ }
+ } else if (ivideo.TV_type == TVMODE_PAL) {
+ vgawb (VB_PART2_ADR, 0x3A);
+ reg = vgarb (VB_PART2_DATA);
+ reg &= 0x1F;
+ vgawb (VB_PART2_DATA, reg);
+
+ if (ivideo.TV_plug == TVPLUG_SVIDEO) {
+ vgawb (VB_PART2_ADR, 0x30);
+ reg = vgarb (VB_PART2_DATA);
+ reg &= 0xDF;
+ vgawb (VB_PART2_DATA, reg);
+ } else if (ivideo.TV_plug == TVPLUG_COMPOSITE) {
+ vgawb (VB_PART2_ADR, 0x30);
+ reg = vgarb (VB_PART2_DATA);
+ reg |= 0x20;
+ vgawb (VB_PART2_DATA, reg);
+
+ switch (ivideo.video_width) {
+ case 640:
+ vgawb (VB_PART2_ADR, 0x35);
+ vgawb (VB_PART2_DATA, 0xF1);
+ vgawb (VB_PART2_ADR, 0x36);
+ vgawb (VB_PART2_DATA, 0xF7);
+ vgawb (VB_PART2_ADR, 0x37);
+ vgawb (VB_PART2_DATA, 0x1F);
+ vgawb (VB_PART2_ADR, 0x38);
+ vgawb (VB_PART2_DATA, 0x32);
+ break;
+ case 720:
+ vgawb (VB_PART2_ADR, 0x35);
+ vgawb (VB_PART2_DATA, 0xF3);
+ vgawb (VB_PART2_ADR, 0x36);
+ vgawb (VB_PART2_DATA, 0x00);
+ vgawb (VB_PART2_ADR, 0x37);
+ vgawb (VB_PART2_DATA, 0x1D);
+ vgawb (VB_PART2_ADR, 0x38);
+ vgawb (VB_PART2_DATA, 0x20);
+ break;
+ case 800:
+ vgawb (VB_PART2_ADR, 0x35);
+ vgawb (VB_PART2_DATA, 0xFC);
+ vgawb (VB_PART2_ADR, 0x36);
+ vgawb (VB_PART2_DATA, 0xFB);
+ vgawb (VB_PART2_ADR, 0x37);
+ vgawb (VB_PART2_DATA, 0x14);
+ vgawb (VB_PART2_ADR, 0x38);
+ vgawb (VB_PART2_DATA, 0x2A);


+ break;
+ }
+ }
+ }

+ // Eden
+ if ((filter >= 0) && (filter <= 7)) {
+ DPRINTK
+ ("FilterTable[%d]-%d: %02x %02x %02x %02x\n",
+ filter_tb, filter,
+ sis_TV_filter[filter_tb].filter[filter][0],
+ sis_TV_filter[filter_tb].filter[filter][1],
+ sis_TV_filter[filter_tb].filter[filter][2],
+ sis_TV_filter[filter_tb].filter[filter][3]
+ );
+ vgawb (VB_PART2_ADR, 0x35);
+ vgawb (VB_PART2_DATA,
+ sis_TV_filter[filter_tb].
+ filter[filter][0]);
+ vgawb (VB_PART2_ADR, 0x36);
+ vgawb (VB_PART2_DATA,
+ sis_TV_filter[filter_tb].
+ filter[filter][1]);
+ vgawb (VB_PART2_ADR, 0x37);
+ vgawb (VB_PART2_DATA,
+ sis_TV_filter[filter_tb].
+ filter[filter][2]);
+ vgawb (VB_PART2_ADR, 0x38);
+ vgawb (VB_PART2_DATA,
+ sis_TV_filter[filter_tb].
+ filter[filter][3]);
+ }
+ // ~Eden
+ }
+ }
X
- return (data);
X }
X
-u32 GetReg3(u16 port)


+static void sisfb_crtc_to_var (struct fb_var_screeninfo *var)

X {
- u32 data;
-
- data = inl(port);
- return (data);
-}
+ u16 VRE, VBE, VRS, VBS, VDE, VT;
+ u16 HRE, HBE, HRS, HBS, HDE, HT;
+ u8 sr_data, cr_data, cr_data2, cr_data3, mr_data;
+ int A, B, C, D, E, F, temp;
+ double hrate, drate;
X
-void ClearDAC(u16 port)
-{
- int i,j;
+ vgawb (SEQ_ADR, IND_SIS_COLOR_MODE);
+ sr_data = vgarb (SEQ_DATA);
X
- vgawb(DAC_ADR, 0x00);
- for(i=0; i<256; i++)
- for(j=0; j<3; j++)
- vgawb(DAC_DATA, 0);
-}
+ if (sr_data & SIS_INTERLACED_MODE)
+ var->vmode = FB_VMODE_INTERLACED;
+ else
+ var->vmode = FB_VMODE_NONINTERLACED;
X
-void ClearBuffer(PHW_DEVICE_EXTENSION pHwExt)
-{
- memset((char *) ivideo.video_vbase, 0,
- video_linelength * ivideo.video_height);
-}
+ switch ((sr_data & 0x1C) >> 2) {
+ case SIS_8BPP_COLOR_MODE:
+ var->bits_per_pixel = 8;
+ break;
+ case SIS_16BPP_COLOR_MODE:
+ var->bits_per_pixel = 16;
+ break;
+ case SIS_32BPP_COLOR_MODE:
+ var->bits_per_pixel = 32;
+ break;
+ }
X
-static void pre_setmode(void)
-{
- unsigned char uCR30=0, uCR31=0;
+ switch (var->bits_per_pixel) {
+ case 8:
+ var->red.length = 6;
+ var->green.length = 6;
+ var->blue.length = 6;
+ video_cmap_len = 256;


+ break;
+ case 16:

+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ video_cmap_len = 16;
X

- switch(uDispType & MASK_DISPTYPE_DISP2)
- {

- case MASK_DISPTYPE_CRT2:
- uCR30 = 0x41;
- uCR31 = 0x40;
- break;
- case MASK_DISPTYPE_LCD:
- uCR30 = 0x21;
- uCR31 = 0x40;
- break;
- case MASK_DISPTYPE_TV:
- if(ivideo.TV_type == TVMODE_HIVISION)
- uCR30 = 0x81;
- else if(ivideo.TV_plug == TVPLUG_SVIDEO)
- uCR30 = 0x09;
- else if(ivideo.TV_plug == TVPLUG_COMPOSITE)
- uCR30 = 0x05;
- else if(ivideo.TV_plug == TVPLUG_SCART)
- uCR30 = 0x11;
- uCR31 = 0x40; /* CR31[0] will be set in setmode() */
X break;
- default:
- uCR30 = 0x00;
- uCR31 = 0x60;
+ case 24:
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ video_cmap_len = 16;


+ break;
+ case 32:

+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ video_cmap_len = 16;
+ break;
X }
X
- vgawb(CRTC_ADR, 0x30);
- vgawb(CRTC_DATA, uCR30);
- vgawb(CRTC_ADR, 0x31);
- vgawb(CRTC_DATA, uCR31);
- vgawb(CRTC_ADR, 0x33);
- vgawb(CRTC_DATA, rate_idx & 0x0f);
-}
+ vgawb (SEQ_ADR, 0xA);
+ sr_data = vgarb (SEQ_DATA);
X
-static void post_setmode(void)
-{
- u8 uTemp;
+ vgawb (CRTC_ADR, 0x6);
+ cr_data = vgarb (CRTC_DATA);
+ vgawb (CRTC_ADR, 0x7);
+ cr_data2 = vgarb (CRTC_DATA);
+ VT =
+ (cr_data & 0xFF) | ((u16) (cr_data2 & 0x01) << 8) |
+ ((u16) (cr_data2 & 0x20) << 4) | ((u16) (sr_data & 0x01) << 10);
+ A = VT + 2;
X
- vgawb(CRTC_ADR, 0x17);
- uTemp = vgarb(CRTC_DATA);
+ vgawb (CRTC_ADR, 0x12);
+ cr_data = vgarb (CRTC_DATA);
+ VDE =
+ (cr_data & 0xff) | ((u16) (cr_data2 & 0x02) << 7) |
+ ((u16) (cr_data2 & 0x40) << 3) | ((u16) (sr_data & 0x02) << 9);
+ E = VDE + 1;
X
- if(crt1off) /* turn off CRT1 */
- uTemp &= ~0x80;
- else /* turn on CRT1 */
- uTemp |= 0x80;
- vgawb(CRTC_DATA, uTemp);
+ vgawb (CRTC_ADR, 0x10);
+ cr_data = vgarb (CRTC_DATA);
+ VRS =
+ (cr_data & 0xff) | ((u16) (cr_data2 & 0x04) << 6) |
+ ((u16) (cr_data2 & 0x80) << 2) | ((u16) (sr_data & 0x08) << 7);
+ F = VRS + 1 - E;
X
- /* disable 24-bit palette RAM and Gamma correction */
- vgawb(SEQ_ADR, 0x07);
- uTemp = vgarb(SEQ_DATA);
- uTemp &= ~0x04;
- vgawb(SEQ_DATA, uTemp);
-}
+ vgawb (CRTC_ADR, 0x15);
+ cr_data = vgarb (CRTC_DATA);
+ vgawb (CRTC_ADR, 0x9);
+ cr_data3 = vgarb (CRTC_DATA);
+ VBS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x08) << 5) |
+ ((u16) (cr_data3 & 0x20) << 4) | ((u16) (sr_data & 0x04) << 8);
+
+ vgawb (CRTC_ADR, 0x16);
+ cr_data = vgarb (CRTC_DATA);
+ VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4);
+ temp = VBE - ((E - 1) & 511);
+ B = (temp > 0) ? temp : (temp + 512);
X
-static void search_mode(const char *name)
-{
- int i = 0;
+ vgawb (CRTC_ADR, 0x11);
+ cr_data = vgarb (CRTC_DATA);
+ VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
+ temp = VRE - ((E + F - 1) & 31);
+ C = (temp > 0) ? temp : (temp + 32);
X
- if (name == NULL)
- return;
+ D = B - F - C;
X
- while (sisbios_mode[i].mode_no != 0) {
- if (!strcmp(name, sisbios_mode[i].name)) {
- mode_idx = i;
- break;
- }
- i++;
- }
+ var->yres = var->yres_virtual = E;
+ var->upper_margin = D;
+ var->lower_margin = F;
+ var->vsync_len = C;


X
- if (mode_idx < 0)

- DPRINTK("Invalid user mode : %s\n", name);
-}
+ vgawb (SEQ_ADR, 0xb);
+ sr_data = vgarb (SEQ_DATA);
X
-static u8 search_refresh_rate(unsigned int rate)
-{
- u16 xres, yres;
- int i = 0;
+ vgawb (CRTC_ADR, 0x0);
+ cr_data = vgarb (CRTC_DATA);
+ HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);
+ A = HT + 5;
X
- xres = sisbios_mode[mode_idx].xres;
- yres = sisbios_mode[mode_idx].yres;
+ vgawb (CRTC_ADR, 0x1);
+ cr_data = vgarb (CRTC_DATA);
+ HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6);
+ E = HDE + 1;
X
- while ((vrate[i].idx != 0) && (vrate[i].xres <= xres)) {
- if ((vrate[i].xres == xres) && (vrate[i].yres == yres)
- && (vrate[i].refresh == rate)) {
- rate_idx = vrate[i].idx;
- return rate_idx;
- }
- i++;
- }
+ vgawb (CRTC_ADR, 0x4);
+ cr_data = vgarb (CRTC_DATA);
+ HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2);
+ F = HRS - E - 3;
X
- DPRINTK("sisfb: Unsupported rate %d in %dx%d mode\n", rate, xres,
- yres);
+ vgawb (CRTC_ADR, 0x2);
+ cr_data = vgarb (CRTC_DATA);
+ HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);
+
+ vgawb (SEQ_ADR, 0xc);
+ sr_data = vgarb (SEQ_DATA);
+ vgawb (CRTC_ADR, 0x3);
+ cr_data = vgarb (CRTC_DATA);
+ vgawb (CRTC_ADR, 0x5);
+ cr_data2 = vgarb (CRTC_DATA);
+ HBE =
+ (cr_data & 0x1f) | ((u16) (cr_data2 & 0x80) >> 2) |
+ ((u16) (sr_data & 0x03) << 6);
+ HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
X
- return 0;
-}
+ temp = HBE - ((E - 1) & 255);
+ B = (temp > 0) ? temp : (temp + 256);
X
-/* ------------------ Public Routines ------------------------------- */
+ temp = HRE - ((E + F + 3) & 63);
+ C = (temp > 0) ? temp : (temp + 64);
X
-/*
- * Get the Fixed Part of the Display
- */
+ D = B - F - C;
X
-static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
- struct fb_info *info)
-{
- DPRINTK("sisfb: sisfb_get_fix:[%d]\n", con);
+ var->xres = var->xres_virtual = E * 8;
+ var->left_margin = D * 8;
+ var->right_margin = F * 8;
+ var->hsync_len = C * 8;
X
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strcpy(fix->id, fb_info.modename);
+ var->activate = FB_ACTIVATE_NOW;
X
- fix->smem_start = ivideo.video_base;
- if(ivideo.video_size > 0x800000)
- fix->smem_len = RESERVED_MEM_SIZE_8M; /* reserved for Xserver */
+ var->sync = 0;
+
+ mr_data = vgarb (0x1C);
+ if (mr_data & 0x80)
+ var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
+ else
+ var->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+ if (mr_data & 0x40)
+ var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
X else
- fix->smem_len = RESERVED_MEM_SIZE_4M; /* reserved for Xserver */
+ var->sync |= FB_SYNC_HOR_HIGH_ACT;
+
+ VT += 2;
+ VT <<= 1;
+ HT = (HT + 5) * 8;
+
+ hrate = (double) ivideo.refresh_rate * (double) VT / 2;
+ drate = hrate * HT;
+ var->pixclock = (u32) (1E12 / drate);
+}
+
+/* ------------------ Public Routines -------------------------------- */
+
+static int sisfb_get_fix (struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+ memset (fix, 0, sizeof (struct fb_fix_screeninfo));
+ strcpy (fix->id, fb_info.modename);
+
+ fix->smem_start = ivideo.video_base;
+
+ /*karl:10/01/2001 */
+ if (!sisfb_mem) {
+ if (ivideo.video_size > 0x800000)
+ fix->smem_len = 0x800000;
+ else
+ fix->smem_len = 0x400000;
+ } else
+ fix->smem_len = sisfb_mem * 0x100000;
X
X fix->type = video_type;
X fix->type_aux = 0;
@@ -1502,135 +2007,110 @@
X fix->ywrapstep = 0;
X fix->line_length = video_linelength;
X fix->mmio_start = ivideo.mmio_base;
- fix->mmio_len = MMIO_SIZE;
+ fix->mmio_len = sisfb_mmio_size;
X fix->accel = FB_ACCEL_SIS_GLAMOUR;
X fix->reserved[0] = ivideo.video_size & 0xFFFF;
X fix->reserved[1] = (ivideo.video_size >> 16) & 0xFFFF;
- fix->reserved[2] = caps; /* capabilities */
+ fix->reserved[2] = sisfb_caps;
X
X return 0;
-}
-
-/*
- * Get the User Defined Part of the Display
- */
X
-static int sisfb_get_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
-{
- DPRINTK("sisfb: sisfb_get_var:[%d]\n", con);
+}
X
+static int sisfb_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
X if (con == -1)
- memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
+ memcpy (var, &default_var, sizeof (struct fb_var_screeninfo));
X else
X *var = fb_display[con].var;
+


X return 0;
X }
X

-/*
- * Set the User Defined Part of the Display
- */
-
-static int sisfb_set_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
+static int sisfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
X {
X int err;
X unsigned int cols, rows;
X
X fb_display[con].var.activate = FB_ACTIVATE_NOW;
X
- /* Set mode */
- if (do_set_var(var, con == currcon, info)) {
- crtc_to_var(var); /* return current mode to user */
+ if (sisfb_do_set_var (var, con == currcon, info)) {
+ sisfb_crtc_to_var (var);


X return -EINVAL;
X }
X

- /* get actual setting value */
- crtc_to_var(var);
+ sisfb_crtc_to_var (var);
X
- /* update display of current console */
- sisfb_set_disp(con, var);
+ sisfb_set_disp (con, var);
X
X if (info->changevar)
X (*info->changevar) (con);
X
- if ((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0)))
+ if ((err = fb_alloc_cmap (&fb_display[con].cmap, 0, 0)))
X return err;
X
- do_install_cmap(con, info);
+ sisfb_do_install_cmap (con, info);
X
- /* inform console to update struct display */
- cols = sisbios_mode[mode_idx].cols;
- rows = sisbios_mode[mode_idx].rows;
- vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
+ cols = sisbios_mode[sisfb_mode_idx].cols;
+ rows = sisbios_mode[sisfb_mode_idx].rows;
+ vc_resize_con (rows, cols, fb_display[con].conp->vc_num);
X
X return 0;
-}
X
+}
X
-/*
- * Get the Colormap
- */
-
-static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info)
+static int sisfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
X {
- DPRINTK("sisfb: sisfb_get_cmap:[%d]\n", con);
-
X if (con == currcon)
- return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
- else if (fb_display[con].cmap.len) /* non default colormap? */
- fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+ return fb_get_cmap (cmap, kspc, sis_getcolreg, info);
+ else if (fb_display[con].cmap.len)
+ fb_copy_cmap (&fb_display[con].cmap, cmap, kspc ? 0 : 2);
X else
- fb_copy_cmap(fb_default_cmap(video_cmap_len), cmap, kspc ? 0 : 2);
+ fb_copy_cmap (fb_default_cmap (video_cmap_len), cmap,
+ kspc ? 0 : 2);
+


X return 0;
X }
X

-/*
- * Set the Colormap
- */
-
-static int sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info)
+static int sisfb_set_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
X {
X int err;
X
- if (!fb_display[con].cmap.len) { /* no colormap allocated */
- err = fb_alloc_cmap(&fb_display[con].cmap, video_cmap_len, 0);
+ if (!fb_display[con].cmap.len) {
+ err = fb_alloc_cmap (&fb_display[con].cmap, video_cmap_len, 0);
X if (err)
X return err;
X }
- if (con == currcon) /* current console */
- return fb_set_cmap(cmap, kspc, sis_setcolreg, info);
+ if (con == currcon)
+ return fb_set_cmap (cmap, kspc, sis_setcolreg, info);
X else
- fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+ fb_copy_cmap (cmap, &fb_display[con].cmap, kspc ? 0 : 1);


X return 0;
X }
X

-static int sisfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg, int con,
- struct fb_info *info)


+static int sisfb_ioctl (struct inode *inode, struct file *file,

+ unsigned int cmd, unsigned long arg, int con, struct fb_info *info)
X {
X switch (cmd) {
X case FBIO_ALLOC:
- if(!capable(CAP_SYS_RAWIO))
+ if (!capable (CAP_SYS_RAWIO))
X return -EPERM;
- sis_malloc((struct sis_memreq *) arg);
+ sis_malloc ((struct sis_memreq *) arg);
X break;
X case FBIO_FREE:
- if(!capable(CAP_SYS_RAWIO))
+ if (!capable (CAP_SYS_RAWIO))
X return -EPERM;
- sis_free(*(unsigned long *) arg);
+ sis_free (*(unsigned long *) arg);
X break;
X case FBIOGET_GLYPH:
- sis_get_glyph((struct GlyInfo *) arg);
+ sis_get_glyph ((SIS_GLYINFO *) arg);
X break;
X case FBIOGET_HWCINFO:
X {
X unsigned long *hwc_offset = (unsigned long *) arg;
X
- if (caps & HW_CURSOR_CAP)
- *hwc_offset = hwcursor_vbase -
+ if (sisfb_caps & HW_CURSOR_CAP)
+ *hwc_offset = sisfb_hwcursor_vbase -
X (unsigned long) ivideo.video_vbase;
X else
X *hwc_offset = 0;
@@ -1638,32 +2118,31 @@
X break;
X }
X case FBIOPUT_MODEINFO:
- {
- struct mode_info *x = (struct mode_info *)arg;
+ {
+ struct mode_info *x = (struct mode_info *) arg;
+
+ ivideo.video_bpp = x->bpp;
+ ivideo.video_width = x->xres;
+ ivideo.video_height = x->yres;
+ ivideo.video_vwidth = x->v_xres;
+ ivideo.video_vheight = x->v_yres;
+ ivideo.org_x = x->org_x;
+ ivideo.org_y = x->org_y;
+ ivideo.refresh_rate = x->vrate;
X
- /* Set Mode Parameters by XServer */
- ivideo.video_bpp = x->bpp;
- ivideo.video_width = x->xres;
- ivideo.video_height = x->yres;
- ivideo.video_vwidth = x->v_xres;
- ivideo.video_vheight = x->v_yres;
- ivideo.org_x = x->org_x;
- ivideo.org_y = x->org_y;
- ivideo.refresh_rate = x->vrate;
-
X break;
X }
X case FBIOGET_DISPINFO:
- sis_dispinfo((struct ap_data *)arg);
+ sis_dispinfo ((struct ap_data *) arg);
X break;
X default:
X return -EINVAL;
X }
X return 0;
+
X }
X
-static int sisfb_mmap(struct fb_info *info, struct file *file,
- struct vm_area_struct *vma)
+static int sisfb_mmap (struct fb_info *info, struct file *file, struct vm_area_struct *vma)
X {
X struct fb_var_screeninfo var;
X unsigned long start;
@@ -1674,18 +2153,16 @@
X return -EINVAL;
X off = vma->vm_pgoff << PAGE_SHIFT;
X
- /* frame buffer memory */
X start = (unsigned long) ivideo.video_base;
- len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.video_size);
+ len = PAGE_ALIGN ((start & ~PAGE_MASK) + ivideo.video_size);
X
X if (off >= len) {
- /* memory mapped io */
X off -= len;
- sisfb_get_var(&var, currcon, info);
+ sisfb_get_var (&var, currcon, info);
X if (var.accel_flags)
X return -EINVAL;
X start = (unsigned long) ivideo.mmio_base;
- len = PAGE_ALIGN((start & ~PAGE_MASK) + MMIO_SIZE);
+ len = PAGE_ALIGN ((start & ~PAGE_MASK) + sisfb_mmio_size);
X }
X
X start &= PAGE_MASK;
@@ -1694,617 +2171,599 @@
X off += start;
X vma->vm_pgoff = off >> PAGE_SHIFT;
X
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__)
X if (boot_cpu_data.x86 > 3)
- pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+ pgprot_val (vma->vm_page_prot) |= _PAGE_PCD;
X #endif
- if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
+ if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start, vma->vm_page_prot))
X return -EAGAIN;
X return 0;
+
X }
X
X static struct fb_ops sisfb_ops = {
- owner: THIS_MODULE,
- fb_get_fix: sisfb_get_fix,
- fb_get_var: sisfb_get_var,
- fb_set_var: sisfb_set_var,
- fb_get_cmap: sisfb_get_cmap,
- fb_set_cmap: sisfb_set_cmap,
- fb_ioctl: sisfb_ioctl,
- fb_mmap: sisfb_mmap,
+ owner:THIS_MODULE,
+ fb_get_fix:sisfb_get_fix,
+ fb_get_var:sisfb_get_var,
+ fb_set_var:sisfb_set_var,
+ fb_get_cmap:sisfb_get_cmap,
+ fb_set_cmap:sisfb_set_cmap,
+ fb_ioctl:sisfb_ioctl,
+ fb_mmap:sisfb_mmap,
X };
X
-int sisfb_setup(char *options)
-{
- char *this_opt;
-
- fb_info.fontname[0] = '\0';
- ivideo.refresh_rate = 0;
-
- if (!options || !*options)
- return 0;
-


- while (this_opt = strsep(&options, ",")) {

- if (!*this_opt)
- continue;
-
- if (!strcmp(this_opt, "inverse")) {
- inverse = 1;
- fb_invert_cmaps();
- } else if (!strncmp(this_opt, "font:", 5)) {
- strcpy(fb_info.fontname, this_opt + 5);
- } else if (!strncmp(this_opt, "mode:", 5)) {
- search_mode(this_opt + 5);
- } else if (!strncmp(this_opt, "vrate:", 6)) {
- ivideo.refresh_rate =
- simple_strtoul(this_opt + 6, NULL, 0);
- } else if (!strncmp(this_opt, "off", 3)) {
- sisfb_off = 1;
- } else if (!strncmp(this_opt, "crt1off", 7)) {
- crt1off = 1;
- } else
- DPRINTK("invalid parameter %s\n", this_opt);


- }
- return 0;
-}

+/* ------------ Interface to the low level console driver -------------*/
X
-static int sisfb_update_var(int con, struct fb_info *info)


+static int sisfb_update_var (int con, struct fb_info *info)

X {
X return 0;
X }
X

-/*
- * Switch Console (called by fbcon.c)
- */
-
-static int sisfb_switch(int con, struct fb_info *info)


+static int sisfb_switch (int con, struct fb_info *info)

X {
X int cols, rows;
X
- DPRINTK("sisfb: switch console from [%d] to [%d]\n", currcon, con);
-
- /* update colormap of current console */
X if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap, 1, sis_getcolreg, info);
+ fb_get_cmap (&fb_display[currcon].cmap, 1, sis_getcolreg, info);
X
X fb_display[con].var.activate = FB_ACTIVATE_NOW;
X
- /* same mode, needn't change mode actually */
-
- if (!memcmp(&fb_display[con].var, &fb_display[currcon].var, sizeof(struct fb_var_screeninfo)))
- {
+ if (!memcmp(&fb_display[con].var, &fb_display[currcon].var, sizeof (struct fb_var_screeninfo))) {
X currcon = con;


X return 1;
X }
X

X currcon = con;
X
- do_set_var(&fb_display[con].var, 1, info);
+ sisfb_do_set_var (&fb_display[con].var, 1, info);
X
- sisfb_set_disp(con, &fb_display[con].var);
+ sisfb_set_disp (con, &fb_display[con].var);
X
- /* Install new colormap */
- do_install_cmap(con, info);
+ sisfb_do_install_cmap (con, info);
X
- cols = sisbios_mode[mode_idx].cols;
- rows = sisbios_mode[mode_idx].rows;
- vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
+ cols = sisbios_mode[sisfb_mode_idx].cols;
+ rows = sisbios_mode[sisfb_mode_idx].rows;
+ vc_resize_con (rows, cols, fb_display[con].conp->vc_num);
X
- sisfb_update_var(con, info);
+ sisfb_update_var (con, info);
X

X return 1;
X
X }
X

-/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
-
-static void sisfb_blank(int blank, struct fb_info *info)


+static void sisfb_blank (int blank, struct fb_info *info)

X {
- u8 CRData;
+ u8 reg;
X
- vgawb(CRTC_ADR, 0x17);
- CRData = vgarb(CRTC_DATA);
+ vgawb (CRTC_ADR, 0x17);


+ reg = vgarb (CRTC_DATA);

X
- if (blank > 0) /* turn off CRT1 */
- CRData &= 0x7f;
- else /* turn on CRT1 */
- CRData |= 0x80;
+ if (blank > 0)
+ reg &= 0x7f;
+ else
+ reg |= 0x80;
X
- vgawb(CRTC_ADR, 0x17);
- vgawb(CRTC_DATA, CRData);
+ vgawb (CRTC_ADR, 0x17);
+ vgawb (CRTC_DATA, reg);
X }
X
-int has_VB(void)
+int sisfb_setup (char *options)
X {
- u8 uSR38, uSR39, uVBChipID;
-
- vgawb(SEQ_ADR, 0x38);
- uSR38 = vgarb(SEQ_DATA);
- vgawb(SEQ_ADR, 0x39);
- uSR39 = vgarb(SEQ_DATA);
- vgawb(IND_SIS_CRT2_PORT_14, 0x0);
- uVBChipID = vgarb(IND_SIS_CRT2_PORT_14+1);
+ char *this_opt;
X
- if (
- ( (HwExt.jChipID == SIS_Glamour) && (uSR38 & 0x20) ) /* 300 */
- ||
- ( (HwExt.jChipID >= SIS_Trojan ) && (uSR38 & 0x20) && (!(uSR39 & 0x80)) ) /* 630/540 */
- ||
- ( (HwExt.jChipID == SIS_Trojan ) && ((HwExt.revision_id & 0xf0) == 0x30) && (uVBChipID == 1) ) /* 630s */
- ||
- ( (HwExt.jChipID == SIS_730) && (uVBChipID == 1) ) /* 730 */
- )
- {
- ivideo.hasVB = HASVB_301;
- return TRUE;
- }
- else
- {
- ivideo.hasVB = HASVB_NONE;
- return FALSE;
- }
-}
+ fb_info.fontname[0] = '\0';
+ ivideo.refresh_rate = 0;
X
-void sis_get301info(void)
-{
- u8 uCRData;
- unsigned long disp_state=0;
+ if (!options || !*options)
+ return 0;


X
- if (HwExt.jChipID >= SIS_Trojan)
- {

- if (!has_VB())
- {
- vgawb(CRTC_ADR, 0x37);
- uCRData = vgarb(CRTC_DATA);
+ for (this_opt = strtok (options, ","); this_opt;
+ this_opt = strtok (NULL, ",")) {


+ if (!*this_opt)
+ continue;
X

- switch((uCRData >> 1) & 0x07)
- {
- case 2:
- ivideo.hasVB = HASVB_LVDS;
- break;
- case 4:
- ivideo.hasVB = HASVB_LVDS_CHRONTEL;
- break;
- case 3:
- ivideo.hasVB = HASVB_TRUMPION;
- break;
- default:
- break;
- }
+ if (!strcmp (this_opt, "inverse")) {
+ sisfb_inverse = 1;
+ fb_invert_cmaps ();
+ } else if (!strncmp (this_opt, "font:", 5)) {
+ strcpy (fb_info.fontname, this_opt + 5);
+ } else if (!strncmp (this_opt, "mode:", 5)) {
+ sisfb_search_mode (this_opt + 5);
+ } else if (!strncmp (this_opt, "vrate:", 6)) {
+ ivideo.refresh_rate =
+ simple_strtoul (this_opt + 6, NULL, 0);
+ } else if (!strncmp (this_opt, "off", 3)) {
+ sisfb_off = 1;
+ } else if (!strncmp (this_opt, "crt1off", 7)) {
+ sisfb_crt1off = 1;
+ } else if (!strncmp (this_opt, "filter:", 7)) {
+ filter = (int) simple_strtoul (this_opt + 7, NULL, 0);
+ }
+ /*karl */
+ else if (!strncmp (this_opt, "tvmode:", 7)) {
+ if (!strncmp (this_opt + 7, "pal", 3))
+ sisfb_tvmode = 1;
+ if (!strncmp (this_opt + 7, "ntsc", 4))
+ sisfb_tvmode = 2;
X }
- }
- else
- {
- has_VB();
- }
+ /*karl:10/01/2001 */
+ else if (!strncmp (this_opt, "mem:", 4)) {
X
- vgawb(CRTC_ADR, 0x32);
- uCRData = vgarb(CRTC_DATA);
-
- switch(uDispType)
- {
- case MASK_DISPTYPE_CRT2:
- disp_state = DISPTYPE_CRT2;
- break;
- case MASK_DISPTYPE_LCD:
- disp_state = DISPTYPE_LCD;
- break;
- case MASK_DISPTYPE_TV:
- disp_state = DISPTYPE_TV;
- break;
- }
+ sisfb_mem = simple_strtoul (this_opt + 4, NULL, 0);
X
- if(disp_state & 0x7)
- {
- if(crt1off)
- disp_state |= DISPMODE_SINGLE;
- else
- disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
+ } else
+ DPRINTK ("invalid parameter %s\n", this_opt);
X }
- else
- disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
-
- ivideo.disp_state = disp_state;
+ return 0;
X }
X
-
-int __init sisfb_init(void)
+int __init sisfb_init (void)
X {
X struct pci_dev *pdev = NULL;
X struct board *b;
X int pdev_valid = 0;
- unsigned char jTemp;
- u8 uSRData, uCRData;
+ //unsigned long rom_vbase;
+ u32 reg32;
+ u16 reg16;
+ u8 reg;
+ int nRes;
X
- outb(0x77, 0x80);
+ outb (0x77, 0x80);
X
X if (sisfb_off)
X return -ENXIO;
X
- pci_for_each_dev(pdev) {
- for (b = dev_list; b->vendor; b++)
- {
+ pci_for_each_dev (pdev)
+ {
+ for (b = sisdev_list; b->vendor; b++) {
X if ((b->vendor == pdev->vendor)
- && (b->device == pdev->device))
- {
+ && (b->device == pdev->device)) {
X pdev_valid = 1;
- strcpy(fb_info.modename, b->name);
+ strcpy (fb_info.modename, b->name);
X ivideo.chip_id = pdev->device;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &HwExt.revision_id);
+ pci_read_config_byte (pdev, PCI_REVISION_ID,
+ &ivideo.revision_id);
+ pci_read_config_word (pdev, PCI_COMMAND, &reg16);
+ // Eden Chen
+ //sishw_ext.uRevisionID = ivideo.revision_id;
+ sishw_ext.jChipRevision = ivideo.revision_id;
+ // ~Eden Chen
+ sisvga_enabled = reg16 & 0x1;


X break;
X }
X }
-

+
X if (pdev_valid)


X break;
X }
-
+

X if (!pdev_valid)
X return -1;
-
- switch(ivideo.chip_id)
- {


+
+ // Eden Chen

+ switch (ivideo.chip_id) {
X case PCI_DEVICE_ID_SI_300:
- HwExt.jChipID = SIS_Glamour;
+ ivideo.chip = SIS_300;
+ sisvga_engine = SIS_300_VGA;
X break;
X case PCI_DEVICE_ID_SI_630_VGA:
- HwExt.jChipID = SIS_Trojan;
+ {
+ sisfb_set_reg4 (0xCF8, 0x80000000);
+ reg32 = sisfb_get_reg3 (0xCFC);
+ if (reg32 == 0x07301039) {
+ ivideo.chip = SIS_730;
+ strcpy (fb_info.modename, "SIS 730");
+ } else
+ ivideo.chip = SIS_630;
+
+ sisvga_engine = SIS_300_VGA;
X break;
+ }
X case PCI_DEVICE_ID_SI_540_VGA:
- HwExt.jChipID = SIS_Spartan;
+ ivideo.chip = SIS_540;
+ sisvga_engine = SIS_300_VGA;
X break;
- case PCI_DEVICE_ID_SI_730_VGA:
- HwExt.jChipID = SIS_730;
+ case PCI_DEVICE_ID_SI_315H:
+ ivideo.chip = SIS_315H;
+ sisvga_engine = SIS_315_VGA;
+ break;
+ case PCI_DEVICE_ID_SI_315:
+ ivideo.chip = SIS_315;
+ sisvga_engine = SIS_315_VGA;
+ break;
+ case PCI_DEVICE_ID_SI_315PRO:
+ ivideo.chip = SIS_315PRO;
+ sisvga_engine = SIS_315_VGA;
+ break;
+ case PCI_DEVICE_ID_SI_550_VGA:
+ ivideo.chip = SIS_550;
+ sisvga_engine = SIS_315_VGA;
X break;
X }
X
- ivideo.video_base = pci_resource_start(pdev, 0);
- ivideo.mmio_base = pci_resource_start(pdev, 1);
- ivideo.vga_base = pci_resource_start(pdev, 2) + 0x30;
-
- HwExt.IOAddress = (unsigned short)ivideo.vga_base;
- rom_base = 0x000C0000;
+ // Eden Chen
+ //sishw_ext.jChipID = ivideo.chip;
+ sishw_ext.jChipType = ivideo.chip;
+ // for Debug
+ if ((sishw_ext.jChipType == SIS_315PRO)
+ || (sishw_ext.jChipType == SIS_315))
+ sishw_ext.jChipType = SIS_315H;


+ // ~Eden Chen
+

+ DPRINTK ("%s is used as %s device(VGA Engine %d).\n",
+ fb_info.modename, sisvga_enabled ? "primary" : "secondary",
+ sisvga_engine);
+
+ ivideo.video_base = pci_resource_start (pdev, 0);
+ ivideo.mmio_base = pci_resource_start (pdev, 1);
+ // Eden Chen
+ //sishw_ext.IOAddress = (unsigned short) ivideo.vga_base
+ // = pci_resource_start(pdev, 2) + 0x30;
+ sishw_ext.ulIOAddress = (unsigned short) ivideo.vga_base = pci_resource_start (pdev, 2) + 0x30;


+ // ~Eden Chen
+

+ sisfb_mmio_size = pci_resource_len (pdev, 1);
+
+ if (!sisvga_enabled)
+ if (pci_enable_device (pdev))
+ return -EIO;
+

+ vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+ vgawb (SEQ_DATA, SIS_PASSWORD);

X
- MMIO_SIZE = pci_resource_len(pdev, 1);
+#ifdef LINUXBIOS
+#ifdef CONFIG_FB_SIS_300


+ if (sisvga_engine == SIS_300_VGA)

+ {
+ vgawb (SEQ_ADR, 0x28);
+ vgawb (SEQ_DATA, 0x37);
X
-#ifdef NOBIOS
- if (pci_enable_device(pdev))
- return -EIO;
- /* Image file instead of VGA-bios */
- HwExt.VirtualRomBase = rom_vbase = (unsigned long) RomData;
-#else
-#ifdef CONFIG_FB_SIS_LINUXBIOS
- if (pci_enable_device(pdev))
- return -EIO;
- HwExt.VirtualRomBase = rom_vbase = 0;
-#else
- request_region(rom_base, 32, "sisfb");
- HwExt.VirtualRomBase = rom_vbase
- = (unsigned long) ioremap(rom_base, MAX_ROM_SCAN);
-#endif
-#endif
- /* set passwd */
- vgawb(SEQ_ADR, IND_SIS_PASSWORD);
- vgawb(SEQ_DATA, SIS_PASSWORD);
-
- /* Enable MMIO & PCI linear address */
- vgawb(SEQ_ADR, IND_SIS_PCI_ADDRESS_SET);
- jTemp = vgarb(SEQ_DATA);
- jTemp |= SIS_PCI_ADDR_ENABLE;
- jTemp |= SIS_MEM_MAP_IO_ENABLE;
- vgawb(SEQ_DATA, jTemp);
-
-#ifdef CONFIG_FB_SIS_LINUXBIOS
- pdev_valid = 0;
- pci_for_each_dev(pdev) {
- u8 uPCIData=0;
+ vgawb (SEQ_ADR, 0x29);
+ vgawb (SEQ_DATA, 0x61);
X
- if ((pdev->vendor == PCI_VENDOR_ID_SI) && (pdev->device==0x630))
- {
- pci_read_config_byte(pdev, 0x63, &uPCIData);
- uPCIData = (uPCIData & 0x70) >> 4;
- ivideo.video_size = (unsigned int)(1 << (uPCIData+21));
- pdev_valid = 1;
- break;
- }
+ vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_1A);
+ reg = vgarb (SEQ_DATA);
+ reg |= SIS_SCRATCH_REG_1A_MASK;
+ vgawb (SEQ_DATA, reg);
X }
-
- if (!pdev_valid)
- return -1;
-#else
- vgawb(SEQ_ADR, IND_SIS_DRAM_SIZE);
- ivideo.video_size = ((unsigned int) ((vgarb(SEQ_DATA) & 0x3f) + 1) << 20);
X #endif
+#ifdef CONFIG_FB_SIS_315
+ if (ivideo.chip == SIS_550) {
+ vgawb (SEQ_ADR, 0x28);
+ vgawb (SEQ_DATA, 0x5A);
+
+ vgawb (SEQ_ADR, 0x29);
+ vgawb (SEQ_DATA, 0x64);
X
+ vgawb (CRTC_ADR, 0x3A);
+ vgawb (CRTC_DATA, 0x00);
+ }
+#endif
+#endif
X
- /* get CRT2 connection state */
- vgawb(SEQ_ADR, 0x17);
- uSRData = vgarb(SEQ_DATA);
- vgawb(CRTC_ADR, 0x32);
- uCRData = vgarb(CRTC_DATA);
-
- ivideo.TV_plug = ivideo.TV_type = 0;
- if((uSRData&0x0F) && (HwExt.jChipID>=SIS_Trojan))
- {
- /* CRT1 connect detection */
- if((uSRData & 0x01) && !crt1off)
- crt1off = 0;
- else
- {
- if(uSRData&0x0E) /* DISP2 connected */
- crt1off = 1;
- else


- crt1off = 0;
- }
-

- /* detection priority : CRT2 > LCD > TV */
- if(uSRData & 0x08 )
- uDispType = MASK_DISPTYPE_CRT2;
- else if(uSRData & 0x02)
- uDispType = MASK_DISPTYPE_LCD;
- else if(uSRData & 0x04)
- {
- if(uSRData & 0x80)
- {
- ivideo.TV_type = TVMODE_HIVISION;
- ivideo.TV_plug = TVPLUG_SVIDEO;
- }
- else if(uSRData & 0x20)
- ivideo.TV_plug = TVPLUG_SVIDEO;
- else if(uSRData & 0x10)
- ivideo.TV_plug = TVPLUG_COMPOSITE;
- else if(uSRData & 0x40)
- ivideo.TV_plug = TVPLUG_SCART;
-
- if(ivideo.TV_type == 0)
- {
- u8 uSR16;
- vgawb(SEQ_ADR, 0x16);
- uSR16 = vgarb(SEQ_DATA);
- if(uSR16 & 0x20)
- ivideo.TV_type = TVMODE_PAL;
- else
- ivideo.TV_type = TVMODE_NTSC;
- }
-
- uDispType = MASK_DISPTYPE_TV;


+ if (sisvga_engine == SIS_315_VGA) {

+ switch (ivideo.chip) {
+ case SIS_315H:
+ case SIS_315:
+ sishw_ext.bIntegratedMMEnabled = TRUE;
+ break;
+ case SIS_550:
+ // Eden Chen
+ //vgawb(SEQ_ADR, IND_SIS_SCRATCH_REG_1A);
+ //reg = vgarb(SEQ_DATA);
+ //if (reg & SIS_SCRATCH_REG_1A_MASK)
+ // sishw_ext.bIntegratedMMEnabled = TRUE;
+ //else
+ // sishw_ext.bIntegratedMMEnabled = FALSE;
+ //for Debug
+ sishw_ext.bIntegratedMMEnabled = TRUE;
+ // ~Eden Chen


+ break;
+ default:
+ break;
X }

- }
- else
- {
- if((uCRData & 0x20) && !crt1off)
- crt1off = 0;
- else
- {
- if(uCRData&0x5F) /* DISP2 connected */
- crt1off = 1;
+ } else if (sisvga_engine == SIS_300_VGA) {
+ if (ivideo.chip == SIS_300) {
+ sishw_ext.bIntegratedMMEnabled = TRUE;
+ } else {
+ vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_1A);
+ reg = vgarb (SEQ_DATA);
+ if (reg & SIS_SCRATCH_REG_1A_MASK)
+ sishw_ext.bIntegratedMMEnabled = TRUE;


X else
- crt1off = 0;

+ sishw_ext.bIntegratedMMEnabled = FALSE;
X }


+ }
+ // Eden Chen

+ sishw_ext.pDevice = NULL;
+ sishw_ext.pjVirtualRomBase = NULL;
+ sishw_ext.pjCustomizedROMImage = NULL;
+ sishw_ext.bSkipDramSizing = 0;
+ sishw_ext.pQueryVGAConfigSpace = &sisfb_query_VGA_config_space;
+ sishw_ext.pQueryNorthBridgeSpace = &sisfb_query_north_bridge_space;
+ strcpy (sishw_ext.szVBIOSVer, "0.84");
+
+ sishw_ext.pSR = vmalloc (sizeof (SIS_DSReg) * SR_BUFFER_SIZE);
+ if (sishw_ext.pSR == NULL)
+ printk (KERN_DEBUG "Allocated SRReg space fail.\n");
+ sishw_ext.pSR[0].jIdx = sishw_ext.pSR[0].jVal = 0xFF;
+
+ sishw_ext.pCR = vmalloc (sizeof (SIS_DSReg) * CR_BUFFER_SIZE);
+ if (sishw_ext.pCR == NULL)
+ printk (KERN_DEBUG "Allocated CRReg space fail.\n");
+ sishw_ext.pCR[0].jIdx = sishw_ext.pCR[0].jVal = 0xFF;


+ // ~Eden Chen
+

+ #ifdef CONFIG_FB_SIS_300
+ if (sisvga_engine == SIS_300_VGA) {

+ if (!sisvga_enabled) {
+ // Eden Chen
+ sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x2000000);
+ //SiSInit300(&sishw_ext);
+ SiSInit (&sishw_ext);


+ vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+ vgawb (SEQ_DATA, SIS_PASSWORD);

+ // ~Eden Chen
+ }
+#ifdef LINUXBIOS
+ else {
+ // Eden Chen
+ sishw_ext.pjVideoMemoryAddress
+ = ioremap (ivideo.video_base, 0x2000000);
+ //SiSInit300(&sishw_ext);
+ SiSInit (&sishw_ext);


+ vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+ vgawb (SEQ_DATA, SIS_PASSWORD);

+ // ~Eden Chen
+ }
+ vgawb (SEQ_ADR, 0x7);
+ reg = vgarb (SEQ_DATA);
+ reg |= 0x10;
+ vgawb (SEQ_DATA, reg);
+#endif
+ sisfb_get_dram_size_300 ();
+ }
+#endif
X
- if(uCRData & 0x10)
- uDispType = MASK_DISPTYPE_CRT2;
- else if(uCRData & 0x08)
- uDispType = MASK_DISPTYPE_LCD;
- else if(uCRData & 0x47)
- {
- uDispType = MASK_DISPTYPE_TV;
-
- if(uCRData & 0x40)
- {
- ivideo.TV_type = TVMODE_HIVISION;
- ivideo.TV_plug = TVPLUG_SVIDEO;
- }
- else if(uCRData & 0x02)
- ivideo.TV_plug = TVPLUG_SVIDEO;
- else if(uCRData & 0x01)
- ivideo.TV_plug = TVPLUG_COMPOSITE;
- else if(uCRData & 0x04)
- ivideo.TV_plug = TVPLUG_SCART;
+ #ifdef CONFIG_FB_SIS_315


+ if (sisvga_engine == SIS_315_VGA) {

+ if (!sisvga_enabled) {
+ /* Mapping Max FB Size for 315 Init */
+ // Eden Chen
+ //sishw_ext.VirtualVideoMemoryAddress
+ sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x8000000);
+ //SiSInit310(&sishw_ext);
+ SiSInit (&sishw_ext);
+

+ vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+ vgawb (SEQ_DATA, SIS_PASSWORD);
+

+ sishw_ext.bSkipDramSizing = TRUE;
+ vgawb (SEQ_ADR, 0x13);
+ sishw_ext.pSR[0].jIdx = 0x13;
+ sishw_ext.pSR[0].jVal = vgarb (SEQ_DATA);
+ vgawb (SEQ_ADR, 0x14);
+ sishw_ext.pSR[1].jIdx = 0x14;
+ sishw_ext.pSR[1].jVal = vgarb (SEQ_DATA);
+ sishw_ext.pSR[2].jIdx = 0xFF;
+ sishw_ext.pSR[2].jVal = 0xFF;
+ // Eden Chen
+ }
+#ifdef LINUXBIOS
+ else {
+ sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x8000000);
+ SiSInit (&sishw_ext);


+ vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+ vgawb (SEQ_DATA, SIS_PASSWORD);
+

+ sishw_ext.bSkipDramSizing = TRUE;
+ vgawb (SEQ_ADR, 0x13);
+ sishw_ext.pSR[0].jIdx = 0x13;
+ sishw_ext.pSR[0].jVal = vgarb (SEQ_DATA);
+ vgawb (SEQ_ADR, 0x14);
+ sishw_ext.pSR[1].jIdx = 0x14;
+ sishw_ext.pSR[1].jVal = vgarb (SEQ_DATA);
+ sishw_ext.pSR[2].jIdx = 0xFF;
+ sishw_ext.pSR[2].jVal = 0xFF;
+ }
+#endif
+ sisfb_get_dram_size_315 ();
+ }
+#endif
+ //Eden Chen
+ vgawb (SEQ_ADR, IND_SIS_PCI_ADDRESS_SET);
+ reg = vgarb (SEQ_DATA);
+ reg |= SIS_PCI_ADDR_ENABLE;
+ reg |= SIS_MEM_MAP_IO_ENABLE;
+ vgawb (SEQ_DATA, reg);
+
+ vgawb (SEQ_ADR, IND_SIS_MODULE_ENABLE);
+ reg = vgarb (SEQ_DATA);
+ reg |= SIS_ENABLE_2D;
+ vgawb (SEQ_DATA, reg);
+ //~Eden Chen


+
+ // Eden Chen

+ sishw_ext.ulVideoMemorySize = ivideo.video_size;
+ // ~Eden Chen
+ if (!request_mem_region (ivideo.video_base, ivideo.video_size, "sisfb FB")) {
+ printk (KERN_ERR "sisfb: cannot reserve frame buffer memory\n");


+ return -ENODEV;
+ }
X

- if(ivideo.TV_type == 0)
- {
- u8 uTemp;
- uTemp = *((u8 *)(HwExt.VirtualRomBase+0x52));
- if(uTemp&0x40)
- {
- uTemp=*((u8 *)(HwExt.VirtualRomBase+0x53));
- }
- else
- {
- vgawb(SEQ_ADR, 0x38);
- uTemp = vgarb(SEQ_DATA);
- }
- if(uTemp & 0x01)
- ivideo.TV_type = TVMODE_PAL;
- else
- ivideo.TV_type = TVMODE_NTSC;
- }
+ if (!request_mem_region (ivideo.mmio_base, sisfb_mmio_size, "sisfb MMIO")) {
+ printk (KERN_ERR "sisfb: cannot reserve MMIO region\n");
+ release_mem_region (ivideo.video_base, ivideo.video_size);
+ return -ENODEV;


+ }
+ // Eden Chen

+ //sishw_ext.VirtualVideoMemoryAddress = ivideo.video_vbase
+ sishw_ext.pjVideoMemoryAddress = ivideo.video_vbase = ioremap (ivideo.video_base, ivideo.video_size);
+ // Eden Chen
+ ivideo.mmio_vbase = ioremap (ivideo.mmio_base, sisfb_mmio_size);
+
+ printk (KERN_INFO
+ "sisfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
+ ivideo.video_base, ivideo.video_vbase, ivideo.video_size / 1024);
+
+ printk (KERN_INFO
+ "sisfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
+ ivideo.mmio_base, ivideo.mmio_vbase, sisfb_mmio_size / 1024);


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

echo 'End of part 084'
echo 'File patch-2.4.15 is continued in part 085'
echo "085" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:58 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part082

#!/bin/sh -x
# this is part 082 of a 115 - part archive


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

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

- }else{
- tempbx=4;
- tempcl=TVDataLen;
- }
- if(SetFlag&TVSimuMode){
- tempbx=tempbx+4;
- }
- if(ModeNo<=0x13){
- tempal=*((UCHAR *)(ROMAddr+ModeIDOffset+0x04)); // si+St_CRT2CRTC
- }else{
- tempal=*((UCHAR *)(ROMAddr+REFIndex+4)); //di+Ext_CRT2CRTC
- }
- tempal=tempal&0x1F;
-
- tempax=tempal*tempcl;
- REFIndex=*((USHORT *)(ROMAddr+tempbx*2+0x20E));
- REFIndex+=tempax;


- }else{ //for LVDS
-

- tempcl=LVDSDataLen;
- tempbx=LCDResInfo-Panel800x600;
- if(LCDInfo&LCDNonExpanding){
- tempbx=tempbx+3;
- }
- if(ModeNo<=0x13){
- tempal=*((UCHAR *)(ROMAddr+ModeIDOffset+0x04)); // si+St_CRT2CRTC
- }else{
- tempal=*((UCHAR *)(ROMAddr+REFIndex+0x04)); // di+Ext_CRT2CRTC
- }
- tempal=tempal&0x1F;
- tempax=tempal*tempcl;
- CRT2PtrData=*((USHORT *)(ROMAddr+ADR_CRT2PtrData)); //ADR_CRT2PtrData is defined in init.def
- REFIndex=*((USHORT *)(ROMAddr+CRT2PtrData+tempbx*2));
- REFIndex+=tempax;
- }
-}
-
-VOID UnLockCRT2(USHORT BaseAddr)
-{
- UCHAR temp3;
- USHORT Part1Port;
- Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
- temp3=(UCHAR)GetReg1(Part1Port,0x24);
- temp3=temp3|0x01;
- SetReg1(Part1Port,0x24,(USHORT)temp3);
-}
-
-VOID SetCRT2ModeRegs(USHORT BaseAddr,USHORT ModeNo)
-{
- USHORT i,j;
- USHORT tempah=0,temp3;
- SHORT tempcl;
- USHORT Part4Port;
- USHORT Part1Port;
- Part4Port=BaseAddr+IND_SIS_CRT2_PORT_14;
- Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
- for(i=0,j=4;i<3;i++,j++){
- SetReg1(Part1Port,j,0);
- }
-
- tempcl=(USHORT)ModeType;
- if(ModeNo>0x13){
- tempcl=tempcl-ModeVGA;
- if(tempcl>=0){
- tempah=((0x010>>tempcl)|0x080);
- }
- }else{
- tempah=0x080;
- }
-
- if(VBInfo&SetInSlaveMode){
- tempah=(tempah^0x0A0);
- }
- if(VBInfo&CRT2DisplayFlag){
- tempah=0;
- }
- SetReg1(Part1Port,0,tempah);
-
- if(IF_DEF_LVDS==0){ //301
- tempah=0x01;
- if(!(VBInfo&SetInSlaveMode)){
- tempah=(tempah|0x02);
- }
- if(!(VBInfo&SetCRT2ToRAMDAC)){
- tempah=(tempah^0x05);
- if(!(VBInfo&SetCRT2ToLCD)){
- tempah=(tempah^0x01);
- }
- }
- tempah=(tempah<<5)&0xFF;
- if(VBInfo&CRT2DisplayFlag){
- tempah=0;
- }
- SetReg1(Part1Port,0x01,tempah);
-
- tempah=tempah>>5;
- if((ModeType==ModeVGA)&&(!(VBInfo&SetInSlaveMode))){
- tempah=tempah|0x010;
- }
- if(LCDResInfo!=Panel1024x768){
- tempah=tempah|0x080;
- }
- if(VBInfo&SetCRT2ToTV){
- if(VBInfo&SetInSlaveMode){
- tempah=tempah|0x020;
- }
- }
-
- temp3=(UCHAR)GetReg1(Part4Port,0x0D);
- temp3=temp3&(~0x0BF);
- temp3=temp3|tempah;
- SetReg1(Part4Port,0x0D,(USHORT)temp3);
- }else{ //LVDS
- tempah=0;
- if(!(VBInfo&SetInSlaveMode)){
- tempah=tempah|0x02;
- }
- tempah=(tempah<<5)&0x0FF;
- if(VBInfo&CRT2DisplayFlag){
- tempah=0;
- }
- SetReg1(Part1Port,0x01,tempah);
- }
-}
-
-VOID SetGroup1(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo,
- PHW_DEVICE_EXTENSION HwDeviceExtension)
-{
- if(IF_DEF_LVDS==0){ //301
- SetGroup1_301(BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
- }else{ //LVDS
- SetGroup1_LVDS(BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
- }
-}
-VOID SetGroup1_LVDS(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo,
- PHW_DEVICE_EXTENSION HwDeviceExtension)
-{
- USHORT temp1,temp2,tempcl,tempch,tempbh,tempal,tempah,tempax,tempbx;
- USHORT tempcx,OldREFIndex,lcdhdee;
- USHORT Part1Port;
- USHORT temppush1,temppush2;
- unsigned long int tempeax,tempebx,tempecx,templong;
-
- Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;


- OldREFIndex=(USHORT)REFIndex; //push di
-

- SetCRT2Offset(Part1Port,ROMAddr);
- SetCRT2FIFO(Part1Port,ROMAddr,ModeNo,HwDeviceExtension);
- SetCRT2Sync(BaseAddr,ROMAddr,ModeNo);
-
- temp1=(VGAHT-1)&0x0FF; //BTVGA2HT 0x08,0x09
- SetReg1(Part1Port,0x08,temp1);
- temp1=(((VGAHT-1)&0xFF00)>>8)<<4;
- SetRegANDOR(Part1Port,0x09,~0x0F0,temp1);
-
-
- temp1=(VGAHDE+12)&0x0FF; //BTVGA2HDEE 0x0A,0x0C
- SetReg1(Part1Port,0x0A,temp1);
-
- temp1=VGAHDE+12; //bx BTVGA@HRS 0x0B,0x0C
- temp2=(VGAHT-VGAHDE)>>2; //cx
- temp1=temp1+temp2;
- temp2=(temp2<<1)+temp1;
- tempcl=temp2&0x0FF;
- //
- SetReg1(Part1Port,0x0B,(USHORT)(temp1&0x0FF));
- tempah=(temp1&0xFF00)>>8;
- tempbh=((((VGAHDE+12)&0xFF00)>>8)<<4)&0x0FF;
- tempah=tempah|tempbh;
- SetReg1(Part1Port,0x0C,tempah);
- SetReg1(Part1Port,0x0D,tempcl); //BTVGA2HRE 0x0D
- tempcx=(VGAVT-1);
- tempah=tempcx&0x0FF;
- SetReg1(Part1Port,0x0E,tempah); //BTVGA2TV 0x0E,0x12
- tempbx=VGAVDE-1;
- tempah=tempbx&0x0FF;
- SetReg1(Part1Port,0x0F,tempah); //BTVGA2VDEE 0x0F,0x12
- tempah=((tempbx&0xFF00)<<3)>>8;
- tempah=tempah|((tempcx&0xFF00)>>8);
- SetReg1(Part1Port,0x12,tempah);
-
- tempbx=(VGAVT+VGAVDE)>>1; //BTVGA2VRS 0x10,0x11
- tempcx=((VGAVT-VGAVDE)>>4)+tempbx+1; //BTVGA2VRE 0x11
- //
- tempah=tempbx&0x0FF;
- SetReg1(Part1Port,0x10,tempah);
- tempbh=(tempbx&0xFF00)>>8;
- tempah=((tempbh<<4)&0x0FF)|(tempcx&0x0F);
- SetReg1(Part1Port,0x11,tempah);
-
- SetRegANDOR(Part1Port,0x13,~0x03C,tempah);
-
- tempax=LCDHDES;
- tempbx=HDE;
- tempcx=HT;
- tempcx=tempcx-tempbx; //HT-HDE
- tempax=tempax+tempbx; //lcdhdee
- tempbx=HT;
- if(tempax>=tempbx){
- tempax=tempax-tempbx;
- }
-
- lcdhdee=tempax;
- tempcx=tempcx>>2; //temp
- tempcx=tempcx+tempax; //lcdhrs
- if(tempcx>=tempbx){
- tempcx=tempcx-tempbx;
- }
-
- tempax=tempcx;
- tempax=tempax>>3; //BPLHRS
- tempah=tempax&0x0FF;
- SetReg1(Part1Port,0x14,tempah); //Part1_14h
- tempah=tempah+2;
- tempah=tempah+0x01F;
- tempcl=tempcx&0x0FF;
- tempcl=tempcl&0x07;
- tempcl=(tempcl<<5)&0xFF; //BPHLHSKEW
- tempah=tempah|tempcl;
- SetReg1(Part1Port,0x15,tempah); //Part1_15h
- tempbx=lcdhdee; //lcdhdee
- tempcx=LCDHDES; //lcdhdes
- tempah=(tempcx&0xFF);
- tempah=tempah&0x07; //BPLHDESKEW
- SetReg1(Part1Port,0x1A,tempah); //Part1_1Ah
- tempcx=tempcx>>3; //BPLHDES
- tempah=(tempcx&0xFF);
- SetReg1(Part1Port,0x16,tempah); //Part1_16h
- tempbx=tempbx>>3; //BPLHDEE
- tempah=tempbx&0xFF;
- SetReg1(Part1Port,0x17,tempah); //Part1_17h
-
- tempcx=VGAVT;
- tempbx=VGAVDE;
- tempcx=tempcx-tempbx; //VGAVT-VGAVDE
- tempbx=LCDVDES; //VGAVDES
- temppush1=tempbx; //push bx temppush1
- if(IF_DEF_TRUMPION==0){
- if(LCDResInfo==Panel800x600){
- tempax=600;
- }else{
- tempax=768;
- }
- }else{
- tempax=VGAVDE;
- }
- tempbx=tempbx+tempax;
- tempax=VT; //VT
- if(tempbx>=VT){
- tempbx=tempbx-tempax;
- }
- temppush2=tempbx; //push bx temppush2
- tempcx=tempcx>>1;
- tempbx=tempbx+tempcx;
- tempbx++; //BPLVRS
- if(tempbx>=tempax){
- tempbx=tempbx-tempax;
- }
- tempah=tempbx&0xFF;
- SetReg1(Part1Port,0x18,tempah); //Part1_18h
- tempcx=tempcx>>3;
- tempcx=tempcx+tempbx;
- tempcx++; //BPLVRE
- tempah=tempcx&0xFF;
- tempah=tempah&0x0F;
- tempah=tempah|0x030;
- SetRegANDOR(Part1Port,0x19,~0x03F,tempah); //Part1_19h
- tempbh=(tempbx&0xFF00)>>8;
- tempbh=tempbh&0x07;
- tempah=tempbh;
- tempah=(tempah<<3)&0xFF; //BPLDESKEW =0
- tempbx=VGAVDE;
- if(tempbx!=VDE){
- tempah=tempah|0x40;
- }
- SetRegANDOR(Part1Port,0x1A,0x07,tempah); //Part1_1Ah
- tempecx=VGAVT;
- tempebx=VDE;
- tempeax=VGAVDE;
- tempecx=tempecx-tempeax; //VGAVT-VGAVDE
- tempeax=tempeax*64;
- templong=tempeax/tempebx;
- if(templong*tempebx<tempeax){
- templong++;
- }
- tempebx=templong; //BPLVCFACT
- if(SetFlag&EnableLVDSDDA){
- tempebx=tempebx&0x03F;
- }
- tempah=(USHORT)(tempebx&0x0FF);
- SetReg1(Part1Port,0x1E,tempah); //Part1_1Eh
- tempbx=temppush2; //pop bx temppush2 BPLVDEE
- tempcx=temppush1; //pop cx temppush1 NPLVDES
- tempbh=(tempbx&0xFF00)>>8;
- tempah=tempah&0x07;
- tempah=tempbh;
- tempah=tempah<<3;
- tempch=(tempcx&0xFF00)>>8;
- tempch=tempah&0x07;
- tempah=tempah|tempch;
- SetReg1(Part1Port,0x1D,tempah); //Part1_1Dh
- tempah=tempbx&0xFF;
- SetReg1(Part1Port,0x1C,tempah); //Part1_1Ch
- tempah=tempcx&0xFF;
- SetReg1(Part1Port,0x1B,tempah); //Part1_1Bh
-
- tempecx=VGAHDE;
- tempebx=HDE;
- tempeax=tempecx;
- tempeax=tempeax<<6;
- tempeax=tempeax<<10;
- tempeax=tempeax/tempebx;
- if(tempebx==tempecx){
- tempeax=65535;
- }
- tempecx=tempeax;
- tempeax=VGAHT;
- tempeax=tempeax<<6;
- tempeax=tempeax<<10;
- tempeax=tempeax/tempecx;
- tempecx=tempecx<<16;
- tempeax=tempeax-1;
- tempax=(USHORT)(tempeax&0x00FFFF);
- tempcx=tempax;
- tempah=tempcx&0x0FF;
- SetReg1(Part1Port,0x1F,tempah); //Part1_1Fh
- tempbx=VDE;
- tempbx--; //BENPLACCEND
- if(SetFlag&EnableLVDSDDA){
- tempbx=1;
- }
- tempah=(tempbx&0xFF00)>>8;
- tempah=(tempah<<3)&0xFF;
- tempch=(tempcx&0xFF00)>>8;
- tempch=tempch&0x07;
- tempah=tempah|tempch;
- SetReg1(Part1Port,0x20,tempah); //Part1_20h
- tempah=tempbx&0xFF;
- SetReg1(Part1Port,0x21,tempah); //Part1_21h
- tempecx=tempecx>>16; //BPLHCFACT
- temp1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
- if(temp1&HalfDCLK){
- tempecx=tempecx>>1;
- }
- tempcx=(USHORT)(tempecx&0x0FFFF);
- tempah=(tempcx&0xFF00)>>8;
- SetReg1(Part1Port,0x22,tempah); //Part1_22h
- tempah=tempcx&0x0FF;
- SetReg1(Part1Port,0x23,tempah); //Part1_23h
- if(IF_DEF_TRUMPION==1){
- tempal=(USHORT)*((UCHAR *)(ROMAddr+ModeIDOffset+0x05)); // si+St_ResInfo
- if(ModeNo>0x13){
- SetFlag=SetFlag|ProgrammingCRT2;
- GetRatePtrCRT2(ROMAddr,ModeNo);
- tempal=*((UCHAR *)(ROMAddr+REFIndex+0x04)); // di+Ext_CRT2CRTC
- tempal=tempal&0x1F;
- }
- tempah=0x80;
- tempal=tempal*tempah;
- REFIndex= offset_Zurac; //offset Zurac need added in rompost.asm
- REFIndex=REFIndex+tempal;
- SetTPData(); //this function not implemented yet
- SetTPData();
- SetTPData();
- SetTPData();
- SetTPData();
- SetTPData();
- SetTPData();
- SetTPData();
- SetTPData();


- }
-
- REFIndex=OldREFIndex; //pop di
- return;
-}
-

-VOID SetTPData(VOID)
-{
- return;
-}
-
-VOID SetGroup1_301(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo,
- PHW_DEVICE_EXTENSION HwDeviceExtension)
-{
- USHORT temp1,temp2,tempcl,tempch,tempbl,tempbh,tempal,tempah,tempax,tempbx;
- USHORT tempcx,OldREFIndex;
- USHORT Part1Port;
- Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;


- OldREFIndex=(USHORT)REFIndex; //push di
-

- SetCRT2Offset(Part1Port,ROMAddr);
- SetCRT2FIFO(Part1Port,ROMAddr,ModeNo,HwDeviceExtension);
- SetCRT2Sync(BaseAddr,ROMAddr,ModeNo);
-
- GetCRT1Ptr(ROMAddr);
-
- temp1=(VGAHT-1)&0x0FF; //BTVGA2HT 0x08,0x09
- SetReg1(Part1Port,0x08,temp1);
- temp1=(((VGAHT-1)&0xFF00)>>8)<<4;
- SetRegANDOR(Part1Port,0x09,~0x0F0,temp1);
-
- temp1=(VGAHDE+12)&0x0FF; //BTVGA2HDEE 0x0A,0x0C
- SetReg1(Part1Port,0x0A,temp1);
-
- temp1=VGAHDE+12; //bx BTVGA@HRS 0x0B,0x0C
- temp2=(VGAHT-VGAHDE)>>2; //cx
- temp1=temp1+temp2;
- temp2=(temp2<<1)+temp1;
- tempcl=temp2&0x0FF;
- if(VBInfo&SetCRT2ToRAMDAC){
- tempbl=*((UCHAR *)(ROMAddr+REFIndex+4)); //di+4
- tempbh=*((UCHAR *)(ROMAddr+REFIndex+14)); //di+14
- temp1=((tempbh>>6)<<8)|tempbl; //temp1->bx
- temp1=(temp1-1)<<3;
- tempcl=*((UCHAR *)(ROMAddr+REFIndex+5)); //di+5
- tempch=*((UCHAR *)(ROMAddr+REFIndex+15)); //di+15
- tempcl=tempcl&0x01F;
- tempch=(tempch&0x04)<<(6-2);
- tempcl=((tempcl|tempch)-1)<<3;
- }
- SetReg1(Part1Port,0x0B,(USHORT)(temp1&0x0FF));
- tempah=(temp1&0xFF00)>>8;
- tempbh=((((VGAHDE+12)&0xFF00)>>8)<<4)&0x0FF;
- tempah=tempah|tempbh;
- SetReg1(Part1Port,0x0C,tempah);
- SetReg1(Part1Port,0x0D,tempcl); //BTVGA2HRE 0x0D
- tempcx=(VGAVT-1);
- tempah=tempcx&0x0FF;
- SetReg1(Part1Port,0x0E,tempah); //BTVGA2TV 0x0E,0x12
- tempbx=VGAVDE-1;
- tempah=tempbx&0x0FF;
- SetReg1(Part1Port,0x0F,tempah); //BTVGA2VDEE 0x0F,0x12
- tempah=((tempbx&0xFF00)<<3)>>8;
- tempah=tempah|((tempcx&0xFF00)>>8);
- SetReg1(Part1Port,0x12,tempah);
-
- tempbx=(VGAVT+VGAVDE)>>1; //BTVGA2VRS 0x10,0x11
- tempcx=((VGAVT-VGAVDE)>>4)+tempbx+1; //BTVGA2VRE 0x11
- if(VBInfo&SetCRT2ToRAMDAC){
- tempbx=*((UCHAR *)(ROMAddr+REFIndex+8)); //di+8
- temp1=*((UCHAR *)(ROMAddr+REFIndex+7)); //di+7
- if(temp1&0x04){
- tempbx=tempbx|0x0100;
- }
- if(temp1&0x080){
- tempbx=tempbx|0x0200;
- }
- temp1=*((UCHAR *)(ROMAddr+REFIndex+13)); //di+13
- if(temp1&0x08){
- tempbx=tempbx|0x0400;
- }
- tempcl= *((UCHAR *)(ROMAddr+REFIndex+9)); //di+9
- tempcx=(tempcx&0xFF00)|(tempcl&0x00FF);
- }
- tempah=tempbx&0x0FF;
- SetReg1(Part1Port,0x10,tempah);
- tempbh=(tempbx&0xFF00)>>8;
- tempah=((tempbh<<4)&0x0FF)|(tempcx&0x0F);
- SetReg1(Part1Port,0x11,tempah);
-
- if(HwDeviceExtension->jChipID == SIS_Glamour)
- {
- tempah=0x10;
- if((LCDResInfo!=Panel1024x768)&&(LCDResInfo==Panel1280x1024)){
- tempah=0x20;
- }
- }else{
- tempah=0x20;
- }
- if(VBInfo&SetCRT2ToTV){
- tempah=0x08;
- }
-
- SetRegANDOR(Part1Port,0x13,~0x03C,tempah);
-
- if(!(VBInfo&SetInSlaveMode)){
- REFIndex=OldREFIndex;
- return;
- }
- if(VBInfo&SetCRT2ToTV){
- tempax=0xFFFF;
- }else{
- tempax=GetVGAHT2();
- }
- tempcl=0x08; //Reg 0x03 Horozontal Total
- temp1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
- if(!(temp1&Charx8Dot)){ //temp1->St_ModeFlag
- tempcl=0x09;
- }
- if(tempax>=VGAHT){
- tempax=VGAHT;
- }
- if(temp1&HalfDCLK){
- tempax=tempax>>1;
- }
- tempax=(tempax/tempcl)-5;
- tempbl=tempax;
- tempah=0xFF; //set MAX HT
- SetReg1(Part1Port,0x03,tempah);
-
- tempax=VGAHDE; //0x04 Horizontal Display End
- if(temp1&HalfDCLK){
- tempax=tempax>>1;
- }
- tempax=(tempax/tempcl)-1;
- tempbh=tempax;
- SetReg1(Part1Port,0x04,tempax);
-
- tempah=tempbh;
- if(VBInfo&SetCRT2ToTV){
- tempah=tempah+2;
- }
- SetReg1(Part1Port,0x05,tempah); //0x05 Horizontal Display Start
- SetReg1(Part1Port,0x06,0x03); //0x06 Horizontal Blank end
- //0x07 horizontal Retrace Start
- tempcx=(tempbl+tempbh)>>1;
- tempah=(tempcx&0xFF)+2;
-
- if(VBInfo&SetCRT2ToTV){
- tempah=tempah-1;
- if(!(temp1&HalfDCLK)){
- if((temp1&Charx8Dot)){
- tempah=tempah+4;
- if(VGAHDE>=800){
- tempah=tempah-6;
- }
- }
- }
- }else{
- if(!(temp1&HalfDCLK)){
- tempah=tempah-4;
- if(VGAHDE>=800){
- tempah=tempah-7;
- if(ModeType==ModeEGA){
- if(VGAVDE==1024){
- tempah=tempah+15;
- if(LCDResInfo!=Panel1280x1024){
- tempah=tempah+7;
- }
- }
- }
- if(VGAHDE>=1280){
- tempah=tempah+28;


- }
- }
- }
- }
-

- SetReg1(Part1Port,0x07,tempah);//0x07 Horizontal Retrace Start
-
- SetReg1(Part1Port,0x08,0); //0x08 Horizontal Retrace End
- SetReg1(Part1Port,0x18,0x03); //0x18 SR08
- SetReg1(Part1Port,0x19,0); //0x19 SR0C
- SetReg1(Part1Port,0x09,0xFF); //0x09 Set Max VT
-
- tempcx=0x121;
- tempcl=0x21;
- tempch=0x01;
- tempbx=VGAVDE; //0x0E Virtical Display End
- if(tempbx==360) tempbx=350;
- if(tempbx==375) tempbx=350;
- if(tempbx==405) tempbx=400;
- tempbx--;
- tempah=tempbx&0x0FF;
- SetReg1(Part1Port,0x0E,tempah);
- SetReg1(Part1Port,0x10,tempah);//0x10 vertical Blank Start
- tempbh=(tempbx&0xFF00)>>8;
- if(tempbh&0x01){
- tempcl=tempcl|0x0A;
- }
- tempah=0;tempal=0x0B;
- if(temp1&DoubleScanMode){
- tempah=tempah|0x080;
- }
- if(tempbh&0x02){
- tempcl=tempcl|0x040;
- tempah=tempah|0x020;
- }
- SetReg1(Part1Port,0x0B,tempah);
- if(tempbh&0x04){
- tempch=tempch|0x06;
- }
-
- SetReg1(Part1Port,0x11,0); //0x11 Vertival Blank End
-
- tempax=VGAVT-tempbx; //0x0C Vertical Retrace Start
- tempax=tempax>>2;
- temp2=tempax; //push ax
- tempax=tempax<<1;
- tempbx=tempax+tempbx;
- if((SetFlag&TVSimuMode)&&(VBInfo&SetPALTV)&&(VGAHDE==800)){
- tempbx=tempbx+40;
- }
- tempah=(tempbx&0x0FF);
- SetReg1(Part1Port,0x0C,tempah);
- tempbh=(tempbx&0xFF00)>>8;
- if(tempbh&0x01){
- tempcl=tempcl|0x04;
- }
- if(tempbh&0x02){
- tempcl=tempcl|0x080;
- }
- if(tempbh&0x04){
- tempch=tempch|0x08;
- }
-
- tempax=temp2; //pop ax
- tempax=(tempax>>2)+1;
- tempbx=tempbx+tempax;
- tempah=(tempbx&0x0FF)&0x0F;
- SetReg1(Part1Port,0x0D,tempah); //0x0D vertical Retrace End
- tempbl=tempbx&0x0FF;
- if(tempbl&0x10){
- tempch=tempch|0x020;
- }
-
- tempah=tempcl;
- SetReg1(Part1Port,0x0A,tempah); //0x0A CR07
- tempah=tempch;
- SetReg1(Part1Port,0x17,tempah); //0x17 SR0A
- tempax=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
- tempah=(tempax&0xFF00)>>8;
- tempah=(tempah>>1)&0x09;
- SetReg1(Part1Port,0x16,tempah); //0x16 SR01
- SetReg1(Part1Port,0x0F,0); //0x0F CR14
- SetReg1(Part1Port,0x12,0); //0x12 CR17
- SetReg1(Part1Port,0x1A,0); //0x1A SR0E


-
- REFIndex=OldREFIndex; //pop di
-}

-
-VOID SetCRT2Offset(USHORT Part1Port,ULONG ROMAddr)
-{
- USHORT offset;
- if(VBInfo&SetInSlaveMode){
- return;
- }
- offset=GetOffset(ROMAddr);
- SetReg1(Part1Port,0x07,(USHORT)(offset&0xFF));
- SetReg1(Part1Port,0x09,(USHORT)((offset&0xFF00)>>8));
- SetReg1(Part1Port,0x03,(USHORT)(((offset>>3)&0xFF)+1));
-}
-
-USHORT GetOffset(ULONG ROMAddr)
-{
- USHORT tempal,temp1,colordepth;
- tempal=*((UCHAR *)(ROMAddr+ModeIDOffset+0x03)); // si+Ext_ModeInfo
- tempal=(tempal>>4)&0xFF;
- ScreenOffset=*((USHORT *)(ROMAddr+0x206)); // Get ScreeOffset table
- tempal=*((UCHAR *)(ROMAddr+ScreenOffset+tempal)); // get ScreenOffset
- tempal=tempal&0xFF;
- temp1=*((UCHAR *)(ROMAddr+REFIndex)); //di+Ext_InfoFlag
- if(temp1&InterlaceMode){
- tempal=tempal<<1;
- }
- colordepth=GetColorDepth(ROMAddr);
- return(tempal*colordepth);
-}
-
-USHORT GetColorDepth(ULONG ROMAddr)
-{
- USHORT ColorDepth[6]={1,2,4,4,6,8};
- USHORT temp;
- int temp1;
- temp=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
- temp1=(temp&ModeInfoFlag)-ModeEGA;
- if(temp1<0) temp1=0;
- return(ColorDepth[temp1]);
-}
-
-VOID SetCRT2FIFO(USHORT Part1Port,ULONG ROMAddr,USHORT ModeNo,
- PHW_DEVICE_EXTENSION HwDeviceExtension)
-{
- USHORT temp,temp1,temp2,temp3,flag;
- USHORT vclk2ptr,latencyindex;
- USHORT oldREFIndex,CRT1ModeNo,oldModeIDOffset;
- long int longtemp;
-
- USHORT LatencyFactor[48]={ 88, 80, 78, 72, 70, 00, // 64 bit BQ=2
- 00, 79, 77, 71, 69, 49, // 64 bit BQ=1
- 88, 80, 78, 72, 70, 00, // 128 bit BQ=2
- 00, 72, 70, 64, 62, 44, // 128 bit BQ=1
- 73, 65, 63, 57, 55, 00, // 64 bit BQ=2
- 00, 64, 62, 56, 54, 34, // 64 bit BQ=1
- 78, 70, 68, 62, 60, 00, // 128 bit BQ=2
- 00, 62, 60, 54, 52, 34}; // 128 bit BQ=1
-
- oldREFIndex=(USHORT)REFIndex; //push REFIndex(CRT2 now)
- oldModeIDOffset=(USHORT)ModeIDOffset; //push ModeIDOffset
-
- CRT1ModeNo=(UCHAR)GetReg1(P3d4,0x34); //get CRT1 ModeNo
- SearchModeID(ROMAddr,CRT1ModeNo); //Get ModeID Table
-
- GetRatePtr(ROMAddr,CRT1ModeNo); //Set REFIndex-> for crt1 refreshrate
- temp1=GetVCLK(ROMAddr,CRT1ModeNo,HwDeviceExtension);
- temp2=GetColorTh(ROMAddr);
- temp3=GetMCLK(ROMAddr);
- temp=((USHORT)(temp1*temp2)/temp3); //temp->bx
- temp1=(UCHAR)GetReg1(P3c4,0x14); //SR_14
- temp1=temp1>>6;
- temp1=temp1<<1;
- if(temp1==0) temp1=1;
- temp1=temp1<<2; //temp1->ax
-
- longtemp=temp1-temp;
-
- temp2=(USHORT)((28*16)/(int)longtemp); //temp2->cx
- if(!((temp2*(int)longtemp)==(28*16))) temp2++;
-
- if( HwDeviceExtension->jChipID == SIS_Glamour ){
- temp1=CalcDelay();
- }else{ //for Trojan and Spartan
- flag=(UCHAR)GetReg1(P3c4,0x14); //SR_14
- if(flag&0x80){
- latencyindex=12; //128 bit
- }else{
- latencyindex=0; //64 bit
- }
- flag=GetQueueConfig();
- if(!(flag&0x01)){
- latencyindex+=24; //GUI timing =0
- }
- if(flag&0x10){
- latencyindex+=6; //BQ =2
- }
- latencyindex=latencyindex + (flag>>5);
- temp1= LatencyFactor[latencyindex];
- temp1=temp1+15;
- flag=(UCHAR)GetReg1(P3c4,0x14); //SR_14
- if(!(flag&0x80)){
- temp1=temp1+5; //64 bit
- }
- }
-
- temp2=temp2+temp1;
- REFIndex=oldREFIndex; //pop REFIndex(CRT2)
- ModeIDOffset=oldModeIDOffset; //pop ModeIDOffset
-
- vclk2ptr=GetVCLK2Ptr(ROMAddr,ModeNo);
- temp1=*((USHORT *)(ROMAddr+vclk2ptr+(VCLKLen-2)));
- temp3=GetColorTh(ROMAddr);
- longtemp=temp1*temp2*temp3;
- temp3=GetMCLK(ROMAddr);
- temp3=temp3<<4;
- temp2=(int)(longtemp/temp3);
- if((long int)temp2*(long int)temp3<(long int)longtemp) temp2++; //temp2->cx
-
- temp1=(UCHAR)GetReg1(Part1Port,0x01); //part1port index 01
-
-
- if( (HwDeviceExtension->jChipID == SIS_Trojan ) &&
- ((HwDeviceExtension->revision_id & 0xf0) == 0x30) ) /* 630s */
- {
- temp1=(temp1&(~0x1F))|0x19;
- }else
- {
- temp1=(temp1&(~0x1F))|0x16;
- }
- SetReg1(Part1Port,0x01,temp1);
-
- if(temp2<=6) temp2=6;
- if(temp2>0x14) temp2=0x14;
- temp1=(UCHAR)GetReg1(Part1Port,0x02); //part1port index 02
- temp1=(temp1&(~0x1F))|temp2;
- SetReg1(Part1Port,0x02,temp1);
-}
-
-USHORT GetVCLK(ULONG ROMAddr,USHORT ModeNo,
- PHW_DEVICE_EXTENSION HwDeviceExtension)
-{
- USHORT tempptr;
- USHORT temp1;
- tempptr=GetVCLKPtr(ROMAddr,ModeNo);
- temp1=*((USHORT *)(ROMAddr+tempptr+(VCLKLen-2)));
-
- return temp1;
-}
-
-USHORT GetQueueConfig(void)
-{
- USHORT tempal,tempbl;
- ULONG tempeax;
-
- SetReg4(0xcf8,0x80000050);
- tempeax=GetReg3(0xcfc);
- tempeax=(tempeax>>24)&0x0f;
- tempbl=(USHORT)tempeax;
- tempbl=tempbl<<4;
-
- SetReg4(0xcf8,0x800000A0);
- tempeax=GetReg3(0xcfc);
- tempeax=(tempeax>>24)&0x0f;
- tempal=(USHORT)tempeax;
- tempbl=tempbl|tempal;
-
- return(tempbl);
-}
-
-USHORT GetVCLKPtr(ULONG ROMAddr,USHORT ModeNo)
-{
- USHORT tempal;
- tempal=(UCHAR)GetReg2((USHORT)(P3ca+0x02)); // Port 3cch
- tempal=((tempal>>2)&0x03);
- if(ModeNo>0x13){
- tempal=*((UCHAR *)(ROMAddr+REFIndex+0x03)); //di+Ext_CRTVCLK
- tempal=tempal&0x03F;
- }
- VCLKLen=GetVCLKLen(ROMAddr);
- tempal=tempal*VCLKLen;
- tempal=tempal+(*((USHORT *)(ROMAddr+0x208))); // VCLKData
- return ((USHORT)tempal);
-}
-
-USHORT GetColorTh(ULONG ROMAddr)
-{
- USHORT temp;
- temp=GetColorDepth(ROMAddr);
- temp=temp>>1;
- if(temp==0) temp++;
- return temp;
-}
-
-USHORT GetMCLK(ULONG ROMAddr)
-{
- USHORT tempmclkptr;
- USHORT tempmclk;
- tempmclkptr=GetMCLKPtr(ROMAddr);
- tempmclk=*((USHORT *)(ROMAddr+tempmclkptr+0x03)); //di+3
- return tempmclk;
-}
-
-USHORT GetMCLKPtr(ULONG ROMAddr)
-{
- USHORT tempdi;
- USHORT tempdramtype,tempax;
-
- tempdi=*((USHORT *)(ROMAddr+0x20C)); // MCLKData
- tempdramtype=GetDRAMType(ROMAddr);
- tempax=5*tempdramtype;
- tempdi=tempdi+tempax;
- return (tempdi);
-}
-
-USHORT GetDRAMType(ULONG ROMAddr)
-{
- USHORT tsoftsetting,temp3;
-
- tsoftsetting=*((UCHAR *)(ROMAddr+0x52));
- if(!(tsoftsetting&SoftDramType)){
- temp3=(UCHAR)GetReg1(P3c4,0x3A);
- tsoftsetting=temp3;
- }
- tsoftsetting=tsoftsetting&0x07;
- return(tsoftsetting);
-}
-
-static USHORT CalcDelay()
-{
- USHORT tempal,tempah,temp1,tempbx;
- USHORT ThTiming[8]={1,2,2,3,0,1,1,2};
- USHORT ThLowB[24]={81,4,72,6,88,8,120,12,
- 55,4,54,6,66,8,90,12,
- 42,4,45,6,55,8,75,12};
-
- tempah=(UCHAR)GetReg1(P3c4,0x18); //SR_18
- tempah=tempah&0x62;
- tempah=tempah>>1;
- tempal=tempah;
- tempah=tempah>>3;
- tempal=tempal|tempah;
- tempal=tempal&0x07;
-
- temp1=ThTiming[tempal]; //temp1->cl
-
- tempbx=(UCHAR)GetReg1(P3c4,0x16); //SR_16
- tempbx=tempbx>>6;
- tempah=(UCHAR)GetReg1(P3c4,0x14); //SR_14
- tempah=((tempah>>4)&0x0C);
- tempbx=((tempbx|tempah)<<1);
-
- tempal=ThLowB[tempbx+1]*temp1;
- tempbx=ThLowB[tempbx];
- tempbx=tempal+tempbx;
-
- return(tempbx);
-}
-
-USHORT GetVCLK2Ptr(ULONG ROMAddr,USHORT ModeNo)
-{
- USHORT tempal;
- USHORT LCDXlat1VCLK[4]={VCLK65,VCLK65,VCLK65,VCLK65};
- USHORT LCDXlat2VCLK[4]={VCLK108_2,VCLK108_2,VCLK108_2,VCLK108_2};
-
- if(ModeNo<=0x13){
- tempal=*((UCHAR *)(ROMAddr+ModeIDOffset+0x04)); // si+St_CRT2CRTC
- }else{
- tempal=*((UCHAR *)(ROMAddr+REFIndex+0x04)); // di+Ext_CRT2CRTC
- }
- tempal=tempal>>6;
- if(LCDResInfo!=Panel1024x768){
- tempal=LCDXlat2VCLK[tempal];
- }else{
- tempal=LCDXlat1VCLK[tempal];
- }
-
- if(VBInfo&SetCRT2ToLCD){
- tempal=tempal;
- }else if(VBInfo&SetCRT2ToTV){
- if(SetFlag&RPLLDIV2XO){
- tempal=TVVCLKDIV2;
- }else{
- tempal=TVVCLK;
- }
- }else{
- tempal=(UCHAR)GetReg2((USHORT)(P3ca+0x02)); // Port 3cch
- tempal=((tempal>>2)&0x03);
- if(ModeNo>0x13){
- tempal=*((UCHAR *)(ROMAddr+REFIndex+0x03)); //di+Ext_CRTVCLK
- tempal=tempal&0x03F;
- }
- }
- VCLKLen=GetVCLKLen(ROMAddr);
- tempal=tempal*VCLKLen;
- tempal=tempal+(*((USHORT *)(ROMAddr+0x208))); // VCLKData
- return ((USHORT)tempal);
-}
-
-USHORT GetVCLKLen(ULONG ROMAddr)
-{
- USHORT VCLKDataStart,vclklabel,temp;
- VCLKDataStart=*((USHORT *)(ROMAddr+0x208));
- for(temp=0;;temp++){
- vclklabel=*((USHORT *)(ROMAddr+VCLKDataStart+temp));
- if(vclklabel==VCLKStartFreq){
- temp=temp+2;
- return(temp);
- }
- }
- return(0);
-}
-
-
-VOID SetCRT2Sync(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo)
-{
- USHORT temp1,tempah=0;
- USHORT temp;
- USHORT Part1Port;
- Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
- if(IF_DEF_LVDS==1){ //LVDS
- if(VBInfo&SetCRT2ToLCD){
- tempah=LCDInfo;
- if(!(tempah&LCDSync)){
- temp=*((USHORT *)(ROMAddr+REFIndex)); //di+Ext_InfoFlag
- tempah=(temp>>8)&0x0C0;
- }else{
- tempah=tempah&0x0C0;
- }
- }
- }else{
- temp=*((USHORT *)(ROMAddr+REFIndex)); //di+Ext_InfoFlag
- tempah=(temp>>8)&0x0C0;
- }
- temp1=(UCHAR)GetReg1(Part1Port,0x19); //part1port index 02
- temp1=(temp1&(~0x0C0))|tempah;
- SetReg1(Part1Port,0x19,temp1);
-}
-
-VOID GetCRT1Ptr(ULONG ROMAddr)
-{
- USHORT temprefcrt1;
- USHORT temp;
- temp=*((UCHAR *)(ROMAddr+REFIndex+0x02)); //di+Ext_CRT1CRTC
- temp=temp&0x03F;
- temp=temp*CRT1Len;
- temprefcrt1=*((USHORT *)(ROMAddr+0x204)); // Get CRT1Table
- REFIndex=temprefcrt1+temp; // di->CRT1Table+Ext_CRT1CRTC*CRT1Len
-}
-
-USHORT GetVGAHT2()
-{
- long int temp1,temp2;
-
- temp1=(VGAVT-VGAVDE)*RVBHCMAX;
- temp1=temp1&0x0FFFF;
- temp2=(VT-VDE)*RVBHCFACT;
- temp2=temp2&0x0FFFF;
- temp2=temp2*HT;
- temp2=temp2/temp1;
- return((USHORT)temp2);
-}
-
-VOID SetGroup2(USHORT BaseAddr,ULONG ROMAddr)
-{
- USHORT tempah,tempbl,tempbh,tempcl,i,j,tempcx,pushcx,tempbx,tempax;
- USHORT tempmodeflag,tempflowflag;
- UCHAR *temp1;
- USHORT *temp2;
- USHORT pushbx;
- USHORT Part2Port;
- long int longtemp;
-
- Part2Port=BaseAddr+IND_SIS_CRT2_PORT_10;
-
- tempcx=VBInfo;
- tempah=VBInfo&0x0FF;
- tempbl=VBInfo&0x0FF;
- tempbh=VBInfo&0x0FF;
- tempbx=(tempbl&0xFF)|(tempbh<<8);
- tempbl=tempbl&0x10;
- tempbh=(tempbh&0x04)<<1;
- tempah=(tempah&0x08)>>1;
- tempah=tempah|tempbh;
- tempbl=tempbl>>3;
- tempah=tempah|tempbl;
- tempah=tempah^0x0C;
-
- if(VBInfo&SetPALTV){
- temp1=(UCHAR *)(ROMAddr+0x0F1); //PALPhase
- temp2=PALTiming;
- }else{
- tempah=tempah|0x10;
- temp1=(UCHAR *)(ROMAddr+0x0ED); //NTSCPhase
- temp2=NTSCTiming;
- }
-
- SetReg1(Part2Port,0x0,tempah);
- for(i=0x31;i<=0x34;i++,temp1++){
- SetReg1(Part2Port,i,*(UCHAR *)temp1);
- }
- for(i=0x01,j=0;i<=0x2D;i++,j++){
- SetReg1(Part2Port,i,temp2[j]);
- }
- for(i=0x39;i<=0x45;i++,j++){
- SetReg1(Part2Port,i,temp2[j]); //di->temp2[j]
- }
-
- tempah=GetReg1(Part2Port,0x0A);
- tempah=tempah|NewFlickerMode;
- SetReg1(Part2Port,0x0A,tempah);
-
- SetReg1(Part2Port,0x35,RY1COE);
- SetReg1(Part2Port,0x36,RY2COE);
- SetReg1(Part2Port,0x37,RY3COE);
- SetReg1(Part2Port,0x38,RY4COE);
-
- tempcx=HT-1;
- tempah=tempcx&0xFF;
- SetReg1(Part2Port,0x1B,tempah);
- tempah=(tempcx&0xFF00)>>8;
- SetRegANDOR(Part2Port,0x1D,~0x0F,(UCHAR)tempah);
-
- tempcx=HT>>1;
- pushcx=tempcx;
-
- tempcx=tempcx+7;
- tempah=(tempcx&0xFF);
- tempah=(tempah<<4)&0xFF;
- SetRegANDOR(Part2Port,0x22,~0x0F0,tempah);
-
-
- tempbx=temp2[j];
- tempbx=tempbx+tempcx;
- tempah=tempbx&0xFF;
- SetReg1(Part2Port,0x24,tempah);
- tempah=(tempbx&0xFF00)>>8;
- tempah=(tempah<<4)&0xFF;
- SetRegANDOR(Part2Port,0x25,~0x0F0,tempah);
-
- tempbx=tempbx+8;
-
- tempah=((tempbx&0xFF)<<4)&0xFF;
- SetRegANDOR(Part2Port,0x29,~0x0F0,tempah);
-
- tempcx=tempcx+temp2[++j];
- tempah=tempcx&0xFF;
- SetReg1(Part2Port,0x27,tempah);
- tempah=(((tempcx&0xFF00)>>8)<<4)&0xFF;
- SetRegANDOR(Part2Port,0x28,~0x0F0,tempah);
-
- tempcx=tempcx+8;
-
- tempah=tempcx&0xFF;
- tempah=(tempah<<4)&0xFF;
- SetRegANDOR(Part2Port,0x2A,~0x0F0,tempah);
-
- tempcx=pushcx; //pop cx
- tempcx=tempcx-temp2[++j];
- tempah=tempcx&0xFF;
- tempah=(tempah<<4)&0xFF;
- SetRegANDOR(Part2Port,0x2D,~0x0F0,tempah);
-
- tempcx=tempcx-11;
- if(!(VBInfo&SetCRT2ToTV)){
- tempax=GetVGAHT2();
- tempcx=tempax-1;
- }
- tempah=tempcx&0xFF;
- SetReg1(Part2Port,0x2E,tempah);
-
- tempbx=VDE;
- if(VGAVDE==360){
- tempbx=746;
- }
- if(VGAVDE==375){
- tempbx=746;
- }
- if(VGAVDE==405){
- tempbx=853;
- }
- if((VBInfo&SetCRT2ToTV)){
- tempbx=tempbx>>1;
- }
-
- tempbx=tempbx-2;
- tempah=tempbx&0xFF;
- SetReg1(Part2Port,0x2F,tempah);
-
- tempah=(tempcx&0xFF00)>>8;
- tempbh=(tempbx&0xFF00)>>8;
- tempbh=(tempbh<<6)&0xFF;
- tempah=tempah|tempbh;
- //assuming <<ifndef>> hivisiontv
- tempah=tempah|0x10;
- if(!(VBInfo&SetCRT2ToSVIDEO)){
- tempah=tempah|0x20;
- }
-
- SetReg1(Part2Port,0x30,tempah);
-
- tempbh=0;
- tempbx=tempbx&0xFF;
-
- tempmodeflag=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
- tempflowflag=0;
- if(!(tempmodeflag&HalfDCLK)){
- tempcx=VGAHDE;
- if(tempcx>=HDE){
- tempbh=tempbh|0x20;
- tempbx=(tempbh<<8)|(tempbx&0xFF);
- tempah=0;
- }
- }
- tempcx=0x0101;
- if(!(tempbh&0x20)){
- if(tempmodeflag&HalfDCLK){
- tempcl=((tempcx&0xFF)<<1)&0xFF;
- tempcx=(tempcx&0xFF00)|tempcl;
- }
- pushbx=tempbx;
- tempax=VGAHDE;
- tempbx=(tempcx&0xFF00)>>8;
- longtemp=tempax*tempbx;
- tempcx=tempcx&0xFF;
- longtemp=longtemp/tempcx;
- longtemp=longtemp*8*1024;
- tempax=(USHORT)((longtemp)/HDE);
- if(tempax*HDE<longtemp){
- tempax=tempax+1;
- }else{
- tempax=tempax;
- }
- tempbx=pushbx;
- tempah=((tempax&0xFF00)>>8)&0x01F;
- tempbh=tempbh|tempah;
- tempah=tempax&0xFF;
- }
-
- SetReg1(Part2Port,0x44,tempah);
- tempah=tempbh;
- SetRegANDOR(Part2Port,0x45,~0x03F,tempah);
-
- if(VBInfo&SetCRT2ToTV){
- return;
- }
-
- tempah=0x01;
- if(LCDResInfo==Panel1280x1024){
- if(ModeType==ModeEGA){
- if(VGAHDE>=1024){
- tempah=0x02;
- }
- }
- }
- SetReg1(Part2Port,0x0B,tempah);
-
- tempbx=HDE-1; //RHACTE=HDE-1
- tempah=tempbx&0xFF;
- SetReg1(Part2Port,0x2C,tempah);
- tempah=(tempbx&0xFF00)>>8;
- tempah=(tempah<<4)&0xFF;
- SetRegANDOR(Part2Port,0x2B,~0x0F0,tempah);
-
- tempbx=VDE-1; //RTVACTEO=(VDE-1)&0xFF
- tempah=tempbx&0xFF;
- SetReg1(Part2Port,0x03,tempah);
- tempah=((tempbx&0xFF00)>>8)&0x07;
- SetRegANDOR(Part2Port,0x0C,~0x07,tempah);
-
- tempcx=VT-1;
- tempah=tempcx&0xFF; //RVTVT=VT-1
- SetReg1(Part2Port,0x19,tempah);
- tempah=(tempcx&0xFF00)>>8;
- tempah=(tempah<<5)&0xFF;
- if(LCDInfo&LCDRGB18Bit){
- tempah=tempah|0x10;
- }
- SetReg1(Part2Port,0x1A,tempah);
-
- tempcx++;
- if(LCDResInfo==Panel1024x768){
- tempbx=768;
- }else{
- tempbx=1024;
- }
-
- if(tempbx==VDE){
- tempax=1;
- }else{
- tempax=tempbx;
- tempax=(tempax-VDE)>>1;
- }
- tempcx=tempcx-tempax; //lcdvdes
- tempbx=tempbx-tempax; //lcdvdee
-
- tempah=tempcx&0xFF; //RVEQ1EQ=lcdvdes
- SetReg1(Part2Port,0x05,tempah);
- tempah=tempbx&0xFF; //RVEQ2EQ=lcdvdee
- SetReg1(Part2Port,0x06,tempah);
-
- tempah=(tempbx&0xFF00)>>8;
- tempah=(tempah<<3)&0xFF;
- tempah=tempah|((tempcx&0xFF00)>>8);
- //RTVACTSE=(lcdvdes&0x700>>8)+(lcdvdee&0x700>>5);
- SetReg1(Part2Port,0x02,tempah);
-
-
- tempcx=(VT-VDE)>>4; //(VT-VDE)>>4
- tempbx=(VT+VDE)>>1;
- tempah=tempbx&0xFF; //RTVACTEE=lcdvrs
- SetReg1(Part2Port,0x04,tempah);
-
- tempah=(tempbx&0xFF00)>>8;
- tempah=(tempah<<4)&0xFF;
- tempbx=tempbx+tempcx+1;
- tempbl=(tempbx&0x0F);
- tempah=tempah|tempbl; //RTVACTSO=lcdvrs&0x700>>4+lcdvre
- SetReg1(Part2Port,0x01,tempah);
-
- tempah=GetReg1(Part2Port,0x09);
- tempah=tempah&0xF0;
- SetReg1(Part2Port,0x09,tempah);
-
- tempah=GetReg1(Part2Port,0x0A);
- tempah=tempah&0xF0;
- SetReg1(Part2Port,0x0A,tempah);
-
- tempcx=(HT-HDE)>>2; //(HT-HDE)>>2
- tempbx=(HDE+7); //lcdhdee
- tempah=tempbx&0xFF; //RHEQPLE=lcdhdee
- SetReg1(Part2Port,0x23,tempah);
- tempah=(tempbx&0xFF00)>>8;
- SetRegANDOR(Part2Port,0x25,~0x0F,tempah);
-
- SetReg1(Part2Port,0x1F,0x07); //RHBLKE=lcdhdes
- tempah=GetReg1(Part2Port,0x20);
- tempah=tempah&0x0F;
- SetReg1(Part2Port,0x20,tempah);
-
- tempbx=tempbx+tempcx;
- tempah=tempbx&0xFF; //RHBURSTS=lcdhrs
- SetReg1(Part2Port,0x1C,tempah);
- tempah=(tempbx&0xFF00)>>8;
- tempah=(tempah<<4)&0xFF;
- SetRegANDOR(Part2Port,0x1D,~0x0F0,tempah);
-
- tempbx=tempbx+tempcx;
- tempah=tempbx&0xFF; //RHSYEXP2S=lcdhre
- SetReg1(Part2Port,0x21,tempah);
-
- tempah=GetReg1(Part2Port,0x17);
- tempah=tempah&0xFB;
- SetReg1(Part2Port,0x17,tempah);
-
- tempah=GetReg1(Part2Port,0x18);
- tempah=tempah&0xDF;
- SetReg1(Part2Port,0x18,tempah);
- return;
-}
-
-VOID SetGroup3(USHORT BaseAddr)
-{
- USHORT i;
- USHORT *tempdi;
- USHORT Part3Port;
- Part3Port=BaseAddr+IND_SIS_CRT2_PORT_12;
- if(VBInfo&SetPALTV){
- tempdi=PALGroup3Data;
- }else{
- tempdi=NTSCGroup3Data;
- }
-
- for(i=0;i<=0x3E;i++){
- SetReg1(Part3Port,i,tempdi[i]);
- }
- return;
-}
-
-VOID SetGroup4(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo)
-{
- USHORT Part4Port;
- USHORT tempax,tempah,tempcx,tempbx,tempbh,tempch,tempmodeflag;
- long int tempebx,tempeax,templong;
- Part4Port=BaseAddr+IND_SIS_CRT2_PORT_14;
-
- tempax=0x0c;
- if(VBInfo&SetCRT2ToTV){
- if(VBInfo&SetInSlaveMode){
- if(!(SetFlag&TVSimuMode)){
- SetFlag=SetFlag|RPLLDIV2XO;
- tempax=tempax|0x04000;
- }
- }else{
- SetFlag=SetFlag|RPLLDIV2XO;
- tempax=tempax|0x04000;
- }
- }
-
- if(LCDResInfo!=Panel1024x768){
- tempax=tempax|0x08000;
- }
- tempah=(tempax&0xFF00)>>8;
- SetReg1(Part4Port,0x0C,tempah);
-
- tempah=RVBHCFACT;
- SetReg1(Part4Port,0x13,tempah);
-
- tempbx=RVBHCMAX;
- tempah=tempbx&0xFF;
- SetReg1(Part4Port,0x14,tempah);
- tempbh=(((tempbx&0xFF00)>>8)<<7)&0xFF;
-
- tempcx=VGAHT-1;
- tempah=tempcx&0xFF;
- SetReg1(Part4Port,0x16,tempah);
- tempch=(((tempcx&0xFF00)>>8)<<3)&0xFF;
- tempbh=tempbh|tempch;
-
- tempcx=VGAVT-1;
- if(!(VBInfo&SetCRT2ToTV)){
- tempcx=tempcx-5;
- }
- tempah=tempcx&0xFF;
- SetReg1(Part4Port,0x17,tempah);
- tempbh=tempbh|((tempcx&0xFF00)>>8);
- tempah=tempbh;
- SetReg1(Part4Port,0x15,tempah);
-
- tempcx=VBInfo;
- tempbx=VGAHDE;
- tempmodeflag=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
- if(tempmodeflag&HalfDCLK){
- tempbx=tempbx>>1;
- }
-
- if(VBInfo&SetCRT2ToLCD){
- tempah=0;
- if(tempbx>800){
- tempah=0x60;
- }
- }else{
- tempah=0x080;
- }
- if(LCDResInfo!=Panel1280x1024){
- tempah=tempah|0x0A;
- }
-
- SetRegANDOR(Part4Port,0x0E,~0xEF,tempah);
-
- tempebx=VDE;
-
- tempcx=RVBHRS;
- tempah=tempcx&0xFF;
- SetReg1(Part4Port,0x18,tempah);
-
- tempeax=VGAVDE;
- tempcx=tempcx|0x04000;
- tempeax=tempeax-tempebx;
- if(tempeax<0){
- tempcx=tempcx^(0x04000);
- tempeax=VGAVDE;
- }
-
- templong=(tempeax*256*1024)/tempebx;
- if(tempeax*256*1024-templong*tempebx>0){
- tempebx=templong+1;
- }else{
- tempebx=templong;
- }
-
-
- tempah=(USHORT)(tempebx&0xFF);
- SetReg1(Part4Port,0x1B,tempah);
- tempah=(USHORT)((tempebx&0xFF00)>>8);
- SetReg1(Part4Port,0x1A,tempah);
- tempebx=tempebx>>16;
- tempah=(USHORT)(tempebx&0xFF);
- tempah=(tempah<<4)&0xFF;
- tempah=tempah|((tempcx&0xFF00)>>8);
- SetReg1(Part4Port,0x19,tempah);
-
- SetCRT2VCLK(BaseAddr,ROMAddr,ModeNo);
-}
-
-VOID SetCRT2VCLK(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo)
-{
- USHORT vclk2ptr;
- USHORT tempah,temp1;
- USHORT Part4Port;
- Part4Port=BaseAddr+IND_SIS_CRT2_PORT_14;
- vclk2ptr=GetVCLK2Ptr(ROMAddr,ModeNo);
- SetReg1(Part4Port,0x0A,0x01);
- tempah=*((UCHAR *)(ROMAddr+vclk2ptr+0x01)); //di+1
- SetReg1(Part4Port,0x0B,tempah);
- tempah=*((UCHAR *)(ROMAddr+vclk2ptr+0x00)); //di
- SetReg1(Part4Port,0x0A,tempah);
- SetReg1(Part4Port,0x12,0x00);
- tempah=0x08;
- if(VBInfo&SetCRT2ToRAMDAC){
- tempah=tempah|0x020;
- }
- temp1=GetReg1(Part4Port,0x12);
- tempah=tempah|temp1;
- SetReg1(Part4Port,0x12,tempah);
-}
-
-VOID SetGroup5(USHORT BaseAddr,ULONG ROMAddr)
-{
- USHORT Part5Port;
- USHORT Pindex,Pdata;
- Part5Port=BaseAddr+IND_SIS_CRT2_PORT_14+2;
- Pindex=Part5Port;
- Pdata=Part5Port+1;
- if(ModeType==ModeVGA){
- if(!(VBInfo&(SetInSlaveMode|LoadDACFlag|CRT2DisplayFlag))){
- EnableCRT2();
- LoadDAC2(ROMAddr,Part5Port);
- }
- }
- return;
-}
-
-VOID EnableCRT2()
-{
- USHORT temp1;
- temp1=GetReg1(P3c4,0x1E);
- temp1=temp1|0x20;
- SetReg1(P3c4,0x1E,temp1); //SR 1E
-}
-
-VOID LoadDAC2(ULONG ROMAddr,USHORT Part5Port)


-{
- USHORT data,data2;
- USHORT time,i,j,k;
- USHORT m,n,o;
- USHORT si,di,bx,dl;
- USHORT al,ah,dh;
- USHORT *table=VGA_DAC;

- USHORT Pindex,Pdata;
- Pindex=Part5Port;
- Pdata=Part5Port+1;


- data=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));
- data=data&DACInfoFlag;
- time=64;
- if(data==0x00) table=MDA_DAC;
- if(data==0x08) table=CGA_DAC;
- if(data==0x10) table=EGA_DAC;
- if(data==0x18) {
- time=256;
- table=VGA_DAC;
- }
- if(time==256) j=16;
- else j=time;
-

- //SetReg3(P3c6,0xFF);
- SetReg3(Pindex,0x00);


-
- for(i=0;i<j;i++) {
- data=table[i];
- for(k=0;k<3;k++) {
- data2=0;
- if(data&0x01) data2=0x2A;
- if(data&0x02) data2=data2+0x15;

- SetReg3(Pdata,data2);


- data=data>>2;
- }
- }
-
- if(time==256) {
- for(i=16;i<32;i++) {
- data=table[i];

- for(k=0;k<3;k++) SetReg3(Pdata,data);


- }
- si=32;
- for(m=0;m<9;m++) {
- di=si;
- bx=si+0x04;
- dl=0;
- for(n=0;n<3;n++) {
- for(o=0;o<5;o++) {
- dh=table[si];
- ah=table[di];
- al=table[bx];
- si++;

- WriteDAC2(Pdata,dl,ah,al,dh);
- } // for 5


- si=si-2;
- for(o=0;o<3;o++) {
- dh=table[bx];
- ah=table[di];
- al=table[si];
- si--;

- WriteDAC2(Pdata,dl,ah,al,dh);
- } // for 3
- dl++;
- } // for 3
- si=si+5;
- } // for 9
- }
-}
-
-VOID WriteDAC2(USHORT Pdata,USHORT dl, USHORT ah, USHORT al, USHORT dh)


-{
- USHORT temp;
- USHORT bh,bl;
-
- bh=ah;
- bl=al;
- if(dl!=0) {
- temp=bh;
- bh=dh;
- dh=temp;
- if(dl==1) {
- temp=bl;
- bl=dh;
- dh=temp;
- }
- else {
- temp=bl;
- bl=bh;
- bh=temp;
- }
- }

- SetReg3(Pdata,(USHORT)dh);
- SetReg3(Pdata,(USHORT)bh);
- SetReg3(Pdata,(USHORT)bl);
-}
-
-VOID LockCRT2(USHORT BaseAddr)
-{
- USHORT Part1Port;
- USHORT Part4Port;
- USHORT temp1;
- Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
- Part4Port=BaseAddr+IND_SIS_CRT2_PORT_14;
- temp1=GetReg1(Part1Port,0x24);
- temp1=temp1&0xFE;
- SetReg1(Part1Port,0x24,temp1);
-}
-
-VOID SetLockRegs()
-{
- USHORT temp1;
-
- if((VBInfo&SetInSlaveMode)&&(!(VBInfo&SetCRT2ToRAMDAC))){
- VBLongWait();
- temp1=GetReg1(P3c4,0x32);
- temp1=temp1|0x20;
- SetReg1(P3c4,0x32,temp1);
- VBLongWait();
- }
-}
-
-VOID EnableBridge(USHORT BaseAddr)
-{
- USHORT part2_02,part2_05;


- USHORT Part2Port,Part1Port;
- Part2Port=BaseAddr+IND_SIS_CRT2_PORT_10;
- Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
-
- if(IF_DEF_LVDS==0){

- part2_02=(UCHAR)GetReg1(Part2Port,0x02);
- part2_05=(UCHAR)GetReg1(Part2Port,0x05);
- SetReg1(Part2Port,0x02,0x38);
- SetReg1(Part2Port,0x05,0xFF);
- LongWait();
- SetRegANDOR(Part2Port,0x00,~0x0E0,0x020);
- WaitVBRetrace(BaseAddr);
- SetReg1(Part2Port,0x02,part2_02);
- SetReg1(Part2Port,0x05,part2_05);
- }else{
- EnableCRT2();
- UnLockCRT2(BaseAddr);
- SetRegANDOR(Part1Port,0x02,~0x040,0x0);
- }
-}
-
-USHORT GetLockInfo(USHORT pattern)
-{
- USHORT temp1;
- temp1=GetReg1(P3d4,0x36);
- return(temp1&pattern);
-}
-
-VOID GetVBInfo(USHORT BaseAddr,ULONG ROMAddr)
-{
- USHORT flag1,tempbx,tempbl,tempbh,tempah;
-
- SetFlag=0;
- tempbx=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
- tempbl=tempbx&ModeInfoFlag;
- ModeType=tempbl;
- tempbx=0;
- flag1=GetReg1(P3c4,0x38); //call BridgeisOn
- if(!(flag1&0x20)){
- VBInfo=CRT2DisplayFlag;
- return;
- }
- tempbl=GetReg1(P3d4,0x30);
- tempbh=GetReg1(P3d4,0x31);
- if(!(tempbl&0x07C)){
- VBInfo=CRT2DisplayFlag;
- return;


- }
- if(IF_DEF_LVDS==1){ //for LVDS

- if(!(tempbl&SetCRT2ToLCD)){
- VBInfo=CRT2DisplayFlag;
- return;
- }
- }
- if(IF_DEF_LVDS==0){ //for 301
- if(tempbl&SetCRT2ToRAMDAC){
- tempbl=tempbl&(SetCRT2ToRAMDAC|SwitchToCRT2|SetSimuScanMode);
- }else if(tempbl&SetCRT2ToLCD){
- tempbl=tempbl&(SetCRT2ToLCD|SwitchToCRT2|SetSimuScanMode);
- }else if(tempbl&SetCRT2ToSCART){
- tempbl=tempbl&(SetCRT2ToSCART|SwitchToCRT2|SetSimuScanMode);
- }else if(tempbl&SetCRT2ToHiVisionTV){
- tempbl=tempbl&(SetCRT2ToHiVisionTV|SwitchToCRT2|SetSimuScanMode);
- }
- }else{ //for LVDS
- if(tempbl&SetCRT2ToLCD){
- tempbl=tempbl&(SetCRT2ToLCD|SwitchToCRT2|SetSimuScanMode);
- }
- }
- tempah=GetReg1(P3d4,0x31);
- if(tempah&(CRT2DisplayFlag>>8)){
- if(!(tempbl&(SwitchToCRT2|SetSimuScanMode))){
- tempbx=SetSimuScanMode|CRT2DisplayFlag;
- tempbh=((tempbx&0xFF00)>>8);
- tempbl=tempbx&0xFF;
- }
- }
- if(!(tempbh&(DriverMode>>8))){
- tempbl=tempbl|SetSimuScanMode;
- }
- VBInfo=tempbl|(tempbh<<8);
- if(!(VBInfo&SetSimuScanMode)){
- if(!(VBInfo&SwitchToCRT2)){
- if(BridgeIsEnable(BaseAddr)){
- if(BridgeInSlave()){
- VBInfo=VBInfo|SetSimuScanMode;
- }
- }
- }
- }
- if(!((VBInfo&(SetSimuScanMode|SwitchToCRT2)))){
- return;
- }
- if(!(VBInfo&DriverMode)){
- VBInfo=VBInfo|SetInSlaveMode;
- if((VBInfo&SetCRT2ToTV)&&(!(VBInfo&SetNotSimuTVMode))){
- SetFlag=SetFlag|TVSimuMode;
- }
- return;
- }
- flag1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
- if(!(flag1&(CRT2Mode|CRT2DisplayFlag))){
- VBInfo=VBInfo|SetInSlaveMode;
- if((VBInfo&SetCRT2ToTV)&&(!(VBInfo&SetNotSimuTVMode))){
- SetFlag=SetFlag|TVSimuMode;
- }
- }
-}
-
-BOOLEAN BridgeIsEnable(USHORT BaseAddr)
-{
- USHORT flag1;
- USHORT Part1Port;
- Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
-
- if(IF_DEF_LVDS==1){
- return 1;
- }
- flag1=GetReg1(P3c4,0x38); //call BridgeisOn
- if(!(flag1&0x20)){ return 0;}
- flag1=GetReg1(Part1Port,0x0);
- if(flag1&0x0a0){
- return 1;
- }else{


- return 0;
- }
-}
-

-BOOLEAN BridgeInSlave()
-{
- USHORT flag1;
- flag1=GetReg1(P3d4,0x31);
- if(flag1&(SetInSlaveMode>>8)){
- return 1;
- }else{


- return 0;
- }
-}
-

-BOOLEAN GetLCDResInfo(ULONG ROMAddr,USHORT P3d4)
-{
- USHORT tempah,tempbh,tempflag;
-
- tempah=(UCHAR)GetReg1(P3d4,0x36);
- tempbh=tempah;
- tempah=tempah&0x0F;
- if(tempah>Panel1280x1024) tempah=Panel1024x768;
- LCDResInfo=tempah;
- tempbh=tempbh>>4;
- LCDTypeInfo=tempbh;
-
- tempah=(UCHAR)GetReg1(P3d4,0x37);
- LCDInfo=tempah;
- if(IF_DEF_TRUMPION){
- LCDInfo=LCDInfo&(~LCDNonExpanding);
- }
- if(IF_DEF_LVDS==1){
- tempflag=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
- if(tempflag&HalfDCLK){
- if(IF_DEF_TRUMPION==0){
- if(!(LCDInfo&LCDNonExpanding)){
- if(LCDResInfo==Panel1024x768){
- tempflag=*((UCHAR *)(ROMAddr+ModeIDOffset+0x09)); //si+Ext_ResInfo
- if(tempflag==4){ //512x384
- SetFlag=SetFlag|EnableLVDSDDA;
- }
- }else{
- if(LCDResInfo==Panel800x600){
- tempflag=*((UCHAR *)(ROMAddr+ModeIDOffset+0x09)); //si+Ext_ResInfo
- if(tempflag==3){ //400x300
- SetFlag=SetFlag|EnableLVDSDDA;
- }
- }
- }
- }else{
- SetFlag=SetFlag|EnableLVDSDDA;
- }
- }else{
- SetFlag=SetFlag|EnableLVDSDDA;
- }
- }
- }
-
- if(!(VBInfo&SetCRT2ToLCD)){
- return 1;
- }
- if(!(VBInfo&(SetSimuScanMode|SwitchToCRT2))){
- return 1;
- }
- if(VBInfo&SetInSlaveMode){
- if(VBInfo&SetNotSimuTVMode){
- SetFlag=SetFlag|LCDVESATiming;
- }
- }else{
- SetFlag=SetFlag|LCDVESATiming;

- }
- return 1;
-}
-

-VOID PresetScratchregister(USHORT P3d4,PHW_DEVICE_EXTENSION HwDeviceExtension)
-{
- SetReg1(P3d4,0x37,0x00);
-}
-
-BOOLEAN GetLCDDDCInfo(PHW_DEVICE_EXTENSION HwDeviceExtension)
-{
- USHORT tempah;
- tempah=(HwDeviceExtension->usLCDType);// set in sisv.c
- //0:no lcd 1:1024x768 2:1280x1024
- if(tempah>0) tempah++; // usLCDType:
- // 0:no lcd 1:800x600 2:1024x768 3:1280x1024
- SetReg1(P3d4,0x36,tempah);//cr 36 0:no LCD 1:800x600 2:1024x768 3:1280x1024
- if(tempah>0) return 1;
- else return 0;
-}
-
-VOID SetTVSystem(PHW_DEVICE_EXTENSION HwDeviceExtension,ULONG ROMAddr)
-{
- USHORT tempah,temp;
-
- if(IF_DEF_LVDS==0){ //301
- if(PRIMARY_VGA==1){ //primary vga


- if(HwDeviceExtension->jChipID >= SIS_Trojan){

- tempah=GetReg1(P3c4,0x17);
- if(tempah&ModeSwitchStatus){
- tempah=GetReg1(P3c4,0x16);
- tempah=tempah&ActivePAL;
- tempah=tempah>>ActivePALShift;
- }else{
- temp=*((UCHAR *)(ROMAddr+SoftSettingAddr));
- if(temp&SoftTVType){
- tempah=*((UCHAR *)(ROMAddr+ModeSettingAddr));
- }else{
- tempah=GetReg1(P3c4,0x38); //SR 38
- }
- }
- }else{
- temp=*((UCHAR *)(ROMAddr+SoftSettingAddr));
- if(temp&SoftTVType){
- tempah=*((UCHAR *)(ROMAddr+ModeSettingAddr));
- }else{
- tempah=GetReg1(P3c4,0x38); //SR 38
- }
- }
- tempah=tempah&0x01; //get SR 38 D0 TV Type Selection
- //0:NTSC 1:PAL
- SetRegANDOR(P3d4,0x31,~0x01,tempah);//set CR 31 D0= SR 38 D0
- }
- else{ //Secondary
- tempah=GetReg1(P3c4,0x38); //SR 38
- tempah=tempah&0x01; //get SR 38 D0 TV Type Selection
- //0:NTSC 1:PAL
- SetRegANDOR(P3d4,0x31,~0x01,tempah);//set CR 31 D0= SR 38 D0
- }


- return;
- }else{ //LVDS

- tempah=GetReg1(P3c4,0x16); //SR 16
- tempah=tempah&ActiveNonExpanding;
- tempah=tempah>>ActiveNonExpandingShift;
- tempah=tempah&0x01;
- tempah=tempah<<LCDNonExpandingShift;
- SetRegANDOR(P3d4,0x37,~LCDNonExpanding,tempah);


- return;
- }
-}
-

-BOOLEAN GetSenseStatus(PHW_DEVICE_EXTENSION HwDeviceExtension,USHORT BaseAddr,ULONG ROMAddr)
-{
- USHORT flag1,tempbx,tempal,tempah,tempcx,i;
- USHORT Part2Port,Part4Port;
- USHORT RGBSenseData,YCSenseData,VideoSenseData;
- USHORT P2reg0,SenseModeNo,OutputSelect;
- Part2Port=BaseAddr+IND_SIS_CRT2_PORT_10;
- Part4Port=BaseAddr+IND_SIS_CRT2_PORT_14;
- RGBSenseData=*((USHORT *)(ROMAddr+0xF8)); //0:F8 in rompost.asm
- YCSenseData=*((USHORT *)(ROMAddr+0xFA)); //0:FA in rompost.asm
- VideoSenseData=*((USHORT *)(ROMAddr+0xFC)); //0:FC in rompost.asm
-
- if(IF_DEF_LVDS==1){
- GetPanelID();
- tempah=LCDSense;
- SetRegANDOR(P3d4,0x32,~0x5F,tempah); //Set CR 32


- return 0;
- }
-

- flag1=GetReg1(P3c4,0x38); //call BridgeisOn
- if(!(flag1&0x20)){ return 0;}
- P2reg0=GetReg1(Part2Port,0x00); //save Part2 Reg index 0
-
- if(!(BridgeIsEnable(BaseAddr))){
- SenseModeNo=0x2E;
- ModeType=ModeVGA;
- VBInfo=SetCRT2ToRAMDAC;
- SetFlag=0;
- SetCRT2Group(BaseAddr,ROMAddr,SenseModeNo,HwDeviceExtension);
- //here perform I/O delay ,read SR 05
- for(i=0;i<0x7FFF;i++){
- flag1=GetReg1(P3c4,0x05);
- }
- }
-
- SetReg1(Part2Port,0x00,0x1C); //Set part2 index 0= 0x1C
- tempah=0;
-
- OutputSelect=*((UCHAR *)(ROMAddr+0xFE)); //OutputSelect 0:FE in Rompost.asm
- if(OutputSelect&SetSCARTOutput){
- tempal=SCARTSense;
- }else{
- tempal=Monitor2Sense;
- }
- tempbx=RGBSenseData;
- tempcx=0x0E08;
- if(Sense(Part4Port,tempbx,tempcx)){
- if(Sense(Part4Port,tempbx,tempcx)){
- tempah=tempah|tempal;
- }
- }
- tempbx=YCSenseData;
- tempcx=0x0604;
- if(Sense(Part4Port,tempbx,tempcx)){
- if(Sense(Part4Port,tempbx,tempcx)){
- tempah=tempah|SVIDEOSense;
- //Skipped lines about HiTVSense, assuming not HiTV
- }
- }
-
- //Assuming not HiTV ,below is of ifndef HiVisionTV
- if(OutputSelect&BoardTVType){
- tempbx=VideoSenseData;
- tempcx=0x0804;
- if(Sense(Part4Port,tempbx,tempcx)){
- if(Sense(Part4Port,tempbx,tempcx)){
- tempah=tempah|AVIDEOSense;
- }
- }
- }else{
- if(!(tempah&SVIDEOSense)){
- tempbx=VideoSenseData;
- tempcx=0x0804;
- if(Sense(Part4Port,tempbx,tempcx)){
- if(Sense(Part4Port,tempbx,tempcx)){
- tempah=tempah|AVIDEOSense;
- }
- }
- }
- }
- //end of ifndef HivisionTv
- if(SenseLCD(HwDeviceExtension,Part4Port,ROMAddr)){
- if(SenseLCD(HwDeviceExtension,Part4Port,ROMAddr)){
- tempah=tempah|LCDSense;
- }
- }
-
- tempbx=0;
- tempcx=0;
- Sense(Part4Port,tempbx,tempcx);
-
- SetRegANDOR(P3d4,0x32,~0x5F,tempah); //Set CR 32
- SetReg1(Part2Port,0x00,P2reg0); //recover Part2 reg index 0
-
- //here skipped lines about DisableCRT2Display

- return 0;
-}
-

-BOOLEAN Sense(USHORT Part4Port,USHORT inputbx,USHORT inputcx)
-{
- USHORT tempah,tempcl,tempch;
-
- tempah=inputbx&0xFF;
- SetReg1(Part4Port,0x11,tempah);//Part4 index 11
- tempah=(inputbx&0xFF00)>>8;
- tempcl=inputcx&0xFF;
- tempah=tempah|tempcl;
- SetRegANDOR(Part4Port,0x10,~0x1F,tempah);//Part4 index 10
-
- tempch=(inputcx&0xFF00)>>8;
- tempch=tempch&0x7F;
- //here skipped lines about call Delay
- tempah=GetReg1(Part4Port,0x03); //Part4 index 03
- tempah=tempah^(0x0E);
- tempah=tempah&tempch;
- if(tempah>0) return 1;
- else return 0;
-}
-
-BOOLEAN SenseLCD(PHW_DEVICE_EXTENSION HwDeviceExtension,USHORT Part4Port,ULONG ROMAddr)
-{
- USHORT SoftSetting;
- USHORT tempah;
- SoftSetting=*((UCHAR *)(ROMAddr+0x52));//0:52 in rompost.asm
- if(GetLCDDDCInfo(HwDeviceExtension)){
- return 1;
- }
- if(SoftSetting&HotPlugFunction){
- tempah=GetReg1(Part4Port,0x0F);
- tempah=tempah&0x3F;
- SetReg1(Part4Port,0x0F,tempah); //Part4 index 0F
- if(Sense(Part4Port,0x0,0x9010)){
- return 1;
- }else{
- return 0;
- }
- }else{


- return 0;
- }
-}

-#endif
-
-VOID SetRegANDOR(USHORT Port,USHORT Index,USHORT DataAND,USHORT DataOR)
-{
- USHORT temp1;
- temp1=GetReg1(Port,Index); //part1port index 02
- temp1=(temp1&(DataAND))|DataOR;
- SetReg1(Port,Index,temp1);
-}
-
-BOOLEAN DetectMonitor(PHW_DEVICE_EXTENSION HwDeviceExtension)
-{
- USHORT flag1 ;
- USHORT DAC_TEST_PARMS[3]={0x0F,0x0F,0x0F};
- USHORT DAC_CLR_PARMS[3]={0x00,0x00,0x00};
-
- flag1=GetReg1(P3c4,0x38); //call BridgeisOn
- if((flag1&0x20)){
- SetReg1(P3d4,0x30,0x41);
- }
-
- SiSSetMode(HwDeviceExtension,0x2E); //set mode to 0x2E instead of 0x3
-
- ClearDAC(P3c8);
- ClearALLBuffer(HwDeviceExtension);
-
- LongWait(); //wait vertical retrace
- LongWait();
-
- flag1=TestMonitorType(DAC_TEST_PARMS[0],DAC_TEST_PARMS[1],
- DAC_TEST_PARMS[2]);
- if(flag1==0){
- flag1=TestMonitorType(DAC_TEST_PARMS[0],DAC_TEST_PARMS[1],
- DAC_TEST_PARMS[2]);
- }
- if(flag1==1){
- SetRegANDOR(P3d4,0x32,~Monitor1Sense,Monitor1Sense);
- }else{
- SetRegANDOR(P3d4,0x32,~Monitor1Sense,0x0);
- }
- TestMonitorType(DAC_CLR_PARMS[0],DAC_CLR_PARMS[1],DAC_CLR_PARMS[2]);
-
- SetReg1(P3d4,0x34,0x4A); //Preset default CRT1 ModeNo =0x4A
- //which is used in SetCRT2FIFO()


- return 1;
-}
-

-BOOLEAN TestMonitorType(USHORT d1,USHORT d2,USHORT d3)
-{
- USHORT temp;
- SetReg3(P3c6,0xFF);
- SetReg3(P3c8,0x00);
- SetReg3(P3c9,d1);
- SetReg3(P3c9,d2);
- SetReg3(P3c9,d3);
- WaitDisplay(); //wait horizontal retrace
- temp=GetReg2(P3c2);
- if(temp&0x10) return 1;
- else return 0;
-}
-
-VOID WaitDisplay(void)


-{
- USHORT temp;
-

- for(temp=0;temp==0;){
- temp=GetReg2(P3da);
- temp=temp&0x01;
- }
- for(;temp==1;){
- temp=GetReg2(P3da);
- temp=temp&0x01;
- }
-}
-
-VOID LongWait(void)


-{
- USHORT temp;
-

- for(temp=1;temp>0;){
- temp=GetReg2(P3da);
- temp=temp&0x08;
- }
- for(;temp==0;){
- temp=GetReg2(P3da);
- temp=temp&0x08;
- }
-}
-
-#ifndef CONFIG_FB_SIS_LINUXBIOS
-
-VOID VBLongWait(VOID)
-{
- USHORT regsr1f,tempah,temp;
-
- regsr1f=GetReg1(P3c4,0x1F);
- tempah=regsr1f&(~0xC0);
- SetReg1(P3c4,0x1F,tempah);
-
- for(temp=1;temp>0;){
- temp=GetReg2(P3da);
- temp=temp&0x08;
- }
- for(;temp==0;){
- temp=GetReg2(P3da);
- temp=temp&0x08;
- }
-
- SetReg1(P3c4,0x1F,regsr1f);
- return;
-}
-
-BOOLEAN WaitVBRetrace(USHORT BaseAddr)
-{
- USHORT temp;
- USHORT Part1Port;
- Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
- temp=GetReg1(Part1Port,0x00);
- if(!(temp&0x80)){


- return 0;
- }
-

- for(temp=0;temp==0;){
- temp=GetReg1(Part1Port,0x25);
- temp=temp&0x01;
- }
- for(;temp>0;){
- temp=GetReg1(Part1Port,0x25);
- temp=temp&0x01;

- }
- return 1;
-}
-

-BOOLEAN GetPanelID(VOID)
-{
- USHORT PanelTypeTable[16]={ SyncPP|Panel800x600|PanelType00,
- SyncPP|Panel1024x768|PanelType01,
- SyncPP|Panel1024x768|PanelType02,
- SyncPP|Panel1024x768|PanelType03,
- SyncPP|Panel1024x768|PanelType04,
- SyncPP|Panel1024x768|PanelType05,
- SyncPP|Panel1024x768|PanelType06,
- SyncPP|Panel1024x768|PanelType07,
- SyncPP|Panel1024x768|PanelType08,
- SyncPP|Panel1024x768|PanelType09,
- SyncPP|Panel800x600|PanelType0A,
- SyncPP|Panel1024x768|PanelType0B,
- SyncPP|Panel1024x768|PanelType0C,
- SyncPP|Panel1024x768|PanelType0D,
- SyncPP|Panel1024x768|PanelType0E,
- SyncPP|Panel1024x768|PanelType0F};
- // Bit 15 BPLVSPLTY
- // Bit 14 BPLHSPLTY
- // Bit 6-3 Panel Type
- // Bit 2-0 Display Resolution(001:800x600 010:1024x768 011:1280x1024)
- USHORT tempah,tempbx;
- USHORT return_flag;
-
- tempah=GetReg1(P3c4,0x18);
- tempbx=tempah&0x0F;
- if(tempah&0x10){
- return_flag=1;
- }else{
- return_flag=0;
- }
-
- if(return_flag==0){
- if(IF_DEF_LVDS==1){
- tempbx=0;
- tempah=GetReg1(P3c4,0x38);
- if(tempah&0x40) tempbx=tempbx|0x08;
- if(tempah&0x20) tempbx=tempbx|0x02;
- if(tempah&0x01) tempbx=tempbx|0x01;
- tempah=GetReg1(P3c4,0x39);
- if(tempah&0x80) tempbx=tempbx|0x04;
- }else{


- return 0;
- }
- }
-

- if(IF_DEF_TRUMPION==1){
- tempbx=1;
- }
- tempbx=PanelTypeTable[tempbx]; //LVDS table entry
- tempbx=tempbx|(USHORT)(LCDSync<<8);
-
- tempah=tempbx&0x0FF;
- SetReg1(P3d4,0x36,tempah);
- tempah=(tempbx&0xFF00)>>8;
- SetRegANDOR(P3d4,0x37,~LCDSyncBit,tempah);


- return 1;
-}
-

-VOID ModCRT1CRTC(ULONG ROMAddr,USHORT ModeNo)
-{
- USHORT OldREFIndex,temp,tempah,i,modeflag1;
-
- OldREFIndex=(USHORT)REFIndex;
- temp=GetLVDSCRT1Ptr(ROMAddr,ModeNo);
- if(temp==0){
- REFIndex=OldREFIndex;
- return;
- }
- tempah=(UCHAR)GetReg1(P3d4,0x11);//unlock cr0-7
- tempah=tempah&0x7F;
- SetReg1(P3d4,0x11,tempah);
- tempah=*((UCHAR *)(ROMAddr+REFIndex));
- SetReg1(P3d4,0x0,tempah);
- REFIndex++;
- for(i=0x02;i<=0x05;REFIndex++){
- tempah=*((UCHAR *)(ROMAddr+REFIndex));
- SetReg1(P3d4,i,tempah);
- }
- for(i=0x06;i<=0x07;REFIndex++){
- tempah=*((UCHAR *)(ROMAddr+REFIndex));
- SetReg1(P3d4,i,tempah);
- }
- for(i=0x10;i<=0x11;REFIndex++){
- tempah=*((UCHAR *)(ROMAddr+REFIndex));
- SetReg1(P3d4,i,tempah);
- }
- for(i=0x15;i<=0x16;REFIndex++){
- tempah=*((UCHAR *)(ROMAddr+REFIndex));
- SetReg1(P3d4,i,tempah);
- }
-
- for(i=0x0A;i<=0x0C;REFIndex++){
- tempah=*((UCHAR *)(ROMAddr+REFIndex));
- SetReg1(P3c4,i,tempah);
- }
- tempah=*((UCHAR *)(ROMAddr+REFIndex));
- tempah=tempah&0x0E0;
- SetReg1(P3c4,0x0E,tempah);
-
- tempah=*((UCHAR *)(ROMAddr+REFIndex));
- tempah=tempah&0x01;
- tempah=tempah<<5;


- modeflag1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag

- if(modeflag1&DoubleScanMode){
- tempah=tempah|0x080;
- }
- SetRegANDOR(P3d4,0x09,~0x020,tempah);
- REFIndex=OldREFIndex;
- return;
-}
-
-VOID SetCRT2ECLK(ULONG ROMAddr, USHORT ModeNo)
-{
- USHORT OldREFIndex,tempah,tempal;
- USHORT P3cc=P3c9+3;
- OldREFIndex=(USHORT)REFIndex;
- if(IF_DEF_TRUMPION==0){ //no trumpion
- tempal=GetReg2(P3cc);
- tempal=tempal&0x0C;
- SetReg3(P3c2,tempal);
- REFIndex=GetVCLKPtr(ROMAddr,ModeNo);
- }else{ //trumpion
- SetFlag=SetFlag&(~ProgrammingCRT2);
- tempal=*((UCHAR *)(ROMAddr+REFIndex+0x03)); //di+Ext_CRTVCLK
- tempal=tempal&0x03F;
- if(tempal==0x02){ //31.5MHz
- REFIndex=REFIndex-Ext2StructSize;
- }
- REFIndex=GetVCLKPtr(ROMAddr,ModeNo);
- SetFlag=SetFlag|ProgrammingCRT2;
- }
- tempal=0x02B;
- if(!(VBInfo&SetInSlaveMode)){
- tempal=tempal+3;
- }
- tempah=*((UCHAR *)(ROMAddr+REFIndex));
- SetReg1(P3c4,tempal,tempah);
- tempah=*((UCHAR *)(ROMAddr+REFIndex+1));
- tempal++;
- SetReg1(P3c4,tempal,tempah);
- REFIndex=OldREFIndex;
- return;
-}
-
-USHORT GetLVDSDesPtr(ULONG ROMAddr,USHORT ModeNo)
-{
- USHORT tempcl,tempbx,tempal,tempptr,LVDSDesPtrData;
- tempcl=LVDSDesDataLen;
- tempbx=LCDTypeInfo;
- if(LCDInfo&LCDNonExpanding){
- tempbx=tempbx+16;
- }
- if(ModeNo<=0x13){
- tempal=*((UCHAR *)(ROMAddr+ModeIDOffset+0x04)); // si+St_CRT2CRTC
- }else{
- tempal=*((UCHAR *)(ROMAddr+REFIndex+4)); //di+Ext_CRT2CRTC
- }
- tempal=tempal&0x1F;
- tempal=tempal*tempcl;
- tempbx=tempbx<<1;
- LVDSDesPtrData=*((USHORT *)(ROMAddr+ADR_LVDSDesPtrData));
- tempptr=*((USHORT *)(ROMAddr+LVDSDesPtrData+tempbx));
- tempptr=tempptr+tempal;
- return(tempptr);
-
-}
-
-BOOLEAN GetLVDSCRT1Ptr(ULONG ROMAddr,USHORT ModeNo)
-{
- USHORT tempal,tempbx,modeflag1;
- USHORT LVDSCRT1DataPtr;
-
- if(!(VBInfo&SetInSlaveMode)){
- return 0;
- }
- if(ModeNo<=0x13){
- tempal=*((UCHAR *)(ROMAddr+ModeIDOffset+0x04)); // si+St_CRT2CRTC
- }else{
- tempal=*((UCHAR *)(ROMAddr+REFIndex+4)); //di+Ext_CRT2CRTC
- }
- tempal=tempal&0x3F;
-
- tempbx=LCDResInfo;
- tempbx=tempbx-Panel800x600;
- if(LCDInfo&LCDNonExpanding){
- tempbx=tempbx+6;
- }


- modeflag1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
- if(modeflag1&HalfDCLK){

- tempbx=tempbx+3;
- }
- tempbx=tempbx<<1;
- LVDSCRT1DataPtr=*((USHORT *)(ROMAddr+ADR_LVDSCRT1DataPtr));
- REFIndex=*((USHORT *)(ROMAddr+LVDSCRT1DataPtr+tempbx));
- tempal=tempal*LVDSCRT1Len;
- REFIndex=REFIndex+tempal;


- return 1;
-}
-

-#endif
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/sis_301.h linux/drivers/video/sis/sis_301.h
--- v2.4.14/linux/drivers/video/sis/sis_301.h Tue Mar 6 19:28:33 2001
+++ linux/drivers/video/sis/sis_301.h Wed Dec 31 16:00:00 1969
@@ -1,224 +0,0 @@


-#include <linux/config.h>
-#include "initdef.h"
-

-USHORT SetFlag,RVBHCFACT,RVBHCMAX,VGAVT,VGAHT,VT,HT,VGAVDE,VGAHDE;
-USHORT VDE,HDE,RVBHRS,NewFlickerMode,RY1COE,RY2COE,RY3COE,RY4COE;
-extern USHORT LCDResInfo,LCDTypeInfo,LCDInfo;
-USHORT VCLKLen;
-USHORT LCDHDES,LCDVDES;
-
-USHORT StResInfo[5][2]={{640,400},{640,350},{720,400},{720,350},{640,480}};
-
-USHORT ModeResInfo[15][4]={{320,200,8,8},{320,240,8,8},{320,400,8,8},
- {400,300,8,8},{512,384,8,8},{640,400,8,16},
- {640,480,8,16},{800,600,8,16},{1024,768,8,16},
- {1280,1024,8,16},{1600,1200,8,16},{1920,1440,8,16},
- {720,480,8,16},{720,576,8,16},{1280,960,8,16}};
-
-
-USHORT NTSCTiming[61]={0x017,0x01D,0x003,0x009,0x005,0x006,0x00C,0x00C,
- 0x094,0x049,0x001,0x00A,0x006,0x00D,0x004,0x00A,
- 0x006,0x014,0x00D,0x004,0x00A,0x000,0x085,0x01B,
- 0x00C,0x050,0x000,0x099,0x000,0x0EC,0x04A,0x017,
- 0x088,0x000,0x04B,0x000,0x000,0x0E2,0x000,0x002,
- 0x003,0x00A,0x065,0x09D,0x008,
- 0x092,0x08F,0x040,0x060,0x080,0x014,0x090,0x08C,
- 0x060,0x014,0x050,0x000,0x040,
- 0x00044,0x002DB,0x0003B};//Ajust xxx
-
-USHORT PALTiming[61]={ 0x019,0x052,0x035,0x06E,0x004,0x038,0x03D,0x070,
- 0x094,0x049,0x001,0x012,0x006,0x03E,0x035,0x06D,
- 0x006,0x014,0x03E,0x035,0x06D,0x000,0x045,0x02B,
- 0x070,0x050,0x000,0x097,0x000,0x0D7,0x05D,0x017,


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

echo 'End of part 082'
echo 'File patch-2.4.15 is continued in part 083'
echo "083" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:02 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part086

#!/bin/sh -x
# this is part 086 of a 115 - part archive


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

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

X obj-y += dquot.o
@@ -26,11 +26,14 @@
X subdir-y += partitions
X
X # Do not add any filesystems before this line
+subdir-$(CONFIG_EXT3_FS) += ext3 # Before ext2 so root fs can be ext3
+subdir-$(CONFIG_JBD) += jbd
X subdir-$(CONFIG_EXT2_FS) += ext2
X subdir-$(CONFIG_ZLIB_FS_INFLATE) += inflate_fs
X subdir-$(CONFIG_CRAMFS) += cramfs
X subdir-$(CONFIG_RAMFS) += ramfs
X subdir-$(CONFIG_CODA_FS) += coda
+subdir-$(CONFIG_INTERMEZZO_FS) += intermezzo
X subdir-$(CONFIG_MINIX_FS) += minix
X subdir-$(CONFIG_FAT_FS) += fat
X subdir-$(CONFIG_UMSDOS_FS) += umsdos
diff -u --recursive --new-file v2.4.14/linux/fs/affs/super.c linux/fs/affs/super.c
--- v2.4.14/linux/fs/affs/super.c Sun Sep 23 11:41:00 2001
+++ linux/fs/affs/super.c Tue Nov 13 09:19:41 2001
@@ -270,7 +270,6 @@
X size = (BLOCK_SIZE / 512) * blocks;
X pr_debug("AFFS: initial blksize=%d, blocks=%d\n", 512, blocks);
X
-#warning
X affs_set_blocksize(sb, PAGE_SIZE);
X /* Try to find root block. Its location depends on the block size. */
X
diff -u --recursive --new-file v2.4.14/linux/fs/autofs4/inode.c linux/fs/autofs4/inode.c
--- v2.4.14/linux/fs/autofs4/inode.c Fri Feb 9 11:29:44 2001
+++ linux/fs/autofs4/inode.c Fri Nov 9 14:11:14 2001
@@ -315,8 +315,10 @@
X inode->i_nlink = 2;
X inode->i_op = &autofs4_dir_inode_operations;
X inode->i_fop = &autofs4_dir_operations;
- } else if (S_ISLNK(inf->mode))
+ } else if (S_ISLNK(inf->mode)) {
+ inode->i_size = inf->size;
X inode->i_op = &autofs4_symlink_inode_operations;
+ }
X
X return inode;
X }
diff -u --recursive --new-file v2.4.14/linux/fs/block_dev.c linux/fs/block_dev.c
--- v2.4.14/linux/fs/block_dev.c Mon Nov 5 15:55:33 2001
+++ linux/fs/block_dev.c Wed Nov 21 14:07:25 2001
@@ -113,6 +113,11 @@


X return 0;
X }
X

+static int blkdev_direct_IO(int rw, struct inode * inode, struct kiobuf * iobuf, unsigned long blocknr, int blocksize)
+{
+ return generic_direct_IO(rw, inode, iobuf, blocknr, blocksize, blkdev_get_block);
+}
+
X static int blkdev_writepage(struct page * page)
X {
X return block_write_full_page(page, blkdev_get_block);
@@ -640,6 +645,7 @@
X sync_page: block_sync_page,
X prepare_write: blkdev_prepare_write,
X commit_write: blkdev_commit_write,
+ direct_IO: blkdev_direct_IO,
X };
X
X struct file_operations def_blk_fops = {
diff -u --recursive --new-file v2.4.14/linux/fs/buffer.c linux/fs/buffer.c
--- v2.4.14/linux/fs/buffer.c Mon Nov 5 15:55:33 2001
+++ linux/fs/buffer.c Wed Nov 21 14:40:17 2001
@@ -45,6 +45,7 @@
X #include <linux/quotaops.h>
X #include <linux/iobuf.h>
X #include <linux/highmem.h>
+#include <linux/module.h>
X #include <linux/completion.h>
X
X #include <asm/uaccess.h>
@@ -538,6 +539,15 @@
X __remove_from_lru_list(bh);
X }
X
+static void remove_from_queues(struct buffer_head *bh)
+{
+ spin_lock(&lru_list_lock);
+ write_lock(&hash_table_lock);
+ __remove_from_queues(bh);
+ write_unlock(&hash_table_lock);
+ spin_unlock(&lru_list_lock);
+}
+
X struct buffer_head * get_hash_table(kdev_t dev, int block, int size)
X {
X struct buffer_head *bh, **p = &hash(dev, block);
@@ -613,8 +623,12 @@
X information that was supposed to be just stored on the physical layer
X by the user.
X
- Thus invalidate_buffers in general usage is not allwowed to trash dirty
- buffers. For example ioctl(FLSBLKBUF) expects dirty data to be preserved.
+ Thus invalidate_buffers in general usage is not allwowed to trash
+ dirty buffers. For example ioctl(FLSBLKBUF) expects dirty data to
+ be preserved. These buffers are simply skipped.
+
+ We also skip buffers which are still in use. For example this can
+ happen if a userspace program is reading the block device.
X
X NOTE: In the case where the user removed a removable-media-disk even if
X there's still dirty data not synced on disk (due a bug in the device driver
@@ -1090,6 +1104,12 @@
X }
X }
X
+void set_buffer_flushtime(struct buffer_head *bh)
+{
+ bh->b_flushtime = jiffies + bdf_prm.b_un.age_buffer;
+}
+EXPORT_SYMBOL(set_buffer_flushtime);
+
X /*
X * A buffer may need to be moved from one buffer list to another
X * (e.g. in case it is not shared any more). Handle this.
@@ -1152,6 +1172,7 @@
X struct buffer_head * bh;
X
X bh = getblk(dev, block, size);
+ touch_buffer(bh);
X if (buffer_uptodate(bh))
X return bh;
X ll_rw_block(READ, 1, &bh);
@@ -1165,7 +1186,7 @@
X /*
X * Note: the caller should wake up the buffer_wait list if needed.
X */
-static __inline__ void __put_unused_buffer_head(struct buffer_head * bh)
+static void __put_unused_buffer_head(struct buffer_head * bh)
X {
X if (bh->b_inode)
X BUG();
@@ -1182,12 +1203,20 @@
X }
X }
X
+void put_unused_buffer_head(struct buffer_head *bh)
+{
+ spin_lock(&unused_list_lock);
+ __put_unused_buffer_head(bh);
+ spin_unlock(&unused_list_lock);
+}
+EXPORT_SYMBOL(put_unused_buffer_head);
+
X /*
X * Reserve NR_RESERVED buffer heads for async IO requests to avoid
X * no-buffer-head deadlock. Return NULL on failure; waiting for
X * buffer heads is now handled in create_buffers().
X */
-static struct buffer_head * get_unused_buffer_head(int async)
+struct buffer_head * get_unused_buffer_head(int async)
X {
X struct buffer_head * bh;
X
@@ -1228,6 +1257,7 @@
X
X return NULL;
X }
+EXPORT_SYMBOL(get_unused_buffer_head);
X
X void set_bh_page (struct buffer_head *bh, struct page *page, unsigned long offset)
X {
@@ -1242,6 +1272,7 @@
X else
X bh->b_data = page_address(page) + offset;
X }
+EXPORT_SYMBOL(set_bh_page);
X
X /*
X * Create the appropriate buffers when given a page for data area and
@@ -1331,10 +1362,36 @@
X clear_bit(BH_Mapped, &bh->b_state);
X clear_bit(BH_Req, &bh->b_state);
X clear_bit(BH_New, &bh->b_state);
+ remove_from_queues(bh);
X unlock_buffer(bh);
X }
X }
X
+/**
+ * try_to_release_page - release old fs-specific metadata on a page


+ *
+ */
+

+int try_to_release_page(struct page * page, int gfp_mask)
+{
+ if (!PageLocked(page))
+ BUG();
+
+ if (!page->mapping)
+ goto try_to_free;
+ if (!page->mapping->a_ops->releasepage)
+ goto try_to_free;
+ if (page->mapping->a_ops->releasepage(page, gfp_mask))
+ goto try_to_free;
+ /*
+ * We couldn't release buffer metadata; don't even bother trying
+ * to release buffers.


+ */
+ return 0;

+try_to_free:
+ return try_to_free_buffers(page, gfp_mask);
+}
+
X /*
X * We don't have to release all buffers here, but
X * we have to be sure that no dirty buffer is left
@@ -1378,7 +1435,7 @@
X * instead.
X */
X if (!offset) {
- if (!try_to_free_buffers(page, 0))
+ if (!try_to_release_page(page, 0))


X return 0;
X }
X

@@ -1406,6 +1463,7 @@
X page->buffers = head;
X page_cache_get(page);
X }
+EXPORT_SYMBOL(create_empty_buffers);
X
X /*
X * We are taking a block for data and we don't want any output from any
@@ -1446,8 +1504,7 @@
X */
X
X /*
- * block_write_full_page() is SMP-safe - currently it's still
- * being called with the kernel lock held, but the code is ready.
+ * block_write_full_page() is SMP threaded - the kernel lock is not held.
X */
X static int __block_write_full_page(struct inode *inode, struct page *page, get_block_t *get_block)
X {
@@ -1941,6 +1998,47 @@
X return tmp.b_blocknr;
X }
X
+int generic_direct_IO(int rw, struct inode * inode, struct kiobuf * iobuf, unsigned long blocknr, int blocksize, get_block_t * get_block)
+{
+ int i, nr_blocks, retval;
+ unsigned long * blocks = iobuf->blocks;
+
+ nr_blocks = iobuf->length / blocksize;
+ /* build the blocklist */
+ for (i = 0; i < nr_blocks; i++, blocknr++) {
+ struct buffer_head bh;
+
+ bh.b_state = 0;
+ bh.b_dev = inode->i_dev;
+ bh.b_size = blocksize;
+
+ retval = get_block(inode, blocknr, &bh, rw == READ ? 0 : 1);
+ if (retval)
+ goto out;
+
+ if (rw == READ) {
+ if (buffer_new(&bh))
+ BUG();
+ if (!buffer_mapped(&bh)) {
+ /* there was an hole in the filesystem */
+ blocks[i] = -1UL;
+ continue;
+ }
+ } else {
+ if (buffer_new(&bh))
+ unmap_underlying_metadata(&bh);
+ if (!buffer_mapped(&bh))
+ BUG();
+ }
+ blocks[i] = bh.b_blocknr;
+ }
+
+ retval = brw_kiovec(rw, 1, &iobuf, inode->i_dev, iobuf->blocks, blocksize);
+
+ out:
+ return retval;
+}
+
X /*
X * IO completion routine for a buffer_head being used for kiobuf IO: we
X * can't dispatch the kiobuf callback until io_count reaches 0.
@@ -2294,10 +2392,13 @@
X unsigned long index;
X int sizebits;
X
- if ((size & 511) || (size > PAGE_SIZE)) {
- printk(KERN_ERR "VFS: grow_buffers: size = %d\n",size);
- return 0;
- }
+ /* Size must be multiple of hard sectorsize */
+ if (size & (get_hardsect_size(dev)-1))
+ BUG();
+ /* Size must be within 512 bytes and PAGE_SIZE */
+ if (size < 512 || size > PAGE_SIZE)
+ BUG();
+
X sizebits = -1;
X do {
X sizebits++;
@@ -2444,6 +2545,7 @@
X wakeup_bdflush();
X return 0;
X }
+EXPORT_SYMBOL(try_to_free_buffers);
X
X /* ================== Debugging =================== */
X
diff -u --recursive --new-file v2.4.14/linux/fs/dquot.c linux/fs/dquot.c
--- v2.4.14/linux/fs/dquot.c Mon Nov 5 15:55:33 2001
+++ linux/fs/dquot.c Thu Nov 22 10:38:31 2001
@@ -189,11 +189,8 @@
X
X static inline void remove_free_dquot(struct dquot *dquot)
X {
- /* sanity check */
- if (list_empty(&dquot->dq_free)) {
- printk("remove_free_dquot: dquot not on the free list??\n");
- return; /* J.K. Just don't do anything */
- }
+ if (list_empty(&dquot->dq_free))
+ return;
X list_del(&dquot->dq_free);
X INIT_LIST_HEAD(&dquot->dq_free);
X nr_free_dquots--;
@@ -330,24 +327,6 @@
X unlock_dquot(dquot);
X }
X
-/*
- * Unhash and selectively clear the dquot structure,
- * but preserve the use count, list pointers, and
- * wait queue.
- */
-void clear_dquot(struct dquot *dquot)
-{
- /* unhash it first */
- remove_dquot_hash(dquot);
- dquot->dq_sb = NULL;
- dquot->dq_id = 0;
- dquot->dq_dev = NODEV;
- dquot->dq_type = -1;
- dquot->dq_flags = 0;
- dquot->dq_referenced = 0;
- memset(&dquot->dq_dqb, 0, sizeof(struct dqblk));
-}
-
X /* Invalidate all dquots on the list, wait for all users. Note that this function is called
X * after quota is disabled so no new quota might be created. As we only insert to the end of
X * inuse list, we don't have to restart searching... */
@@ -363,6 +342,7 @@
X continue;
X if (dquot->dq_type != type)
X continue;
+ dquot->dq_flags |= DQ_INVAL;
X if (dquot->dq_count)
X /*
X * Wait for any users of quota. As we have already cleared the flags in
@@ -384,6 +364,7 @@
X struct list_head *head;
X struct dquot *dquot;
X
+ lock_kernel();
X restart:
X for (head = inuse_list.next; head != &inuse_list; head = head->next) {
X dquot = list_entry(head, struct dquot, dq_inuse);
@@ -405,6 +386,7 @@
X goto restart;
X }
X dqstats.syncs++;
+ unlock_kernel();


X return 0;
X }
X

@@ -428,7 +410,9 @@
X
X int shrink_dqcache_memory(int priority, unsigned int gfp_mask)
X {
+ lock_kernel();
X prune_dqcache(nr_free_dquots / (priority + 1));
+ unlock_kernel();
X kmem_cache_shrink(dquot_cachep);
X return 0;
X }
@@ -465,12 +449,13 @@
X return;
X }
X dquot->dq_count--;
- /* Place at end of LRU free queue */
- put_dquot_last(dquot);
+ /* If dquot is going to be invalidated invalidate_dquots() is going to free it so */
+ if (!(dquot->dq_flags & DQ_INVAL))
+ put_dquot_last(dquot); /* Place at end of LRU free queue */
X wake_up(&dquot->dq_wait_free);
X }
X
-struct dquot *get_empty_dquot(void)
+static struct dquot *get_empty_dquot(void)
X {
X struct dquot *dquot;
X
@@ -633,9 +618,11 @@
X /* Free list of dquots - called from inode.c */
X void put_dquot_list(struct list_head *tofree_head)
X {
- struct list_head *act_head = tofree_head->next;
+ struct list_head *act_head;
X struct dquot *dquot;
X
+ lock_kernel();
+ act_head = tofree_head->next;
X /* So now we have dquots on the list... Just free them */
X while (act_head != tofree_head) {
X dquot = list_entry(act_head, struct dquot, dq_free);
@@ -644,6 +631,7 @@
X INIT_LIST_HEAD(&dquot->dq_free);
X dqput(dquot);
X }
+ unlock_kernel();
X }
X
X static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
@@ -1289,6 +1277,7 @@
X short cnt;
X struct quota_mount_options *dqopt = sb_dqopt(sb);
X
+ lock_kernel();
X if (!sb)
X goto out;
X
@@ -1313,6 +1302,7 @@
X }
X up(&dqopt->dqoff_sem);
X out:
+ unlock_kernel();


X return 0;
X }
X

diff -u --recursive --new-file v2.4.14/linux/fs/ext2/ialloc.c linux/fs/ext2/ialloc.c
--- v2.4.14/linux/fs/ext2/ialloc.c Tue Oct 9 17:06:53 2001
+++ linux/fs/ext2/ialloc.c Sun Nov 11 09:59:56 2001
@@ -39,37 +39,27 @@
X * Read the inode allocation bitmap for a given block_group, reading
X * into the specified slot in the superblock's bitmap cache.
X *
- * Return >=0 on success or a -ve error code.
+ * Return buffer_head of bitmap on success or NULL.
X */
-static int read_inode_bitmap (struct super_block * sb,
- unsigned long block_group,
- unsigned int bitmap_nr)
+static struct buffer_head *read_inode_bitmap (struct super_block * sb,
+ unsigned long block_group)
X {
- struct ext2_group_desc * gdp;
- struct buffer_head * bh = NULL;
- int retval = 0;
-
- gdp = ext2_get_group_desc (sb, block_group, NULL);
- if (!gdp) {
- retval = -EIO;
+ struct ext2_group_desc *desc;
+ struct buffer_head *bh = NULL;
+
+ desc = ext2_get_group_desc(sb, block_group, NULL);
+ if (!desc)
X goto error_out;
- }
- bh = bread (sb->s_dev, le32_to_cpu(gdp->bg_inode_bitmap), sb->s_blocksize);
- if (!bh) {
+
+ bh = bread(sb->s_dev, le32_to_cpu(desc->bg_inode_bitmap),
+ sb->s_blocksize);
+ if (!bh)
X ext2_error (sb, "read_inode_bitmap",
X "Cannot read inode bitmap - "
X "block_group = %lu, inode_bitmap = %lu",
- block_group, (unsigned long) gdp->bg_inode_bitmap);
- retval = -EIO;
- }
- /*
- * On IO error, just leave a zero in the superblock's block pointer for
- * this group. The IO will be retried next time.
- */
+ block_group, (unsigned long) desc->bg_inode_bitmap);
X error_out:
- sb->u.ext2_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
- sb->u.ext2_sb.s_inode_bitmap[bitmap_nr] = bh;
- return retval;
+ return bh;
X }
X
X /*
@@ -83,79 +73,62 @@
X * 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
X * this function reads the bitmap without maintaining a LRU cache.
X *
- * Return the slot used to store the bitmap, or a -ve error code.
+ * Return the buffer_head of the bitmap or the ERR_PTR(error)
X */
-static int load_inode_bitmap (struct super_block * sb,
- unsigned int block_group)
+static struct buffer_head *load_inode_bitmap (struct super_block * sb,
+ unsigned int block_group)
X {
- int i, j, retval = 0;
- unsigned long inode_bitmap_number;
- struct buffer_head * inode_bitmap;
+ int i, slot = 0;
+ struct ext2_sb_info *sbi = &sb->u.ext2_sb;
+ struct buffer_head *bh = sbi->s_inode_bitmap[0];
X
- if (block_group >= sb->u.ext2_sb.s_groups_count)
+ if (block_group >= sbi->s_groups_count)
X ext2_panic (sb, "load_inode_bitmap",
X "block_group >= groups_count - "
X "block_group = %d, groups_count = %lu",
- block_group, sb->u.ext2_sb.s_groups_count);
- if (sb->u.ext2_sb.s_loaded_inode_bitmaps > 0 &&
- sb->u.ext2_sb.s_inode_bitmap_number[0] == block_group &&
- sb->u.ext2_sb.s_inode_bitmap[0] != NULL)
- return 0;
- if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED) {
- if (sb->u.ext2_sb.s_inode_bitmap[block_group]) {
- if (sb->u.ext2_sb.s_inode_bitmap_number[block_group] != block_group)
- ext2_panic (sb, "load_inode_bitmap",
- "block_group != inode_bitmap_number");
- else
- return block_group;
- } else {
- retval = read_inode_bitmap (sb, block_group,
- block_group);
- if (retval < 0)
- return retval;
- return block_group;
- }
+ block_group, sbi->s_groups_count);
+
+ if (sbi->s_loaded_inode_bitmaps > 0 &&
+ sbi->s_inode_bitmap_number[0] == block_group && bh)
+ goto found;
+
+ if (sbi->s_groups_count <= EXT2_MAX_GROUP_LOADED) {
+ slot = block_group;
+ bh = sbi->s_inode_bitmap[slot];
+ if (!bh)
+ goto read_it;
+ if (sbi->s_inode_bitmap_number[slot] == slot)
+ goto found;
+ ext2_panic (sb, "load_inode_bitmap",
+ "block_group != inode_bitmap_number");
X }
X
- for (i = 0; i < sb->u.ext2_sb.s_loaded_inode_bitmaps &&
- sb->u.ext2_sb.s_inode_bitmap_number[i] != block_group;
+ bh = NULL;
+ for (i = 0; i < sbi->s_loaded_inode_bitmaps &&
+ sbi->s_inode_bitmap_number[i] != block_group;
X i++)
X ;
- if (i < sb->u.ext2_sb.s_loaded_inode_bitmaps &&
- sb->u.ext2_sb.s_inode_bitmap_number[i] == block_group) {
- inode_bitmap_number = sb->u.ext2_sb.s_inode_bitmap_number[i];
- inode_bitmap = sb->u.ext2_sb.s_inode_bitmap[i];
- for (j = i; j > 0; j--) {
- sb->u.ext2_sb.s_inode_bitmap_number[j] =
- sb->u.ext2_sb.s_inode_bitmap_number[j - 1];
- sb->u.ext2_sb.s_inode_bitmap[j] =
- sb->u.ext2_sb.s_inode_bitmap[j - 1];
- }
- sb->u.ext2_sb.s_inode_bitmap_number[0] = inode_bitmap_number;
- sb->u.ext2_sb.s_inode_bitmap[0] = inode_bitmap;
-
- /*
- * There's still one special case here --- if inode_bitmap == 0
- * then our last attempt to read the bitmap failed and we have
- * just ended up caching that failure. Try again to read it.
- */
- if (!inode_bitmap)
- retval = read_inode_bitmap (sb, block_group, 0);
-
- } else {
- if (sb->u.ext2_sb.s_loaded_inode_bitmaps < EXT2_MAX_GROUP_LOADED)
- sb->u.ext2_sb.s_loaded_inode_bitmaps++;
- else
- brelse (sb->u.ext2_sb.s_inode_bitmap[EXT2_MAX_GROUP_LOADED - 1]);
- for (j = sb->u.ext2_sb.s_loaded_inode_bitmaps - 1; j > 0; j--) {
- sb->u.ext2_sb.s_inode_bitmap_number[j] =
- sb->u.ext2_sb.s_inode_bitmap_number[j - 1];
- sb->u.ext2_sb.s_inode_bitmap[j] =
- sb->u.ext2_sb.s_inode_bitmap[j - 1];
- }
- retval = read_inode_bitmap (sb, block_group, 0);
- }
- return retval;
+ if (i < sbi->s_loaded_inode_bitmaps)
+ bh = sbi->s_inode_bitmap[i];
+ else if (sbi->s_loaded_inode_bitmaps < EXT2_MAX_GROUP_LOADED)
+ sbi->s_loaded_inode_bitmaps++;
+ else
+ brelse (sbi->s_inode_bitmap[--i]);
+
+ while (i--) {
+ sbi->s_inode_bitmap_number[i+1] = sbi->s_inode_bitmap_number[i];
+ sbi->s_inode_bitmap[i+1] = sbi->s_inode_bitmap[i];
+ }
+
+read_it:
+ if (!bh)
+ bh = read_inode_bitmap (sb, block_group);
+ sbi->s_inode_bitmap_number[slot] = block_group;
+ sbi->s_inode_bitmap[slot] = bh;
+ if (!bh)
+ return ERR_PTR(-EIO);
+found:
+ return bh;
X }
X
X /*
@@ -183,8 +156,7 @@
X struct buffer_head * bh2;
X unsigned long block_group;
X unsigned long bit;
- int bitmap_nr;
- struct ext2_group_desc * gdp;
+ struct ext2_group_desc * desc;
X struct ext2_super_block * es;
X
X ino = inode->i_ino;
@@ -215,24 +187,22 @@
X }
X block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb);
X bit = (ino - 1) % EXT2_INODES_PER_GROUP(sb);
- bitmap_nr = load_inode_bitmap (sb, block_group);
- if (bitmap_nr < 0)
+ bh = load_inode_bitmap (sb, block_group);
+ if (IS_ERR(bh))
X goto error_return;
X
- bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
-
X /* Ok, now we can actually update the inode bitmaps.. */
X if (!ext2_clear_bit (bit, bh->b_data))
X ext2_error (sb, "ext2_free_inode",
X "bit already cleared for inode %lu", ino);
X else {
- gdp = ext2_get_group_desc (sb, block_group, &bh2);
- if (gdp) {
- gdp->bg_free_inodes_count =
- cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) + 1);
+ desc = ext2_get_group_desc (sb, block_group, &bh2);
+ if (desc) {
+ desc->bg_free_inodes_count =
+ cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) + 1);
X if (is_directory)
- gdp->bg_used_dirs_count =
- cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) - 1);
+ desc->bg_used_dirs_count =
+ cpu_to_le16(le16_to_cpu(desc->bg_used_dirs_count) - 1);
X }
X mark_buffer_dirty(bh2);
X es->s_free_inodes_count =
@@ -259,23 +229,101 @@
X * For other inodes, search forward from the parent directory\'s block
X * group to find a free inode.
X */
+
+static int find_group_dir(struct super_block *sb, int parent_group)
+{
+ struct ext2_super_block * es = sb->u.ext2_sb.s_es;
+ int ngroups = sb->u.ext2_sb.s_groups_count;
+ int avefreei = le32_to_cpu(es->s_free_inodes_count) / ngroups;
+ struct ext2_group_desc *desc, *best_desc = NULL;
+ struct buffer_head *bh, *best_bh = NULL;
+ int group, best_group = -1;
+
+ for (group = 0; group < ngroups; group++) {
+ desc = ext2_get_group_desc (sb, group, &bh);
+ if (!desc || !desc->bg_free_inodes_count)
+ continue;
+ if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
+ continue;
+ if (!best_desc ||
+ (le16_to_cpu(desc->bg_free_blocks_count) >
+ le16_to_cpu(best_desc->bg_free_blocks_count))) {
+ best_group = group;
+ best_desc = desc;
+ best_bh = bh;
+ }
+ }
+ if (!best_desc)
+ return -1;
+ best_desc->bg_free_inodes_count =
+ cpu_to_le16(le16_to_cpu(best_desc->bg_free_inodes_count) - 1);
+ best_desc->bg_used_dirs_count =
+ cpu_to_le16(le16_to_cpu(best_desc->bg_used_dirs_count) + 1);
+ mark_buffer_dirty(best_bh);
+ return best_group;
+}
+
+static int find_group_other(struct super_block *sb, int parent_group)
+{
+ int ngroups = sb->u.ext2_sb.s_groups_count;
+ struct ext2_group_desc *desc;
+ struct buffer_head *bh;
+ int group, i;
+
+ /*
+ * Try to place the inode in its parent directory
+ */
+ group = parent_group;
+ desc = ext2_get_group_desc (sb, group, &bh);
+ if (desc && le16_to_cpu(desc->bg_free_inodes_count))
+ goto found;
+
+ /*
+ * Use a quadratic hash to find a group with a
+ * free inode
+ */
+ for (i = 1; i < ngroups; i <<= 1) {
+ group += i;
+ if (group >= ngroups)
+ group -= ngroups;
+ desc = ext2_get_group_desc (sb, group, &bh);
+ if (desc && le16_to_cpu(desc->bg_free_inodes_count))
+ goto found;
+ }
+
+ /*
+ * That failed: try linear search for a free inode
+ */
+ group = parent_group + 1;
+ for (i = 2; i < ngroups; i++) {
+ if (++group >= ngroups)
+ group = 0;
+ desc = ext2_get_group_desc (sb, group, &bh);
+ if (desc && le16_to_cpu(desc->bg_free_inodes_count))
+ goto found;
+ }


+
+ return -1;
+

+found:
+ desc->bg_free_inodes_count =
+ cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) - 1);
+ mark_buffer_dirty(bh);
+ return group;
+}
+
X struct inode * ext2_new_inode (const struct inode * dir, int mode)
X {
X struct super_block * sb;
X struct buffer_head * bh;
X struct buffer_head * bh2;
- int i, j, avefreei;
+ int group, i;
+ ino_t ino;
X struct inode * inode;
- int bitmap_nr;
- struct ext2_group_desc * gdp;
- struct ext2_group_desc * tmp;
+ struct ext2_group_desc * desc;
X struct ext2_super_block * es;
X int err;
X
- /* Cannot create files in a deleted directory */
- if (!dir || !dir->i_nlink)
- return ERR_PTR(-EPERM);
-
X sb = dir->i_sb;
X inode = new_inode(sb);
X if (!inode)
@@ -284,138 +332,41 @@
X lock_super (sb);
X es = sb->u.ext2_sb.s_es;
X repeat:
- gdp = NULL; i=0;
-
- if (S_ISDIR(mode)) {
- avefreei = le32_to_cpu(es->s_free_inodes_count) /
- sb->u.ext2_sb.s_groups_count;
-/* I am not yet convinced that this next bit is necessary.
- i = dir->u.ext2_i.i_block_group;
- for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
- tmp = ext2_get_group_desc (sb, i, &bh2);
- if (tmp &&
- (le16_to_cpu(tmp->bg_used_dirs_count) << 8) <
- le16_to_cpu(tmp->bg_free_inodes_count)) {
- gdp = tmp;
- break;
- }
- else
- i = ++i % sb->u.ext2_sb.s_groups_count;
- }
-*/
- if (!gdp) {
- for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
- tmp = ext2_get_group_desc (sb, j, &bh2);
- if (tmp &&
- le16_to_cpu(tmp->bg_free_inodes_count) &&
- le16_to_cpu(tmp->bg_free_inodes_count) >= avefreei) {
- if (!gdp ||
- (le16_to_cpu(tmp->bg_free_blocks_count) >
- le16_to_cpu(gdp->bg_free_blocks_count))) {
- i = j;
- gdp = tmp;


- }
- }
- }
- }
- }

+ if (S_ISDIR(mode))
+ group = find_group_dir(sb, dir->u.ext2_i.i_block_group);
X else
- {
- /*
- * Try to place the inode in its parent directory
- */
- i = dir->u.ext2_i.i_block_group;
- tmp = ext2_get_group_desc (sb, i, &bh2);
- if (tmp && le16_to_cpu(tmp->bg_free_inodes_count))
- gdp = tmp;
- else
- {
- /*
- * Use a quadratic hash to find a group with a
- * free inode
- */
- for (j = 1; j < sb->u.ext2_sb.s_groups_count; j <<= 1) {
- i += j;
- if (i >= sb->u.ext2_sb.s_groups_count)
- i -= sb->u.ext2_sb.s_groups_count;
- tmp = ext2_get_group_desc (sb, i, &bh2);
- if (tmp &&
- le16_to_cpu(tmp->bg_free_inodes_count)) {
- gdp = tmp;
- break;
- }
- }
- }
- if (!gdp) {
- /*
- * That failed: try linear search for a free inode
- */
- i = dir->u.ext2_i.i_block_group + 1;
- for (j = 2; j < sb->u.ext2_sb.s_groups_count; j++) {
- if (++i >= sb->u.ext2_sb.s_groups_count)
- i = 0;
- tmp = ext2_get_group_desc (sb, i, &bh2);
- if (tmp &&
- le16_to_cpu(tmp->bg_free_inodes_count)) {
- gdp = tmp;
- break;
- }
- }
- }
- }
+ group = find_group_other(sb, dir->u.ext2_i.i_block_group);
X
X err = -ENOSPC;
- if (!gdp)
+ if (group == -1)
X goto fail;
X
X err = -EIO;
- bitmap_nr = load_inode_bitmap (sb, i);
- if (bitmap_nr < 0)
- goto fail;
-
- bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
- if ((j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,
- EXT2_INODES_PER_GROUP(sb))) <
- EXT2_INODES_PER_GROUP(sb)) {
- if (ext2_set_bit (j, bh->b_data)) {
- ext2_error (sb, "ext2_new_inode",
- "bit already set for inode %d", j);
- goto repeat;
- }
- mark_buffer_dirty(bh);
- if (sb->s_flags & MS_SYNCHRONOUS) {
- ll_rw_block (WRITE, 1, &bh);
- wait_on_buffer (bh);
- }
- } else {
- if (le16_to_cpu(gdp->bg_free_inodes_count) != 0) {
- ext2_error (sb, "ext2_new_inode",
- "Free inodes count corrupted in group %d",
- i);
- /* Is it really ENOSPC? */
- err = -ENOSPC;
- if (sb->s_flags & MS_RDONLY)
- goto fail;
+ bh = load_inode_bitmap (sb, group);
+ if (IS_ERR(bh))
+ goto fail2;
+
+ i = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,
+ EXT2_INODES_PER_GROUP(sb));
+ if (i >= EXT2_INODES_PER_GROUP(sb))
+ goto bad_count;
+ ext2_set_bit (i, bh->b_data);
X
- gdp->bg_free_inodes_count = 0;
- mark_buffer_dirty(bh2);
- }
- goto repeat;
+ mark_buffer_dirty(bh);
+ if (sb->s_flags & MS_SYNCHRONOUS) {
+ ll_rw_block (WRITE, 1, &bh);
+ wait_on_buffer (bh);
X }
- j += i * EXT2_INODES_PER_GROUP(sb) + 1;
- if (j < EXT2_FIRST_INO(sb) || j > le32_to_cpu(es->s_inodes_count)) {
+
+ ino = group * EXT2_INODES_PER_GROUP(sb) + i + 1;
+ if (ino < EXT2_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
X ext2_error (sb, "ext2_new_inode",
X "reserved inode or inode > inodes count - "
- "block_group = %d,inode=%d", i, j);
+ "block_group = %d,inode=%ld", group, ino);
X err = -EIO;
- goto fail;
+ goto fail2;
X }
- gdp->bg_free_inodes_count =
- cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
- if (S_ISDIR(mode))
- gdp->bg_used_dirs_count =
- cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
- mark_buffer_dirty(bh2);
+
X es->s_free_inodes_count =
X cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1);
X mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
@@ -431,22 +382,15 @@
X inode->i_gid = current->fsgid;
X inode->i_mode = mode;
X
- inode->i_ino = j;
+ inode->i_ino = ino;
X inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */
X inode->i_blocks = 0;
X inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
X inode->u.ext2_i.i_new_inode = 1;
X inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags;
X if (S_ISLNK(mode))
- inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FL | EXT2_APPEND_FL);
- inode->u.ext2_i.i_faddr = 0;
- inode->u.ext2_i.i_frag_no = 0;
- inode->u.ext2_i.i_frag_size = 0;
- inode->u.ext2_i.i_file_acl = 0;
- inode->u.ext2_i.i_dir_acl = 0;
- inode->u.ext2_i.i_dtime = 0;
- inode->u.ext2_i.i_prealloc_count = 0;
- inode->u.ext2_i.i_block_group = i;
+ inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FL|EXT2_APPEND_FL);
+ inode->u.ext2_i.i_block_group = group;
X if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
X inode->i_flags |= S_SYNC;
X insert_inode_hash(inode);
@@ -464,40 +408,59 @@
X ext2_debug ("allocating inode %lu\n", inode->i_ino);
X return inode;
X
+fail2:
+ desc = ext2_get_group_desc (sb, group, &bh2);
+ desc->bg_free_inodes_count =
+ cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) + 1);
+ if (S_ISDIR(mode))
+ desc->bg_used_dirs_count =
+ cpu_to_le16(le16_to_cpu(desc->bg_used_dirs_count) - 1);
+ mark_buffer_dirty(bh2);
X fail:
X unlock_super(sb);
X make_bad_inode(inode);
X iput(inode);
X return ERR_PTR(err);
+
+bad_count:
+ ext2_error (sb, "ext2_new_inode",
+ "Free inodes count corrupted in group %d",
+ group);
+ /* Is it really ENOSPC? */
+ err = -ENOSPC;
+ if (sb->s_flags & MS_RDONLY)
+ goto fail;
+
+ desc = ext2_get_group_desc (sb, group, &bh2);
+ desc->bg_free_inodes_count = 0;
+ mark_buffer_dirty(bh2);
+ goto repeat;
X }
X
X unsigned long ext2_count_free_inodes (struct super_block * sb)
X {
X #ifdef EXT2FS_DEBUG
X struct ext2_super_block * es;
- unsigned long desc_count, bitmap_count, x;
- int bitmap_nr;
- struct ext2_group_desc * gdp;
+ unsigned long desc_count = 0, bitmap_count = 0;
X int i;
X
X lock_super (sb);
X es = sb->u.ext2_sb.s_es;
- desc_count = 0;
- bitmap_count = 0;
- gdp = NULL;
X for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
- gdp = ext2_get_group_desc (sb, i, NULL);
- if (!gdp)
+ struct ext2_group_desc *desc = ext2_get_group_desc (sb, i, NULL);
+ struct buffer_head *bh;
+ unsigned x;
+
+ if (!desc)
X continue;
- desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
- bitmap_nr = load_inode_bitmap (sb, i);
- if (bitmap_nr < 0)
+ desc_count += le16_to_cpu(desc->bg_free_inodes_count);
+ bh = load_inode_bitmap (sb, i);
+ if (IS_ERR(bh))
X continue;
X
- x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
- EXT2_INODES_PER_GROUP(sb) / 8);
+ x = ext2_count_free (bh, EXT2_INODES_PER_GROUP(sb) / 8);
X printk ("group %d: stored = %d, counted = %lu\n",
- i, le16_to_cpu(gdp->bg_free_inodes_count), x);
+ i, le16_to_cpu(desc->bg_free_inodes_count), x);
X bitmap_count += x;
X }
X printk("ext2_count_free_inodes: stored = %lu, computed = %lu, %lu\n",
@@ -513,39 +476,35 @@
X /* Called at mount-time, super-block is locked */
X void ext2_check_inodes_bitmap (struct super_block * sb)
X {
- struct ext2_super_block * es;
- unsigned long desc_count, bitmap_count, x;
- int bitmap_nr;
- struct ext2_group_desc * gdp;
+ struct ext2_super_block * es = sb->u.ext2_sb.s_es;
+ unsigned long desc_count = 0, bitmap_count = 0;
X int i;
X
- es = sb->u.ext2_sb.s_es;
- desc_count = 0;
- bitmap_count = 0;
- gdp = NULL;
X for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
- gdp = ext2_get_group_desc (sb, i, NULL);
- if (!gdp)
+ struct ext2_group_desc *desc = ext2_get_group_desc(sb, i, NULL);
+ struct buffer_head *bh;
+ unsigned x;
+
+ if (!desc)
X continue;
- desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
- bitmap_nr = load_inode_bitmap (sb, i);
- if (bitmap_nr < 0)
+ desc_count += le16_to_cpu(desc->bg_free_inodes_count);
+ bh = load_inode_bitmap (sb, i);
+ if (IS_ERR(bh))
X continue;
X
- x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
- EXT2_INODES_PER_GROUP(sb) / 8);
- if (le16_to_cpu(gdp->bg_free_inodes_count) != x)
+ x = ext2_count_free (bh, EXT2_INODES_PER_GROUP(sb) / 8);
+ if (le16_to_cpu(desc->bg_free_inodes_count) != x)
X ext2_error (sb, "ext2_check_inodes_bitmap",
X "Wrong free inodes count in group %d, "
X "stored = %d, counted = %lu", i,
- le16_to_cpu(gdp->bg_free_inodes_count), x);
+ le16_to_cpu(desc->bg_free_inodes_count), x);
X bitmap_count += x;
X }
X if (le32_to_cpu(es->s_free_inodes_count) != bitmap_count)
X ext2_error (sb, "ext2_check_inodes_bitmap",
X "Wrong free inodes count in super block, "
X "stored = %lu, counted = %lu",
- (unsigned long) le32_to_cpu(es->s_free_inodes_count),
+ (unsigned long)le32_to_cpu(es->s_free_inodes_count),
X bitmap_count);
X }
X #endif
diff -u --recursive --new-file v2.4.14/linux/fs/ext2/inode.c linux/fs/ext2/inode.c
--- v2.4.14/linux/fs/ext2/inode.c Tue Oct 23 22:48:53 2001
+++ linux/fs/ext2/inode.c Wed Nov 21 14:07:25 2001
@@ -592,13 +592,18 @@
X {
X return generic_block_bmap(mapping,block,ext2_get_block);
X }
+static int ext2_direct_IO(int rw, struct inode * inode, struct kiobuf * iobuf, unsigned long blocknr, int blocksize)
+{
+ return generic_direct_IO(rw, inode, iobuf, blocknr, blocksize, ext2_get_block);
+}
X struct address_space_operations ext2_aops = {
X readpage: ext2_readpage,
X writepage: ext2_writepage,
X sync_page: block_sync_page,
X prepare_write: ext2_prepare_write,
X commit_write: generic_commit_write,
- bmap: ext2_bmap
+ bmap: ext2_bmap,
+ direct_IO: ext2_direct_IO,
X };
X
X /*
diff -u --recursive --new-file v2.4.14/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v2.4.14/linux/fs/ext2/super.c Tue Oct 9 17:06:53 2001
+++ linux/fs/ext2/super.c Mon Nov 12 09:34:16 2001
@@ -640,9 +640,9 @@
X if (sb->s_root) {
X dput(sb->s_root);
X sb->s_root = NULL;
- printk ("EXT2-fs: corrupt root inode, run e2fsck\n");
+ printk(KERN_ERR "EXT2-fs: corrupt root inode, run e2fsck\n");
X } else
- printk ("EXT2-fs: get root inode failed\n");
+ printk(KERN_ERR "EXT2-fs: get root inode failed\n");
X goto failed_mount2;
X }
X ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY);
diff -u --recursive --new-file v2.4.14/linux/fs/ext3/Makefile linux/fs/ext3/Makefile
--- v2.4.14/linux/fs/ext3/Makefile Wed Dec 31 16:00:00 1969
+++ linux/fs/ext3/Makefile Fri Nov 9 14:25:04 2001
@@ -0,0 +1,16 @@
+#
+# Makefile for the linux ext2-filesystem routines.
+#
+# 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 definitions are now in the main makefile...
+
+O_TARGET := ext3.o
+
+obj-y := acl.o balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
+ ioctl.o namei.o super.o symlink.o
+obj-m := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.14/linux/fs/ext3/acl.c linux/fs/ext3/acl.c
--- v2.4.14/linux/fs/ext3/acl.c Wed Dec 31 16:00:00 1969
+++ linux/fs/ext3/acl.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,17 @@
+/*
+ * linux/fs/ext3/acl.c
+ *
+ * Copyright (C) 1993, 1994, 1995
+ * Remy Card (ca...@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ */
+
+#include <linux/fs.h>
+#include <linux/sched.h>
+
+
+/*
+ * This file will contain the Access Control Lists management for the
+ * second extended file system.
+ */
diff -u --recursive --new-file v2.4.14/linux/fs/ext3/balloc.c linux/fs/ext3/balloc.c
--- v2.4.14/linux/fs/ext3/balloc.c Wed Dec 31 16:00:00 1969
+++ linux/fs/ext3/balloc.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,995 @@
+/*
+ * linux/fs/ext3/balloc.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (ca...@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * Enhanced block allocation by Stephen Tweedie (s...@redhat.com), 1993
+ * Big-endian to little-endian byte-swapping/bitmaps by
+ * David S. Miller (da...@caip.rutgers.edu), 1995
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/ext3_jbd.h>
+#include <linux/locks.h>
+#include <linux/quotaops.h>
+
+/*
+ * balloc.c contains the blocks allocation and deallocation routines
+ */
+
+/*
+ * The free blocks are managed by bitmaps. A file system contains several
+ * blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap
+ * block for inodes, N blocks for the inode table and data blocks.
+ *
+ * The file system contains group descriptors which are located after the
+ * super block. Each descriptor contains the number of the bitmap block and
+ * the free blocks count in the block. The descriptors are loaded in memory
+ * when a file system is mounted (see ext3_read_super).
+ */
+
+
+#define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1)
+
+struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
+ unsigned int block_group,
+ struct buffer_head ** bh)
+{
+ unsigned long group_desc;
+ unsigned long desc;
+ struct ext3_group_desc * gdp;
+
+ if (block_group >= sb->u.ext3_sb.s_groups_count) {
+ ext3_error (sb, "ext3_get_group_desc",
+ "block_group >= groups_count - "
+ "block_group = %d, groups_count = %lu",
+ block_group, sb->u.ext3_sb.s_groups_count);
+


+ return NULL;
+ }
+

+ group_desc = block_group / EXT3_DESC_PER_BLOCK(sb);
+ desc = block_group % EXT3_DESC_PER_BLOCK(sb);
+ if (!sb->u.ext3_sb.s_group_desc[group_desc]) {
+ ext3_error (sb, "ext3_get_group_desc",
+ "Group descriptor not loaded - "
+ "block_group = %d, group_desc = %lu, desc = %lu",
+ block_group, group_desc, desc);


+ return NULL;
+ }
+

+ gdp = (struct ext3_group_desc *)
+ sb->u.ext3_sb.s_group_desc[group_desc]->b_data;
+ if (bh)
+ *bh = sb->u.ext3_sb.s_group_desc[group_desc];
+ return gdp + desc;
+}
+
+/*
+ * Read the bitmap for a given block_group, reading into the specified
+ * slot in the superblock's bitmap cache.
+ *
+ * Return >=0 on success or a -ve error code.
+ */
+
+static int read_block_bitmap (struct super_block * sb,
+ unsigned int block_group,
+ unsigned long bitmap_nr)
+{
+ struct ext3_group_desc * gdp;
+ struct buffer_head * bh = NULL;
+ int retval = -EIO;
+
+ gdp = ext3_get_group_desc (sb, block_group, NULL);
+ if (!gdp)
+ goto error_out;
+ retval = 0;
+ bh = bread (sb->s_dev,
+ le32_to_cpu(gdp->bg_block_bitmap), sb->s_blocksize);
+ if (!bh) {
+ ext3_error (sb, "read_block_bitmap",
+ "Cannot read block bitmap - "
+ "block_group = %d, block_bitmap = %lu",
+ block_group, (unsigned long) gdp->bg_block_bitmap);
+ retval = -EIO;
+ }
+ /*
+ * On IO error, just leave a zero in the superblock's block pointer for
+ * this group. The IO will be retried next time.
+ */
+error_out:
+ sb->u.ext3_sb.s_block_bitmap_number[bitmap_nr] = block_group;
+ sb->u.ext3_sb.s_block_bitmap[bitmap_nr] = bh;
+ return retval;
+}
+
+/*
+ * load_block_bitmap loads the block bitmap for a blocks group
+ *
+ * It maintains a cache for the last bitmaps loaded. This cache is managed
+ * with a LRU algorithm.
+ *
+ * Notes:
+ * 1/ There is one cache per mounted file system.
+ * 2/ If the file system contains less than EXT3_MAX_GROUP_LOADED groups,
+ * this function reads the bitmap without maintaining a LRU cache.
+ *
+ * Return the slot used to store the bitmap, or a -ve error code.
+ */
+static int __load_block_bitmap (struct super_block * sb,
+ unsigned int block_group)
+{
+ int i, j, retval = 0;
+ unsigned long block_bitmap_number;
+ struct buffer_head * block_bitmap;
+
+ if (block_group >= sb->u.ext3_sb.s_groups_count)
+ ext3_panic (sb, "load_block_bitmap",
+ "block_group >= groups_count - "
+ "block_group = %d, groups_count = %lu",
+ block_group, sb->u.ext3_sb.s_groups_count);
+
+ if (sb->u.ext3_sb.s_groups_count <= EXT3_MAX_GROUP_LOADED) {
+ if (sb->u.ext3_sb.s_block_bitmap[block_group]) {
+ if (sb->u.ext3_sb.s_block_bitmap_number[block_group] ==
+ block_group)
+ return block_group;
+ ext3_error (sb, "__load_block_bitmap",
+ "block_group != block_bitmap_number");
+ }
+ retval = read_block_bitmap (sb, block_group, block_group);
+ if (retval < 0)
+ return retval;
+ return block_group;
+ }
+
+ for (i = 0; i < sb->u.ext3_sb.s_loaded_block_bitmaps &&
+ sb->u.ext3_sb.s_block_bitmap_number[i] != block_group; i++)
+ ;
+ if (i < sb->u.ext3_sb.s_loaded_block_bitmaps &&
+ sb->u.ext3_sb.s_block_bitmap_number[i] == block_group) {
+ block_bitmap_number = sb->u.ext3_sb.s_block_bitmap_number[i];
+ block_bitmap = sb->u.ext3_sb.s_block_bitmap[i];
+ for (j = i; j > 0; j--) {
+ sb->u.ext3_sb.s_block_bitmap_number[j] =
+ sb->u.ext3_sb.s_block_bitmap_number[j - 1];
+ sb->u.ext3_sb.s_block_bitmap[j] =
+ sb->u.ext3_sb.s_block_bitmap[j - 1];
+ }
+ sb->u.ext3_sb.s_block_bitmap_number[0] = block_bitmap_number;
+ sb->u.ext3_sb.s_block_bitmap[0] = block_bitmap;
+
+ /*
+ * There's still one special case here --- if block_bitmap == 0
+ * then our last attempt to read the bitmap failed and we have
+ * just ended up caching that failure. Try again to read it.
+ */
+ if (!block_bitmap)
+ retval = read_block_bitmap (sb, block_group, 0);
+ } else {
+ if (sb->u.ext3_sb.s_loaded_block_bitmaps<EXT3_MAX_GROUP_LOADED)
+ sb->u.ext3_sb.s_loaded_block_bitmaps++;
+ else
+ brelse (sb->u.ext3_sb.s_block_bitmap
+ [EXT3_MAX_GROUP_LOADED - 1]);
+ for (j = sb->u.ext3_sb.s_loaded_block_bitmaps - 1;
+ j > 0; j--) {
+ sb->u.ext3_sb.s_block_bitmap_number[j] =
+ sb->u.ext3_sb.s_block_bitmap_number[j - 1];
+ sb->u.ext3_sb.s_block_bitmap[j] =
+ sb->u.ext3_sb.s_block_bitmap[j - 1];
+ }
+ retval = read_block_bitmap (sb, block_group, 0);
+ }
+ return retval;
+}
+
+/*
+ * Load the block bitmap for a given block group. First of all do a couple
+ * of fast lookups for common cases and then pass the request onto the guts
+ * of the bitmap loader.
+ *
+ * Return the slot number of the group in the superblock bitmap cache's on
+ * success, or a -ve error code.
+ *
+ * There is still one inconsistency here --- if the number of groups in this
+ * filesystems is <= EXT3_MAX_GROUP_LOADED, then we have no way of
+ * differentiating between a group for which we have never performed a bitmap
+ * IO request, and a group for which the last bitmap read request failed.
+ */
+static inline int load_block_bitmap (struct super_block * sb,
+ unsigned int block_group)
+{
+ int slot;
+
+ /*
+ * Do the lookup for the slot. First of all, check if we're asking
+ * for the same slot as last time, and did we succeed that last time?
+ */
+ if (sb->u.ext3_sb.s_loaded_block_bitmaps > 0 &&
+ sb->u.ext3_sb.s_block_bitmap_number[0] == block_group &&
+ sb->u.ext3_sb.s_block_bitmap[0]) {
+ return 0;
+ }
+ /*
+ * Or can we do a fast lookup based on a loaded group on a filesystem
+ * small enough to be mapped directly into the superblock?
+ */
+ else if (sb->u.ext3_sb.s_groups_count <= EXT3_MAX_GROUP_LOADED &&
+ sb->u.ext3_sb.s_block_bitmap_number[block_group]==block_group
+ && sb->u.ext3_sb.s_block_bitmap[block_group]) {
+ slot = block_group;
+ }
+ /*
+ * If not, then do a full lookup for this block group.
+ */
+ else {
+ slot = __load_block_bitmap (sb, block_group);
+ }
+
+ /*
+ * <0 means we just got an error
+ */
+ if (slot < 0)
+ return slot;
+
+ /*
+ * If it's a valid slot, we may still have cached a previous IO error,
+ * in which case the bh in the superblock cache will be zero.
+ */
+ if (!sb->u.ext3_sb.s_block_bitmap[slot])
+ return -EIO;
+
+ /*
+ * Must have been read in OK to get this far.
+ */
+ return slot;
+}
+
+/* Free given blocks, update quota and i_blocks field */
+void ext3_free_blocks (handle_t *handle, struct inode * inode,
+ unsigned long block, unsigned long count)
+{
+ struct buffer_head *bitmap_bh;
+ struct buffer_head *gd_bh;
+ unsigned long block_group;
+ unsigned long bit;
+ unsigned long i;
+ int bitmap_nr;
+ unsigned long overflow;
+ struct super_block * sb;
+ struct ext3_group_desc * gdp;
+ struct ext3_super_block * es;
+ int err = 0, ret;
+ int dquot_freed_blocks = 0;
+
+ sb = inode->i_sb;
+ if (!sb) {
+ printk ("ext3_free_blocks: nonexistent device");
+ return;
+ }
+ lock_super (sb);
+ es = sb->u.ext3_sb.s_es;
+ if (block < le32_to_cpu(es->s_first_data_block) ||
+ (block + count) > le32_to_cpu(es->s_blocks_count)) {
+ ext3_error (sb, "ext3_free_blocks",
+ "Freeing blocks not in datazone - "
+ "block = %lu, count = %lu", block, count);
+ goto error_return;
+ }
+
+ ext3_debug ("freeing block %lu\n", block);
+
+do_more:
+ overflow = 0;
+ block_group = (block - le32_to_cpu(es->s_first_data_block)) /
+ EXT3_BLOCKS_PER_GROUP(sb);
+ bit = (block - le32_to_cpu(es->s_first_data_block)) %
+ EXT3_BLOCKS_PER_GROUP(sb);
+ /*
+ * Check to see if we are freeing blocks across a group
+ * boundary.
+ */
+ if (bit + count > EXT3_BLOCKS_PER_GROUP(sb)) {
+ overflow = bit + count - EXT3_BLOCKS_PER_GROUP(sb);
+ count -= overflow;
+ }
+ bitmap_nr = load_block_bitmap (sb, block_group);
+ if (bitmap_nr < 0)
+ goto error_return;
+
+ bitmap_bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr];
+ gdp = ext3_get_group_desc (sb, block_group, &gd_bh);
+ if (!gdp)
+ goto error_return;
+
+ if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
+ in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
+ in_range (block, le32_to_cpu(gdp->bg_inode_table),
+ sb->u.ext3_sb.s_itb_per_group) ||
+ in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
+ sb->u.ext3_sb.s_itb_per_group))
+ ext3_error (sb, "ext3_free_blocks",
+ "Freeing blocks in system zones - "
+ "Block = %lu, count = %lu",
+ block, count);
+
+ /*
+ * We are about to start releasing blocks in the bitmap,
+ * so we need undo access.
+ */
+ /* @@@ check errors */
+ BUFFER_TRACE(bitmap_bh, "getting undo access");
+ err = ext3_journal_get_undo_access(handle, bitmap_bh);
+ if (err)
+ goto error_return;
+
+ /*
+ * We are about to modify some metadata. Call the journal APIs
+ * to unshare ->b_data if a currently-committing transaction is
+ * using it
+ */
+ BUFFER_TRACE(gd_bh, "get_write_access");
+ err = ext3_journal_get_write_access(handle, gd_bh);
+ if (err)
+ goto error_return;
+
+ BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
+ err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
+ if (err)
+ goto error_return;
+


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

+ /*
+ * An HJ special. This is expensive...
+ */
+#ifdef CONFIG_JBD_DEBUG
+ {
+ struct buffer_head *debug_bh;
+ debug_bh = get_hash_table(sb->s_dev, block + i,
+ sb->s_blocksize);
+ if (debug_bh) {
+ BUFFER_TRACE(debug_bh, "Deleted!");
+ if (!bh2jh(bitmap_bh)->b_committed_data)
+ BUFFER_TRACE(debug_bh,
+ "No commited data in bitmap");
+ BUFFER_TRACE2(debug_bh, bitmap_bh, "bitmap");
+ __brelse(debug_bh);
+ }
+ }
+#endif
+ BUFFER_TRACE(bitmap_bh, "clear bit");
+ if (!ext3_clear_bit (bit + i, bitmap_bh->b_data)) {
+ ext3_error (sb, __FUNCTION__,
+ "bit already cleared for block %lu",
+ block + i);
+ BUFFER_TRACE(bitmap_bh, "bit already cleared");
+ } else {
+ dquot_freed_blocks++;
+ gdp->bg_free_blocks_count =
+ cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)+1);
+ es->s_free_blocks_count =
+ cpu_to_le32(le32_to_cpu(es->s_free_blocks_count)+1);
+ }
+ /* @@@ This prevents newly-allocated data from being
+ * freed and then reallocated within the same
+ * transaction.
+ *
+ * Ideally we would want to allow that to happen, but to
+ * do so requires making journal_forget() capable of
+ * revoking the queued write of a data block, which
+ * implies blocking on the journal lock. *forget()
+ * cannot block due to truncate races.
+ *
+ * Eventually we can fix this by making journal_forget()
+ * return a status indicating whether or not it was able
+ * to revoke the buffer. On successful revoke, it is
+ * safe not to set the allocation bit in the committed
+ * bitmap, because we know that there is no outstanding
+ * activity on the buffer any more and so it is safe to
+ * reallocate it.
+ */
+ BUFFER_TRACE(bitmap_bh, "clear in b_committed_data");
+ J_ASSERT_BH(bitmap_bh,
+ bh2jh(bitmap_bh)->b_committed_data != NULL);
+ ext3_set_bit(bit + i, bh2jh(bitmap_bh)->b_committed_data);
+ }
+
+ /* We dirtied the bitmap block */
+ BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
+ err = ext3_journal_dirty_metadata(handle, bitmap_bh);
+
+ /* And the group descriptor block */
+ BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
+ ret = ext3_journal_dirty_metadata(handle, gd_bh);
+ if (!err) err = ret;
+
+ /* And the superblock */
+ BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "dirtied superblock");
+ ret = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
+ if (!err) err = ret;
+
+ if (overflow && !err) {
+ block += count;
+ count = overflow;
+ goto do_more;
+ }
+ sb->s_dirt = 1;
+error_return:
+ ext3_std_error(sb, err);
+ unlock_super(sb);
+ if (dquot_freed_blocks)
+ DQUOT_FREE_BLOCK(inode, dquot_freed_blocks);
+ return;
+}
+
+/* For ext3 allocations, we must not reuse any blocks which are
+ * allocated in the bitmap buffer's "last committed data" copy. This
+ * prevents deletes from freeing up the page for reuse until we have
+ * committed the delete transaction.
+ *
+ * If we didn't do this, then deleting something and reallocating it as
+ * data would allow the old block to be overwritten before the
+ * transaction committed (because we force data to disk before commit).
+ * This would lead to corruption if we crashed between overwriting the
+ * data and committing the delete.
+ *
+ * @@@ We may want to make this allocation behaviour conditional on
+ * data-writes at some point, and disable it for metadata allocations or
+ * sync-data inodes.
+ */
+static int ext3_test_allocatable(int nr, struct buffer_head *bh)
+{
+ if (ext3_test_bit(nr, bh->b_data))
+ return 0;
+ if (!buffer_jbd(bh) || !bh2jh(bh)->b_committed_data)
+ return 1;
+ return !ext3_test_bit(nr, bh2jh(bh)->b_committed_data);
+}
+
+/*
+ * Find an allocatable block in a bitmap. We honour both the bitmap and
+ * its last-committed copy (if that exists), and perform the "most
+ * appropriate allocation" algorithm of looking for a free block near
+ * the initial goal; then for a free byte somewhere in the bitmap; then
+ * for any free bit in the bitmap.
+ */
+static int find_next_usable_block(int start,
+ struct buffer_head *bh, int maxblocks)
+{
+ int here, next;
+ char *p, *r;
+
+ if (start > 0) {
+ /*
+ * The goal was occupied; search forward for a free
+ * block within the next XX blocks.
+ *
+ * end_goal is more or less random, but it has to be
+ * less than EXT3_BLOCKS_PER_GROUP. Aligning up to the
+ * next 64-bit boundary is simple..
+ */
+ int end_goal = (start + 63) & ~63;
+ here = ext3_find_next_zero_bit(bh->b_data, end_goal, start);
+ if (here < end_goal && ext3_test_allocatable(here, bh))
+ return here;
+
+ ext3_debug ("Bit not found near goal\n");
+
+ }
+
+ here = start;
+ if (here < 0)
+ here = 0;
+
+ /*
+ * There has been no free block found in the near vicinity of
+ * the goal: do a search forward through the block groups,
+ * searching in each group first for an entire free byte in the
+ * bitmap and then for any free bit.
+ *
+ * Search first in the remainder of the current group
+ */
+ p = ((char *) bh->b_data) + (here >> 3);
+ r = memscan(p, 0, (maxblocks - here + 7) >> 3);
+ next = (r - ((char *) bh->b_data)) << 3;
+
+ if (next < maxblocks && ext3_test_allocatable(next, bh))
+ return next;
+
+ /* The bitmap search --- search forward alternately
+ * through the actual bitmap and the last-committed copy
+ * until we find a bit free in both. */
+
+ while (here < maxblocks) {
+ next = ext3_find_next_zero_bit ((unsigned long *) bh->b_data,
+ maxblocks, here);
+ if (next >= maxblocks)
+ return -1;
+ if (ext3_test_allocatable(next, bh))
+ return next;
+
+ J_ASSERT_BH(bh, bh2jh(bh)->b_committed_data);
+ here = ext3_find_next_zero_bit
+ ((unsigned long *) bh2jh(bh)->b_committed_data,
+ maxblocks, next);
+ }


+ return -1;
+}
+

+/*
+ * ext3_new_block uses a goal block to assist allocation. If the goal is
+ * free, or there is a free block within 32 blocks of the goal, that block
+ * is allocated. Otherwise a forward search is made for a free block; within
+ * each block group the search first looks for an entire free byte in the block
+ * bitmap, and then for any free bit if that fails.
+ * This function also updates quota and i_blocks field.
+ */
+int ext3_new_block (handle_t *handle, struct inode * inode,
+ unsigned long goal, u32 * prealloc_count,
+ u32 * prealloc_block, int * errp)
+{
+ struct buffer_head * bh, *bhtmp;
+ struct buffer_head * bh2;
+#if 0
+ char * p, * r;
+#endif
+ int i, j, k, tmp, alloctmp;
+ int bitmap_nr;
+ int fatal = 0, err;
+ struct super_block * sb;
+ struct ext3_group_desc * gdp;
+ struct ext3_super_block * es;
+#ifdef EXT3FS_DEBUG
+ static int goal_hits = 0, goal_attempts = 0;
+#endif
+ *errp = -ENOSPC;
+ sb = inode->i_sb;
+ if (!sb) {
+ printk ("ext3_new_block: nonexistent device");


+ return 0;
+ }
+

+ /*
+ * Check quota for allocation of this block.
+ */
+ if (DQUOT_ALLOC_BLOCK(inode, 1)) {
+ *errp = -EDQUOT;


+ return 0;
+ }
+

+ lock_super (sb);
+ es = sb->u.ext3_sb.s_es;
+ if (le32_to_cpu(es->s_free_blocks_count) <=
+ le32_to_cpu(es->s_r_blocks_count) &&
+ ((sb->u.ext3_sb.s_resuid != current->fsuid) &&
+ (sb->u.ext3_sb.s_resgid == 0 ||
+ !in_group_p (sb->u.ext3_sb.s_resgid)) &&
+ !capable(CAP_SYS_RESOURCE)))
+ goto out;
+
+ ext3_debug ("goal=%lu.\n", goal);
+
+ /*
+ * First, test whether the goal block is free.
+ */
+ if (goal < le32_to_cpu(es->s_first_data_block) ||
+ goal >= le32_to_cpu(es->s_blocks_count))
+ goal = le32_to_cpu(es->s_first_data_block);
+ i = (goal - le32_to_cpu(es->s_first_data_block)) /
+ EXT3_BLOCKS_PER_GROUP(sb);
+ gdp = ext3_get_group_desc (sb, i, &bh2);
+ if (!gdp)
+ goto io_error;
+
+ if (le16_to_cpu(gdp->bg_free_blocks_count) > 0) {
+ j = ((goal - le32_to_cpu(es->s_first_data_block)) %
+ EXT3_BLOCKS_PER_GROUP(sb));
+#ifdef EXT3FS_DEBUG
+ if (j)
+ goal_attempts++;
+#endif
+ bitmap_nr = load_block_bitmap (sb, i);
+ if (bitmap_nr < 0)
+ goto io_error;
+
+ bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr];
+
+ ext3_debug ("goal is at %d:%d.\n", i, j);
+
+ if (ext3_test_allocatable(j, bh)) {
+#ifdef EXT3FS_DEBUG
+ goal_hits++;
+ ext3_debug ("goal bit allocated.\n");
+#endif
+ goto got_block;
+ }
+
+ j = find_next_usable_block(j, bh, EXT3_BLOCKS_PER_GROUP(sb));
+ if (j >= 0)
+ goto search_back;
+ }
+
+ ext3_debug ("Bit not found in block group %d.\n", i);
+
+ /*
+ * Now search the rest of the groups. We assume that
+ * i and gdp correctly point to the last group visited.
+ */
+ for (k = 0; k < sb->u.ext3_sb.s_groups_count; k++) {
+ i++;
+ if (i >= sb->u.ext3_sb.s_groups_count)
+ i = 0;
+ gdp = ext3_get_group_desc (sb, i, &bh2);
+ if (!gdp) {
+ *errp = -EIO;
+ goto out;
+ }
+ if (le16_to_cpu(gdp->bg_free_blocks_count) > 0) {
+ bitmap_nr = load_block_bitmap (sb, i);
+ if (bitmap_nr < 0)
+ goto io_error;
+
+ bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr];
+ j = find_next_usable_block(-1, bh,
+ EXT3_BLOCKS_PER_GROUP(sb));
+ if (j >= 0)
+ goto search_back;
+ }
+ }
+
+ /* No space left on the device */
+ unlock_super (sb);
+ return 0;
+
+search_back:
+ /*
+ * We have succeeded in finding a free byte in the block
+ * bitmap. Now search backwards up to 7 bits to find the
+ * start of this group of free blocks.
+ */
+ for ( k = 0;
+ k < 7 && j > 0 && ext3_test_allocatable(j - 1, bh);
+ k++, j--)
+ ;
+
+got_block:
+
+ ext3_debug ("using block group %d(%d)\n", i, gdp->bg_free_blocks_count);
+
+ /* Make sure we use undo access for the bitmap, because it is
+ critical that we do the frozen_data COW on bitmap buffers in
+ all cases even if the buffer is in BJ_Forget state in the
+ committing transaction. */
+ BUFFER_TRACE(bh, "get undo access for marking new block");
+ fatal = ext3_journal_get_undo_access(handle, bh);
+ if (fatal) goto out;
+
+ BUFFER_TRACE(bh2, "get_write_access");
+ fatal = ext3_journal_get_write_access(handle, bh2);
+ if (fatal) goto out;
+
+ BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
+ fatal = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
+ if (fatal) goto out;
+
+ tmp = j + i * EXT3_BLOCKS_PER_GROUP(sb)
+ + le32_to_cpu(es->s_first_data_block);
+
+ if (tmp == le32_to_cpu(gdp->bg_block_bitmap) ||
+ tmp == le32_to_cpu(gdp->bg_inode_bitmap) ||
+ in_range (tmp, le32_to_cpu(gdp->bg_inode_table),
+ sb->u.ext3_sb.s_itb_per_group))
+ ext3_error (sb, "ext3_new_block",
+ "Allocating block in system zone - "
+ "block = %u", tmp);
+
+ /* The superblock lock should guard against anybody else beating
+ * us to this point! */
+ J_ASSERT_BH(bh, !ext3_test_bit(j, bh->b_data));
+ BUFFER_TRACE(bh, "setting bitmap bit");
+ ext3_set_bit(j, bh->b_data);
+
+#ifdef CONFIG_JBD_DEBUG
+ {
+ struct buffer_head *debug_bh;
+
+ /* Record bitmap buffer state in the newly allocated block */
+ debug_bh = get_hash_table(sb->s_dev, tmp, sb->s_blocksize);
+ if (debug_bh) {
+ BUFFER_TRACE(debug_bh, "state when allocated");
+ BUFFER_TRACE2(debug_bh, bh, "bitmap state");
+ brelse(debug_bh);
+ }
+ }
+#endif
+ if (buffer_jbd(bh) && bh2jh(bh)->b_committed_data)
+ J_ASSERT_BH(bh, !ext3_test_bit(j, bh2jh(bh)->b_committed_data));
+ bhtmp = bh;
+ alloctmp = j;
+
+ ext3_debug ("found bit %d\n", j);
+
+ /*
+ * Do block preallocation now if required.
+ */
+#ifdef EXT3_PREALLOCATE
+ /*
+ * akpm: this is not enabled for ext3. Need to use
+ * ext3_test_allocatable()
+ */
+ /* Writer: ->i_prealloc* */
+ if (prealloc_count && !*prealloc_count) {
+ int prealloc_goal;
+ unsigned long next_block = tmp + 1;
+
+ prealloc_goal = es->s_prealloc_blocks ?
+ es->s_prealloc_blocks : EXT3_DEFAULT_PREALLOC_BLOCKS;
+
+ *prealloc_block = next_block;
+ /* Writer: end */


+ for (k = 1;

+ k < prealloc_goal && (j + k) < EXT3_BLOCKS_PER_GROUP(sb);


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

echo 'End of part 086'
echo 'File patch-2.4.15 is continued in part 087'
echo "087" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:47 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part071

#!/bin/sh -x
# this is part 071 of a 115 - part archive


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

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

+ } else {
+ /* we've got a command, let's do it! */
+ US_DEBUG(usb_stor_show_command(us->srb));
+ us->proto_handler(us->srb, us);
+ }
X }
X
X /* unlock the device pointers */
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- v2.4.14/linux/drivers/usb/uhci.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/usb/uhci.c Fri Nov 9 13:41:42 2001
@@ -2623,7 +2623,7 @@
X uhci->dev = dev;
X uhci->io_addr = io_addr;
X uhci->io_size = io_size;
- dev->driver_data = uhci;
+ pci_set_drvdata(dev, uhci);
X
X #ifdef CONFIG_PROC_FS
X uhci->num = uhci_num++;
@@ -2931,7 +2931,7 @@
X
X static void __devexit uhci_pci_remove(struct pci_dev *dev)
X {
- struct uhci *uhci = dev->driver_data;
+ struct uhci *uhci = pci_get_drvdata(dev);
X
X if (uhci->bus->root_hub)
X usb_disconnect(&uhci->bus->root_hub);
@@ -2956,14 +2956,14 @@
X #ifdef CONFIG_PM
X static int uhci_pci_suspend(struct pci_dev *dev, u32 state)
X {
- suspend_hc((struct uhci *) dev->driver_data);
+ suspend_hc((struct uhci *) pci_get_drvdata(dev));
X return 0;
X }
X
X static int uhci_pci_resume(struct pci_dev *dev)
X {
- reset_hc((struct uhci *) dev->driver_data);
- start_hc((struct uhci *) dev->driver_data);
+ reset_hc((struct uhci *) pci_get_drvdata(dev));
+ start_hc((struct uhci *) pci_get_drvdata(dev));
X return 0;
X }
X #endif
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c
--- v2.4.14/linux/drivers/usb/usb-ohci.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/usb/usb-ohci.c Fri Nov 9 13:41:42 2001
@@ -2372,7 +2372,7 @@
X ohci->regs = mem_base;
X
X ohci->ohci_dev = dev;
- dev->driver_data = ohci;
+ pci_set_drvdata(dev, ohci);
X
X INIT_LIST_HEAD (&ohci->ohci_hcd_list);
X list_add (&ohci->ohci_hcd_list, &ohci_hcd_list);
@@ -2411,7 +2411,7 @@
X free_irq (ohci->irq, ohci);
X ohci->irq = -1;
X }
- ohci->ohci_dev->driver_data = 0;
+ pci_set_drvdata(ohci->ohci_dev, NULL);
X
X usb_deregister_bus (ohci->bus);
X usb_free_bus (ohci->bus);
@@ -2600,7 +2600,7 @@
X static void __devexit
X ohci_pci_remove (struct pci_dev *dev)
X {
- ohci_t *ohci = (ohci_t *) dev->driver_data;
+ ohci_t *ohci = pci_get_drvdata(dev);
X
X dbg ("remove %s controller usb-%s%s%s",
X hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
@@ -2636,7 +2636,7 @@
X static int
X ohci_pci_suspend (struct pci_dev *dev, u32 state)
X {
- ohci_t *ohci = (ohci_t *) dev->driver_data;
+ ohci_t *ohci = pci_get_drvdata(dev);
X unsigned long flags;
X u16 cmd;
X
@@ -2715,7 +2715,7 @@
X static int
X ohci_pci_resume (struct pci_dev *dev)
X {
- ohci_t *ohci = (ohci_t *) dev->driver_data;
+ ohci_t *ohci = pci_get_drvdata(dev);
X int temp;


X unsigned long flags;
X

diff -u --recursive --new-file v2.4.14/linux/drivers/usb/usb-skeleton.c linux/drivers/usb/usb-skeleton.c
--- v2.4.14/linux/drivers/usb/usb-skeleton.c Tue Oct 9 17:06:53 2001
+++ linux/drivers/usb/usb-skeleton.c Mon Nov 12 09:53:56 2001
@@ -1,5 +1,5 @@
X /*
- * USB Skeleton driver - 0.5
+ * USB Skeleton driver - 0.6
X *
X * Copyright (c) 2001 Greg Kroah-Hartman (gr...@kroah.com)
X *
@@ -22,6 +22,8 @@
X *
X * History:
X *
+ * 2001_11_05 - 0.6 - fix minor locking problem in skel_disconnect.
+ * Thanks to Pete Zaitcev for the fix.
X * 2001_09_04 - 0.5 - fix devfs bug in skel_disconnect. Thanks to wim delvaux
X * 2001_08_21 - 0.4 - more small bug fixes.
X * 2001_05_29 - 0.3 - more bug fixes based on review from linux-usb-devel
@@ -604,6 +606,7 @@
X
X /* if the device is not opened, then we clean up right now */
X if (!dev->open_count) {
+ up (&dev->sem);
X skel_delete (dev);
X } else {
X dev->udev = NULL;
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c
--- v2.4.14/linux/drivers/usb/usb-uhci.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/usb/usb-uhci.c Fri Nov 9 13:41:42 2001
@@ -2848,7 +2848,7 @@
X _static void __devexit
X uhci_pci_remove (struct pci_dev *dev)
X {
- uhci_t *s = (uhci_t*) dev->driver_data;
+ uhci_t *s = pci_get_drvdata(dev);
X struct usb_device *root_hub = s->bus->root_hub;
X
X s->running = 0; // Don't allow submit_urb
@@ -2895,14 +2895,14 @@
X _static int
X uhci_pci_suspend (struct pci_dev *dev, u32 state)
X {
- reset_hc((uhci_t *) dev->driver_data);
+ reset_hc((uhci_t *) pci_get_drvdata(dev));


X return 0;
X }
X

X _static int
X uhci_pci_resume (struct pci_dev *dev)
X {
- start_hc((uhci_t *) dev->driver_data);
+ start_hc((uhci_t *) pci_get_drvdata(dev));
X return 0;
X }
X #endif
@@ -3006,7 +3006,7 @@
X }
X
X //chain new uhci device into global list
- dev->driver_data = s;
+ pci_set_drvdata(dev, s);
X devs=s;
X
X return 0;
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.4.14/linux/drivers/usb/usb.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/usb/usb.c Wed Nov 21 09:59:11 2001
@@ -1019,7 +1019,7 @@
X /*-------------------------------------------------------------------*/
X int usb_submit_urb(urb_t *urb)
X {
- if (urb && urb->dev)
+ if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
X return urb->dev->bus->op->submit_urb(urb);
X else
X return -ENODEV;
@@ -1028,7 +1028,7 @@
X /*-------------------------------------------------------------------*/
X int usb_unlink_urb(urb_t *urb)
X {
- if (urb && urb->dev)
+ if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
X return urb->dev->bus->op->unlink_urb(urb);
X else
X return -ENODEV;
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/usbnet.c linux/drivers/usb/usbnet.c
--- v2.4.14/linux/drivers/usb/usbnet.c Mon Nov 5 15:55:32 2001
+++ linux/drivers/usb/usbnet.c Wed Nov 21 09:51:08 2001
@@ -16,6 +16,7 @@
X *
X * - AnchorChip 2720
X * - Belkin, eTEK (interops with Win32 drivers)
+ * - GeneSys GL620USB-A
X * - "Linux Devices" (like iPaq and similar SA-1100 based PDAs)
X * - NetChip 1080 (interoperates with NetChip Win32 drivers)
X * - Prolific PL-2301/2302 (replaces "plusb" driver)
@@ -76,6 +77,11 @@
X * 17-oct-2001 Handle "Advance USBNET" product, like Belkin/eTEK devices,
X * from Ioannis Mavroukakis <i.mavr...@btinternet.com>;
X * rx unlinks somehow weren't async; minor cleanup.
+ * 03-nov-2001 Merged GeneSys driver; original code from Jiun-Jie Huang
+ * <hua...@genesyslogic.com.tw>, updated by Stanislav Brabec
+ * <u...@penguin.cz>. Made framing options (NetChip/GeneSys)
+ * tie mostly to (sub)driver info. Workaround some PL-2302
+ * chips that seem to reject SET_INTERFACE requests.
X *
X *-------------------------------------------------------------------------*/
X
@@ -101,6 +107,7 @@
X
X #define CONFIG_USB_AN2720
X #define CONFIG_USB_BELKIN
+#define CONFIG_USB_GENESYS
X #define CONFIG_USB_LINUXDEV
X #define CONFIG_USB_NET1080
X #define CONFIG_USB_PL2301
@@ -157,7 +164,10 @@
X // protocol/interface state
X struct net_device net;
X struct net_device_stats stats;
+
+#ifdef CONFIG_USB_NET1080
X u16 packet_id;
+#endif
X
X // various kinds of pending driver work
X struct sk_buff_head rxq;
@@ -173,6 +183,7 @@
X
X int flags;
X #define FLAG_FRAMING_NC 0x0001 /* guard against device dropouts */
+#define FLAG_FRAMING_GL 0x0002 /* genelink batches packets */
X #define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */
X
X /* reset device ... can sleep */
@@ -181,7 +192,15 @@
X /* see if peer is connected ... can sleep */
X int (*check_connect)(struct usbnet *);
X
+ /* fixup rx packet (strip framing) */
+ int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
+
+ /* fixup tx packet (add framing) */
+ struct sk_buff *(*tx_fixup)(struct usbnet *dev,
+ struct sk_buff *skb, int flags);
+
X // FIXME -- also an interrupt mechanism
+ // useful for at least PL2301/2302 and GL620USB-A
X
X /* framework currently "knows" bulk EPs talk packets */
X int in; /* rx endpoint */
@@ -224,47 +243,6 @@
X #define devinfo(usbnet, fmt, arg...) \
X printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net.name, ## arg)
X
-/*-------------------------------------------------------------------------
- *
- * NetChip framing of ethernet packets, supporting additional error
- * checks for links that may drop bulk packets from inside messages.
- * Odd USB length == always short read for last usb packet.
- * - nc_header
- * - Ethernet header (14 bytes)
- * - payload
- * - (optional padding byte, if needed so length becomes odd)
- * - nc_trailer
- *
- * This framing is to be avoided for non-NetChip devices.
- */
-
-struct nc_header { // packed:
- u16 hdr_len; // sizeof nc_header (LE, all)
- u16 packet_len; // payload size (including ethhdr)
- u16 packet_id; // detects dropped packets
-#define MIN_HEADER 6
-
- // all else is optional, and must start with:
- // u16 vendorId; // from usb-if
- // u16 productId;
-} __attribute__((__packed__));
-
-#define PAD_BYTE ((unsigned char)0xAC)
-
-struct nc_trailer {
- u16 packet_id;
-} __attribute__((__packed__));
-
-// packets may use FLAG_FRAMING_NC and optional pad
-#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \
- + sizeof (struct ethhdr) \
- + (mtu) \
- + 1 \
- + sizeof (struct nc_trailer))
-
-#define MIN_FRAMED FRAMED_SIZE(0)
-
-
X
X #ifdef CONFIG_USB_AN2720
X
@@ -313,6 +291,330 @@
X
X
X
+#ifdef CONFIG_USB_GENESYS
+
+/*-------------------------------------------------------------------------
+ *
+ * GeneSys GL620USB-A (www.genesyslogic.com.tw)
+ *
+ * ... should partially interop with the Win32 driver for this hardware
+ * The GeneSys docs imply there's some NDIS issue motivating this framing.
+ *
+ *-------------------------------------------------------------------------*/
+
+// control msg write command
+#define GENELINK_CONNECT_WRITE 0xF0
+// interrupt pipe index
+#define GENELINK_INTERRUPT_PIPE 0x03
+// interrupt read buffer size
+#define INTERRUPT_BUFSIZE 0x08
+// interrupt pipe interval value
+#define GENELINK_INTERRUPT_INTERVAL 0x10
+// max transmit packet number per transmit
+#define GL_MAX_TRANSMIT_PACKETS 32
+// max packet length
+#define GL_MAX_PACKET_LEN 1514
+// max receive buffer size
+#define GL_RCV_BUF_SIZE \
+ (((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4)
+
+struct gl_packet {
+ u32 packet_length;
+ char packet_data [1];
+};
+
+struct gl_header {
+ u32 packet_count;
+ struct gl_packet packets;
+};
+
+#ifdef GENLINK_ACK
+
+// FIXME: this code is incomplete, not debugged; it doesn't
+// handle interrupts correctly. interrupts should be generic
+// code like all other device I/O, anyway.
+
+struct gl_priv {
+ struct urb *irq_urb;
+ char irq_buf [INTERRUPT_BUFSIZE];
+};
+
+static inline int gl_control_write (struct usbnet *dev, u8 request, u16 value)
+{
+ int retval;
+
+ retval = usb_control_msg (dev->udev,
+ usb_sndctrlpipe (dev->udev, 0),
+ request,
+ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ value,
+ 0, // index
+ 0, // data buffer
+ 0, // size
+ CONTROL_TIMEOUT_JIFFIES);


+ return retval;
+}
+

+static void gl_interrupt_complete (struct urb *urb)
+{
+ int status = urb->status;
+
+ if (status)
+ dbg ("gl_interrupt_complete fail - %X", status);
+ else
+ dbg ("gl_interrupt_complete success...");
+}
+
+static int gl_interrupt_read (struct usbnet *dev)
+{
+ struct gl_priv *priv = dev->priv_data;
+ int retval;
+
+ // issue usb interrupt read
+ if (priv && priv->irq_urb) {
+ // submit urb
+ if ((retval = usb_submit_urb (priv->irq_urb)) != 0)
+ dbg ("gl_interrupt_read: submit fail - %X...", retval);
+ else
+ dbg ("gl_interrupt_read: submit success...");
+ }
+


+ return 0;
+}
+

+// check whether another side is connected
+static int genelink_check_connect (struct usbnet *dev)
+{
+ int retval;
+
+ dbg ("genelink_check_connect...");
+
+ // detect whether another side is connected
+ if ((retval = gl_control_write (dev, GENELINK_CONNECT_WRITE, 0)) != 0) {
+ dbg ("%s: genelink_check_connect write fail - %X",
+ dev->net.name, retval);


+ return retval;
+ }
+

+ // usb interrupt read to ack another side
+ if ((retval = gl_interrupt_read (dev)) != 0) {
+ dbg ("%s: genelink_check_connect read fail - %X",
+ dev->net.name, retval);


+ return retval;
+ }
+

+ dbg ("%s: genelink_check_connect read success", dev->net.name);


+ return 0;
+}
+

+// allocate and initialize the private data for genelink
+static int genelink_init (struct usbnet *dev)
+{
+ struct gl_priv *priv;
+
+ // allocate the private data structure
+ if ((priv = kmalloc (sizeof *priv, GFP_KERNEL)) == 0) {
+ dbg ("%s: cannot allocate private data per device",
+ dev->net.name);
+ return -ENOMEM;
+ }
+
+ // allocate irq urb
+ if ((priv->irq_urb = usb_alloc_urb (0)) == 0) {
+ dbg ("%s: cannot allocate private irq urb per device",
+ dev->net.name);
+ kfree (priv);
+ return -ENOMEM;
+ }
+
+ // fill irq urb
+ FILL_INT_URB (priv->irq_urb, dev->udev,
+ usb_rcvintpipe (dev->udev, GENELINK_INTERRUPT_PIPE),
+ priv->irq_buf, INTERRUPT_BUFSIZE,
+ gl_interrupt_complete, 0,
+ GENELINK_INTERRUPT_INTERVAL);
+
+ // set private data pointer
+ dev->priv_data = priv;
+


+ return 0;
+}
+

+// release the private data
+static int genelink_free (struct usbnet *dev)
+{
+ struct gl_priv *priv = dev->priv_data;
+
+ if (!priv)
+ return 0;
+
+// FIXME: can't cancel here; it's synchronous, and
+// should have happened earlier in any case (interrupt
+// handling needs to be generic)
+
+ // cancel irq urb first
+ usb_unlink_urb (priv->irq_urb);
+
+ // free irq urb
+ usb_free_urb (priv->irq_urb);
+
+ // free the private data structure
+ kfree (priv);
+


+ return 0;
+}
+

+#else
+
+static int genelink_check_connect (struct usbnet *dev)
+{
+ dbg ("%s: assuming peer is connected", dev->net.name);


+ return 0;
+}
+

+#endif
+
+// reset the device status
+static int genelink_reset (struct usbnet *dev)
+{
+ // we don't need to reset, just return 0


+ return 0;
+}
+

+static int genelink_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
+{
+ struct gl_header *header;
+ struct gl_packet *packet;
+ struct sk_buff *gl_skb;
+ int status;
+ u32 size;
+
+ header = (struct gl_header *) skb->data;
+
+ // get the packet count of the received skb
+ le32_to_cpus (&header->packet_count);
+ if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS)
+ || (header->packet_count < 0)) {
+ dbg ("genelink: illegal received packet count %d",
+ header->packet_count);


+ return 0;
+ }
+

+ // set the current packet pointer to the first packet
+ packet = &header->packets;
+
+ // decrement the length for the packet count size 4 bytes
+ skb_pull (skb, 4);
+
+ while (header->packet_count > 1) {
+ // get the packet length
+ size = packet->packet_length;
+
+ // this may be a broken packet
+ if (size > GL_MAX_PACKET_LEN) {
+ dbg ("genelink: illegal rx length %d", size);


+ return 0;
+ }
+

+ // allocate the skb for the individual packet
+ gl_skb = alloc_skb (size, GFP_ATOMIC);
+ if (gl_skb == 0)
+ return 0;
+
+ // copy the packet data to the new skb
+ memcpy (gl_skb->data, packet->packet_data, size);
+
+ // set skb data size
+ gl_skb->len = size;
+ gl_skb->dev = &dev->net;
+
+ // determine the packet's protocol ID
+ gl_skb->protocol = eth_type_trans (gl_skb, &dev->net);
+
+ // update the status
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += size;
+
+ // notify os of the received packet
+ status = netif_rx (gl_skb);
+
+ // advance to the next packet
+ packet = (struct gl_packet *)
+ &packet->packet_data [size];
+ header->packet_count--;
+
+ // shift the data pointer to the next gl_packet
+ skb_pull (skb, size + 4);
+ }
+
+ // skip the packet length field 4 bytes
+ skb_pull (skb, 4);
+
+ if (skb->len > GL_MAX_PACKET_LEN) {
+ dbg ("genelink: illegal rx length %d", skb->len);
+ return 0;
+ }
+ return 1;
+}
+
+static struct sk_buff *
+genelink_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags)
+{
+ int padlen;
+ int length = skb->len;
+ int headroom = skb_headroom (skb);
+ int tailroom = skb_tailroom (skb);
+ u32 *packet_count;
+ u32 *packet_len;
+
+ // FIXME: magic numbers, bleech
+ padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1;
+
+ if ((!skb_cloned (skb))
+ && ((headroom + tailroom) >= (padlen + (4 + 4*1)))) {
+ if ((headroom < (4 + 4*1)) || (tailroom < padlen)) {
+ skb->data = memmove (skb->head + (4 + 4*1),
+ skb->data, skb->len);
+ skb->tail = skb->data + skb->len;
+ }
+ } else {
+ struct sk_buff *skb2;
+ skb2 = skb_copy_expand (skb, (4 + 4*1) , padlen, flags);
+ dev_kfree_skb_any (skb);
+ skb = skb2;
+ }
+
+ // attach the packet count to the header
+ packet_count = (u32 *) skb_push (skb, (4 + 4*1));
+ packet_len = packet_count + 1;
+
+ // FIXME little endian?
+ *packet_count = 1;
+ *packet_len = length;
+
+ // add padding byte
+ if ((skb->len % EP_SIZE (dev)) == 0)
+ skb_put (skb, 1);
+
+ return skb;
+}
+
+static const struct driver_info genelink_info = {
+ description: "Genesys GeneLink",
+ flags: FLAG_FRAMING_GL | FLAG_NO_SETINT,
+ reset: genelink_reset,
+ check_connect: genelink_check_connect,
+ rx_fixup: genelink_rx_fixup,
+ tx_fixup: genelink_tx_fixup,
+
+ in: 1, out: 2,
+ epsize: 64,
+};
+
+#endif /* CONFIG_USB_GENESYS */
+
+
+
X #ifdef CONFIG_USB_LINUXDEV
X
X /*-------------------------------------------------------------------------
@@ -348,10 +650,51 @@
X /*-------------------------------------------------------------------------
X *
X * Netchip 1080 driver ... http://www.netchip.com
+ * Used in LapLink cables
X *
X *-------------------------------------------------------------------------*/
X
X /*
+ * NetChip framing of ethernet packets, supporting additional error
+ * checks for links that may drop bulk packets from inside messages.
+ * Odd USB length == always short read for last usb packet.
+ * - nc_header
+ * - Ethernet header (14 bytes)
+ * - payload
+ * - (optional padding byte, if needed so length becomes odd)
+ * - nc_trailer
+ *
+ * This framing is to be avoided for non-NetChip devices.
+ */
+
+struct nc_header { // packed:
+ u16 hdr_len; // sizeof nc_header (LE, all)
+ u16 packet_len; // payload size (including ethhdr)
+ u16 packet_id; // detects dropped packets
+#define MIN_HEADER 6
+
+ // all else is optional, and must start with:
+ // u16 vendorId; // from usb-if
+ // u16 productId;
+} __attribute__((__packed__));
+
+#define PAD_BYTE ((unsigned char)0xAC)
+
+struct nc_trailer {
+ u16 packet_id;
+} __attribute__((__packed__));
+
+// packets may use FLAG_FRAMING_NC and optional pad
+#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \
+ + sizeof (struct ethhdr) \
+ + (mtu) \
+ + 1 \
+ + sizeof (struct nc_trailer))
+
+#define MIN_FRAMED FRAMED_SIZE(0)
+
+
+/*
X * Zero means no timeout; else, how long a 64 byte bulk packet may be queued
X * before the hardware drops it. If that's done, the driver will need to
X * frame network packets to guard against the dropped USB packets. The win32
@@ -636,11 +979,113 @@


X return 0;
X }
X

+static int net1080_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
+{
+ struct nc_header *header;
+ struct nc_trailer *trailer;
+
+ if (!(skb->len & 0x01)
+ || MIN_FRAMED > skb->len
+ || skb->len > FRAMED_SIZE (dev->net.mtu)) {
+ dev->stats.rx_frame_errors++;
+ dbg ("rx framesize %d range %d..%d mtu %d", skb->len,
+ MIN_FRAMED, FRAMED_SIZE (dev->net.mtu),
+ dev->net.mtu
+ );


+ return 0;
+ }
+

+ header = (struct nc_header *) skb->data;
+ le16_to_cpus (&header->hdr_len);
+ le16_to_cpus (&header->packet_len);
+ if (FRAMED_SIZE (header->packet_len) > MAX_PACKET) {
+ dev->stats.rx_frame_errors++;
+ dbg ("packet too big, %d", header->packet_len);
+ return 0;
+ } else if (header->hdr_len < MIN_HEADER) {
+ dev->stats.rx_frame_errors++;
+ dbg ("header too short, %d", header->hdr_len);
+ return 0;
+ } else if (header->hdr_len > MIN_HEADER) {
+ // out of band data for us?
+ dbg ("header OOB, %d bytes",
+ header->hdr_len - MIN_HEADER);
+ // switch (vendor/product ids) { ... }
+ }
+ skb_pull (skb, header->hdr_len);
+
+ trailer = (struct nc_trailer *)
+ (skb->data + skb->len - sizeof *trailer);
+ skb_trim (skb, skb->len - sizeof *trailer);
+
+ if ((header->packet_len & 0x01) == 0) {
+ if (skb->data [header->packet_len] != PAD_BYTE) {
+ dev->stats.rx_frame_errors++;
+ dbg ("bad pad");
+ return 0;
+ }
+ skb_trim (skb, skb->len - 1);
+ }
+ if (skb->len != header->packet_len) {
+ dev->stats.rx_frame_errors++;
+ dbg ("bad packet len %d (expected %d)",
+ skb->len, header->packet_len);
+ return 0;
+ }
+ if (header->packet_id != get_unaligned (&trailer->packet_id)) {
+ dev->stats.rx_fifo_errors++;
+ dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
+ header->packet_id, trailer->packet_id);
+ return 0;
+ }
+#if 0
+ devdbg (dev, "frame <rx h %d p %d id %d", header->hdr_len,
+ header->packet_len, header->packet_id);
+#endif


+ return 1;
+}
+

+static struct sk_buff *
+net1080_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags)
+{
+ int padlen;
+ struct sk_buff *skb2;
+
+ padlen = ((skb->len + sizeof (struct nc_header)
+ + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;
+ if (!skb_cloned (skb)) {
+ int headroom = skb_headroom (skb);
+ int tailroom = skb_tailroom (skb);
+
+ if ((padlen + sizeof (struct nc_trailer)) <= tailroom
+ && sizeof (struct nc_header) <= headroom)
+ return skb;
+
+ if ((sizeof (struct nc_header) + padlen
+ + sizeof (struct nc_trailer)) <
+ (headroom + tailroom)) {
+ skb->data = memmove (skb->head
+ + sizeof (struct nc_header),
+ skb->data, skb->len);
+ skb->tail = skb->data + skb->len;
+ return skb;
+ }
+ }
+ skb2 = skb_copy_expand (skb,
+ sizeof (struct nc_header),
+ sizeof (struct nc_trailer) + padlen,
+ flags);
+ dev_kfree_skb_any (skb);
+ return skb2;
+}
+
X static const struct driver_info net1080_info = {
X description: "NetChip TurboCONNECT",
X flags: FLAG_FRAMING_NC,
X reset: net1080_reset,
X check_connect: net1080_check_connect,
+ rx_fixup: net1080_rx_fixup,
+ tx_fixup: net1080_tx_fixup,
X
X in: 1, out: 1, // direction distinguishes these
X epsize: 64,
@@ -714,6 +1159,8 @@
X
X static const struct driver_info prolific_info = {
X description: "Prolific PL-2301/PL-2302",
+ flags: FLAG_NO_SETINT,
+ /* some PL-2302 versions seem to fail usb_set_interface() */
X reset: pl_reset,
X check_connect: pl_check_connect,
X
@@ -737,11 +1184,19 @@
X
X if (new_mtu <= MIN_PACKET || new_mtu > MAX_PACKET)
X return -EINVAL;
+#ifdef CONFIG_USB_NET1080
X if (((dev->driver_info->flags) & FLAG_FRAMING_NC)) {
X if (FRAMED_SIZE (new_mtu) > MAX_PACKET)
X return -EINVAL;
+ }
+#endif
+#ifdef CONFIG_USB_GENESYS
+ if (((dev->driver_info->flags) & FLAG_FRAMING_GL)
+ && new_mtu > GL_MAX_PACKET_LEN)
+ return -EINVAL;
+#endif
X // no second zero-length packet read wanted after mtu-sized packets
- } else if (((new_mtu + sizeof (struct ethhdr)) % EP_SIZE (dev)) == 0)
+ if (((new_mtu + sizeof (struct ethhdr)) % EP_SIZE (dev)) == 0)
X return -EDOM;
X net->mtu = new_mtu;
X return 0;
@@ -785,9 +1240,16 @@
X unsigned long lockflags;
X size_t size;
X
+#ifdef CONFIG_USB_NET1080
X if (dev->driver_info->flags & FLAG_FRAMING_NC)
X size = FRAMED_SIZE (dev->net.mtu);
X else
+#endif
+#ifdef CONFIG_USB_GENESYS
+ if (dev->driver_info->flags & FLAG_FRAMING_GL)
+ size = GL_RCV_BUF_SIZE;
+ else
+#endif
X size = (sizeof (struct ethhdr) + dev->net.mtu);
X
X if ((skb = alloc_skb (size, flags)) == 0) {
@@ -841,72 +1303,10 @@
X
X static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
X {
- if (dev->driver_info->flags & FLAG_FRAMING_NC) {
- struct nc_header *header;
- struct nc_trailer *trailer;
-
- if (!(skb->len & 0x01)
- || MIN_FRAMED > skb->len
- || skb->len > FRAMED_SIZE (dev->net.mtu)) {
- dev->stats.rx_frame_errors++;
- dbg ("rx framesize %d range %d..%d mtu %d", skb->len,
- MIN_FRAMED, FRAMED_SIZE (dev->net.mtu),
- dev->net.mtu
- );
- goto error;
- }
-
- header = (struct nc_header *) skb->data;
- le16_to_cpus (&header->hdr_len);
- le16_to_cpus (&header->packet_len);
- if (FRAMED_SIZE (header->packet_len) > MAX_PACKET) {
- dev->stats.rx_frame_errors++;
- dbg ("packet too big, %d", header->packet_len);
- goto error;
- } else if (header->hdr_len < MIN_HEADER) {
- dev->stats.rx_frame_errors++;
- dbg ("header too short, %d", header->hdr_len);
- goto error;
- } else if (header->hdr_len > MIN_HEADER) {
- // out of band data for us?
- dbg ("header OOB, %d bytes",
- header->hdr_len - MIN_HEADER);
- // switch (vendor/product ids) { ... }
- }
- skb_pull (skb, header->hdr_len);
-
- trailer = (struct nc_trailer *)
- (skb->data + skb->len - sizeof *trailer);
- skb_trim (skb, skb->len - sizeof *trailer);
-
- if ((header->packet_len & 0x01) == 0) {
- if (skb->data [header->packet_len] != PAD_BYTE) {
- dev->stats.rx_frame_errors++;
- dbg ("bad pad");
- goto error;
- }
- skb_trim (skb, skb->len - 1);
- }
- if (skb->len != header->packet_len) {
- dev->stats.rx_frame_errors++;
- dbg ("bad packet len %d (expected %d)",
- skb->len, header->packet_len);
- goto error;
- }
- if (header->packet_id != get_unaligned (&trailer->packet_id)) {
- dev->stats.rx_fifo_errors++;
- dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
- header->packet_id, trailer->packet_id);
- goto error;
- }
-#if 0
- devdbg (dev, "frame <rx h %d p %d id %d", header->hdr_len,
- header->packet_len, header->packet_id);
-#endif
- } else {
- // we trust the network stack to remove
- // the extra byte we may have appended
- }
+ if (dev->driver_info->rx_fixup
+ && !dev->driver_info->rx_fixup (dev, skb))
+ goto error;
+ // else network stack removes extra byte if we forced a short packet
X
X if (skb->len) {
X int status;
@@ -922,7 +1322,7 @@
X devdbg (dev, "< rx, len %d, type 0x%x",
X skb->len + sizeof (struct ethhdr), skb->protocol);
X #endif
- memset (skb->cb,0,sizeof(struct skb_data));
+ memset (skb->cb, 0, sizeof (struct skb_data));
X status = netif_rx (skb);
X if (status != NET_RX_SUCCESS)
X devdbg (dev, "netif_rx status %d", status);
@@ -1040,7 +1440,7 @@
X DECLARE_WAITQUEUE (wait, current);
X
X mutex_lock (&dev->mutex);
- netif_stop_queue(net);
+ netif_stop_queue (net);
X
X devdbg (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
X dev->stats.rx_packets, dev->stats.tx_packets,
@@ -1056,7 +1456,7 @@
X while (skb_queue_len (&dev->rxq)
X && skb_queue_len (&dev->txq)
X && skb_queue_len (&dev->done)) {
- set_current_state(TASK_UNINTERRUPTIBLE);
+ set_current_state (TASK_UNINTERRUPTIBLE);
X schedule_timeout (UNLINK_TIMEOUT_JIFFIES);
X dbg ("waited for %d urb completions", temp);
X }
@@ -1099,8 +1499,10 @@
X netif_start_queue (net);
X devdbg (dev, "open: enable queueing (rx %d, tx %d) mtu %d %s framing",
X RX_QLEN, TX_QLEN, dev->net.mtu,
- (info->flags & FLAG_FRAMING_NC)
- ? "NetChip"
+ (info->flags & (FLAG_FRAMING_NC | FLAG_FRAMING_GL))
+ ? ((info->flags & FLAG_FRAMING_NC)
+ ? "NetChip"
+ : "GeneSys")
X : "raw"
X );
X
@@ -1116,7 +1518,7 @@
X /* usb_clear_halt cannot be called in interrupt context */
X
X static void
-tx_clear_halt(void *data)
+tx_clear_halt (void *data)
X {
X struct usbnet *dev = data;
X
@@ -1137,7 +1539,7 @@
X if (dev->ctrl_task.sync == 0) {
X dev->ctrl_task.routine = tx_clear_halt;
X dev->ctrl_task.data = dev;
- schedule_task(&dev->ctrl_task);
+ schedule_task (&dev->ctrl_task);
X } else {
X dbg ("Cannot clear TX stall");
X }
@@ -1161,41 +1563,6 @@
X
X /*-------------------------------------------------------------------------*/
X
-static inline struct sk_buff *fixup_skb (struct sk_buff *skb, int flags)
-{
- int padlen;
- struct sk_buff *skb2;
-
- padlen = ((skb->len + sizeof (struct nc_header)
- + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;
- if (!skb_cloned (skb)) {
- int headroom = skb_headroom (skb);
- int tailroom = skb_tailroom (skb);
-
- if ((padlen + sizeof (struct nc_trailer)) <= tailroom
- && sizeof (struct nc_header) <= headroom)
- return skb;
-
- if ((sizeof (struct nc_header) + padlen
- + sizeof (struct nc_trailer)) <
- (headroom + tailroom)) {
- skb->data = memmove (skb->head
- + sizeof (struct nc_header),
- skb->data, skb->len);
- skb->tail = skb->data + skb->len;
- return skb;
- }
- }
- skb2 = skb_copy_expand (skb,
- sizeof (struct nc_header),
- sizeof (struct nc_trailer) + padlen,
- flags);
- dev_kfree_skb_any (skb);
- return skb2;
-}
-
-/*-------------------------------------------------------------------------*/
-
X static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
X {
X struct usbnet *dev = (struct usbnet *) net->priv;
@@ -1203,21 +1570,23 @@
X int retval = NET_XMIT_SUCCESS;
X struct urb *urb = 0;
X struct skb_data *entry;
- struct nc_header *header = 0;
- struct nc_trailer *trailer = 0;
X struct driver_info *info = dev->driver_info;
X int flags;
+#ifdef CONFIG_USB_NET1080
+ struct nc_header *header = 0;
+ struct nc_trailer *trailer = 0;
+#endif /* CONFIG_USB_NET1080 */
X
X flags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL;
X
- if (info->flags & FLAG_FRAMING_NC) {
- struct sk_buff *skb2;
- skb2 = fixup_skb (skb, flags);
- if (!skb2) {
- dbg ("can't fixup skb");
+ // some devices want funky USB-level framing, for
+ // win32 driver (usually) and/or hardware quirks
+ if (info->tx_fixup) {
+ skb = info->tx_fixup (dev, skb, flags);
+ if (!skb) {
+ dbg ("can't tx_fixup skb");
X goto drop;
X }
- skb = skb2;
X }
X
X if (!(urb = usb_alloc_urb (0))) {
@@ -1231,6 +1600,10 @@
X entry->state = tx_start;
X entry->length = length;
X
+ // FIXME: reorganize a bit, so that fixup() fills out NetChip
+ // framing too. (Packet ID update needs the spinlock...)
+
+#ifdef CONFIG_USB_NET1080
X if (info->flags & FLAG_FRAMING_NC) {
X header = (struct nc_header *) skb_push (skb, sizeof *header);
X header->hdr_len = cpu_to_le16 (sizeof (*header));
@@ -1238,20 +1611,12 @@
X if (!((skb->len + sizeof *trailer) & 0x01))
X *skb_put (skb, 1) = PAD_BYTE;
X trailer = (struct nc_trailer *) skb_put (skb, sizeof *trailer);
- } else if ((length % EP_SIZE (dev)) == 0) {
- // not all hardware behaves with USB_ZERO_PACKET,
- // so we add an extra one-byte packet
- if (skb_shared (skb)) {
- struct sk_buff *skb2;
- skb2 = skb_unshare (skb, flags);
- if (!skb2) {
- dbg ("can't unshare skb");
- goto drop;
- }
- skb = skb2;
- }
+ } else
+#endif /* CONFIG_USB_NET1080 */
+
+ /* don't assume the hardware handles USB_ZERO_PACKET */
+ if ((length % EP_SIZE (dev)) == 0)
X skb->len++;
- }
X
X FILL_BULK_URB (urb, dev->udev,
X usb_sndbulkpipe (dev->udev, info->out),
@@ -1263,6 +1628,8 @@
X // FIXME urb->timeout = ... jiffies ... ;
X
X spin_lock_irqsave (&dev->txq.lock, flags);
+
+#ifdef CONFIG_USB_NET1080
X if (info->flags & FLAG_FRAMING_NC) {
X header->packet_id = cpu_to_le16 (dev->packet_id++);
X put_unaligned (header->packet_id, &trailer->packet_id);
@@ -1272,6 +1639,7 @@
X header->packet_id);
X #endif
X }
+#endif /* CONFIG_USB_NET1080 */
X
X netif_stop_queue (net);
X if ((retval = usb_submit_urb (urb)) != 0) {
@@ -1290,7 +1658,8 @@
X drop:
X retval = NET_XMIT_DROP;
X dev->stats.tx_dropped++;
- dev_kfree_skb_any (skb);
+ if (skb)
+ dev_kfree_skb_any (skb);
X usb_free_urb (urb);
X #ifdef VERBOSE
X } else {
@@ -1516,9 +1885,12 @@
X },
X #endif
X
-// GeneSys GL620USB (www.genesyslogic.com.tw)
-// (patch exists against an older driver version)
-
+#ifdef CONFIG_USB_GENESYS
+{
+ USB_DEVICE (0x05e3, 0x0502), // GL620USB-A
+ driver_info: (unsigned long) &genelink_info,
+},
+#endif
X
X #ifdef CONFIG_USB_LINUXDEV
X /*
@@ -1552,6 +1924,8 @@
X driver_info: (unsigned long) &prolific_info,
X },
X #endif
+
+/* KC2190 from www.sepoong.co.kr "InstaNET" */
X
X { }, // END
X };
diff -u --recursive --new-file v2.4.14/linux/drivers/video/Config.in linux/drivers/video/Config.in
--- v2.4.14/linux/drivers/video/Config.in Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/Config.in Wed Nov 14 15:16:31 2001
@@ -64,10 +64,10 @@
X fi
X fi
X if [ "$CONFIG_PPC" = "y" ]; then
- bool ' Open Firmware frame buffer device support' CONFIG_FB_OF
- bool ' Apple "control" display support' CONFIG_FB_CONTROL
- bool ' Apple "platinum" display support' CONFIG_FB_PLATINUM
- bool ' Apple "valkyrie" display support' CONFIG_FB_VALKYRIE
+ dep_bool ' Open Firmware frame buffer device support' CONFIG_FB_OF $CONFIG_ALL_PPC
+ dep_bool ' Apple "control" display support' CONFIG_FB_CONTROL $CONFIG_ALL_PPC
+ dep_bool ' Apple "platinum" display support' CONFIG_FB_PLATINUM $CONFIG_ALL_PPC
+ dep_bool ' Apple "valkyrie" display support' CONFIG_FB_VALKYRIE $CONFIG_ALL_PPC
X bool ' Chips 65550 display support' CONFIG_FB_CT65550
X bool ' IMS Twin Turbo display support' CONFIG_FB_IMSTT
X bool ' S3 Trio display support' CONFIG_FB_S3TRIO
diff -u --recursive --new-file v2.4.14/linux/drivers/video/acornfb.c linux/drivers/video/acornfb.c
--- v2.4.14/linux/drivers/video/acornfb.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/acornfb.c Wed Nov 14 14:52:20 2001
@@ -1528,7 +1528,7 @@
X
X acornfb_init_fbinfo();
X
- while (opt = strsep(&options, ",")) {
+ while ((opt = strsep(&options, ",")) != NULL) {
X if (!*opt)
X continue;
X
diff -u --recursive --new-file v2.4.14/linux/drivers/video/amifb.c linux/drivers/video/amifb.c
--- v2.4.14/linux/drivers/video/amifb.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/amifb.c Wed Nov 14 14:52:20 2001
@@ -1192,7 +1192,9 @@


X if (!options || !*options)
X return 0;
X

- while (this_opt = strsep(&options, ",")) {

+ while ((this_opt = strsep(&options, ",")) != NULL) {

+ if (!*this_opt)
+ continue;

X if (!strcmp(this_opt, "inverse")) {

X amifb_inverse = 1;
X fb_invert_cmaps();
diff -u --recursive --new-file v2.4.14/linux/drivers/video/aty128fb.c linux/drivers/video/aty128fb.c
--- v2.4.14/linux/drivers/video/aty128fb.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/aty128fb.c Sun Nov 11 10:09:37 2001
@@ -7,6 +7,9 @@
X * Ani Joshi / Jeff Garzik
X * - Code cleanup
X *
+ * Andreas Hundt <an...@convergence.de>
+ * - FB_ACTIVATE fixes
+ *
X * Based off of Geert's atyfb.c and vfb.c.
X *
X * TODO:
@@ -143,7 +146,7 @@
X };
X
X /* supported Rage128 chipsets */
-static const struct aty128_chip_info aty128_pci_probe_list[] __initdata =
+static struct aty128_chip_info aty128_pci_probe_list[] __initdata =
X {
X {"Rage128 RE (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RE, rage_128},
X {"Rage128 RF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RF, rage_128},
@@ -217,7 +220,7 @@
X static char *mode __initdata = NULL;
X static int nomtrr __initdata = 0;
X
-static const char *mode_option __initdata = NULL;
+static char *mode_option __initdata = NULL;
X
X #ifdef CONFIG_PPC
X static int default_vmode __initdata = VMODE_1024_768_60;
@@ -880,7 +883,11 @@
X crtc->pitch = vxres >> 3;
X
X crtc->offset = 0;
- crtc->offset_cntl = 0;
+
+ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
+ crtc->offset_cntl = 0x00010000;
+ else
+ crtc->offset_cntl = 0;
X
X crtc->vxres = vxres;
X crtc->vyres = vyres;
@@ -1363,7 +1370,7 @@
X
X aty128_encode_var(var, &par, info);
X
- if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
+ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
X return 0;
X
X oldxres = display->var.xres;
@@ -2591,6 +2598,7 @@
X #ifdef MODULE
X MODULE_AUTHOR("(c)1999-2000 Brad Douglas <br...@neruo.com>");
X MODULE_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards");
+MODULE_LICENSE("GPL");
X MODULE_PARM(noaccel, "i");
X MODULE_PARM_DESC(noaccel, "Disable hardware acceleration (0 or 1=disabled) (default=0)");
X MODULE_PARM(font, "s");
diff -u --recursive --new-file v2.4.14/linux/drivers/video/clgenfb.c linux/drivers/video/clgenfb.c
--- v2.4.14/linux/drivers/video/clgenfb.c Mon Nov 5 15:55:33 2001
+++ linux/drivers/video/clgenfb.c Mon Nov 19 15:19:42 2001
@@ -31,7 +31,7 @@


X *
X */
X

-#define CLGEN_VERSION "1.9.9"
+#define CLGEN_VERSION "1.9.9.1"
X
X #include <linux/config.h>
X #include <linux/module.h>
@@ -86,7 +86,6 @@
X /* disable runtime assertions? */
X /* #define CLGEN_NDEBUG */
X
-
X /* debug output */
X #ifdef CLGEN_DEBUG
X #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
@@ -115,6 +114,7 @@
X #define FALSE 0
X
X #define MB_ (1024*1024)
+#define KB_ (1024)
X
X #define MAX_NUM_BOARDS 7
X
@@ -439,11 +439,23 @@
X {0, 8, 0},
X {0, 8, 0},
X {0, 0, 0},
- 0, 0, -1, -1, FB_ACCEL_NONE, 40000, 32, 32, 33, 10, 96, 2,
+ 0, 0, -1, -1, FB_ACCEL_NONE, 40000, 48, 16, 32, 8, 96, 4,
X FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
X }
X },
X
+ {"800x600", /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
+ {
+ 800, 600, 800, 600, 0, 0, 8, 0,


+ {0, 8, 0},
+ {0, 8, 0},
+ {0, 8, 0},
+ {0, 0, 0},

+ 0, 0, -1, -1, FB_ACCEL_NONE, 20000, 128, 16, 24, 2, 96, 6,
+ 0, FB_VMODE_NONINTERLACED
+ }
+ },
+
X /*
X Modeline from XF86Config:
X Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805
@@ -455,8 +467,8 @@
X {0, 8, 0},
X {0, 8, 0},
X {0, 0, 0},
- 0, 0, -1, -1, FB_ACCEL_NONE, 12500, 92, 112, 31, 2, 204, 4,
- FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ 0, 0, -1, -1, FB_ACCEL_NONE, 12500, 144, 32, 30, 2, 192, 6,
+ 0, FB_VMODE_NONINTERLACED
X }
X }
X };
@@ -2404,22 +2416,27 @@
X * seem to have. */
X static unsigned int __init clgen_get_memsize (caddr_t regbase)
X {
- unsigned long mem = 1 * MB_;
+ unsigned long mem;
X unsigned char SRF;


X
X DPRINTK ("ENTER\n");
X

X SRF = vga_rseq (regbase, CL_SEQRF);
- if ((SRF & 0x18) == 0x18) {
+ switch ((SRF & 0x18)) {
+ case 0x08: mem = 512 * 1024; break;
+ case 0x10: mem = 1024 * 1024; break;
X /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
X * on the 5430. */
- mem *= 2;
+ case 0x18: mem = 2048 * 1024; break;
+ default: printk ("CLgenfb: Unknown memory size!\n");
+ mem = 1024 * 1024;
X }
X if (SRF & 0x80) {
X /* If DRAM bank switching is enabled, there must be twice as much
X * memory installed. (4MB on the 5434) */
X mem *= 2;
X }
+ /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
X return mem;


X
X DPRINTK ("EXIT\n");

@@ -2562,9 +2579,9 @@
X info->fbmem_phys = board_addr;
X info->size = board_size;
X
- printk (" RAM (%lu MB) at 0x%lx, ", info->size / MB_, board_addr);
+ printk (" RAM (%lu kB) at 0x%lx, ", info->size / KB_, board_addr);
X
- printk (KERN_INFO "Cirrus Logic chipset on PCI bus\n");
+ printk ("Cirrus Logic chipset on PCI bus\n");


X
X DPRINTK ("EXIT, returning 0\n");
X return 0;

diff -u --recursive --new-file v2.4.14/linux/drivers/video/controlfb.c linux/drivers/video/controlfb.c
--- v2.4.14/linux/drivers/video/controlfb.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/controlfb.c Wed Nov 14 14:52:20 2001
@@ -1423,7 +1423,7 @@
X if (!options || !*options)
X return;
X

- while (this_opt = strsep(&options, ",")) {

+ while ((this_opt = strsep(&options, ",")) != NULL) {

X if (!strncmp(this_opt, "font:", 5)) {
X char *p;
X int i;

diff -u --recursive --new-file v2.4.14/linux/drivers/video/cyberfb.c linux/drivers/video/cyberfb.c
--- v2.4.14/linux/drivers/video/cyberfb.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/cyberfb.c Wed Nov 14 14:52:20 2001
@@ -1022,7 +1022,9 @@


X return 0;
X }
X

- while (this_opt = strsep(&options, ",")) {

+ while ((this_opt = strsep(&options, ",")) != NULL) {

+ if (!*this_opt)
+ continue;

X if (!strcmp(this_opt, "inverse")) {
X Cyberfb_inverse = 1;
X fb_invert_cmaps();

diff -u --recursive --new-file v2.4.14/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.4.14/linux/drivers/video/fbmem.c Thu Oct 11 08:02:26 2001
+++ linux/drivers/video/fbmem.c Wed Nov 14 15:41:37 2001
@@ -563,8 +563,10 @@
X /* memory mapped io */
X off -= len;
X fb->fb_get_var(&var, PROC_CONSOLE(info), info);
- if (var.accel_flags)
+ if (var.accel_flags) {
+ unlock_kernel();
X return -EINVAL;
+ }
X start = fix.mmio_start;
X len = PAGE_ALIGN((start & ~PAGE_MASK)+fix.mmio_len);
X }
diff -u --recursive --new-file v2.4.14/linux/drivers/video/fm2fb.c linux/drivers/video/fm2fb.c
--- v2.4.14/linux/drivers/video/fm2fb.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/fm2fb.c Wed Nov 14 14:52:20 2001
@@ -430,7 +430,7 @@


X if (!options || !*options)
X return 0;
X

- while (this_opt = strsep(&options, ",")) {

+ while ((this_opt = strsep(&options, ",")) != NULL) {

X if (!strncmp(this_opt, "pal", 3))
X fm2fb_mode = FM2FB_MODE_PAL;
X else if (!strncmp(this_opt, "ntsc", 4))
diff -u --recursive --new-file v2.4.14/linux/drivers/video/hgafb.c linux/drivers/video/hgafb.c
--- v2.4.14/linux/drivers/video/hgafb.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/hgafb.c Mon Nov 12 09:46:25 2001
@@ -312,10 +312,10 @@
X static int __init hga_card_detect(void)
X {
X int count=0;
- u16 *p, p_save;
- u16 *q, q_save;
+ unsigned long p, q;
+ unsigned short p_save, q_save;
X
- hga_vram_base = VGA_MAP_MEM(0xb0000);
+ hga_vram_base = 0xb0000;
X hga_vram_len = 0x08000;
X
X if (request_region(0x3b0, 12, "hgafb"))
@@ -325,14 +325,14 @@
X
X /* do a memory check */
X
- p = (u16 *) hga_vram_base;
- q = (u16 *) (hga_vram_base + 0x01000);
+ p = hga_vram_base;
+ q = hga_vram_base + 0x01000;
X
- p_save = scr_readw(p); q_save = scr_readw(q);
+ p_save = isa_readw(p); q_save = isa_readw(q);
X
- scr_writew(0xaa55, p); if (scr_readw(p) == 0xaa55) count++;
- scr_writew(0x55aa, p); if (scr_readw(p) == 0x55aa) count++;
- scr_writew(p_save, p);
+ isa_writew(0xaa55, p); if (isa_readw(p) == 0xaa55) count++;
+ isa_writew(0x55aa, p); if (isa_readw(p) == 0x55aa) count++;
+ isa_writew(p_save, p);
X
X if (count != 2) {
X return 0;
@@ -717,7 +717,7 @@
X if (!nologo) hga_show_logo();


X #endif /* MODULE */

X
- hga_fix.smem_start = hga_vram_base;
+ hga_fix.smem_start = VGA_MAP_MEM(hga_vram_base);
X hga_fix.smem_len = hga_vram_len;
X
X disp.var = hga_default_var;
@@ -795,7 +795,7 @@


X if (!options || !*options)
X return 0;
X

- while (this_opt = strsep(&options, ",")) {

+ while ((this_opt = strsep(&options, ","))) {
X if (!strncmp(this_opt, "font:", 5))
X strcpy(fb_info.fontname, this_opt+5);
X }
diff -u --recursive --new-file v2.4.14/linux/drivers/video/igafb.c linux/drivers/video/igafb.c
--- v2.4.14/linux/drivers/video/igafb.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/igafb.c Wed Nov 14 14:52:20 2001


@@ -773,7 +773,7 @@
X if (!options || !*options)
X return 0;
X

- while (this_opt = strsep(&options, ",")) {

+ while ((this_opt = strsep(&options, ",")) != NULL) {

X if (!strncmp(this_opt, "font:", 5)) {
X char *p;
X int i;

diff -u --recursive --new-file v2.4.14/linux/drivers/video/imsttfb.c linux/drivers/video/imsttfb.c
--- v2.4.14/linux/drivers/video/imsttfb.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/imsttfb.c Wed Nov 14 14:52:20 2001
@@ -1950,7 +1950,7 @@
X
X init_imstt(p);
X
- pdev->driver_data = p;
+ pci_set_drvdata(pdev, p);
X
X return 0;
X }
@@ -1958,7 +1958,7 @@
X static void __devexit
X imsttfb_remove(struct pci_dev *pdev)
X {
- struct fb_info_imstt *p = (struct fb_info_imstt *)pdev->driver_data;
+ struct fb_info_imstt *p = pci_get_drvdata(pdev);
X
X unregister_framebuffer(&p->info);
X iounmap(p->cmap_regs);
@@ -1977,7 +1977,7 @@


X if (!options || !*options)
X return 0;
X

- while (this_opt = strsep(&options, ",")) {

+ while ((this_opt = strsep(&options, ",")) != NULL) {

X if (!strncmp(this_opt, "font:", 5)) {
X char *p;
X int i;

diff -u --recursive --new-file v2.4.14/linux/drivers/video/macfb.c linux/drivers/video/macfb.c
--- v2.4.14/linux/drivers/video/macfb.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/macfb.c Wed Nov 14 14:52:20 2001
@@ -848,7 +848,7 @@
X if (!options || !*options)
X return;
X

- while (this_opt = strsep(&options, ",")) {

+ while ((this_opt = strsep(&options, ",")) != NULL) {
X if (!*this_opt) continue;
X

X if (! strcmp(this_opt, "inverse"))
diff -u --recursive --new-file v2.4.14/linux/drivers/video/matrox/i2c-matroxfb.c linux/drivers/video/matrox/i2c-matroxfb.c
--- v2.4.14/linux/drivers/video/matrox/i2c-matroxfb.c Tue Oct 9 17:06:53 2001
+++ linux/drivers/video/matrox/i2c-matroxfb.c Fri Nov 9 14:07:41 2001


@@ -1,3 +1,15 @@
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
+ *
+ * (c) 1998-2001 Petr Vandrovec <vand...@vc.cvut.cz>
+ *
+ * Version: 1.51 2001/01/19
+ *
+ * See matroxfb_base.c for contributors.

+ *
+ */
+

X #include "matroxfb_base.h"
X #include "matroxfb_maven.h"
X #include <linux/i2c.h>
@@ -282,8 +294,8 @@
X return NULL;
X
X matroxfb_DAC_lock_irqsave(flags);
- matroxfb_DAC_out(PMINFO DAC_XGENIODATA, 0x00);
- matroxfb_DAC_out(PMINFO DAC_XGENIOCTRL, 0xFF);
+ matroxfb_DAC_out(PMINFO DAC_XGENIODATA, 0xFF);
+ matroxfb_DAC_out(PMINFO DAC_XGENIOCTRL, 0x00);
X matroxfb_DAC_unlock_irqrestore(flags);


X
X memset(m2info, 0, sizeof(*m2info));

@@ -343,7 +355,7 @@
X matroxfb_unregister_driver(&i2c_matroxfb);
X }
X
-MODULE_AUTHOR("(c) 1999 Petr Vandrovec <vand...@vc.cvut.cz>");


+MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec <vand...@vc.cvut.cz>");

X MODULE_DESCRIPTION("Support module providing I2C buses present on Matrox videocards");
X
X module_init(i2c_matroxfb_init);
diff -u --recursive --new-file v2.4.14/linux/drivers/video/matrox/matroxfb_DAC1064.c linux/drivers/video/matrox/matroxfb_DAC1064.c
--- v2.4.14/linux/drivers/video/matrox/matroxfb_DAC1064.c Tue Oct 9 17:06:53 2001
+++ linux/drivers/video/matrox/matroxfb_DAC1064.c Fri Nov 9 14:07:41 2001
@@ -321,7 +321,8 @@
X outDAC1064(PMINFO 0x20, 0x04);
X outDAC1064(PMINFO 0x1F, ACCESS_FBINFO(devflags.dfp_type));
X if (ACCESS_FBINFO(devflags.g450dac)) {
- outDAC1064(PMINFO M1064_X8B, 0xCC); /* only matrox know... */
+ outDAC1064(PMINFO M1064_XSYNCCTRL, 0xCC); /* only matrox know... */
+ outDAC1064(PMINFO M1064_XPWRCTRL, 0x1F); /* powerup everything */
X outDAC1064(PMINFO M1064_XOUTPUTCONN, hw->DACreg[POS1064_XOUTPUTCONN]);
X }
X }
diff -u --recursive --new-file v2.4.14/linux/drivers/video/matrox/matroxfb_DAC1064.h linux/drivers/video/matrox/matroxfb_DAC1064.h
--- v2.4.14/linux/drivers/video/matrox/matroxfb_DAC1064.h Fri Dec 29 14:07:23 2000
+++ linux/drivers/video/matrox/matroxfb_DAC1064.h Fri Nov 9 14:07:41 2001
@@ -138,11 +138,13 @@
X #define M1064_XTVO_DATA 0x88
X
X #define M1064_XOUTPUTCONN 0x8A
-#define M1064_X8B 0x8B
+#define M1064_XSYNCCTRL 0x8B
X #define M1064_XPIXPLL2STAT 0x8C
X #define M1064_XPIXPLL2P 0x8D
X #define M1064_XPIXPLL2N 0x8E
X #define M1064_XPIXPLL2M 0x8F
+
+#define M1064_XPWRCTRL 0xA0
X
X enum POS1064 {
X POS1064_XCURADDL=0, POS1064_XCURADDH, POS1064_XCURCTRL,
diff -u --recursive --new-file v2.4.14/linux/drivers/video/matrox/matroxfb_base.c linux/drivers/video/matrox/matroxfb_base.c
--- v2.4.14/linux/drivers/video/matrox/matroxfb_base.c Tue Oct 23 22:48:52 2001
+++ linux/drivers/video/matrox/matroxfb_base.c Wed Nov 14 14:52:20 2001
@@ -988,8 +988,6 @@
X #undef minfo
X }
X
-static int matroxfb_switch(int con, struct fb_info *info);
-
X static int matroxfb_get_vblank(CPMINFO struct fb_vblank *vblank)
X {
X unsigned int sts1;
@@ -1183,7 +1181,7 @@
X fb_ioctl: matroxfb_ioctl,
X };
X
-static int matroxfb_switch(int con, struct fb_info *info)
+int matroxfb_switch(int con, struct fb_info *info)
X {
X #define minfo ((struct matrox_fb_info*)info)
X struct fb_cmap* cmap;
@@ -1414,11 +1412,11 @@
X #define DEVF_VIDEO64BIT 0x0001
X #define DEVF_SWAPS 0x0002
X #define DEVF_SRCORG 0x0004
-/* #define DEVF_recycled 0x0008 */
+#define DEVF_BOTHDACS 0x0008 /* put CRTC1 on both outputs by default */
X #define DEVF_CROSS4MB 0x0010
X #define DEVF_TEXT4B 0x0020
X #define DEVF_DDC_8_2 0x0040
-/* #define DEVF_recycled 0x0080 */
+#define DEVF_G550DAC 0x0080
X #define DEVF_SUPPORT32MB 0x0100
X #define DEVF_ANY_VXRES 0x0200
X #define DEVF_TEXT16B 0x0400
@@ -1434,6 +1432,7 @@
X #define DEVF_G400 (DEVF_G2CORE | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2)
X /* if you'll find how to drive DFP... */
X #define DEVF_G450 (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2 | DEVF_G450DAC | DEVF_SRCORG)
+#define DEVF_G550 (DEVF_G450 | DEVF_G550DAC | DEVF_BOTHDACS)
X
X static struct board {
X unsigned short vendor, device, rev, svid, sid;
@@ -1477,13 +1476,13 @@
X "Mystique 220 (PCI)"},
X #endif
X #ifdef CONFIG_FB_MATROX_G100
- {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100, 0xFF,
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_MM, 0xFF,
X PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MGA_G100_PCI,
X DEVF_G100,
X 230000,
X &vbG100,
X "MGA-G100 (PCI)"},
- {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100, 0xFF,
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_MM, 0xFF,
X 0, 0,
X DEVF_G100,
X 230000,
@@ -1561,24 +1560,30 @@
X 230000,
X &vbG200,
X "G200 (AGP)"},
- {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400_AGP, 0x80,
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400, 0x80,
X PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MILLENNIUM_G400_MAX_AGP,
X DEVF_G400,
X 360000,
X &vbG400,
X "Millennium G400 MAX (AGP)"},
- {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400_AGP, 0x80,
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400, 0x80,
X 0, 0,
X DEVF_G400,
X 300000,
X &vbG400,
X "G400 (AGP)"},
- {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400_AGP, 0xFF,
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400, 0xFF,
X 0, 0,
X DEVF_G450,
X 500000, /* ??? vco goes up to 900MHz... */
X &vbG400,
- "G450 (AGP)"},
+ "G450"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G550, 0xFF,
+ 0, 0,
+ DEVF_G550,
+ 500000,
+ &vbG400,
+ "G550"},
X #endif
X {0, 0, 0xFF,
X 0, 0,
@@ -1641,8 +1646,18 @@
X if (dfp)
X ACCESS_FBINFO(output.ph) |= MATROXFB_OUTPUT_CONN_DFP;
X }
+ if (b->flags & DEVF_BOTHDACS) {
+#ifdef CONFIG_FB_MATROX_G450
+ ACCESS_FBINFO(output.all) |= MATROXFB_OUTPUT_CONN_SECONDARY;
+ ACCESS_FBINFO(output.ph) |= MATROXFB_OUTPUT_CONN_SECONDARY;
+#else
+ printk(KERN_INFO "Only digital output of G550 is now working (in analog mode). Enable G450 support in\n");
+ printk(KERN_INFO "kernel configuration if you have analog monitor connected to G550 analog output.\n");
+#endif
+ }
X ACCESS_FBINFO(devflags.dfp_type) = dfp_type;
X ACCESS_FBINFO(devflags.g450dac) = b->flags & DEVF_G450DAC;
+ ACCESS_FBINFO(devflags.g550dac) = b->flags & DEVF_G550DAC;
X ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode);
X ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode);
X
@@ -2060,7 +2075,7 @@
X ACCESS_FBINFO(pcidev) = pdev;
X ACCESS_FBINFO(dead) = 0;
X ACCESS_FBINFO(usecount) = 0;
- pdev->driver_data = MINFO;
+ pci_set_drvdata(pdev, MINFO);
X /* CMDLINE */
X memcpy(ACCESS_FBINFO(fbcon.fontname), fontname, sizeof(ACCESS_FBINFO(fbcon.fontname)));
X /* DEVFLAGS */
@@ -2122,7 +2137,7 @@
X static void pci_remove_matrox(struct pci_dev* pdev) {
X struct matrox_fb_info* minfo;
X
- minfo = pdev->driver_data;
+ minfo = pci_get_drvdata(pdev);
X matroxfb_remove(PMINFO 1);
X }
X
@@ -2140,7 +2155,7 @@
X PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
X #endif
X #ifdef CONFIG_FB_MATROX_G100
- {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100,
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_MM,
X PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
X {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP,
X PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -2148,7 +2163,9 @@
X PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
X {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP,
X PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400_AGP,
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G550,
X PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
X #endif
X {0, 0,
@@ -2355,7 +2372,7 @@


X if (!options || !*options)
X return 0;
X

- while (this_opt = strsep(&options, ",")) {

+ while ((this_opt = strsep(&options, ",")) != NULL) {
X if (!*this_opt) continue;
X

X dprintk("matroxfb_setup: option %s\n", this_opt);
@@ -2638,6 +2655,7 @@
X module_exit(matrox_done);
X EXPORT_SYMBOL(matroxfb_register_driver);
X EXPORT_SYMBOL(matroxfb_unregister_driver);
+EXPORT_SYMBOL(matroxfb_switch);
X
X /*
X * Overrides for Emacs so that we follow Linus's tabbing style.
diff -u --recursive --new-file v2.4.14/linux/drivers/video/matrox/matroxfb_base.h linux/drivers/video/matrox/matroxfb_base.h
--- v2.4.14/linux/drivers/video/matrox/matroxfb_base.h Tue Oct 9 17:06:53 2001
+++ linux/drivers/video/matrox/matroxfb_base.h Fri Nov 9 14:07:41 2001
@@ -146,21 +146,6 @@
X #ifndef PCI_SS_VENDOR_ID_MATROX
X #define PCI_SS_VENDOR_ID_MATROX PCI_VENDOR_ID_MATROX
X #endif
-#ifndef PCI_DEVICE_ID_MATROX_G200_PCI
-#define PCI_DEVICE_ID_MATROX_G200_PCI 0x0520
-#endif
-#ifndef PCI_DEVICE_ID_MATROX_G200_AGP
-#define PCI_DEVICE_ID_MATROX_G200_AGP 0x0521
-#endif
-#ifndef PCI_DEVICE_ID_MATROX_G100
-#define PCI_DEVICE_ID_MATROX_G100 0x1000
-#endif
-#ifndef PCI_DEVICE_ID_MATROX_G100_AGP
-#define PCI_DEVICE_ID_MATROX_G100_AGP 0x1001
-#endif
-#ifndef PCI_DEVICE_ID_MATROX_G400_AGP
-#define PCI_DEVICE_ID_MATROX_G400_AGP 0x0525
-#endif
X
X #ifndef PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP
X #define PCI_SS_ID_MATROX_GENERIC 0xFF00
@@ -533,6 +518,7 @@
X /* 0 except for 6MB Millenium */
X int memtype;
X int g450dac;
+ int g550dac;
X int dfp_type;
X } devflags;
X struct display_switch dispsw;
diff -u --recursive --new-file v2.4.14/linux/drivers/video/matrox/matroxfb_crtc2.c linux/drivers/video/matrox/matroxfb_crtc2.c
--- v2.4.14/linux/drivers/video/matrox/matroxfb_crtc2.c Fri May 25 09:54:50 2001
+++ linux/drivers/video/matrox/matroxfb_crtc2.c Fri Nov 9 14:07:41 2001
@@ -130,14 +130,31 @@
X if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY)
X tmp |= 0x00100000; /* connect CRTC2 to DAC */
X }
+ if (mt->interlaced) {
+ tmp |= 0x02000000; /* interlaced, second field is bigger, as G450 apparently ignores it */
+ mt->VDisplay >>= 1;
+ mt->VSyncStart >>= 1;
+ mt->VSyncEnd >>= 1;
+ mt->VTotal >>= 1;
+ }
X mga_outl(0x3C10, tmp | 0x10000000); /* depth and so on... 0x10000000 is VIDRST polarity */
X mga_outl(0x3C14, ((mt->HDisplay - 8) << 16) | (mt->HTotal - 8));
X mga_outl(0x3C18, ((mt->HSyncEnd - 8) << 16) | (mt->HSyncStart - 8));
X mga_outl(0x3C1C, ((mt->VDisplay - 1) << 16) | (mt->VTotal - 1));
X mga_outl(0x3C20, ((mt->VSyncEnd - 1) << 16) | (mt->VSyncStart - 1));
X mga_outl(0x3C24, ((mt->VSyncStart) << 16) | (mt->HSyncStart)); /* preload */
- mga_outl(0x3C28, pos); /* vmemory start */
- mga_outl(0x3C40, p->var.xres_virtual * (p->var.bits_per_pixel >> 3));
+ {
+ u_int32_t linelen = p->var.xres_virtual * (p->var.bits_per_pixel >> 3);
+ if (mt->interlaced) {
+ /* field #0 is smaller, so... */
+ mga_outl(0x3C2C, pos); /* field #1 vmemory start */
+ mga_outl(0x3C28, pos + linelen); /* field #0 vmemory start */
+ linelen <<= 1;
+ } else {
+ mga_outl(0x3C28, pos); /* vmemory start */
+ }
+ mga_outl(0x3C40, linelen);
+ }
X tmp = 0x0FFF0000; /* line compare */
X if (mt->sync & FB_SYNC_HOR_HIGH_ACT)
X tmp |= 0x00000100;
@@ -155,11 +172,20 @@
X static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info,
X struct fb_var_screeninfo* var) {
X unsigned int pos;
+ unsigned int linelen;
+ unsigned int pixelsize;
X
X #define minfo (m2info->primary_dev)
- pos = (var->yoffset * var->xres_virtual + var->xoffset) * var->bits_per_pixel >> 3;
+ pixelsize = var->bits_per_pixel >> 3;
+ linelen = var->xres_virtual * pixelsize;
+ pos = var->yoffset * linelen + var->xoffset * pixelsize;
X pos += m2info->video.offbase;
- mga_outl(0x3C28, pos);
+ if (var->vmode & FB_VMODE_INTERLACED) {
+ mga_outl(0x3C2C, pos);
+ mga_outl(0x3C28, pos + linelen);
+ } else {
+ mga_outl(0x3C28, pos);
+ }
X #undef minfo
X }
X
@@ -700,15 +726,13 @@
X m2info->mmio.len = ACCESS_FBINFO(mmio.len);
X
X /*
- * If we have two outputs, connect CRTC2 to it...
+ * If we have unused output, connect CRTC2 to it...
X */
- if (ACCESS_FBINFO(output.all) & MATROXFB_OUTPUT_CONN_SECONDARY) {
+ if ((ACCESS_FBINFO(output.all) & MATROXFB_OUTPUT_CONN_SECONDARY) &&
+ !(ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) &&
+ !(ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP)) {
X ACCESS_FBINFO(output.sh) |= MATROXFB_OUTPUT_CONN_SECONDARY;
- ACCESS_FBINFO(output.ph) &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
- if (ACCESS_FBINFO(output.all) & MATROXFB_OUTPUT_CONN_DFP) {
- ACCESS_FBINFO(output.sh) &= ~MATROXFB_OUTPUT_CONN_DFP;
- ACCESS_FBINFO(output.ph) &= ~MATROXFB_OUTPUT_CONN_DFP;
- }
+ ACCESS_FBINFO(output.sh) &= ~MATROXFB_OUTPUT_CONN_DFP;
X }
X
X matroxfb_dh_set_var(&matroxfb_dh_defined, -2, &m2info->fbcon);
@@ -815,6 +839,7 @@
X
X MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec <vand...@vc.cvut.cz>");
X MODULE_DESCRIPTION("Matrox G400 CRTC2 driver");
+MODULE_LICENSE("GPL");
X module_init(matroxfb_crtc2_init);
X module_exit(matroxfb_crtc2_exit);
X /* we do not have __setup() yet */
diff -u --recursive --new-file v2.4.14/linux/drivers/video/matrox/matroxfb_g450.c linux/drivers/video/matrox/matroxfb_g450.c
--- v2.4.14/linux/drivers/video/matrox/matroxfb_g450.c Tue Jul 3 17:08:21 2001
+++ linux/drivers/video/matrox/matroxfb_g450.c Fri Nov 9 14:07:41 2001


@@ -1,3 +1,15 @@
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
+ *
+ * (c) 1998-2001 Petr Vandrovec <vand...@vc.cvut.cz>
+ *
+ * Version: 1.51 2001/01/19
+ *
+ * See matroxfb_base.c for contributors.

+ *
+ */
+

X #include "matroxfb_g450.h"


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

echo 'End of part 071'
echo 'File patch-2.4.15 is continued in part 072'
echo "072" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:04 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part088

#!/bin/sh -x
# this is part 088 of a 115 - part archive


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

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

+ branch[n].bh = bh;
+ lock_buffer(bh);
+ BUFFER_TRACE(bh, "call get_create_access");
+ err = ext3_journal_get_create_access(handle, bh);
+ if (err) {
+ unlock_buffer(bh);
+ brelse(bh);
+ break;
+ }
+
+ memset(bh->b_data, 0, blocksize);
+ branch[n].p = (u32*) bh->b_data + offsets[n];
+ *branch[n].p = branch[n].key;
+ BUFFER_TRACE(bh, "marking uptodate");
+ mark_buffer_uptodate(bh, 1);
+ unlock_buffer(bh);
+
+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
+ err = ext3_journal_dirty_metadata(handle, bh);
+ if (err)
+ break;
+
+ parent = nr;
+ }
+ if (IS_SYNC(inode))
+ handle->h_sync = 1;
+ }
+ if (n == num)
+ return 0;
+
+ /* Allocation failed, free what we already allocated */
+ for (i = 1; i < keys; i++) {
+ BUFFER_TRACE(branch[i].bh, "call journal_forget");
+ ext3_journal_forget(handle, branch[i].bh);
+ }
+ for (i = 0; i < keys; i++)
+ ext3_free_blocks(handle, inode, le32_to_cpu(branch[i].key), 1);
+ return err;
+}
+
+/**
+ * ext3_splice_branch - splice the allocated branch onto inode.
+ * @inode: owner
+ * @block: (logical) number of block we are adding
+ * @chain: chain of indirect blocks (with a missing link - see
+ * ext3_alloc_branch)
+ * @where: location of missing link
+ * @num: number of blocks we are adding
+ *
+ * This function verifies that chain (up to the missing link) had not
+ * changed, fills the missing link and does all housekeeping needed in
+ * inode (->i_blocks, etc.). In case of success we end up with the full
+ * chain to new block and return 0. Otherwise (== chain had been changed)
+ * we free the new blocks (forgetting their buffer_heads, indeed) and
+ * return -EAGAIN.
+ */
+
+static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block,
+ Indirect chain[4], Indirect *where, int num)
+{
+ int i;
+ int err = 0;
+
+ /*
+ * If we're splicing into a [td]indirect block (as opposed to the
+ * inode) then we need to get write access to the [td]indirect block
+ * before the splice.
+ */
+ if (where->bh) {
+ BUFFER_TRACE(where->bh, "get_write_access");
+ err = ext3_journal_get_write_access(handle, where->bh);
+ if (err)
+ goto err_out;
+ }
+ /* Verify that place we are splicing to is still there and vacant */
+
+ /* Writer: pointers, ->i_next_alloc* */
+ if (!verify_chain(chain, where-1) || *where->p)


+ /* Writer: end */

+ goto changed;
+
+ /* That's it */
+
+ *where->p = where->key;
+ inode->u.ext3_i.i_next_alloc_block = block;
+ inode->u.ext3_i.i_next_alloc_goal = le32_to_cpu(where[num-1].key);
+#ifdef SEARCH_FROM_ZERO
+ inode->u.ext3_i.i_next_alloc_block = 0;
+ inode->u.ext3_i.i_next_alloc_goal = 0;
+#endif


+ /* Writer: end */
+

+ /* We are done with atomic stuff, now do the rest of housekeeping */
+
+ inode->i_ctime = CURRENT_TIME;
+ ext3_mark_inode_dirty(handle, inode);
+
+ /* had we spliced it onto indirect block? */
+ if (where->bh) {
+ /*
+ * akpm: If we spliced it onto an indirect block, we haven't
+ * altered the inode. Note however that if it is being spliced
+ * onto an indirect block at the very end of the file (the
+ * file is growing) then we *will* alter the inode to reflect
+ * the new i_size. But that is not done here - it is done in
+ * generic_commit_write->__mark_inode_dirty->ext3_dirty_inode.
+ */
+ jbd_debug(5, "splicing indirect only\n");
+ BUFFER_TRACE(where->bh, "call ext3_journal_dirty_metadata");
+ err = ext3_journal_dirty_metadata(handle, where->bh);
+ if (err)
+ goto err_out;
+ } else {
+ /*
+ * OK, we spliced it into the inode itself on a direct block.
+ * Inode was dirtied above.
+ */
+ jbd_debug(5, "splicing direct\n");
+ }
+ return err;
+
+changed:
+ /*
+ * AKPM: if where[i].bh isn't part of the current updating
+ * transaction then we explode nastily. Test this code path.
+ */
+ jbd_debug(1, "the chain changed: try again\n");
+ err = -EAGAIN;
+
+err_out:
+ for (i = 1; i < num; i++) {
+ BUFFER_TRACE(where[i].bh, "call journal_forget");
+ ext3_journal_forget(handle, where[i].bh);
+ }
+ /* For the normal collision cleanup case, we free up the blocks.
+ * On genuine filesystem errors we don't even think about doing
+ * that. */
+ if (err == -EAGAIN)
+ for (i = 0; i < num; i++)
+ ext3_free_blocks(handle, inode,
+ le32_to_cpu(where[i].key), 1);
+ return err;
+}
+
+/*
+ * Allocation strategy is simple: if we have to allocate something, we will
+ * have to go the whole way to leaf. So let's do it before attaching anything
+ * to tree, set linkage between the newborn blocks, write them if sync is
+ * required, recheck the path, free and repeat if check fails, otherwise
+ * set the last missing link (that will protect us from any truncate-generated
+ * removals - all blocks on the path are immune now) and possibly force the
+ * write on the parent block.
+ * That has a nice additional property: no special recovery from the failed
+ * allocations is needed - we simply release blocks and do not touch anything
+ * reachable from inode.
+ *
+ * akpm: `handle' can be NULL if create == 0.
+ */
+
+static int ext3_get_block_handle(handle_t *handle, struct inode *inode,
+ long iblock,
+ struct buffer_head *bh_result, int create)
+{
+ int err = -EIO;
+ int offsets[4];
+ Indirect chain[4];
+ Indirect *partial;
+ unsigned long goal;
+ int left;
+ int depth = ext3_block_to_path(inode, iblock, offsets);
+ loff_t new_size;
+
+ J_ASSERT(handle != NULL || create == 0);
+
+ if (depth == 0)
+ goto out;
+
+ lock_kernel();
+reread:
+ partial = ext3_get_branch(inode, depth, offsets, chain, &err);
+
+ /* Simplest case - block found, no allocation needed */
+ if (!partial) {
+ bh_result->b_state &= ~(1UL << BH_New);
+got_it:
+ bh_result->b_dev = inode->i_dev;
+ bh_result->b_blocknr = le32_to_cpu(chain[depth-1].key);
+ bh_result->b_state |= (1UL << BH_Mapped);
+ /* Clean up and exit */
+ partial = chain+depth-1; /* the whole chain */
+ goto cleanup;
+ }
+
+ /* Next simple case - plain lookup or failed read of indirect block */
+ if (!create || err == -EIO) {
+cleanup:
+ while (partial > chain) {
+ BUFFER_TRACE(partial->bh, "call brelse");
+ brelse(partial->bh);
+ partial--;
+ }
+ BUFFER_TRACE(bh_result, "returned");
+ unlock_kernel();
+out:
+ return err;
+ }
+
+ /*
+ * Indirect block might be removed by truncate while we were
+ * reading it. Handling of that case (forget what we've got and
+ * reread) is taken out of the main path.
+ */
+ if (err == -EAGAIN)
+ goto changed;
+
+ if (ext3_find_goal(inode, iblock, chain, partial, &goal) < 0)
+ goto changed;
+
+ left = (chain + depth) - partial;
+
+ /*
+ * Block out ext3_truncate while we alter the tree
+ */
+ down_read(&inode->u.ext3_i.truncate_sem);
+ err = ext3_alloc_branch(handle, inode, left, goal,
+ offsets+(partial-chain), partial);
+
+ /* The ext3_splice_branch call will free and forget any buffers
+ * on the new chain if there is a failure, but that risks using
+ * up transaction credits, especially for bitmaps where the
+ * credits cannot be returned. Can we handle this somehow? We
+ * may need to return -EAGAIN upwards in the worst case. --sct */
+ if (!err)
+ err = ext3_splice_branch(handle, inode, iblock, chain,
+ partial, left);
+ up_read(&inode->u.ext3_i.truncate_sem);
+ if (err == -EAGAIN)
+ goto changed;
+ if (err)
+ goto cleanup;
+
+ new_size = inode->i_size;
+ /*
+ * This is not racy against ext3_truncate's modification of i_disksize
+ * because VM/VFS ensures that the file cannot be extended while
+ * truncate is in progress. It is racy between multiple parallel
+ * instances of get_block, but we have the BKL.
+ */
+ if (new_size > inode->u.ext3_i.i_disksize)
+ inode->u.ext3_i.i_disksize = new_size;
+
+ bh_result->b_state |= (1UL << BH_New);
+ goto got_it;
+
+changed:
+ while (partial > chain) {
+ jbd_debug(1, "buffer chain changed, retrying\n");
+ BUFFER_TRACE(partial->bh, "brelsing");
+ brelse(partial->bh);
+ partial--;
+ }
+ goto reread;
+}
+
+static int ext3_get_block(struct inode *inode, long iblock,
+ struct buffer_head *bh_result, int create)
+{
+ handle_t *handle = 0;
+ int ret;
+
+ if (create) {
+ handle = ext3_journal_current_handle();
+ J_ASSERT(handle != 0);
+ }
+ ret = ext3_get_block_handle(handle, inode, iblock, bh_result, create);
+ return ret;
+}
+
+/*
+ * `handle' can be NULL if create is zero
+ */
+struct buffer_head *ext3_getblk(handle_t *handle, struct inode * inode,
+ long block, int create, int * errp)
+{
+ struct buffer_head dummy;


+ int fatal = 0, err;
+

+ J_ASSERT(handle != NULL || create == 0);
+
+ dummy.b_state = 0;
+ dummy.b_blocknr = -1000;
+ buffer_trace_init(&dummy.b_history);
+ *errp = ext3_get_block_handle(handle, inode, block, &dummy, create);
+ if (!*errp && buffer_mapped(&dummy)) {
+ struct buffer_head *bh;
+ bh = getblk(dummy.b_dev, dummy.b_blocknr,
+ inode->i_sb->s_blocksize);
+ if (buffer_new(&dummy)) {
+ J_ASSERT(create != 0);
+ J_ASSERT(handle != 0);
+
+ /* Now that we do not always journal data, we
+ should keep in mind whether this should
+ always journal the new buffer as metadata.
+ For now, regular file writes use
+ ext3_get_block instead, so it's not a
+ problem. */
+ lock_kernel();
+ lock_buffer(bh);
+ BUFFER_TRACE(bh, "call get_create_access");
+ fatal = ext3_journal_get_create_access(handle, bh);
+ if (!fatal) {
+ memset(bh->b_data, 0,
+ inode->i_sb->s_blocksize);
+ mark_buffer_uptodate(bh, 1);
+ }
+ unlock_buffer(bh);
+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
+ err = ext3_journal_dirty_metadata(handle, bh);
+ if (!fatal) fatal = err;
+ unlock_kernel();
+ } else {
+ BUFFER_TRACE(bh, "not a new buffer");
+ }
+ if (fatal) {
+ *errp = fatal;
+ brelse(bh);


+ bh = NULL;
+ }

+ return bh;


+ }
+ return NULL;
+}
+

+struct buffer_head *ext3_bread(handle_t *handle, struct inode * inode,
+ int block, int create, int *err)
+{
+ struct buffer_head * bh;
+ int prev_blocks;
+
+ prev_blocks = inode->i_blocks;
+
+ bh = ext3_getblk (handle, inode, block, create, err);
+ if (!bh)
+ return bh;
+#ifdef EXT3_PREALLOCATE
+ /*
+ * If the inode has grown, and this is a directory, then use a few
+ * more of the preallocated blocks to keep directory fragmentation
+ * down. The preallocated blocks are guaranteed to be contiguous.
+ */
+ if (create &&
+ S_ISDIR(inode->i_mode) &&
+ inode->i_blocks > prev_blocks &&
+ EXT3_HAS_COMPAT_FEATURE(inode->i_sb,
+ EXT3_FEATURE_COMPAT_DIR_PREALLOC)) {
+ int i;
+ struct buffer_head *tmp_bh;
+
+ for (i = 1;
+ inode->u.ext3_i.i_prealloc_count &&
+ i < EXT3_SB(inode->i_sb)->s_es->s_prealloc_dir_blocks;
+ i++) {
+ /*
+ * ext3_getblk will zero out the contents of the
+ * directory for us
+ */
+ tmp_bh = ext3_getblk(handle, inode,
+ block+i, create, err);
+ if (!tmp_bh) {
+ brelse (bh);
+ return 0;
+ }
+ brelse (tmp_bh);
+ }
+ }
+#endif
+ if (buffer_uptodate(bh))
+ return bh;
+ ll_rw_block (READ, 1, &bh);
+ wait_on_buffer (bh);
+ if (buffer_uptodate(bh))
+ return bh;
+ brelse (bh);
+ *err = -EIO;


+ return NULL;
+}
+

+static int walk_page_buffers( handle_t *handle,
+ struct buffer_head *head,
+ unsigned from,
+ unsigned to,
+ int *partial,
+ int (*fn)( handle_t *handle,
+ struct buffer_head *bh))
+{
+ struct buffer_head *bh;
+ unsigned block_start, block_end;
+ unsigned blocksize = head->b_size;
+ int err, ret = 0;
+
+ for ( bh = head, block_start = 0;
+ ret == 0 && (bh != head || !block_start);
+ block_start = block_end, bh = bh->b_this_page)
+ {
+ block_end = block_start + blocksize;
+ if (block_end <= from || block_start >= to) {
+ if (partial && !buffer_uptodate(bh))
+ *partial = 1;
+ continue;
+ }
+ err = (*fn)(handle, bh);
+ if (!ret)
+ ret = err;
+ }
+ return ret;
+}
+
+/*
+ * To preserve ordering, it is essential that the hole instantiation and
+ * the data write be encapsulated in a single transaction. We cannot
+ * close off a transaction and start a new one between the ext3_get_block()
+ * and the commit_write(). So doing the journal_start at the start of
+ * prepare_write() is the right place.
+ *
+ * Also, this function can nest inside ext3_writepage() ->
+ * block_write_full_page(). In that case, we *know* that ext3_writepage()
+ * has generated enough buffer credits to do the whole page. So we won't
+ * block on the journal in that case, which is good, because the caller may
+ * be PF_MEMALLOC.
+ *
+ * By accident, ext3 can be reentered when a transaction is open via
+ * quota file writes. If we were to commit the transaction while thus
+ * reentered, there can be a deadlock - we would be holding a quota
+ * lock, and the commit would never complete if another thread had a
+ * transaction open and was blocking on the quota lock - a ranking
+ * violation.
+ *
+ * So what we do is to rely on the fact that journal_stop/journal_start
+ * will _not_ run commit under these circumstances because handle->h_ref
+ * is elevated. We'll still have enough credits for the tiny quotafile
+ * write.
+ */
+
+static int do_journal_get_write_access(handle_t *handle,
+ struct buffer_head *bh)
+{
+ return ext3_journal_get_write_access(handle, bh);
+}
+
+static int ext3_prepare_write(struct file *file, struct page *page,
+ unsigned from, unsigned to)
+{
+ struct inode *inode = page->mapping->host;
+ handle_t *handle = ext3_journal_current_handle();
+ int ret, needed_blocks = ext3_writepage_trans_blocks(inode);
+
+ lock_kernel();
+ handle = ext3_journal_start(inode, needed_blocks);
+ if (IS_ERR(handle)) {
+ ret = PTR_ERR(handle);
+ goto out;
+ }
+ ret = block_prepare_write(page, from, to, ext3_get_block);
+ if (ret != 0)
+ goto prepare_write_failed;
+
+ if (ext3_should_journal_data(inode))
+ ret = walk_page_buffers(handle, page->buffers,
+ from, to, NULL, do_journal_get_write_access);
+prepare_write_failed:
+ if (ret)
+ ext3_journal_stop(handle, inode);
+out:
+ unlock_kernel();


+ return ret;
+}
+

+static int journal_dirty_sync_data(handle_t *handle, struct buffer_head *bh)
+{
+ return ext3_journal_dirty_data(handle, bh, 0);
+}
+
+/*
+ * For ext3_writepage(). We also brelse() the buffer to account for
+ * the bget() which ext3_writepage() performs.
+ */
+static int journal_dirty_async_data(handle_t *handle, struct buffer_head *bh)
+{
+ int ret = ext3_journal_dirty_data(handle, bh, 1);
+ __brelse(bh);


+ return ret;
+}
+

+/* For commit_write() in data=journal mode */
+static int commit_write_fn(handle_t *handle, struct buffer_head *bh)
+{
+ set_bit(BH_Uptodate, &bh->b_state);
+ return ext3_journal_dirty_metadata(handle, bh);
+}
+
+/*
+ * We need to pick up the new inode size which generic_commit_write gave us
+ * `file' can be NULL - eg, when called from block_symlink().
+ *
+ * ext3 inode->i_dirty_buffers policy: If we're journalling data we
+ * definitely don't want them to appear on the inode at all - instead
+ * we need to manage them at the JBD layer and we need to intercept
+ * the relevant sync operations and translate them into journal operations.
+ *
+ * If we're not journalling data then we can just leave the buffers
+ * on ->i_dirty_buffers. If someone writes them out for us then thanks.
+ * Otherwise we'll do it in commit, if we're using ordered data.
+ */
+
+static int ext3_commit_write(struct file *file, struct page *page,
+ unsigned from, unsigned to)
+{
+ handle_t *handle = ext3_journal_current_handle();
+ struct inode *inode = page->mapping->host;
+ int ret = 0, ret2;
+
+ lock_kernel();
+ if (ext3_should_journal_data(inode)) {
+ /*
+ * Here we duplicate the generic_commit_write() functionality
+ */
+ int partial = 0;
+ loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+
+ ret = walk_page_buffers(handle, page->buffers,
+ from, to, &partial, commit_write_fn);
+ if (!partial)
+ SetPageUptodate(page);
+ kunmap(page);
+ if (pos > inode->i_size)
+ inode->i_size = pos;
+ set_bit(EXT3_STATE_JDATA, &inode->u.ext3_i.i_state);
+ } else {
+ if (ext3_should_order_data(inode)) {
+ ret = walk_page_buffers(handle, page->buffers,
+ from, to, NULL, journal_dirty_sync_data);
+ }
+ /* Be careful here if generic_commit_write becomes a
+ * required invocation after block_prepare_write. */
+ if (ret == 0)
+ ret = generic_commit_write(file, page, from, to);
+ }
+ if (inode->i_size > inode->u.ext3_i.i_disksize) {
+ inode->u.ext3_i.i_disksize = inode->i_size;
+ ret2 = ext3_mark_inode_dirty(handle, inode);
+ if (!ret)
+ ret = ret2;
+ }
+ ret2 = ext3_journal_stop(handle, inode);
+ unlock_kernel();
+ if (!ret)
+ ret = ret2;
+ return ret;
+}
+
+/*
+ * bmap() is special. It gets used by applications such as lilo and by
+ * the swapper to find the on-disk block of a specific piece of data.
+ *
+ * Naturally, this is dangerous if the block concerned is still in the
+ * journal. If somebody makes a swapfile on an ext3 data-journaling
+ * filesystem and enables swap, then they may get a nasty shock when the
+ * data getting swapped to that swapfile suddenly gets overwritten by
+ * the original zero's written out previously to the journal and
+ * awaiting writeback in the kernel's buffer cache.
+ *
+ * So, if we see any bmap calls here on a modified, data-journaled file,
+ * take extra steps to flush any blocks which might be in the cache.
+ */
+static int ext3_bmap(struct address_space *mapping, long block)
+{
+ struct inode *inode = mapping->host;
+ journal_t *journal;
+ int err;
+
+ if (test_and_clear_bit(EXT3_STATE_JDATA, &inode->u.ext3_i.i_state)) {
+ /*
+ * This is a REALLY heavyweight approach, but the use of
+ * bmap on dirty files is expected to be extremely rare:
+ * only if we run lilo or swapon on a freshly made file
+ * do we expect this to happen.
+ *
+ * (bmap requires CAP_SYS_RAWIO so this does not
+ * represent an unprivileged user DOS attack --- we'd be
+ * in trouble if mortal users could trigger this path at
+ * will.)
+ *
+ * NB. EXT3_STATE_JDATA is not set on files other than
+ * regular files. If somebody wants to bmap a directory
+ * or symlink and gets confused because the buffer
+ * hasn't yet been flushed to disk, they deserve
+ * everything they get.
+ */
+
+ journal = EXT3_JOURNAL(inode);
+ journal_lock_updates(journal);
+ err = journal_flush(journal);
+ journal_unlock_updates(journal);
+
+ if (err)


+ return 0;
+ }
+

+ return generic_block_bmap(mapping,block,ext3_get_block);
+}
+
+static int bget_one(handle_t *handle, struct buffer_head *bh)
+{
+ atomic_inc(&bh->b_count);


+ return 0;
+}
+

+/*
+ * Note that we always start a transaction even if we're not journalling
+ * data. This is to preserve ordering: any hole instantiation within
+ * __block_write_full_page -> ext3_get_block() should be journalled
+ * along with the data so we don't crash and then get metadata which
+ * refers to old data.
+ *
+ * In all journalling modes block_write_full_page() will start the I/O.
+ *
+ * Problem:
+ *
+ * ext3_writepage() -> kmalloc() -> __alloc_pages() -> page_launder() ->
+ * ext3_writepage()
+ *
+ * Similar for:
+ *
+ * ext3_file_write() -> generic_file_write() -> __alloc_pages() -> ...
+ *
+ * Same applies to ext3_get_block(). We will deadlock on various things like
+ * lock_journal and i_truncate_sem.
+ *
+ * Setting PF_MEMALLOC here doesn't work - too many internal memory
+ * allocations fail.
+ *
+ * 16May01: If we're reentered then journal_current_handle() will be
+ * non-zero. We simply *return*.
+ *
+ * 1 July 2001: @@@ FIXME:
+ * In journalled data mode, a data buffer may be metadata against the
+ * current transaction. But the same file is part of a shared mapping
+ * and someone does a writepage() on it.
+ *
+ * We will move the buffer onto the async_data list, but *after* it has
+ * been dirtied. So there's a small window where we have dirty data on
+ * BJ_Metadata.
+ *
+ * Note that this only applies to the last partial page in the file. The
+ * bit which block_write_full_page() uses prepare/commit for. (That's
+ * broken code anyway: it's wrong for msync()).
+ *
+ * It's a rare case: affects the final partial page, for journalled data
+ * where the file is subject to bith write() and writepage() in the same
+ * transction. To fix it we'll need a custom block_write_full_page().
+ * We'll probably need that anyway for journalling writepage() output.
+ *
+ * We don't honour synchronous mounts for writepage(). That would be
+ * disastrous. Any write() or metadata operation will sync the fs for
+ * us.
+ */
+static int ext3_writepage(struct page *page)
+{
+ struct inode *inode = page->mapping->host;
+ struct buffer_head *page_buffers;
+ handle_t *handle = NULL;
+ int ret = 0, err;
+ int needed;
+ int order_data;
+
+ J_ASSERT(PageLocked(page));
+
+ /*
+ * We give up here if we're reentered, because it might be
+ * for a different filesystem. One *could* look for a
+ * nested transaction opportunity.
+ */
+ lock_kernel();
+ if (ext3_journal_current_handle())
+ goto out_fail;
+
+ needed = ext3_writepage_trans_blocks(inode);
+ if (current->flags & PF_MEMALLOC)
+ handle = ext3_journal_try_start(inode, needed);
+ else
+ handle = ext3_journal_start(inode, needed);
+
+ if (IS_ERR(handle)) {
+ ret = PTR_ERR(handle);
+ goto out_fail;
+ }
+
+ order_data = ext3_should_order_data(inode) ||
+ ext3_should_journal_data(inode);
+
+ unlock_kernel();
+
+ page_buffers = NULL; /* Purely to prevent compiler warning */
+
+ /* bget() all the buffers */
+ if (order_data) {
+ if (!page->buffers)
+ create_empty_buffers(page,
+ inode->i_dev, inode->i_sb->s_blocksize);
+ page_buffers = page->buffers;
+ walk_page_buffers(handle, page_buffers, 0,
+ PAGE_CACHE_SIZE, NULL, bget_one);
+ }
+
+ ret = block_write_full_page(page, ext3_get_block);
+
+ /*
+ * The page can become unlocked at any point now, and
+ * truncate can then come in and change things. So we
+ * can't touch *page from now on. But *page_buffers is
+ * safe due to elevated refcount.
+ */
+
+ handle = ext3_journal_current_handle();
+ lock_kernel();
+
+ /* And attach them to the current transaction */
+ if (order_data) {
+ err = walk_page_buffers(handle, page_buffers,
+ 0, PAGE_CACHE_SIZE, NULL, journal_dirty_async_data);
+ if (!ret)
+ ret = err;
+ }
+
+ err = ext3_journal_stop(handle, inode);
+ if (!ret)
+ ret = err;
+ unlock_kernel();
+ return ret;
+
+out_fail:
+
+ unlock_kernel();
+ SetPageDirty(page);
+ UnlockPage(page);


+ return ret;
+}
+

+static int ext3_readpage(struct file *file, struct page *page)
+{
+ return block_read_full_page(page,ext3_get_block);
+}
+
+
+static int ext3_flushpage(struct page *page, unsigned long offset)
+{
+ journal_t *journal = EXT3_JOURNAL(page->mapping->host);
+ return journal_flushpage(journal, page, offset);
+}
+
+static int ext3_releasepage(struct page *page, int wait)
+{
+ journal_t *journal = EXT3_JOURNAL(page->mapping->host);
+ return journal_try_to_free_buffers(journal, page, wait);
+}
+
+
+struct address_space_operations ext3_aops = {
+ readpage: ext3_readpage, /* BKL not held. Don't need */
+ writepage: ext3_writepage, /* BKL not held. We take it */
+ sync_page: block_sync_page,
+ prepare_write: ext3_prepare_write, /* BKL not held. We take it */
+ commit_write: ext3_commit_write, /* BKL not held. We take it */
+ bmap: ext3_bmap, /* BKL held */
+ flushpage: ext3_flushpage, /* BKL not held. Don't need */
+ releasepage: ext3_releasepage, /* BKL not held. Don't need */
+};
+
+/*
+ * ext3_block_truncate_page() zeroes out a mapping from file offset `from'
+ * up to the end of the block which corresponds to `from'.
+ * This required during truncate. We need to physically zero the tail end
+ * of that block so it doesn't yield old data if the file is later grown.
+ */
+static int ext3_block_truncate_page(handle_t *handle,
+ struct address_space *mapping, loff_t from)
+{
+ unsigned long index = from >> PAGE_CACHE_SHIFT;
+ unsigned offset = from & (PAGE_CACHE_SIZE-1);
+ unsigned blocksize, iblock, length, pos;
+ struct inode *inode = mapping->host;
+ struct page *page;
+ struct buffer_head *bh;
+ int err;
+
+ blocksize = inode->i_sb->s_blocksize;
+ length = offset & (blocksize - 1);
+
+ /* Block boundary? Nothing to do */
+ if (!length)
+ return 0;
+
+ length = blocksize - length;
+ iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
+
+ page = grab_cache_page(mapping, index);
+ err = -ENOMEM;
+ if (!page)
+ goto out;
+
+ if (!page->buffers)
+ create_empty_buffers(page, inode->i_dev, blocksize);
+
+ /* Find the buffer that contains "offset" */
+ bh = page->buffers;
+ pos = blocksize;
+ while (offset >= pos) {
+ bh = bh->b_this_page;
+ iblock++;
+ pos += blocksize;
+ }
+
+ err = 0;
+ if (!buffer_mapped(bh)) {
+ /* Hole? Nothing to do */
+ if (buffer_uptodate(bh))
+ goto unlock;
+ ext3_get_block(inode, iblock, bh, 0);
+ /* Still unmapped? Nothing to do */
+ if (!buffer_mapped(bh))
+ goto unlock;
+ }
+
+ /* Ok, it's mapped. Make sure it's up-to-date */
+ if (Page_Uptodate(page))
+ set_bit(BH_Uptodate, &bh->b_state);
+
+ if (!buffer_uptodate(bh)) {
+ err = -EIO;
+ ll_rw_block(READ, 1, &bh);
+ wait_on_buffer(bh);
+ /* Uhhuh. Read error. Complain and punt. */
+ if (!buffer_uptodate(bh))
+ goto unlock;
+ }
+
+ if (ext3_should_journal_data(inode)) {
+ BUFFER_TRACE(bh, "get write access");
+ err = ext3_journal_get_write_access(handle, bh);
+ if (err)
+ goto unlock;
+ }
+
+ memset(kmap(page) + offset, 0, length);
+ flush_dcache_page(page);
+ kunmap(page);
+
+ BUFFER_TRACE(bh, "zeroed end of block");
+
+ err = 0;
+ if (ext3_should_journal_data(inode)) {
+ err = ext3_journal_dirty_metadata(handle, bh);
+ } else {
+ if (ext3_should_order_data(inode))
+ err = ext3_journal_dirty_data(handle, bh, 0);
+ __mark_buffer_dirty(bh);
+ }
+
+unlock:
+ UnlockPage(page);
+ page_cache_release(page);
+out:
+ return err;
+}
+
+/*
+ * Probably it should be a library function... search for first non-zero word
+ * or memcmp with zero_page, whatever is better for particular architecture.
+ * Linus?
+ */
+static inline int all_zeroes(u32 *p, u32 *q)
+{
+ while (p < q)
+ if (*p++)
+ return 0;


+ return 1;
+}
+

+/**
+ * ext3_find_shared - find the indirect blocks for partial truncation.
+ * @inode: inode in question
+ * @depth: depth of the affected branch
+ * @offsets: offsets of pointers in that branch (see ext3_block_to_path)
+ * @chain: place to store the pointers to partial indirect blocks
+ * @top: place to the (detached) top of branch
+ *
+ * This is a helper function used by ext3_truncate().
+ *
+ * When we do truncate() we may have to clean the ends of several
+ * indirect blocks but leave the blocks themselves alive. Block is
+ * partially truncated if some data below the new i_size is refered
+ * from it (and it is on the path to the first completely truncated
+ * data block, indeed). We have to free the top of that path along
+ * with everything to the right of the path. Since no allocation
+ * past the truncation point is possible until ext3_truncate()
+ * finishes, we may safely do the latter, but top of branch may
+ * require special attention - pageout below the truncation point
+ * might try to populate it.
+ *
+ * We atomically detach the top of branch from the tree, store the
+ * block number of its root in *@top, pointers to buffer_heads of
+ * partially truncated blocks - in @chain[].bh and pointers to
+ * their last elements that should not be removed - in
+ * @chain[].p. Return value is the pointer to last filled element
+ * of @chain.
+ *
+ * The work left to caller to do the actual freeing of subtrees:
+ * a) free the subtree starting from *@top
+ * b) free the subtrees whose roots are stored in
+ * (@chain[i].p+1 .. end of @chain[i].bh->b_data)
+ * c) free the subtrees growing from the inode past the @chain[0].
+ * (no partially truncated stuff there). */
+
+static Indirect *ext3_find_shared(struct inode *inode,
+ int depth,
+ int offsets[4],
+ Indirect chain[4],
+ u32 *top)
+{
+ Indirect *partial, *p;
+ int k, err;
+
+ *top = 0;
+ /* Make k index the deepest non-null offest + 1 */
+ for (k = depth; k > 1 && !offsets[k-1]; k--)
+ ;
+ partial = ext3_get_branch(inode, k, offsets, chain, &err);
+ /* Writer: pointers */
+ if (!partial)
+ partial = chain + k-1;
+ /*
+ * If the branch acquired continuation since we've looked at it -
+ * fine, it should all survive and (new) top doesn't belong to us.
+ */
+ if (!partial->key && *partial->p)


+ /* Writer: end */

+ goto no_top;
+ for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--)
+ ;
+ /*
+ * OK, we've found the last block that must survive. The rest of our
+ * branch should be detached before unlocking. However, if that rest
+ * of branch is all ours and does not grow immediately from the inode
+ * it's easier to cheat and just decrement partial->p.
+ */
+ if (p == chain + k - 1 && p > chain) {
+ p->p--;
+ } else {
+ *top = *p->p;
+ /* Nope, don't do this in ext3. Must leave the tree intact */
+#if 0
+ *p->p = 0;
+#endif
+ }


+ /* Writer: end */
+

+ while(partial > p)
+ {
+ brelse(partial->bh);
+ partial--;
+ }
+no_top:
+ return partial;
+}
+
+/*
+ * Zero a number of block pointers in either an inode or an indirect block.
+ * If we restart the transaction we must again get write access to the
+ * indirect block for further modification.
+ *
+ * We release `count' blocks on disk, but (last - first) may be greater
+ * than `count' because there can be holes in there.
+ */
+static void
+ext3_clear_blocks(handle_t *handle, struct inode *inode, struct buffer_head *bh,
+ unsigned long block_to_free, unsigned long count,
+ u32 *first, u32 *last)
+{
+ u32 *p;
+ kdev_t dev = inode->i_sb->s_dev;
+ unsigned long blocksize = inode->i_sb->s_blocksize;
+
+ if (try_to_extend_transaction(handle, inode)) {
+ if (bh) {
+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
+ ext3_journal_dirty_metadata(handle, bh);
+ }
+ ext3_mark_inode_dirty(handle, inode);
+ ext3_journal_test_restart(handle, inode);
+ BUFFER_TRACE(bh, "get_write_access");
+ ext3_journal_get_write_access(handle, bh);
+ }
+
+ /*
+ * Any buffers which are on the journal will be in memory. We find
+ * them on the hash table so journal_revoke() will run journal_forget()
+ * on them. We've already detached each block from the file, so
+ * bforget() in journal_forget() should be safe.
+ *
+ * AKPM: turn on bforget in journal_forget()!!!
+ */
+ for (p = first; p < last; p++) {
+ u32 nr = le32_to_cpu(*p);
+ if (nr) {


+ struct buffer_head *bh;
+

+ *p = 0;
+ bh = get_hash_table(dev, nr, blocksize);
+ ext3_forget(handle, 0, inode, bh, nr);
+ }
+ }
+
+ ext3_free_blocks(handle, inode, block_to_free, count);
+}
+
+/**
+ * ext3_free_data - free a list of data blocks
+ * @handle: handle for this transaction
+ * @inode: inode we are dealing with
+ * @this_bh: indirect buffer_head which contains *@first and *@last
+ * @first: array of block numbers
+ * @last: points immediately past the end of array
+ *
+ * We are freeing all blocks refered from that array (numbers are stored as
+ * little-endian 32-bit) and updating @inode->i_blocks appropriately.
+ *
+ * We accumulate contiguous runs of blocks to free. Conveniently, if these
+ * blocks are contiguous then releasing them at one time will only affect one
+ * or two bitmap blocks (+ group descriptor(s) and superblock) and we won't
+ * actually use a lot of journal space.
+ *
+ * @this_bh will be %NULL if @first and @last point into the inode's direct
+ * block pointers.
+ */
+static void ext3_free_data(handle_t *handle, struct inode *inode,
+ struct buffer_head *this_bh, u32 *first, u32 *last)
+{
+ unsigned long block_to_free = 0; /* Starting block # of a run */
+ unsigned long count = 0; /* Number of blocks in the run */
+ u32 *block_to_free_p = NULL; /* Pointer into inode/ind
+ corresponding to
+ block_to_free */
+ unsigned long nr; /* Current block # */
+ u32 *p; /* Pointer into inode/ind
+ for current block */
+ int err;
+
+ if (this_bh) { /* For indirect block */
+ BUFFER_TRACE(this_bh, "get_write_access");
+ err = ext3_journal_get_write_access(handle, this_bh);
+ /* Important: if we can't update the indirect pointers
+ * to the blocks, we can't free them. */
+ if (err)
+ return;
+ }
+
+ for (p = first; p < last; p++) {
+ nr = le32_to_cpu(*p);
+ if (nr) {
+ /* accumulate blocks to free if they're contiguous */
+ if (count == 0) {
+ block_to_free = nr;
+ block_to_free_p = p;
+ count = 1;
+ } else if (nr == block_to_free + count) {
+ count++;
+ } else {
+ ext3_clear_blocks(handle, inode, this_bh,
+ block_to_free,
+ count, block_to_free_p, p);
+ block_to_free = nr;
+ block_to_free_p = p;
+ count = 1;
+ }
+ }
+ }
+
+ if (count > 0)
+ ext3_clear_blocks(handle, inode, this_bh, block_to_free,
+ count, block_to_free_p, p);
+
+ if (this_bh) {
+ BUFFER_TRACE(this_bh, "call ext3_journal_dirty_metadata");
+ ext3_journal_dirty_metadata(handle, this_bh);
+ }
+}
+
+/**
+ * ext3_free_branches - free an array of branches
+ * @handle: JBD handle for this transaction
+ * @inode: inode we are dealing with
+ * @parent_bh: the buffer_head which contains *@first and *@last
+ * @first: array of block numbers
+ * @last: pointer immediately past the end of array
+ * @depth: depth of the branches to free
+ *
+ * We are freeing all blocks refered from these branches (numbers are
+ * stored as little-endian 32-bit) and updating @inode->i_blocks
+ * appropriately.
+ */
+static void ext3_free_branches(handle_t *handle, struct inode *inode,
+ struct buffer_head *parent_bh,
+ u32 *first, u32 *last, int depth)
+{
+ unsigned long nr;
+ u32 *p;
+
+ if (is_handle_aborted(handle))
+ return;
+
+ if (depth--) {
+ struct buffer_head *bh;
+ int addr_per_block = EXT3_ADDR_PER_BLOCK(inode->i_sb);
+ p = last;
+ while (--p >= first) {
+ nr = le32_to_cpu(*p);
+ if (!nr)
+ continue; /* A hole */
+
+ /* Go read the buffer for the next level down */
+ bh = bread(inode->i_dev, nr, inode->i_sb->s_blocksize);
+
+ /*
+ * A read failure? Report error and clear slot
+ * (should be rare).
+ */
+ if (!bh) {
+ ext3_error(inode->i_sb, "ext3_free_branches",
+ "Read failure, inode=%ld, block=%ld",
+ inode->i_ino, nr);
+ continue;
+ }
+
+ /* This zaps the entire block. Bottom up. */
+ BUFFER_TRACE(bh, "free child branches");
+ ext3_free_branches(handle, inode, bh, (u32*)bh->b_data,
+ (u32*)bh->b_data + addr_per_block,
+ depth);
+
+ /*
+ * We've probably journalled the indirect block several
+ * times during the truncate. But it's no longer
+ * needed and we now drop it from the transaction via
+ * journal_revoke().
+ *
+ * That's easy if it's exclusively part of this
+ * transaction. But if it's part of the committing
+ * transaction then journal_forget() will simply
+ * brelse() it. That means that if the underlying
+ * block is reallocated in ext3_get_block(),
+ * unmap_underlying_metadata() will find this block
+ * and will try to get rid of it. damn, damn.
+ *
+ * If this block has already been committed to the
+ * journal, a revoke record will be written. And
+ * revoke records must be emitted *before* clearing
+ * this block's bit in the bitmaps.
+ */
+ ext3_forget(handle, 1, inode, bh, bh->b_blocknr);
+
+ /*
+ * Everything below this this pointer has been
+ * released. Now let this top-of-subtree go.
+ *
+ * We want the freeing of this indirect block to be
+ * atomic in the journal with the updating of the
+ * bitmap block which owns it. So make some room in
+ * the journal.
+ *
+ * We zero the parent pointer *after* freeing its
+ * pointee in the bitmaps, so if extend_transaction()
+ * for some reason fails to put the bitmap changes and
+ * the release into the same transaction, recovery
+ * will merely complain about releasing a free block,
+ * rather than leaking blocks.
+ */
+ if (is_handle_aborted(handle))
+ return;
+ if (try_to_extend_transaction(handle, inode)) {
+ ext3_mark_inode_dirty(handle, inode);
+ ext3_journal_test_restart(handle, inode);
+ }
+
+ ext3_free_blocks(handle, inode, nr, 1);
+
+ if (parent_bh) {
+ /*
+ * The block which we have just freed is
+ * pointed to by an indirect block: journal it
+ */
+ BUFFER_TRACE(parent_bh, "get_write_access");
+ if (!ext3_journal_get_write_access(handle,
+ parent_bh)){
+ *p = 0;
+ BUFFER_TRACE(parent_bh,
+ "call ext3_journal_dirty_metadata");
+ ext3_journal_dirty_metadata(handle,
+ parent_bh);


+ }
+ }
+ }
+ } else {

+ /* We have reached the bottom of the tree. */
+ BUFFER_TRACE(parent_bh, "free data blocks");
+ ext3_free_data(handle, inode, parent_bh, first, last);
+ }
+}
+
+/*
+ * ext3_truncate()
+ *
+ * We block out ext3_get_block() block instantiations across the entire
+ * transaction, and VFS/VM ensures that ext3_truncate() cannot run
+ * simultaneously on behalf of the same inode.
+ *
+ * As we work through the truncate and commmit bits of it to the journal there
+ * is one core, guiding principle: the file's tree must always be consistent on
+ * disk. We must be able to restart the truncate after a crash.
+ *
+ * The file's tree may be transiently inconsistent in memory (although it
+ * probably isn't), but whenever we close off and commit a journal transaction,
+ * the contents of (the filesystem + the journal) must be consistent and
+ * restartable. It's pretty simple, really: bottom up, right to left (although
+ * left-to-right works OK too).
+ *
+ * Note that at recovery time, journal replay occurs *before* the restart of
+ * truncate against the orphan inode list.
+ *
+ * The committed inode has the new, desired i_size (which is the same as
+ * i_disksize in this case). After a crash, ext3_orphan_cleanup() will see
+ * that this inode's truncate did not complete and it will again call
+ * ext3_truncate() to have another go. So there will be instantiated blocks
+ * to the right of the truncation point in a crashed ext3 filesystem. But
+ * that's fine - as long as they are linked from the inode, the post-crash
+ * ext3_truncate() run will find them and release them.
+ */
+
+void ext3_truncate(struct inode * inode)
+{
+ handle_t *handle;
+ u32 *i_data = inode->u.ext3_i.i_data;
+ int addr_per_block = EXT3_ADDR_PER_BLOCK(inode->i_sb);
+ int offsets[4];
+ Indirect chain[4];
+ Indirect *partial;
+ int nr = 0;
+ int n;
+ long last_block;
+ unsigned blocksize;
+
+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+ S_ISLNK(inode->i_mode)))
+ return;
+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+ return;
+
+ ext3_discard_prealloc(inode);
+
+ handle = start_transaction(inode);
+ if (IS_ERR(handle))
+ return; /* AKPM: return what? */
+
+ blocksize = inode->i_sb->s_blocksize;
+ last_block = (inode->i_size + blocksize-1)
+ >> EXT3_BLOCK_SIZE_BITS(inode->i_sb);
+
+ ext3_block_truncate_page(handle, inode->i_mapping, inode->i_size);
+
+
+ n = ext3_block_to_path(inode, last_block, offsets);
+ if (n == 0)
+ goto out_stop; /* error */
+
+ /*
+ * OK. This truncate is going to happen. We add the inode to the
+ * orphan list, so that if this truncate spans multiple transactions,
+ * and we crash, we will resume the truncate when the filesystem
+ * recovers. It also marks the inode dirty, to catch the new size.
+ *
+ * Implication: the file must always be in a sane, consistent
+ * truncatable state while each transaction commits.
+ */
+ if (ext3_orphan_add(handle, inode))
+ goto out_stop;
+
+ /*
+ * The orphan list entry will now protect us from any crash which
+ * occurs before the truncate completes, so it is now safe to propagate
+ * the new, shorter inode size (held for now in i_size) into the
+ * on-disk inode. We do this via i_disksize, which is the value which
+ * ext3 *really* writes onto the disk inode.
+ */
+ inode->u.ext3_i.i_disksize = inode->i_size;
+
+ /*
+ * From here we block out all ext3_get_block() callers who want to
+ * modify the block allocation tree.
+ */
+ down_write(&inode->u.ext3_i.truncate_sem);
+
+ if (n == 1) { /* direct blocks */
+ ext3_free_data(handle, inode, NULL, i_data+offsets[0],
+ i_data + EXT3_NDIR_BLOCKS);
+ goto do_indirects;
+ }
+
+ partial = ext3_find_shared(inode, n, offsets, chain, &nr);
+ /* Kill the top of shared branch (not detached) */
+ if (nr) {
+ if (partial == chain) {
+ /* Shared branch grows from the inode */
+ ext3_free_branches(handle, inode, NULL,
+ &nr, &nr+1, (chain+n-1) - partial);
+ *partial->p = 0;
+ /*
+ * We mark the inode dirty prior to restart,
+ * and prior to stop. No need for it here.
+ */
+ } else {
+ /* Shared branch grows from an indirect block */
+ BUFFER_TRACE(partial->bh, "get_write_access");
+ ext3_free_branches(handle, inode, partial->bh,
+ partial->p,
+ partial->p+1, (chain+n-1) - partial);
+ }
+ }
+ /* Clear the ends of indirect blocks on the shared branch */
+ while (partial > chain) {
+ ext3_free_branches(handle, inode, partial->bh, partial->p + 1,
+ (u32*)partial->bh->b_data + addr_per_block,
+ (chain+n-1) - partial);
+ BUFFER_TRACE(partial->bh, "call brelse");
+ brelse (partial->bh);
+ partial--;
+ }
+do_indirects:
+ /* Kill the remaining (whole) subtrees */
+ switch (offsets[0]) {
+ default:
+ nr = i_data[EXT3_IND_BLOCK];
+ if (nr) {
+ ext3_free_branches(handle, inode, NULL,
+ &nr, &nr+1, 1);
+ i_data[EXT3_IND_BLOCK] = 0;
+ }
+ case EXT3_IND_BLOCK:
+ nr = i_data[EXT3_DIND_BLOCK];
+ if (nr) {
+ ext3_free_branches(handle, inode, NULL,
+ &nr, &nr+1, 2);
+ i_data[EXT3_DIND_BLOCK] = 0;
+ }
+ case EXT3_DIND_BLOCK:
+ nr = i_data[EXT3_TIND_BLOCK];
+ if (nr) {
+ ext3_free_branches(handle, inode, NULL,
+ &nr, &nr+1, 3);
+ i_data[EXT3_TIND_BLOCK] = 0;
+ }
+ case EXT3_TIND_BLOCK:
+ ;
+ }
+ up_write(&inode->u.ext3_i.truncate_sem);
+ inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ ext3_mark_inode_dirty(handle, inode);
+
+ /* In a multi-transaction truncate, we only make the final
+ * transaction synchronous */
+ if (IS_SYNC(inode))
+ handle->h_sync = 1;
+out_stop:
+ /*
+ * If this was a simple ftruncate(), and the file will remain alive
+ * then we need to clear up the orphan record which we created above.
+ * However, if this was a real unlink then we were called by
+ * ext3_delete_inode(), and we allow that function to clean up the
+ * orphan info for us.
+ */
+ if (inode->i_nlink)
+ ext3_orphan_del(handle, inode);
+
+ ext3_journal_stop(handle, inode);
+}
+
+/*
+ * ext3_get_inode_loc returns with an extra refcount against the
+ * inode's underlying buffer_head on success.
+ */
+
+int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
+{
+ struct buffer_head *bh = 0;
+ unsigned long block;
+ unsigned long block_group;


+ unsigned long group_desc;
+ unsigned long desc;

+ unsigned long offset;


+ struct ext3_group_desc * gdp;
+

+ if ((inode->i_ino != EXT3_ROOT_INO &&
+ inode->i_ino != EXT3_ACL_IDX_INO &&
+ inode->i_ino != EXT3_ACL_DATA_INO &&
+ inode->i_ino != EXT3_JOURNAL_INO &&
+ inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
+ inode->i_ino > le32_to_cpu(
+ inode->i_sb->u.ext3_sb.s_es->s_inodes_count)) {
+ ext3_error (inode->i_sb, "ext3_get_inode_loc",
+ "bad inode number: %lu", inode->i_ino);
+ goto bad_inode;
+ }
+ block_group = (inode->i_ino - 1) / EXT3_INODES_PER_GROUP(inode->i_sb);
+ if (block_group >= inode->i_sb->u.ext3_sb.s_groups_count) {
+ ext3_error (inode->i_sb, "ext3_get_inode_loc",
+ "group >= groups count");
+ goto bad_inode;
+ }
+ group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(inode->i_sb);
+ desc = block_group & (EXT3_DESC_PER_BLOCK(inode->i_sb) - 1);
+ bh = inode->i_sb->u.ext3_sb.s_group_desc[group_desc];
+ if (!bh) {
+ ext3_error (inode->i_sb, "ext3_get_inode_loc",
+ "Descriptor not loaded");
+ goto bad_inode;
+ }
+
+ gdp = (struct ext3_group_desc *) bh->b_data;
+ /*
+ * Figure out the offset within the block group inode table
+ */
+ offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)) *
+ EXT3_INODE_SIZE(inode->i_sb);
+ block = le32_to_cpu(gdp[desc].bg_inode_table) +
+ (offset >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
+ if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {
+ ext3_error (inode->i_sb, "ext3_get_inode_loc",
+ "unable to read inode block - "
+ "inode=%lu, block=%lu", inode->i_ino, block);
+ goto bad_inode;
+ }
+ offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
+
+ iloc->bh = bh;
+ iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
+ iloc->block_group = block_group;


+
+ return 0;
+

+ bad_inode:


+ return -EIO;
+}
+

+void ext3_read_inode(struct inode * inode)
+{
+ struct ext3_iloc iloc;
+ struct ext3_inode *raw_inode;
+ struct buffer_head *bh;
+ int block;
+
+ if(ext3_get_inode_loc(inode, &iloc))
+ goto bad_inode;
+ bh = iloc.bh;
+ raw_inode = iloc.raw_inode;
+ init_rwsem(&inode->u.ext3_i.truncate_sem);
+ inode->i_mode = le16_to_cpu(raw_inode->i_mode);
+ inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
+ inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
+ if(!(test_opt (inode->i_sb, NO_UID32))) {
+ inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
+ inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
+ }
+ inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
+ inode->i_size = le32_to_cpu(raw_inode->i_size);
+ inode->i_atime = le32_to_cpu(raw_inode->i_atime);
+ inode->i_ctime = le32_to_cpu(raw_inode->i_ctime);
+ inode->i_mtime = le32_to_cpu(raw_inode->i_mtime);
+ inode->u.ext3_i.i_dtime = le32_to_cpu(raw_inode->i_dtime);
+ /* We now have enough fields to check if the inode was active or not.
+ * This is needed because nfsd might try to access dead inodes
+ * the test is that same one that e2fsck uses
+ * NeilBrown 1999oct15
+ */
+ if (inode->i_nlink == 0) {
+ if (inode->i_mode == 0 ||
+ !(inode->i_sb->u.ext3_sb.s_mount_state & EXT3_ORPHAN_FS)) {
+ /* this inode is deleted */
+ brelse (bh);
+ goto bad_inode;
+ }
+ /* The only unlinked inodes we let through here have
+ * valid i_mode and are being read by the orphan
+ * recovery code: that's fine, we're about to complete
+ * the process of deleting those. */
+ }
+ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size
+ * (for stat), not the fs block
+ * size */
+ inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
+ inode->i_version = ++event;
+ inode->u.ext3_i.i_flags = le32_to_cpu(raw_inode->i_flags);
+#ifdef EXT3_FRAGMENTS
+ inode->u.ext3_i.i_faddr = le32_to_cpu(raw_inode->i_faddr);
+ inode->u.ext3_i.i_frag_no = raw_inode->i_frag;
+ inode->u.ext3_i.i_frag_size = raw_inode->i_fsize;
+#endif
+ inode->u.ext3_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
+ if (!S_ISREG(inode->i_mode)) {
+ inode->u.ext3_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
+ } else {
+ inode->i_size |=
+ ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32;
+ }
+ inode->u.ext3_i.i_disksize = inode->i_size;
+ inode->i_generation = le32_to_cpu(raw_inode->i_generation);
+#ifdef EXT3_PREALLOCATE
+ inode->u.ext3_i.i_prealloc_count = 0;
+#endif
+ inode->u.ext3_i.i_block_group = iloc.block_group;
+
+ /*
+ * NOTE! The in-memory inode i_data array is in little-endian order
+ * even on big-endian machines: we do NOT byteswap the block numbers!
+ */
+ for (block = 0; block < EXT3_N_BLOCKS; block++)
+ inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
+ INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
+
+ brelse (iloc.bh);
+
+ if (inode->i_ino == EXT3_ACL_IDX_INO ||
+ inode->i_ino == EXT3_ACL_DATA_INO)
+ /* Nothing to do */ ;
+ else if (S_ISREG(inode->i_mode)) {
+ inode->i_op = &ext3_file_inode_operations;
+ inode->i_fop = &ext3_file_operations;
+ inode->i_mapping->a_ops = &ext3_aops;
+ } else if (S_ISDIR(inode->i_mode)) {
+ inode->i_op = &ext3_dir_inode_operations;
+ inode->i_fop = &ext3_dir_operations;
+ } else if (S_ISLNK(inode->i_mode)) {
+ if (!inode->i_blocks)
+ inode->i_op = &ext3_fast_symlink_inode_operations;
+ else {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_mapping->a_ops = &ext3_aops;
+ }
+ } else
+ init_special_inode(inode, inode->i_mode,
+ le32_to_cpu(iloc.raw_inode->i_block[0]));
+ /* inode->i_attr_flags = 0; unused */
+ if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL) {
+ /* inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; unused */
+ inode->i_flags |= S_SYNC;
+ }
+ if (inode->u.ext3_i.i_flags & EXT3_APPEND_FL) {
+ /* inode->i_attr_flags |= ATTR_FLAG_APPEND; unused */
+ inode->i_flags |= S_APPEND;
+ }
+ if (inode->u.ext3_i.i_flags & EXT3_IMMUTABLE_FL) {
+ /* inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE; unused */
+ inode->i_flags |= S_IMMUTABLE;
+ }
+ if (inode->u.ext3_i.i_flags & EXT3_NOATIME_FL) {
+ /* inode->i_attr_flags |= ATTR_FLAG_NOATIME; unused */
+ inode->i_flags |= S_NOATIME;
+ }
+ return;
+
+bad_inode:
+ make_bad_inode(inode);


+ return;
+}
+
+/*

+ * Post the struct inode info into an on-disk inode location in the
+ * buffer-cache. This gobbles the caller's reference to the
+ * buffer_head in the inode location struct.
+ */
+
+static int ext3_do_update_inode(handle_t *handle,
+ struct inode *inode,
+ struct ext3_iloc *iloc)
+{
+ struct ext3_inode *raw_inode = iloc->raw_inode;
+ struct buffer_head *bh = iloc->bh;
+ int err = 0, rc, block;
+
+ if (handle) {
+ BUFFER_TRACE(bh, "get_write_access");
+ err = ext3_journal_get_write_access(handle, bh);
+ if (err)
+ goto out_brelse;
+ }
+ raw_inode->i_mode = cpu_to_le16(inode->i_mode);
+ if(!(test_opt(inode->i_sb, NO_UID32))) {
+ raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));
+ raw_inode->i_gid_low = cpu_to_le16(low_16_bits(inode->i_gid));
+/*
+ * Fix up interoperability with old kernels. Otherwise, old inodes get
+ * re-used with the upper 16 bits of the uid/gid intact
+ */
+ if(!inode->u.ext3_i.i_dtime) {
+ raw_inode->i_uid_high =
+ cpu_to_le16(high_16_bits(inode->i_uid));
+ raw_inode->i_gid_high =
+ cpu_to_le16(high_16_bits(inode->i_gid));
+ } else {
+ raw_inode->i_uid_high = 0;
+ raw_inode->i_gid_high = 0;
+ }
+ } else {
+ raw_inode->i_uid_low =
+ cpu_to_le16(fs_high2lowuid(inode->i_uid));
+ raw_inode->i_gid_low =
+ cpu_to_le16(fs_high2lowgid(inode->i_gid));
+ raw_inode->i_uid_high = 0;
+ raw_inode->i_gid_high = 0;
+ }
+ raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
+ raw_inode->i_size = cpu_to_le32(inode->u.ext3_i.i_disksize);
+ raw_inode->i_atime = cpu_to_le32(inode->i_atime);
+ raw_inode->i_ctime = cpu_to_le32(inode->i_ctime);
+ raw_inode->i_mtime = cpu_to_le32(inode->i_mtime);
+ raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
+ raw_inode->i_dtime = cpu_to_le32(inode->u.ext3_i.i_dtime);
+ raw_inode->i_flags = cpu_to_le32(inode->u.ext3_i.i_flags);
+#ifdef EXT3_FRAGMENTS
+ raw_inode->i_faddr = cpu_to_le32(inode->u.ext3_i.i_faddr);
+ raw_inode->i_frag = inode->u.ext3_i.i_frag_no;
+ raw_inode->i_fsize = inode->u.ext3_i.i_frag_size;
+#else
+ /* If we are not tracking these fields in the in-memory inode,
+ * then preserve them on disk, but still initialise them to zero
+ * for new inodes. */
+ if (inode->u.ext3_i.i_state & EXT3_STATE_NEW) {
+ raw_inode->i_faddr = 0;
+ raw_inode->i_frag = 0;
+ raw_inode->i_fsize = 0;
+ }
+#endif
+ raw_inode->i_file_acl = cpu_to_le32(inode->u.ext3_i.i_file_acl);
+ if (!S_ISREG(inode->i_mode)) {
+ raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext3_i.i_dir_acl);
+ } else {
+ raw_inode->i_size_high =
+ cpu_to_le32(inode->u.ext3_i.i_disksize >> 32);
+ if (inode->u.ext3_i.i_disksize > 0x7fffffffULL) {
+ struct super_block *sb = inode->i_sb;
+ if (!EXT3_HAS_RO_COMPAT_FEATURE(sb,
+ EXT3_FEATURE_RO_COMPAT_LARGE_FILE) ||
+ EXT3_SB(sb)->s_es->s_rev_level ==
+ cpu_to_le32(EXT3_GOOD_OLD_REV)) {
+ /* If this is the first large file
+ * created, add a flag to the superblock.
+ */
+ err = ext3_journal_get_write_access(handle,
+ sb->u.ext3_sb.s_sbh);
+ if (err)
+ goto out_brelse;
+ ext3_update_dynamic_rev(sb);
+ EXT3_SET_RO_COMPAT_FEATURE(sb,
+ EXT3_FEATURE_RO_COMPAT_LARGE_FILE);


+ sb->s_dirt = 1;

+ handle->h_sync = 1;
+ err = ext3_journal_dirty_metadata(handle,
+ sb->u.ext3_sb.s_sbh);
+ }
+ }
+ }
+ raw_inode->i_generation = le32_to_cpu(inode->i_generation);
+ if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
+ raw_inode->i_block[0] =
+ cpu_to_le32(kdev_t_to_nr(inode->i_rdev));
+ else for (block = 0; block < EXT3_N_BLOCKS; block++)
+ raw_inode->i_block[block] = inode->u.ext3_i.i_data[block];
+
+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
+ rc = ext3_journal_dirty_metadata(handle, bh);
+ if (!err)
+ err = rc;
+ inode->u.ext3_i.i_state &= ~EXT3_STATE_NEW;
+
+out_brelse:
+ brelse (bh);
+ ext3_std_error(inode->i_sb, err);
+ return err;
+}
+
+/*
+ * ext3_write_inode()
+ *
+ * We are called from a few places:
+ *
+ * - Within generic_file_write() for O_SYNC files.
+ * Here, there will be no transaction running. We wait for any running
+ * trasnaction to commit.
+ *
+ * - Within sys_sync(), kupdate and such.
+ * We wait on commit, if tol to.
+ *
+ * - Within prune_icache() (PF_MEMALLOC == true)
+ * Here we simply return. We can't afford to block kswapd on the
+ * journal commit.
+ *
+ * In all cases it is actually safe for us to return without doing anything,
+ * because the inode has been copied into a raw inode buffer in
+ * ext3_mark_inode_dirty(). This is a correctness thing for O_SYNC and for
+ * knfsd.
+ *
+ * Note that we are absolutely dependent upon all inode dirtiers doing the
+ * right thing: they *must* call mark_inode_dirty() after dirtying info in
+ * which we are interested.
+ *
+ * It would be a bug for them to not do this. The code:
+ *
+ * mark_inode_dirty(inode)
+ * stuff();
+ * inode->i_size = expr;
+ *
+ * is in error because a kswapd-driven write_inode() could occur while
+ * `stuff()' is running, and the new i_size will be lost. Plus the inode
+ * will no longer be on the superblock's dirty inode list.
+ */
+void ext3_write_inode(struct inode *inode, int wait)
+{
+ if (current->flags & PF_MEMALLOC)
+ return;
+
+ if (ext3_journal_current_handle()) {
+ jbd_debug(0, "called recursively, non-PF_MEMALLOC!\n");
+ return;
+ }
+
+ if (!wait)
+ return;
+
+ ext3_force_commit(inode->i_sb);
+}
+
+/*
+ * ext3_setattr()
+ *
+ * Called from notify_change.
+ *
+ * We want to trap VFS attempts to truncate the file as soon as
+ * possible. In particular, we want to make sure that when the VFS
+ * shrinks i_size, we put the inode on the orphan list and modify
+ * i_disksize immediately, so that during the subsequent flushing of
+ * dirty pages and freeing of disk blocks, we can guarantee that any
+ * commit will leave the blocks being flushed in an unused state on
+ * disk. (On recovery, the inode will get truncated and the blocks will
+ * be freed, so we have a strong guarantee that no future commit will
+ * leave these blocks visible to the user.)
+ *
+ * This is only needed for regular files. rmdir() has its own path, and
+ * we can never truncate a direcory except on final unlink (at which
+ * point i_nlink is zero so recovery is easy.)
+ *
+ * Called with the BKL.
+ */
+
+int ext3_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ struct inode *inode = dentry->d_inode;
+ int error, rc;
+
+ error = inode_change_ok(inode, attr);
+ if (error)
+ return error;
+
+ if (attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
+ handle_t *handle;
+
+ handle = ext3_journal_start(inode, 3);
+ if (IS_ERR(handle)) {
+ error = PTR_ERR(handle);
+ goto err_out;
+ }
+
+ error = ext3_orphan_add(handle, inode);
+ inode->u.ext3_i.i_disksize = attr->ia_size;
+ rc = ext3_mark_inode_dirty(handle, inode);
+ if (!error)
+ error = rc;
+ ext3_journal_stop(handle, inode);
+ }
+
+ inode_setattr(inode, attr);
+
+ /* If inode_setattr's call to ext3_truncate failed to get a
+ * transaction handle at all, we need to clean up the in-core
+ * orphan list manually. */
+ if (inode->i_nlink)
+ ext3_orphan_del(NULL, inode);
+
+err_out:
+ ext3_std_error(inode->i_sb, error);


+ return 0;
+}
+
+

+/*
+ * akpm: how many blocks doth make a writepage()?
+ *
+ * With N blocks per page, it may be:
+ * N data blocks
+ * 2 indirect block
+ * 2 dindirect
+ * 1 tindirect
+ * N+5 bitmap blocks (from the above)
+ * N+5 group descriptor summary blocks
+ * 1 inode block
+ * 1 superblock.
+ * 2 * EXT3_SINGLEDATA_TRANS_BLOCKS for the quote files
+ *
+ * 3 * (N + 5) + 2 + 2 * EXT3_SINGLEDATA_TRANS_BLOCKS
+ *
+ * With ordered or writeback data it's the same, less the N data blocks.
+ *
+ * If the inode's direct blocks can hold an integral number of pages then a
+ * page cannot straddle two indirect blocks, and we can only touch one indirect
+ * and dindirect block, and the "5" above becomes "3".
+ *
+ * This still overestimates under most circumstances. If we were to pass the
+ * start and end offsets in here as well we could do block_to_path() on each
+ * block and work out the exact number of indirects which are touched. Pah.
+ */
+
+int ext3_writepage_trans_blocks(struct inode *inode)
+{
+ int bpp = ext3_journal_blocks_per_page(inode);
+ int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
+ int ret;
+
+ if (ext3_should_journal_data(inode))
+ ret = 3 * (bpp + indirects) + 2;
+ else
+ ret = 2 * (bpp + indirects) + 2;
+
+#ifdef CONFIG_QUOTA
+ ret += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
+#endif
+
+ return ret;


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

echo 'End of part 088'
echo 'File patch-2.4.15 is continued in part 089'
echo "089" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:05 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part089

#!/bin/sh -x
# this is part 089 of a 115 - part archive


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

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

+
+int
+ext3_mark_iloc_dirty(handle_t *handle,

+ struct inode *inode,
+ struct ext3_iloc *iloc)
+{

+ int err = 0;
+

+ if (handle) {
+ /* the do_update_inode consumes one bh->b_count */
+ atomic_inc(&iloc->bh->b_count);
+ err = ext3_do_update_inode(handle, inode, iloc);
+ /* ext3_do_update_inode() does journal_dirty_metadata */
+ brelse(iloc->bh);
+ } else {
+ printk(KERN_EMERG __FUNCTION__ ": called with no handle!\n");


+ }
+ return err;
+}
+

+/*
+ * On success, We end up with an outstanding reference count against
+ * iloc->bh. This _must_ be cleaned up later.
+ */
+
+int
+ext3_reserve_inode_write(handle_t *handle, struct inode *inode,
+ struct ext3_iloc *iloc)
+{
+ int err = 0;
+ if (handle) {
+ err = ext3_get_inode_loc(inode, iloc);
+ if (!err) {
+ BUFFER_TRACE(iloc->bh, "get_write_access");
+ err = ext3_journal_get_write_access(handle, iloc->bh);
+ if (err) {
+ brelse(iloc->bh);
+ iloc->bh = NULL;
+ }
+ }
+ }


+ ext3_std_error(inode->i_sb, err);
+ return err;
+}
+
+/*

+ * akpm: What we do here is to mark the in-core inode as clean
+ * with respect to inode dirtiness (it may still be data-dirty).
+ * This means that the in-core inode may be reaped by prune_icache
+ * without having to perform any I/O. This is a very good thing,
+ * because *any* task may call prune_icache - even ones which
+ * have a transaction open against a different journal.
+ *
+ * Is this cheating? Not really. Sure, we haven't written the
+ * inode out, but prune_icache isn't a user-visible syncing function.
+ * Whenever the user wants stuff synced (sys_sync, sys_msync, sys_fsync)
+ * we start and wait on commits.
+ *
+ * Is this efficient/effective? Well, we're being nice to the system
+ * by cleaning up our inodes proactively so they can be reaped
+ * without I/O. But we are potentially leaving up to five seconds'
+ * worth of inodes floating about which prune_icache wants us to
+ * write out. One way to fix that would be to get prune_icache()
+ * to do a write_super() to free up some memory. It has the desired
+ * effect.
+ */
+int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode)


+{
+ struct ext3_iloc iloc;

+ int err;
+
+ err = ext3_reserve_inode_write(handle, inode, &iloc);
+ if (!err)
+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);


+ return err;
+}
+
+/*

+ * akpm: ext3_dirty_inode() is called from __mark_inode_dirty()
+ *
+ * We're really interested in the case where a file is being extended.
+ * i_size has been changed by generic_commit_write() and we thus need
+ * to include the updated inode in the current transaction.
+ *
+ * Also, DQUOT_ALLOC_SPACE() will always dirty the inode when blocks
+ * are allocated to the file.
+ *
+ * If the inode is marked synchronous, we don't honour that here - doing
+ * so would cause a commit on atime updates, which we don't bother doing.
+ * We handle synchronous inodes at the highest possible level.
+ */
+void ext3_dirty_inode(struct inode *inode)
+{
+ handle_t *current_handle = ext3_journal_current_handle();
+ handle_t *handle;
+
+ lock_kernel();
+ handle = ext3_journal_start(inode, 1);
+ if (IS_ERR(handle))
+ goto out;
+ if (current_handle &&
+ current_handle->h_transaction != handle->h_transaction) {
+ /* This task has a transaction open against a different fs */
+ printk(KERN_EMERG __FUNCTION__": transactions do not match!\n");
+ } else {
+ jbd_debug(5, "marking dirty. outer handle=%p\n",
+ current_handle);
+ ext3_mark_inode_dirty(handle, inode);
+ }


+ ext3_journal_stop(handle, inode);
+out:
+ unlock_kernel();
+}

+
+#ifdef AKPM
+/*
+ * Bind an inode's backing buffer_head into this transaction, to prevent
+ * it from being flushed to disk early. Unlike
+ * ext3_reserve_inode_write, this leaves behind no bh reference and
+ * returns no iloc structure, so the caller needs to repeat the iloc
+ * lookup to mark the inode dirty later.


+ */
+static inline int

+ext3_pin_inode(handle_t *handle, struct inode *inode)


+{
+ struct ext3_iloc iloc;
+

+ int err = 0;

+ if (handle) {
+ err = ext3_get_inode_loc(inode, &iloc);
+ if (!err) {
+ BUFFER_TRACE(iloc.bh, "get_write_access");
+ err = journal_get_write_access(handle, iloc.bh);
+ if (!err)
+ err = ext3_journal_dirty_metadata(handle,
+ iloc.bh);
+ brelse(iloc.bh);
+ }
+ }


+ ext3_std_error(inode->i_sb, err);
+ return err;
+}

+#endif
+
+int ext3_change_inode_journal_flag(struct inode *inode, int val)
+{
+ journal_t *journal;
+ handle_t *handle;
+ int err;
+
+ /*
+ * We have to be very careful here: changing a data block's
+ * journaling status dynamically is dangerous. If we write a
+ * data block to the journal, change the status and then delete
+ * that block, we risk forgetting to revoke the old log record
+ * from the journal and so a subsequent replay can corrupt data.
+ * So, first we make sure that the journal is empty and that
+ * nobody is changing anything.


+ */
+
+ journal = EXT3_JOURNAL(inode);

+ if (is_journal_aborted(journal) || IS_RDONLY(inode))
+ return -EROFS;
+
+ journal_lock_updates(journal);
+ journal_flush(journal);
+
+ /*
+ * OK, there are no updates running now, and all cached data is
+ * synced to disk. We are now in a completely consistent state
+ * which doesn't have anything in the journal, and we know that
+ * no filesystem updates are running, so it is safe to modify
+ * the inode's in-core data-journaling state flag now.
+ */
+
+ if (val)
+ inode->u.ext3_i.i_flags |= EXT3_JOURNAL_DATA_FL;
+ else
+ inode->u.ext3_i.i_flags &= ~EXT3_JOURNAL_DATA_FL;
+
+ journal_unlock_updates(journal);
+
+ /* Finally we can mark the inode as dirty. */
+
+ handle = ext3_journal_start(inode, 1);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+
+ err = ext3_mark_inode_dirty(handle, inode);


+ handle->h_sync = 1;

+ ext3_journal_stop(handle, inode);


+ ext3_std_error(inode->i_sb, err);
+

+ return err;
+}
+
+

+/*
+ * ext3_aops_journal_start().
+ *
+ * <This function died, but the comment lives on>
+ *
+ * We need to take the inode semaphore *outside* the
+ * journal_start/journal_stop. Otherwise, a different task could do a
+ * wait_for_commit() while holding ->i_sem, which deadlocks. The rule
+ * is: transaction open/closes are considered to be a locking operation
+ * and they nest *inside* ->i_sem.
+ * ----------------------------------------------------------------------------
+ * Possible problem:
+ * ext3_file_write()
+ * -> generic_file_write()
+ * -> __alloc_pages()
+ * -> page_launder()
+ * -> ext3_writepage()
+ *
+ * And the writepage can be on a different fs while we have a
+ * transaction open against this one! Bad.
+ *
+ * I tried making the task PF_MEMALLOC here, but that simply results in
+ * 0-order allocation failures passed back to generic_file_write().
+ * Instead, we rely on the reentrancy protection in ext3_writepage().
+ * ----------------------------------------------------------------------------
+ * When we do the journal_start() here we don't really need to reserve
+ * any blocks - we won't need any until we hit ext3_prepare_write(),
+ * which does all the needed journal extending. However! There is a
+ * problem with quotas:
+ *
+ * Thread 1:
+ * sys_sync
+ * ->sync_dquots
+ * ->commit_dquot
+ * ->lock_dquot
+ * ->write_dquot
+ * ->ext3_file_write
+ * ->journal_start
+ * ->ext3_prepare_write
+ * ->journal_extend
+ * ->journal_start
+ * Thread 2:
+ * ext3_create (for example)
+ * ->ext3_new_inode
+ * ->dquot_initialize
+ * ->lock_dquot
+ *
+ * Deadlock. Thread 1's journal_start blocks because thread 2 has a
+ * transaction open. Thread 2's transaction will never close because
+ * thread 2 is stuck waiting for the dquot lock.
+ *
+ * So. We must ensure that thread 1 *never* needs to extend the journal
+ * for quota writes. We do that by reserving enough journal blocks
+ * here, in ext3_aops_journal_start() to ensure that the forthcoming "see if we
+ * need to extend" test in ext3_prepare_write() succeeds.
+ */
+
+
+MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/fs/ext3/ioctl.c linux/fs/ext3/ioctl.c
--- v2.4.14/linux/fs/ext3/ioctl.c Wed Dec 31 16:00:00 1969
+++ linux/fs/ext3/ioctl.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,170 @@
+/*
+ * linux/fs/ext3/ioctl.c


+ *
+ * Copyright (C) 1993, 1994, 1995
+ * Remy Card (ca...@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ */
+
+#include <linux/fs.h>

+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/ext3_jbd.h>

+#include <linux/sched.h>
+#include <asm/uaccess.h>
+
+
+int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned int flags;
+
+ ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg);
+
+ switch (cmd) {
+ case EXT3_IOC_GETFLAGS:
+ flags = inode->u.ext3_i.i_flags & EXT3_FL_USER_VISIBLE;
+ return put_user(flags, (int *) arg);
+ case EXT3_IOC_SETFLAGS: {


+ handle_t *handle = NULL;

+ int err;
+ struct ext3_iloc iloc;
+ unsigned int oldflags;
+ unsigned int jflag;
+
+ if (IS_RDONLY(inode))
+ return -EROFS;
+
+ if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ return -EPERM;
+
+ if (get_user(flags, (int *) arg))
+ return -EFAULT;
+
+ oldflags = inode->u.ext3_i.i_flags;
+
+ /* The JOURNAL_DATA flag is modifiable only by root */
+ jflag = flags & EXT3_JOURNAL_DATA_FL;
+
+ /*
+ * The IMMUTABLE and APPEND_ONLY flags can only be changed by
+ * the relevant capability.
+ *
+ * This test looks nicer. Thanks to Pauline Middelink
+ */
+ if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
+ if (!capable(CAP_LINUX_IMMUTABLE))
+ return -EPERM;
+ }
+
+ /*
+ * The JOURNAL_DATA flag can only be changed by
+ * the relevant capability.
+ */
+ if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) {
+ if (!capable(CAP_SYS_RESOURCE))
+ return -EPERM;
+ }
+
+
+ handle = ext3_journal_start(inode, 1);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);


+ if (IS_SYNC(inode))
+ handle->h_sync = 1;

+ err = ext3_reserve_inode_write(handle, inode, &iloc);
+ if (err)
+ goto flags_err;
+
+ flags = flags & EXT3_FL_USER_MODIFIABLE;
+ flags |= oldflags & ~EXT3_FL_USER_MODIFIABLE;
+ inode->u.ext3_i.i_flags = flags;
+
+ if (flags & EXT3_SYNC_FL)


+ inode->i_flags |= S_SYNC;

+ else
+ inode->i_flags &= ~S_SYNC;
+ if (flags & EXT3_APPEND_FL)


+ inode->i_flags |= S_APPEND;

+ else
+ inode->i_flags &= ~S_APPEND;
+ if (flags & EXT3_IMMUTABLE_FL)


+ inode->i_flags |= S_IMMUTABLE;

+ else
+ inode->i_flags &= ~S_IMMUTABLE;
+ if (flags & EXT3_NOATIME_FL)


+ inode->i_flags |= S_NOATIME;

+ else
+ inode->i_flags &= ~S_NOATIME;


+ inode->i_ctime = CURRENT_TIME;
+

+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
+flags_err:
+ ext3_journal_stop(handle, inode);
+ if (err)
+ return err;
+
+ if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL))
+ err = ext3_change_inode_journal_flag(inode, jflag);
+ return err;
+ }
+ case EXT3_IOC_GETVERSION:
+ case EXT3_IOC_GETVERSION_OLD:
+ return put_user(inode->i_generation, (int *) arg);
+ case EXT3_IOC_SETVERSION:
+ case EXT3_IOC_SETVERSION_OLD: {
+ handle_t *handle;
+ struct ext3_iloc iloc;
+ __u32 generation;
+ int err;
+
+ if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ return -EPERM;
+ if (IS_RDONLY(inode))
+ return -EROFS;
+ if (get_user(generation, (int *) arg))
+ return -EFAULT;
+
+ handle = ext3_journal_start(inode, 1);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ err = ext3_reserve_inode_write(handle, inode, &iloc);
+ if (err)
+ return err;


+
+ inode->i_ctime = CURRENT_TIME;

+ inode->i_generation = generation;
+
+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
+ ext3_journal_stop(handle, inode);
+ return err;
+ }
+#ifdef CONFIG_JBD_DEBUG
+ case EXT3_IOC_WAIT_FOR_READONLY:
+ /*
+ * This is racy - by the time we're woken up and running,
+ * the superblock could be released. And the module could
+ * have been unloaded. So sue me.
+ *
+ * Returns 1 if it slept, else zero.
+ */
+ {


+ struct super_block *sb = inode->i_sb;

+ DECLARE_WAITQUEUE(wait, current);
+ int ret = 0;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&sb->u.ext3_sb.ro_wait_queue, &wait);
+ if (timer_pending(&sb->u.ext3_sb.turn_ro_timer)) {
+ schedule();


+ ret = 1;
+ }

+ remove_wait_queue(&sb->u.ext3_sb.ro_wait_queue, &wait);


+ return ret;
+ }
+#endif

+ default:
+ return -ENOTTY;
+ }
+}
diff -u --recursive --new-file v2.4.14/linux/fs/ext3/namei.c linux/fs/ext3/namei.c
--- v2.4.14/linux/fs/ext3/namei.c Wed Dec 31 16:00:00 1969
+++ linux/fs/ext3/namei.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,1125 @@
+/*
+ * linux/fs/ext3/namei.c


+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (ca...@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *

+ * from
+ *
+ * linux/fs/minix/namei.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *


+ * Big-endian to little-endian byte-swapping/bitmaps by
+ * David S. Miller (da...@caip.rutgers.edu), 1995

+ * Directory entry file type support and forward compatibility hooks
+ * for B-tree directories by Theodore Ts'o (ty...@mit.edu), 1998


+ */
+
+#include <linux/fs.h>

+#include <linux/jbd.h>
+#include <linux/sched.h>
+#include <linux/ext3_fs.h>
+#include <linux/ext3_jbd.h>
+#include <linux/fcntl.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/locks.h>
+#include <linux/quotaops.h>
+
+
+/*
+ * define how far ahead to read directories while searching them.
+ */
+#define NAMEI_RA_CHUNKS 2
+#define NAMEI_RA_BLOCKS 4
+#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
+#define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
+
+/*
+ * NOTE! unlike strncmp, ext3_match returns 1 for success, 0 for failure.
+ *
+ * `len <= EXT3_NAME_LEN' is guaranteed by caller.
+ * `de != NULL' is guaranteed by caller.
+ */
+static inline int ext3_match (int len, const char * const name,
+ struct ext3_dir_entry_2 * de)
+{
+ if (len != de->name_len)
+ return 0;
+ if (!de->inode)
+ return 0;
+ return !memcmp(name, de->name, len);
+}
+
+/*
+ * Returns 0 if not found, -1 on failure, and 1 on success
+ */
+static int inline search_dirblock(struct buffer_head * bh,
+ struct inode *dir,
+ struct dentry *dentry,
+ unsigned long offset,
+ struct ext3_dir_entry_2 ** res_dir)
+{
+ struct ext3_dir_entry_2 * de;
+ char * dlimit;
+ int de_len;
+ const char *name = dentry->d_name.name;
+ int namelen = dentry->d_name.len;
+
+ de = (struct ext3_dir_entry_2 *) bh->b_data;
+ dlimit = bh->b_data + dir->i_sb->s_blocksize;
+ while ((char *) de < dlimit) {
+ /* this code is executed quadratically often */
+ /* do minimal checking `by hand' */
+
+ if ((char *) de + namelen <= dlimit &&
+ ext3_match (namelen, name, de)) {
+ /* found a match - just to be sure, do a full check */
+ if (!ext3_check_dir_entry("ext3_find_entry",
+ dir, de, bh, offset))
+ return -1;
+ *res_dir = de;
+ return 1;
+ }
+ /* prevent looping on a bad block */
+ de_len = le16_to_cpu(de->rec_len);
+ if (de_len <= 0)
+ return -1;
+ offset += de_len;
+ de = (struct ext3_dir_entry_2 *) ((char *) de + de_len);


+ }
+ return 0;
+}
+

+/*
+ * ext3_find_entry()
+ *
+ * finds an entry in the specified directory with the wanted name. It
+ * returns the cache buffer in which the entry was found, and the entry
+ * itself (as a parameter - res_dir). It does NOT read the inode of the
+ * entry - you'll have to do that yourself if you want to.
+ *
+ * The returned buffer_head has ->b_count elevated. The caller is expected
+ * to brelse() it when appropriate.
+ */
+static struct buffer_head * ext3_find_entry (struct dentry *dentry,
+ struct ext3_dir_entry_2 ** res_dir)
+{


+ struct super_block * sb;

+ struct buffer_head * bh_use[NAMEI_RA_SIZE];
+ struct buffer_head * bh, *ret = NULL;
+ unsigned long start, block, b;
+ int ra_max = 0; /* Number of bh's in the readahead
+ buffer, bh_use[] */
+ int ra_ptr = 0; /* Current index into readahead
+ buffer */
+ int num = 0;
+ int nblocks, i, err;
+ struct inode *dir = dentry->d_parent->d_inode;
+
+ *res_dir = NULL;
+ sb = dir->i_sb;
+
+ nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
+ start = dir->u.ext3_i.i_dir_start_lookup;
+ if (start >= nblocks)
+ start = 0;
+ block = start;
+restart:
+ do {
+ /*
+ * We deal with the read-ahead logic here.
+ */
+ if (ra_ptr >= ra_max) {
+ /* Refill the readahead buffer */
+ ra_ptr = 0;
+ b = block;
+ for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) {
+ /*
+ * Terminate if we reach the end of the
+ * directory and must wrap, or if our
+ * search has finished at this block.
+ */
+ if (b >= nblocks || (num && block == start)) {
+ bh_use[ra_max] = NULL;
+ break;
+ }
+ num++;
+ bh = ext3_getblk(NULL, dir, b++, 0, &err);
+ bh_use[ra_max] = bh;
+ if (bh)


+ ll_rw_block(READ, 1, &bh);
+ }

+ }
+ if ((bh = bh_use[ra_ptr++]) == NULL)
+ goto next;
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+ /* read error, skip block & hope for the best */
+ brelse(bh);
+ goto next;
+ }
+ i = search_dirblock(bh, dir, dentry,
+ block << EXT3_BLOCK_SIZE_BITS(sb), res_dir);
+ if (i == 1) {
+ dir->u.ext3_i.i_dir_start_lookup = block;
+ ret = bh;
+ goto cleanup_and_exit;
+ } else {
+ brelse(bh);
+ if (i < 0)
+ goto cleanup_and_exit;
+ }
+ next:
+ if (++block >= nblocks)
+ block = 0;
+ } while (block != start);
+
+ /*
+ * If the directory has grown while we were searching, then
+ * search the last part of the directory before giving up.
+ */
+ block = nblocks;
+ nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
+ if (block < nblocks) {
+ start = 0;
+ goto restart;
+ }
+
+cleanup_and_exit:
+ /* Clean up the read-ahead blocks */
+ for (; ra_ptr < ra_max; ra_ptr++)
+ brelse (bh_use[ra_ptr]);


+ return ret;
+}
+

+static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry)
+{
+ struct inode * inode;
+ struct ext3_dir_entry_2 * de;


+ struct buffer_head * bh;
+

+ if (dentry->d_name.len > EXT3_NAME_LEN)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ bh = ext3_find_entry(dentry, &de);
+ inode = NULL;
+ if (bh) {
+ unsigned long ino = le32_to_cpu(de->inode);
+ brelse (bh);
+ inode = iget(dir->i_sb, ino);
+
+ if (!inode)
+ return ERR_PTR(-EACCES);
+ }
+ d_add(dentry, inode);


+ return NULL;
+}
+

+#define S_SHIFT 12
+static unsigned char ext3_type_by_mode[S_IFMT >> S_SHIFT] = {
+ [S_IFREG >> S_SHIFT] EXT3_FT_REG_FILE,
+ [S_IFDIR >> S_SHIFT] EXT3_FT_DIR,
+ [S_IFCHR >> S_SHIFT] EXT3_FT_CHRDEV,
+ [S_IFBLK >> S_SHIFT] EXT3_FT_BLKDEV,
+ [S_IFIFO >> S_SHIFT] EXT3_FT_FIFO,
+ [S_IFSOCK >> S_SHIFT] EXT3_FT_SOCK,
+ [S_IFLNK >> S_SHIFT] EXT3_FT_SYMLINK,
+};
+
+static inline void ext3_set_de_type(struct super_block *sb,
+ struct ext3_dir_entry_2 *de,
+ umode_t mode) {
+ if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_FILETYPE))
+ de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
+}
+
+/*
+ * ext3_add_entry()
+ *
+ * adds a file entry to the specified directory, using the same
+ * semantics as ext3_find_entry(). It returns NULL if it failed.
+ *
+ * NOTE!! The inode part of 'de' is left at 0 - which means you
+ * may not sleep between calling this and putting something into
+ * the entry, as someone else might have used it while you slept.
+ */
+
+/*
+ * AKPM: the journalling code here looks wrong on the error paths
+ */
+static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
+ struct inode *inode)
+{
+ struct inode *dir = dentry->d_parent->d_inode;
+ const char *name = dentry->d_name.name;
+ int namelen = dentry->d_name.len;
+ unsigned long offset;
+ unsigned short rec_len;


+ struct buffer_head * bh;

+ struct ext3_dir_entry_2 * de, * de1;


+ struct super_block * sb;

+ int retval;
+
+ sb = dir->i_sb;
+
+ if (!namelen)
+ return -EINVAL;
+ bh = ext3_bread (handle, dir, 0, 0, &retval);
+ if (!bh)
+ return retval;
+ rec_len = EXT3_DIR_REC_LEN(namelen);
+ offset = 0;
+ de = (struct ext3_dir_entry_2 *) bh->b_data;
+ while (1) {
+ if ((char *)de >= sb->s_blocksize + bh->b_data) {
+ brelse (bh);
+ bh = NULL;
+ bh = ext3_bread (handle, dir,
+ offset >> EXT3_BLOCK_SIZE_BITS(sb), 1, &retval);
+ if (!bh)
+ return retval;
+ if (dir->i_size <= offset) {
+ if (dir->i_size == 0) {
+ brelse(bh);
+ return -ENOENT;
+ }
+
+ ext3_debug ("creating next block\n");
+


+ BUFFER_TRACE(bh, "get_write_access");
+ ext3_journal_get_write_access(handle, bh);

+ de = (struct ext3_dir_entry_2 *) bh->b_data;
+ de->inode = 0;
+ de->rec_len = le16_to_cpu(sb->s_blocksize);
+ dir->u.ext3_i.i_disksize =
+ dir->i_size = offset + sb->s_blocksize;
+ dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
+ ext3_mark_inode_dirty(handle, dir);
+ } else {
+
+ ext3_debug ("skipping to next block\n");
+
+ de = (struct ext3_dir_entry_2 *) bh->b_data;
+ }
+ }
+ if (!ext3_check_dir_entry ("ext3_add_entry", dir, de, bh,
+ offset)) {
+ brelse (bh);
+ return -ENOENT;
+ }
+ if (ext3_match (namelen, name, de)) {
+ brelse (bh);
+ return -EEXIST;
+ }
+ if ((le32_to_cpu(de->inode) == 0 &&
+ le16_to_cpu(de->rec_len) >= rec_len) ||
+ (le16_to_cpu(de->rec_len) >=
+ EXT3_DIR_REC_LEN(de->name_len) + rec_len)) {


+ BUFFER_TRACE(bh, "get_write_access");
+ ext3_journal_get_write_access(handle, bh);

+ /* By now the buffer is marked for journaling */
+ offset += le16_to_cpu(de->rec_len);
+ if (le32_to_cpu(de->inode)) {
+ de1 = (struct ext3_dir_entry_2 *) ((char *) de +
+ EXT3_DIR_REC_LEN(de->name_len));
+ de1->rec_len =
+ cpu_to_le16(le16_to_cpu(de->rec_len) -
+ EXT3_DIR_REC_LEN(de->name_len));
+ de->rec_len = cpu_to_le16(
+ EXT3_DIR_REC_LEN(de->name_len));
+ de = de1;
+ }
+ de->file_type = EXT3_FT_UNKNOWN;
+ if (inode) {
+ de->inode = cpu_to_le32(inode->i_ino);
+ ext3_set_de_type(dir->i_sb, de, inode->i_mode);
+ } else
+ de->inode = 0;
+ de->name_len = namelen;
+ memcpy (de->name, name, namelen);
+ /*
+ * XXX shouldn't update any times until successful
+ * completion of syscall, but too many callers depend
+ * on this.
+ *
+ * XXX similarly, too many callers depend on
+ * ext3_new_inode() setting the times, but error
+ * recovery deletes the inode, so the worst that can
+ * happen is that the times are slightly out of date
+ * and/or different from the directory change time.
+ */
+ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
+ ext3_mark_inode_dirty(handle, dir);
+ dir->i_version = ++event;


+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
+ ext3_journal_dirty_metadata(handle, bh);

+ brelse(bh);
+ return 0;
+ }
+ offset += le16_to_cpu(de->rec_len);
+ de = (struct ext3_dir_entry_2 *)
+ ((char *) de + le16_to_cpu(de->rec_len));
+ }
+ brelse (bh);
+ return -ENOSPC;
+}
+
+/*
+ * ext3_delete_entry deletes a directory entry by merging it with the
+ * previous entry
+ */
+static int ext3_delete_entry (handle_t *handle,
+ struct inode * dir,
+ struct ext3_dir_entry_2 * de_del,
+ struct buffer_head * bh)
+{
+ struct ext3_dir_entry_2 * de, * pde;
+ int i;
+
+ i = 0;
+ pde = NULL;
+ de = (struct ext3_dir_entry_2 *) bh->b_data;
+ while (i < bh->b_size) {
+ if (!ext3_check_dir_entry("ext3_delete_entry", dir, de, bh, i))
+ return -EIO;
+ if (de == de_del) {


+ BUFFER_TRACE(bh, "get_write_access");
+ ext3_journal_get_write_access(handle, bh);

+ if (pde)
+ pde->rec_len =
+ cpu_to_le16(le16_to_cpu(pde->rec_len) +
+ le16_to_cpu(de->rec_len));
+ else
+ de->inode = 0;
+ dir->i_version = ++event;


+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
+ ext3_journal_dirty_metadata(handle, bh);

+ return 0;
+ }
+ i += le16_to_cpu(de->rec_len);
+ pde = de;
+ de = (struct ext3_dir_entry_2 *)
+ ((char *) de + le16_to_cpu(de->rec_len));
+ }
+ return -ENOENT;
+}
+
+/*
+ * ext3_mark_inode_dirty is somewhat expensive, so unlike ext2 we
+ * do not perform it in these functions. We perform it at the call site,
+ * if it is needed.
+ */
+static inline void ext3_inc_count(handle_t *handle, struct inode *inode)
+{
+ inode->i_nlink++;
+}
+
+static inline void ext3_dec_count(handle_t *handle, struct inode *inode)
+{
+ inode->i_nlink--;
+}
+
+static int ext3_add_nondir(handle_t *handle,
+ struct dentry *dentry, struct inode *inode)
+{
+ int err = ext3_add_entry(handle, dentry, inode);
+ if (!err) {
+ d_instantiate(dentry, inode);
+ return 0;
+ }
+ ext3_dec_count(handle, inode);
+ iput(inode);


+ return err;
+}
+
+/*

+ * By the time this is called, we already have created
+ * the directory cache entry for the new file, but it
+ * is so far negative - it has no inode.
+ *
+ * If the create succeeds, we fill in the inode information
+ * with d_instantiate().
+ */
+static int ext3_create (struct inode * dir, struct dentry * dentry, int mode)
+{
+ handle_t *handle;
+ struct inode * inode;
+ int err;
+
+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+
+ if (IS_SYNC(dir))


+ handle->h_sync = 1;
+

+ inode = ext3_new_inode (handle, dir, mode);
+ err = PTR_ERR(inode);
+ if (!IS_ERR(inode)) {


+ inode->i_op = &ext3_file_inode_operations;
+ inode->i_fop = &ext3_file_operations;
+ inode->i_mapping->a_ops = &ext3_aops;

+ ext3_mark_inode_dirty(handle, inode);
+ err = ext3_add_nondir(handle, dentry, inode);
+ }
+ ext3_journal_stop(handle, dir);


+ return err;
+}
+

+static int ext3_mknod (struct inode * dir, struct dentry *dentry,
+ int mode, int rdev)
+{
+ handle_t *handle;
+ struct inode *inode;
+ int err;
+
+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+
+ if (IS_SYNC(dir))


+ handle->h_sync = 1;
+

+ inode = ext3_new_inode (handle, dir, mode);
+ err = PTR_ERR(inode);
+ if (!IS_ERR(inode)) {
+ init_special_inode(inode, mode, rdev);
+ ext3_mark_inode_dirty(handle, inode);
+ err = ext3_add_nondir(handle, dentry, inode);
+ }
+ ext3_journal_stop(handle, dir);


+ return err;
+}
+

+static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
+{
+ handle_t *handle;
+ struct inode * inode;
+ struct buffer_head * dir_block;
+ struct ext3_dir_entry_2 * de;
+ int err;
+
+ if (dir->i_nlink >= EXT3_LINK_MAX)
+ return -EMLINK;
+
+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+
+ if (IS_SYNC(dir))


+ handle->h_sync = 1;
+

+ inode = ext3_new_inode (handle, dir, S_IFDIR);
+ err = PTR_ERR(inode);
+ if (IS_ERR(inode))
+ goto out_stop;
+


+ inode->i_op = &ext3_dir_inode_operations;
+ inode->i_fop = &ext3_dir_operations;

+ inode->i_size = inode->u.ext3_i.i_disksize = inode->i_sb->s_blocksize;
+ inode->i_blocks = 0;
+ dir_block = ext3_bread (handle, inode, 0, 1, &err);
+ if (!dir_block) {
+ inode->i_nlink--; /* is this nlink == 0? */
+ ext3_mark_inode_dirty(handle, inode);
+ iput (inode);
+ goto out_stop;
+ }
+ BUFFER_TRACE(dir_block, "get_write_access");
+ ext3_journal_get_write_access(handle, dir_block);
+ de = (struct ext3_dir_entry_2 *) dir_block->b_data;
+ de->inode = cpu_to_le32(inode->i_ino);
+ de->name_len = 1;
+ de->rec_len = cpu_to_le16(EXT3_DIR_REC_LEN(de->name_len));
+ strcpy (de->name, ".");
+ ext3_set_de_type(dir->i_sb, de, S_IFDIR);
+ de = (struct ext3_dir_entry_2 *)
+ ((char *) de + le16_to_cpu(de->rec_len));
+ de->inode = cpu_to_le32(dir->i_ino);
+ de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT3_DIR_REC_LEN(1));
+ de->name_len = 2;
+ strcpy (de->name, "..");
+ ext3_set_de_type(dir->i_sb, de, S_IFDIR);
+ inode->i_nlink = 2;
+ BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
+ ext3_journal_dirty_metadata(handle, dir_block);
+ brelse (dir_block);
+ inode->i_mode = S_IFDIR | mode;
+ if (dir->i_mode & S_ISGID)
+ inode->i_mode |= S_ISGID;
+ ext3_mark_inode_dirty(handle, inode);
+ err = ext3_add_entry (handle, dentry, inode);
+ if (err)
+ goto out_no_entry;
+ dir->i_nlink++;
+ dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
+ ext3_mark_inode_dirty(handle, dir);
+ d_instantiate(dentry, inode);
+out_stop:
+ ext3_journal_stop(handle, dir);
+ return err;
+
+out_no_entry:
+ inode->i_nlink = 0;
+ ext3_mark_inode_dirty(handle, inode);
+ iput (inode);


+ goto out_stop;
+}
+

+/*
+ * routine to check that the specified directory is empty (for rmdir)
+ */
+static int empty_dir (struct inode * inode)
+{
+ unsigned long offset;
+ struct buffer_head * bh;
+ struct ext3_dir_entry_2 * de, * de1;


+ struct super_block * sb;

+ int err;
+
+ sb = inode->i_sb;
+ if (inode->i_size < EXT3_DIR_REC_LEN(1) + EXT3_DIR_REC_LEN(2) ||
+ !(bh = ext3_bread (NULL, inode, 0, 0, &err))) {
+ ext3_warning (inode->i_sb, "empty_dir",
+ "bad directory (dir #%lu) - no data block",
+ inode->i_ino);
+ return 1;
+ }
+ de = (struct ext3_dir_entry_2 *) bh->b_data;
+ de1 = (struct ext3_dir_entry_2 *)
+ ((char *) de + le16_to_cpu(de->rec_len));
+ if (le32_to_cpu(de->inode) != inode->i_ino ||
+ !le32_to_cpu(de1->inode) ||
+ strcmp (".", de->name) ||
+ strcmp ("..", de1->name)) {
+ ext3_warning (inode->i_sb, "empty_dir",
+ "bad directory (dir #%lu) - no `.' or `..'",
+ inode->i_ino);
+ brelse (bh);
+ return 1;
+ }
+ offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
+ de = (struct ext3_dir_entry_2 *)
+ ((char *) de1 + le16_to_cpu(de1->rec_len));
+ while (offset < inode->i_size ) {
+ if (!bh ||
+ (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
+ brelse (bh);
+ bh = ext3_bread (NULL, inode,
+ offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err);
+ if (!bh) {
+#if 0
+ ext3_error (sb, "empty_dir",
+ "directory #%lu contains a hole at offset %lu",
+ inode->i_ino, offset);
+#endif
+ offset += sb->s_blocksize;
+ continue;
+ }
+ de = (struct ext3_dir_entry_2 *) bh->b_data;
+ }
+ if (!ext3_check_dir_entry ("empty_dir", inode, de, bh,
+ offset)) {
+ brelse (bh);
+ return 1;
+ }
+ if (le32_to_cpu(de->inode)) {


+ brelse (bh);
+ return 0;
+ }

+ offset += le16_to_cpu(de->rec_len);
+ de = (struct ext3_dir_entry_2 *)
+ ((char *) de + le16_to_cpu(de->rec_len));
+ }
+ brelse (bh);
+ return 1;
+}
+
+/* ext3_orphan_add() links an unlinked or truncated inode into a list of
+ * such inodes, starting at the superblock, in case we crash before the
+ * file is closed/deleted, or in case the inode truncate spans multiple
+ * transactions and the last transaction is not recovered after a crash.
+ *
+ * At filesystem recovery time, we walk this list deleting unlinked
+ * inodes and truncating linked inodes in ext3_orphan_cleanup().
+ */
+int ext3_orphan_add(handle_t *handle, struct inode *inode)
+{


+ struct super_block *sb = inode->i_sb;

+ struct ext3_iloc iloc;
+ int err = 0, rc;
+
+ lock_super(sb);
+ if (!list_empty(&inode->u.ext3_i.i_orphan))
+ goto out_unlock;
+
+ /* Orphan handling is only valid for files with data blocks
+ * being truncated, or files being unlinked. */
+
+ /* @@@ FIXME: Observation from aviro:
+ * I think I can trigger J_ASSERT in ext3_orphan_add(). We block
+ * here (on lock_super()), so race with ext3_link() which might bump
+ * ->i_nlink. For, say it, character device. Not a regular file,
+ * not a directory, not a symlink and ->i_nlink > 0.
+ */
+ J_ASSERT ((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+ S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
+
+ BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
+ err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
+ if (err)
+ goto out_unlock;
+
+ err = ext3_reserve_inode_write(handle, inode, &iloc);
+ if (err)
+ goto out_unlock;
+
+ /* Insert this inode at the head of the on-disk orphan list... */
+ NEXT_ORPHAN(inode) = le32_to_cpu(EXT3_SB(sb)->s_es->s_last_orphan);
+ EXT3_SB(sb)->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
+ err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
+ rc = ext3_mark_iloc_dirty(handle, inode, &iloc);


+ if (!err)
+ err = rc;
+

+ /* Only add to the head of the in-memory list if all the
+ * previous operations succeeded. If the orphan_add is going to
+ * fail (possibly taking the journal offline), we can't risk
+ * leaving the inode on the orphan list: stray orphan-list
+ * entries can cause panics at unmount time.
+ *
+ * This is safe: on error we're going to ignore the orphan list
+ * anyway on the next recovery. */
+ if (!err)
+ list_add(&inode->u.ext3_i.i_orphan, &EXT3_SB(sb)->s_orphan);
+
+ jbd_debug(4, "superblock will point to %ld\n", inode->i_ino);
+ jbd_debug(4, "orphan inode %ld will point to %d\n",
+ inode->i_ino, NEXT_ORPHAN(inode));
+out_unlock:
+ unlock_super(sb);


+ ext3_std_error(inode->i_sb, err);
+ return err;
+}
+
+/*

+ * ext3_orphan_del() removes an unlinked or truncated inode from the list
+ * of such inodes stored on disk, because it is finally being cleaned up.
+ */
+int ext3_orphan_del(handle_t *handle, struct inode *inode)
+{
+ struct list_head *prev;
+ struct ext3_sb_info *sbi;
+ ino_t ino_next;
+ struct ext3_iloc iloc;


+ int err = 0;
+

+ lock_super(inode->i_sb);
+ if (list_empty(&inode->u.ext3_i.i_orphan)) {
+ unlock_super(inode->i_sb);


+ return 0;
+ }
+

+ ino_next = NEXT_ORPHAN(inode);
+ prev = inode->u.ext3_i.i_orphan.prev;
+ sbi = EXT3_SB(inode->i_sb);
+
+ jbd_debug(4, "remove inode %ld from orphan list\n", inode->i_ino);
+
+ list_del(&inode->u.ext3_i.i_orphan);
+ INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
+
+ /* If we're on an error path, we may not have a valid
+ * transaction handle with which to update the orphan list on
+ * disk, but we still need to remove the inode from the linked
+ * list in memory. */
+ if (!handle)
+ goto out;
+
+ err = ext3_reserve_inode_write(handle, inode, &iloc);
+ if (err)
+ goto out_err;
+
+ if (prev == &sbi->s_orphan) {
+ jbd_debug(4, "superblock will point to %ld\n", ino_next);
+ BUFFER_TRACE(sbi->s_sbh, "get_write_access");
+ err = ext3_journal_get_write_access(handle, sbi->s_sbh);


+ if (err)
+ goto out_brelse;

+ sbi->s_es->s_last_orphan = cpu_to_le32(ino_next);
+ err = ext3_journal_dirty_metadata(handle, sbi->s_sbh);
+ } else {
+ struct ext3_iloc iloc2;
+ struct inode *i_prev =
+ list_entry(prev, struct inode, u.ext3_i.i_orphan);
+
+ jbd_debug(4, "orphan inode %ld will point to %ld\n",
+ i_prev->i_ino, ino_next);
+ err = ext3_reserve_inode_write(handle, i_prev, &iloc2);


+ if (err)
+ goto out_brelse;

+ NEXT_ORPHAN(i_prev) = ino_next;
+ err = ext3_mark_iloc_dirty(handle, i_prev, &iloc2);
+ }
+ if (err)
+ goto out_brelse;
+ NEXT_ORPHAN(inode) = 0;
+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);


+ if (err)
+ goto out_brelse;
+

+out_err:
+ ext3_std_error(inode->i_sb, err);
+out:
+ unlock_super(inode->i_sb);
+ return err;
+
+out_brelse:
+ brelse(iloc.bh);


+ goto out_err;
+}
+

+static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
+{
+ int retval;
+ struct inode * inode;


+ struct buffer_head * bh;

+ struct ext3_dir_entry_2 * de;
+ handle_t *handle;
+
+ handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+
+ retval = -ENOENT;
+ bh = ext3_find_entry (dentry, &de);
+ if (!bh)
+ goto end_rmdir;
+
+ if (IS_SYNC(dir))


+ handle->h_sync = 1;
+

+ inode = dentry->d_inode;
+ DQUOT_INIT(inode);
+
+ retval = -EIO;
+ if (le32_to_cpu(de->inode) != inode->i_ino)
+ goto end_rmdir;
+
+ retval = -ENOTEMPTY;
+ if (!empty_dir (inode))
+ goto end_rmdir;
+
+ retval = ext3_delete_entry(handle, dir, de, bh);
+ if (retval)
+ goto end_rmdir;
+ if (inode->i_nlink != 2)
+ ext3_warning (inode->i_sb, "ext3_rmdir",
+ "empty directory has nlink!=2 (%d)",
+ inode->i_nlink);


+ inode->i_version = ++event;

+ inode->i_nlink = 0;
+ /* There's no need to set i_disksize: the fact that i_nlink is
+ * zero will ensure that the right thing happens during any
+ * recovery. */
+ inode->i_size = 0;
+ ext3_orphan_add(handle, inode);
+ ext3_mark_inode_dirty(handle, inode);
+ dir->i_nlink--;
+ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
+ ext3_mark_inode_dirty(handle, dir);
+
+end_rmdir:
+ ext3_journal_stop(handle, dir);
+ brelse (bh);
+ return retval;
+}
+
+static int ext3_unlink(struct inode * dir, struct dentry *dentry)
+{
+ int retval;
+ struct inode * inode;


+ struct buffer_head * bh;

+ struct ext3_dir_entry_2 * de;
+ handle_t *handle;
+
+ handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+
+ if (IS_SYNC(dir))


+ handle->h_sync = 1;
+

+ retval = -ENOENT;
+ bh = ext3_find_entry (dentry, &de);
+ if (!bh)
+ goto end_unlink;
+
+ inode = dentry->d_inode;
+ DQUOT_INIT(inode);
+
+ retval = -EIO;
+ if (le32_to_cpu(de->inode) != inode->i_ino)
+ goto end_unlink;
+
+ if (!inode->i_nlink) {
+ ext3_warning (inode->i_sb, "ext3_unlink",
+ "Deleting nonexistent file (%lu), %d",
+ inode->i_ino, inode->i_nlink);
+ inode->i_nlink = 1;
+ }
+ retval = ext3_delete_entry(handle, dir, de, bh);
+ if (retval)
+ goto end_unlink;
+ dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
+ ext3_mark_inode_dirty(handle, dir);
+ inode->i_nlink--;
+ if (!inode->i_nlink)
+ ext3_orphan_add(handle, inode);
+ ext3_mark_inode_dirty(handle, inode);
+ inode->i_ctime = dir->i_ctime;


+ retval = 0;
+

+end_unlink:
+ ext3_journal_stop(handle, dir);
+ brelse (bh);
+ return retval;
+}
+
+static int ext3_symlink (struct inode * dir,
+ struct dentry *dentry, const char * symname)
+{
+ handle_t *handle;
+ struct inode * inode;
+ int l, err;
+
+ l = strlen(symname)+1;
+ if (l > dir->i_sb->s_blocksize)
+ return -ENAMETOOLONG;
+
+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 5);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+
+ if (IS_SYNC(dir))


+ handle->h_sync = 1;
+

+ inode = ext3_new_inode (handle, dir, S_IFLNK|S_IRWXUGO);
+ err = PTR_ERR(inode);
+ if (IS_ERR(inode))
+ goto out_stop;
+
+ if (l > sizeof (inode->u.ext3_i.i_data)) {


+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_mapping->a_ops = &ext3_aops;

+ /*
+ * block_symlink() calls back into ext3_prepare/commit_write.
+ * We have a transaction open. All is sweetness. It also sets
+ * i_size in generic_commit_write().
+ */
+ err = block_symlink(inode, symname, l);
+ if (err)
+ goto out_no_entry;
+ } else {
+ inode->i_op = &ext3_fast_symlink_inode_operations;
+ memcpy((char*)&inode->u.ext3_i.i_data,symname,l);
+ inode->i_size = l-1;


+ }
+ inode->u.ext3_i.i_disksize = inode->i_size;

+ ext3_mark_inode_dirty(handle, inode);
+ err = ext3_add_nondir(handle, dentry, inode);
+out_stop:
+ ext3_journal_stop(handle, dir);
+ return err;
+
+out_no_entry:
+ ext3_dec_count(handle, inode);
+ ext3_mark_inode_dirty(handle, inode);
+ iput (inode);


+ goto out_stop;
+}
+

+static int ext3_link (struct dentry * old_dentry,
+ struct inode * dir, struct dentry *dentry)
+{
+ handle_t *handle;
+ struct inode *inode = old_dentry->d_inode;
+ int err;
+
+ if (S_ISDIR(inode->i_mode))
+ return -EPERM;
+
+ if (inode->i_nlink >= EXT3_LINK_MAX)
+ return -EMLINK;
+
+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+
+ if (IS_SYNC(dir))


+ handle->h_sync = 1;
+

+ inode->i_ctime = CURRENT_TIME;

+ ext3_inc_count(handle, inode);
+ atomic_inc(&inode->i_count);
+
+ ext3_mark_inode_dirty(handle, inode);
+ err = ext3_add_nondir(handle, dentry, inode);
+ ext3_journal_stop(handle, dir);


+ return err;
+}
+

+#define PARENT_INO(buffer) \
+ ((struct ext3_dir_entry_2 *) ((char *) buffer + \
+ le16_to_cpu(((struct ext3_dir_entry_2 *) buffer)->rec_len)))->inode
+
+/*
+ * Anybody can rename anything with this: the permission checks are left to the
+ * higher-level routines.
+ */
+static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
+ struct inode * new_dir,struct dentry *new_dentry)
+{
+ handle_t *handle;
+ struct inode * old_inode, * new_inode;
+ struct buffer_head * old_bh, * new_bh, * dir_bh;
+ struct ext3_dir_entry_2 * old_de, * new_de;
+ int retval;
+
+ old_bh = new_bh = dir_bh = NULL;
+
+ handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+
+ if (IS_SYNC(old_dir) || IS_SYNC(new_dir))


+ handle->h_sync = 1;
+

+ old_bh = ext3_find_entry (old_dentry, &old_de);
+ /*
+ * Check for inode number is _not_ due to possible IO errors.
+ * We might rmdir the source, keep it as pwd of some process
+ * and merrily kill the link to whatever was created under the
+ * same name. Goodbye sticky bit ;-<
+ */
+ old_inode = old_dentry->d_inode;
+ retval = -ENOENT;
+ if (!old_bh || le32_to_cpu(old_de->inode) != old_inode->i_ino)
+ goto end_rename;
+
+ new_inode = new_dentry->d_inode;
+ new_bh = ext3_find_entry (new_dentry, &new_de);
+ if (new_bh) {
+ if (!new_inode) {
+ brelse (new_bh);
+ new_bh = NULL;
+ } else {
+ DQUOT_INIT(new_inode);
+ }
+ }
+ if (S_ISDIR(old_inode->i_mode)) {
+ if (new_inode) {
+ retval = -ENOTEMPTY;
+ if (!empty_dir (new_inode))
+ goto end_rename;
+ }
+ retval = -EIO;
+ dir_bh = ext3_bread (handle, old_inode, 0, 0, &retval);
+ if (!dir_bh)
+ goto end_rename;
+ if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
+ goto end_rename;
+ retval = -EMLINK;
+ if (!new_inode && new_dir!=old_dir &&
+ new_dir->i_nlink >= EXT3_LINK_MAX)
+ goto end_rename;
+ }
+ if (!new_bh) {
+ retval = ext3_add_entry (handle, new_dentry, old_inode);
+ if (retval)
+ goto end_rename;
+ } else {
+ BUFFER_TRACE(new_bh, "get write access");
+ BUFFER_TRACE(new_bh, "get_write_access");
+ ext3_journal_get_write_access(handle, new_bh);
+ new_de->inode = le32_to_cpu(old_inode->i_ino);
+ if (EXT3_HAS_INCOMPAT_FEATURE(new_dir->i_sb,
+ EXT3_FEATURE_INCOMPAT_FILETYPE))
+ new_de->file_type = old_de->file_type;
+ new_dir->i_version = ++event;
+ BUFFER_TRACE(new_bh, "call ext3_journal_dirty_metadata");
+ ext3_journal_dirty_metadata(handle, new_bh);
+ brelse(new_bh);
+ new_bh = NULL;
+ }
+
+ /*
+ * Like most other Unix systems, set the ctime for inodes on a
+ * rename.
+ */
+ old_inode->i_ctime = CURRENT_TIME;
+ ext3_mark_inode_dirty(handle, old_inode);
+
+ /*
+ * ok, that's it
+ */
+ ext3_delete_entry(handle, old_dir, old_de, old_bh);
+
+ if (new_inode) {
+ new_inode->i_nlink--;
+ new_inode->i_ctime = CURRENT_TIME;
+ }
+ old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+ old_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
+ if (dir_bh) {
+ BUFFER_TRACE(dir_bh, "get_write_access");
+ ext3_journal_get_write_access(handle, dir_bh);
+ PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
+ BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata");
+ ext3_journal_dirty_metadata(handle, dir_bh);
+ old_dir->i_nlink--;
+ if (new_inode) {
+ new_inode->i_nlink--;
+ } else {
+ new_dir->i_nlink++;
+ new_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
+ ext3_mark_inode_dirty(handle, new_dir);
+ }
+ }
+ ext3_mark_inode_dirty(handle, old_dir);
+ if (new_inode) {
+ ext3_mark_inode_dirty(handle, new_inode);
+ if (!new_inode->i_nlink)
+ ext3_orphan_add(handle, new_inode);
+ }


+ retval = 0;
+

+end_rename:
+ brelse (dir_bh);
+ brelse (old_bh);
+ brelse (new_bh);
+ ext3_journal_stop(handle, old_dir);
+ return retval;
+}
+
+/*
+ * directories can handle most operations...
+ */
+struct inode_operations ext3_dir_inode_operations = {
+ create: ext3_create, /* BKL held */
+ lookup: ext3_lookup, /* BKL held */
+ link: ext3_link, /* BKL held */
+ unlink: ext3_unlink, /* BKL held */
+ symlink: ext3_symlink, /* BKL held */
+ mkdir: ext3_mkdir, /* BKL held */
+ rmdir: ext3_rmdir, /* BKL held */
+ mknod: ext3_mknod, /* BKL held */
+ rename: ext3_rename, /* BKL held */
+};
diff -u --recursive --new-file v2.4.14/linux/fs/ext3/super.c linux/fs/ext3/super.c
--- v2.4.14/linux/fs/ext3/super.c Wed Dec 31 16:00:00 1969
+++ linux/fs/ext3/super.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,1745 @@
+/*
+ * linux/fs/ext3/super.c


+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (ca...@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *

+ * from
+ *
+ * linux/fs/minix/inode.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *


+ * Big-endian to little-endian byte-swapping/bitmaps by
+ * David S. Miller (da...@caip.rutgers.edu), 1995
+ */
+
+#include <linux/config.h>

+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/sched.h>


+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/ext3_jbd.h>

+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/locks.h>
+#include <linux/blkdev.h>
+#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_JBD_DEBUG
+static int ext3_ro_after; /* Make fs read-only after this many jiffies */
+#endif
+
+static int ext3_load_journal(struct super_block *, struct ext3_super_block *);
+static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
+ int);
+static void ext3_commit_super (struct super_block * sb,
+ struct ext3_super_block * es,
+ int sync);
+static void ext3_mark_recovery_complete(struct super_block * sb,
+ struct ext3_super_block * es);
+static void ext3_clear_journal_err(struct super_block * sb,
+ struct ext3_super_block * es);
+
+#ifdef CONFIG_JBD_DEBUG
+int journal_no_write[2];
+
+/*
+ * Debug code for turning filesystems "read-only" after a specified
+ * amount of time. This is for crash/recovery testing.
+ */
+
+static void make_rdonly(kdev_t dev, int *no_write)
+{
+ if (dev) {
+ printk(KERN_WARNING "Turning device %s read-only\n",
+ bdevname(dev));
+ *no_write = 0xdead0000 + dev;
+ }
+}
+
+static void turn_fs_readonly(unsigned long arg)
+{
+ struct super_block *sb = (struct super_block *)arg;
+
+ make_rdonly(sb->s_dev, &journal_no_write[0]);
+ make_rdonly(EXT3_SB(sb)->s_journal->j_dev, &journal_no_write[1]);
+ wake_up(&EXT3_SB(sb)->ro_wait_queue);
+}
+
+static void setup_ro_after(struct super_block *sb)
+{
+ struct ext3_sb_info *sbi = EXT3_SB(sb);
+ init_timer(&sbi->turn_ro_timer);
+ if (ext3_ro_after) {
+ printk(KERN_DEBUG "fs will go read-only in %d jiffies\n",
+ ext3_ro_after);
+ init_waitqueue_head(&sbi->ro_wait_queue);
+ journal_no_write[0] = 0;
+ journal_no_write[1] = 0;
+ sbi->turn_ro_timer.function = turn_fs_readonly;
+ sbi->turn_ro_timer.data = (unsigned long)sb;
+ sbi->turn_ro_timer.expires = jiffies + ext3_ro_after;
+ ext3_ro_after = 0;
+ add_timer(&sbi->turn_ro_timer);
+ }
+}
+
+static void clear_ro_after(struct super_block *sb)
+{
+ del_timer_sync(&EXT3_SB(sb)->turn_ro_timer);
+ journal_no_write[0] = 0;
+ journal_no_write[1] = 0;
+ ext3_ro_after = 0;
+}
+#else
+#define setup_ro_after(sb) do {} while (0)
+#define clear_ro_after(sb) do {} while (0)
+#endif
+
+
+static char error_buf[1024];
+
+/* Determine the appropriate response to ext3_error on a given filesystem */
+
+static int ext3_error_behaviour(struct super_block *sb)
+{
+ /* First check for mount-time options */
+ if (test_opt (sb, ERRORS_PANIC))
+ return EXT3_ERRORS_PANIC;
+ if (test_opt (sb, ERRORS_RO))
+ return EXT3_ERRORS_RO;
+ if (test_opt (sb, ERRORS_CONT))
+ return EXT3_ERRORS_CONTINUE;
+
+ /* If no overrides were specified on the mount, then fall back
+ * to the default behaviour set in the filesystem's superblock
+ * on disk. */
+ switch (le16_to_cpu(sb->u.ext3_sb.s_es->s_errors)) {
+ case EXT3_ERRORS_PANIC:
+ return EXT3_ERRORS_PANIC;
+ case EXT3_ERRORS_RO:
+ return EXT3_ERRORS_RO;


+ default:
+ break;
+ }

+ return EXT3_ERRORS_CONTINUE;
+}
+
+/* Deal with the reporting of failure conditions on a filesystem such as
+ * inconsistencies detected or read IO failures.
+ *
+ * On ext2, we can store the error state of the filesystem in the
+ * superblock. That is not possible on ext3, because we may have other
+ * write ordering constraints on the superblock which prevent us from
+ * writing it out straight away; and given that the journal is about to
+ * be aborted, we can't rely on the current, or future, transactions to
+ * write out the superblock safely.
+ *
+ * We'll just use the journal_abort() error code to record an error in
+ * the journal instead. On recovery, the journal will compain about
+ * that error until we've noted it down and cleared it.
+ */
+
+static void ext3_handle_error(struct super_block *sb)
+{
+ struct ext3_super_block *es = EXT3_SB(sb)->s_es;
+
+ EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
+ es->s_state |= cpu_to_le32(EXT3_ERROR_FS);
+


+ if (sb->s_flags & MS_RDONLY)

+ return;
+
+ if (ext3_error_behaviour(sb) != EXT3_ERRORS_CONTINUE) {
+ EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
+ journal_abort(EXT3_SB(sb)->s_journal, -EIO);
+ }
+
+ if (ext3_error_behaviour(sb) == EXT3_ERRORS_PANIC)
+ panic ("EXT3-fs (device %s): panic forced after error\n",
+ bdevname(sb->s_dev));
+
+ if (ext3_error_behaviour(sb) == EXT3_ERRORS_RO) {
+ printk (KERN_CRIT "Remounting filesystem read-only\n");
+ sb->s_flags |= MS_RDONLY;
+ }
+
+ ext3_commit_super(sb, es, 1);
+}
+
+void ext3_error (struct super_block * sb, const char * function,
+ const char * fmt, ...)


+{
+ va_list args;
+

+ va_start (args, fmt);
+ vsprintf (error_buf, fmt, args);
+ va_end (args);
+
+ printk (KERN_CRIT "EXT3-fs error (device %s): %s: %s\n",
+ bdevname(sb->s_dev), function, error_buf);
+
+ ext3_handle_error(sb);
+}
+
+const char *ext3_decode_error(struct super_block * sb, int errno, char nbuf[16])
+{
+ char *errstr = NULL;
+
+ switch (errno) {
+ case -EIO:
+ errstr = "IO failure";
+ break;
+ case -ENOMEM:
+ errstr = "Out of memory";
+ break;
+ case -EROFS:
+ if (!sb || EXT3_SB(sb)->s_journal->j_flags & JFS_ABORT)
+ errstr = "Journal has aborted";
+ else
+ errstr = "Readonly filesystem";
+ break;
+ default:
+ /* If the caller passed in an extra buffer for unknown
+ * errors, textualise them now. Else we just return
+ * NULL. */
+ if (nbuf) {
+ /* Check for truncated error codes... */
+ if (snprintf(nbuf, 16, "error %d", -errno) >= 0)
+ errstr = nbuf;
+ }
+
+ break;
+ }
+
+ return errstr;
+}
+
+/* __ext3_std_error decodes expected errors from journaling functions
+ * automatically and invokes the appropriate error response. */
+
+void __ext3_std_error (struct super_block * sb, const char * function,
+ int errno)
+{
+ char nbuf[16];
+ const char *errstr = ext3_decode_error(sb, errno, nbuf);
+
+ printk (KERN_CRIT "EXT3-fs error (device %s) in %s: %s\n",
+ bdevname(sb->s_dev), function, errstr);
+
+ ext3_handle_error(sb);
+}
+
+/*
+ * ext3_abort is a much stronger failure handler than ext3_error. The
+ * abort function may be used to deal with unrecoverable failures such
+ * as journal IO errors or ENOMEM at a critical moment in log management.
+ *
+ * We unconditionally force the filesystem into an ABORT|READONLY state,
+ * unless the error response on the fs has been set to panic in which
+ * case we take the easy way out and panic immediately.
+ */
+
+void ext3_abort (struct super_block * sb, const char * function,
+ const char * fmt, ...)


+{
+ va_list args;
+

+ printk (KERN_CRIT "ext3_abort called.\n");
+
+ va_start (args, fmt);
+ vsprintf (error_buf, fmt, args);
+ va_end (args);
+
+ if (ext3_error_behaviour(sb) == EXT3_ERRORS_PANIC)
+ panic ("EXT3-fs panic (device %s): %s: %s\n",
+ bdevname(sb->s_dev), function, error_buf);
+
+ printk (KERN_CRIT "EXT3-fs abort (device %s): %s: %s\n",
+ bdevname(sb->s_dev), function, error_buf);
+


+ if (sb->s_flags & MS_RDONLY)

+ return;
+
+ printk (KERN_CRIT "Remounting filesystem read-only\n");
+ sb->u.ext3_sb.s_mount_state |= EXT3_ERROR_FS;
+ sb->s_flags |= MS_RDONLY;
+ sb->u.ext3_sb.s_mount_opt |= EXT3_MOUNT_ABORT;
+ journal_abort(EXT3_SB(sb)->s_journal, -EIO);
+}
+
+/* Deal with the reporting of failure conditions while running, such as
+ * inconsistencies in operation or invalid system states.
+ *
+ * Use ext3_error() for cases of invalid filesystem states, as that will
+ * record an error on disk and force a filesystem check on the next boot.
+ */
+NORET_TYPE void ext3_panic (struct super_block * sb, const char * function,
+ const char * fmt, ...)


+{
+ va_list args;
+

+ va_start (args, fmt);
+ vsprintf (error_buf, fmt, args);
+ va_end (args);
+
+ /* this is to prevent panic from syncing this filesystem */
+ /* AKPM: is this sufficient? */
+ sb->s_flags |= MS_RDONLY;
+ panic ("EXT3-fs panic (device %s): %s: %s\n",
+ bdevname(sb->s_dev), function, error_buf);
+}
+
+void ext3_warning (struct super_block * sb, const char * function,
+ const char * fmt, ...)


+{
+ va_list args;
+

+ va_start (args, fmt);
+ vsprintf (error_buf, fmt, args);
+ va_end (args);
+ printk (KERN_WARNING "EXT3-fs warning (device %s): %s: %s\n",
+ bdevname(sb->s_dev), function, error_buf);
+}
+
+void ext3_update_dynamic_rev(struct super_block *sb)
+{
+ struct ext3_super_block *es = EXT3_SB(sb)->s_es;
+
+ if (le32_to_cpu(es->s_rev_level) > EXT3_GOOD_OLD_REV)
+ return;
+
+ ext3_warning(sb, __FUNCTION__,
+ "updating to rev %d because of new feature flag, "
+ "running e2fsck is recommended",
+ EXT3_DYNAMIC_REV);
+
+ es->s_first_ino = cpu_to_le32(EXT3_GOOD_OLD_FIRST_INO);
+ es->s_inode_size = cpu_to_le16(EXT3_GOOD_OLD_INODE_SIZE);
+ es->s_rev_level = cpu_to_le32(EXT3_DYNAMIC_REV);
+ /* leave es->s_feature_*compat flags alone */
+ /* es->s_uuid will be set by e2fsck if empty */
+
+ /*
+ * The rest of the superblock fields should be zero, and if not it
+ * means they are likely already in use, so leave them alone. We
+ * can leave it up to e2fsck to clean up any inconsistencies there.
+ */
+}
+
+/*
+ * Open the external journal device
+ */
+static struct block_device *ext3_blkdev_get(kdev_t dev)
+{
+ struct block_device *bdev;
+ int err = -ENODEV;
+
+ bdev = bdget(kdev_t_to_nr(dev));
+ if (bdev == NULL)
+ goto fail;
+ err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_FS);
+ if (err < 0)
+ goto fail;
+ return bdev;
+
+fail:
+ printk(KERN_ERR "EXT3: failed to open journal device %s: %d\n",
+ bdevname(dev), err);


+ return NULL;
+}
+

+/*
+ * Release the journal device
+ */
+static int ext3_blkdev_put(struct block_device *bdev)
+{
+ return blkdev_put(bdev, BDEV_FS);
+}
+
+static int ext3_blkdev_remove(struct ext3_sb_info *sbi)
+{
+ struct block_device *bdev;
+ int ret = -ENODEV;
+
+ bdev = sbi->journal_bdev;
+ if (bdev) {
+ ret = ext3_blkdev_put(bdev);
+ sbi->journal_bdev = 0;


+ }
+ return ret;
+}
+

+#define orphan_list_entry(l) list_entry((l), struct inode, u.ext3_i.i_orphan)
+
+static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi)
+{
+ struct list_head *l;
+
+ printk(KERN_ERR "sb orphan head is %d\n",
+ le32_to_cpu(sbi->s_es->s_last_orphan));
+
+ printk(KERN_ERR "sb_info orphan list:\n");
+ list_for_each(l, &sbi->s_orphan) {
+ struct inode *inode = orphan_list_entry(l);
+ printk(KERN_ERR " "
+ "inode 0x%04x:%ld at %p: mode %o, nlink %d, next %d\n",
+ inode->i_dev, inode->i_ino, inode,
+ inode->i_mode, inode->i_nlink,
+ le32_to_cpu(NEXT_ORPHAN(inode)));
+ }
+}
+
+void ext3_put_super (struct super_block * sb)
+{
+ struct ext3_sb_info *sbi = EXT3_SB(sb);
+ struct ext3_super_block *es = sbi->s_es;
+ kdev_t j_dev = sbi->s_journal->j_dev;
+ int i;
+
+ journal_destroy(sbi->s_journal);
+ if (!(sb->s_flags & MS_RDONLY)) {
+ EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
+ es->s_state = le16_to_cpu(sbi->s_mount_state);
+ BUFFER_TRACE(sbi->s_sbh, "marking dirty");
+ mark_buffer_dirty(sbi->s_sbh);
+ ext3_commit_super(sb, es, 1);
+ }
+
+ for (i = 0; i < sbi->s_gdb_count; i++)
+ brelse(sbi->s_group_desc[i]);
+ kfree(sbi->s_group_desc);
+ for (i = 0; i < EXT3_MAX_GROUP_LOADED; i++)
+ brelse(sbi->s_inode_bitmap[i]);
+ for (i = 0; i < EXT3_MAX_GROUP_LOADED; i++)
+ brelse(sbi->s_block_bitmap[i]);
+ brelse(sbi->s_sbh);
+
+ /* Debugging code just in case the in-memory inode orphan list
+ * isn't empty. The on-disk one can be non-empty if we've
+ * detected an error and taken the fs readonly, but the
+ * in-memory list had better be clean by this point. */
+ if (!list_empty(&sbi->s_orphan))
+ dump_orphan_list(sb, sbi);
+ J_ASSERT(list_empty(&sbi->s_orphan));
+
+ invalidate_buffers(sb->s_dev);
+ if (j_dev != sb->s_dev) {
+ /*
+ * Invalidate the journal device's buffers. We don't want them
+ * floating about in memory - the physical journal device may
+ * hotswapped, and it breaks the `ro-after' testing code.
+ */
+ fsync_no_super(j_dev);
+ invalidate_buffers(j_dev);
+ ext3_blkdev_remove(sbi);
+ }
+ clear_ro_after(sb);


+
+ return;
+}
+

+static struct super_operations ext3_sops = {
+ read_inode: ext3_read_inode, /* BKL held */
+ write_inode: ext3_write_inode, /* BKL not held. Don't need */
+ dirty_inode: ext3_dirty_inode, /* BKL not held. We take it */
+ put_inode: ext3_put_inode, /* BKL not held. Don't need */
+ delete_inode: ext3_delete_inode, /* BKL not held. We take it */
+ put_super: ext3_put_super, /* BKL held */
+ write_super: ext3_write_super, /* BKL held */
+ write_super_lockfs: ext3_write_super_lockfs, /* BKL not held. Take it */
+ unlockfs: ext3_unlockfs, /* BKL not held. We take it */
+ statfs: ext3_statfs, /* BKL held */
+ remount_fs: ext3_remount, /* BKL held */
+};
+
+static int want_value(char *value, char *option)
+{
+ if (!value || !*value) {
+ printk(KERN_NOTICE "EXT3-fs: the %s option needs an argument\n",
+ option);
+ return -1;


+ }
+ return 0;
+}
+

+static int want_null_value(char *value, char *option)


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

echo 'End of part 089'
echo 'File patch-2.4.15 is continued in part 090'
echo "090" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:59 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part083

#!/bin/sh -x
# this is part 083 of a 115 - part archive


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

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

- 0x088,0x000,0x045,0x000,0x000,0x0E8,0x000,0x002,
- 0x00D,0x000,0x068,0x0B0,0x00B,
- 0x092,0x08F,0x040,0x060,0x080,0x014,0x090,0x08C,
- 0x060,0x014,0x063,0x000,0x040,
- 0x0003E,0x002E1,0x00028};//Ajust xxx
-
-USHORT HiTVTiming[61]={0x017,0x01D,0x003,0x009,0x005,0x006,0x00C,0x00C,


- 0x094,0x049,0x001,0x00A,0x006,0x00D,0x004,0x00A,
- 0x006,0x014,0x00D,0x004,0x00A,0x000,0x085,0x01B,
- 0x00C,0x050,0x000,0x099,0x000,0x0EC,0x04A,0x017,
- 0x088,0x000,0x04B,0x000,0x000,0x0E2,0x000,0x002,
- 0x003,0x00A,0x065,0x09D,0x008,
- 0x092,0x08F,0x040,0x060,0x080,0x014,0x090,0x08C,
- 0x060,0x014,0x050,0x000,0x040,

- 0x00027,0x0FFFC,0x0003B};//Ajust xxx
-
-USHORT HiTVTimingSimu[61]={0x020,0x054,0x02C,0x060,0x008,0x031,0x03A,0x061,
- 0x028,0x002,0x001,0x03D,0x006,0x00D,0x004,0x00A,
- 0x006,0x014,0x00D,0x004,0x00A,0x000,0x0C5,0x03F,
- 0x064,0x090,0x000,0x0AA,0x000,0x006,0x060,0x003,
- 0x011,0x005,0x011,0x00F,0x010,0x011,0x000,0x000,
- 0x005,0x005,0x034,0x034,0x008,
- 0x092,0x00F,0x040,0x060,0x080,0x014,0x090,0x08C,
- 0x060,0x004,0x05F,0x000,0x060,
- 0x0000E,0x0FFFC,0x00042};//Ajust xxx
-
-USHORT HiTVGroup3Data[63]={0x000,0x01A,0x022,0x063,0x062,0x022,0x008,0x05B,
- 0x0FF,0x021,0x0AD,0x0AD,0x055,0x077,0x02A,0x0A6,
- 0x025,0x02F,0x047,0x0FA,0x0C8,0x0FF,0x08E,0x020,
- 0x08C,0x06E,0x060,0x02D,0x056,0x047,0x070,0x044,
- 0x056,0x036,0x04F,0x06E,0x03F,0x080,0x000,0x080,
- 0x045,0x07D,0x003,0x0A5,0x076,0x020,0x01A,0x0A4,
- 0x014,0x005,0x003,0x07E,0x064,0x031,0x014,0x075,
- 0x018,0x005,0x018,0x005,0x04C,0x0A8,0x001};
-
-USHORT HiTVGroup3Simu[63]={0x000,0x01A,0x022,0x063,0x062,0x022,0x008,0x094,
- 0x0DA,0x020,0x0B7,0x0B7,0x055,0x047,0x02A,0x0A6,
- 0x025,0x02F,0x047,0x0FA,0x0C8,0x0FF,0x08E,0x020,
- 0x08C,0x06E,0x060,0x015,0x026,0x0D3,0x0E4,0x011,
- 0x056,0x036,0x04F,0x06E,0x03F,0x080,0x000,0x080,
- 0x066,0x035,0x001,0x047,0x00E,0x010,0x0BE,0x0B4,
- 0x001,0x005,0x003,0x07E,0x065,0x031,0x014,0x075,
- 0x018,0x005,0x018,0x005,0x04C,0x0A8,0x001};
-
-USHORT NTSCGroup3Data[63]= {0x000,0x014,0x015,0x025,0x055,0x015,0x00B,0x089,
- 0x0D7,0x040,0x0B0,0x0B0,0x0FF,0x0C4,0x045,0x0A6,
- 0x025,0x02F,0x067,0x0F6,0x0BF,0x0FF,0x08E,0x020,
- 0x08C,0x0DA,0x060,0x092,0x0C8,0x055,0x08B,0x000,
- 0x051,0x004,0x018,0x00A,0x0F8,0x087,0x000,0x080,
- 0x03B,0x03B,0x000,0x0F0,0x0F0,0x000,0x0F0,0x0F0,
- 0x000,0x051,0x00F,0x00F,0x008,0x00F,0x008,0x06F,
- 0x018,0x005,0x005,0x005,0x04C,0x0AA,0x001};
-
-USHORT PALGroup3Data[63]={0x000,0x01A,0x022,0x063,0x062,0x022,0x008,0x085,
- 0x0C3,0x020,0x0A4,0x0A4,0x055,0x047,0x02A,0x0A6,
- 0x025,0x02F,0x047,0x0FA,0x0C8,0x0FF,0x08E,0x020,
- 0x08C,0x0DC,0x060,0x092,0x0C8,0x04F,0x085,0x000,
- 0x056,0x036,0x04F,0x06E,0x0FE,0x083,0x054,0x081,
- 0x030,0x030,0x000,0x0F3,0x0F3,0x000,0x0A2,0x0A2,
- 0x000,0x048,0x0FE,0x07E,0x008,0x040,0x008,0x091,
- 0x018,0x005,0x018,0x005,0x04C,0x0A8,0x001};
-
-VOID overwriteregs(ULONG ROMAddr, USHORT BaseAddr);
-VOID SetDefCRT2ExtRegs(USHORT BaseAddr);
-BOOLEAN SetCRT2Group(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo,
- PHW_DEVICE_EXTENSION HwDeviceExtension);
-USHORT GetRatePtrCRT2(ULONG ROMAddr, USHORT ModeNo);
-BOOLEAN AjustCRT2Rate(ULONG ROMAddr);
-VOID SaveCRT2Info(USHORT ModeNo);
-VOID DisableLockRegs(VOID);
-VOID DisableCRT2(VOID);
-VOID DisableBridge(USHORT BaseAddr);
-VOID GetCRT2Data(ULONG ROMAddr,USHORT ModeNo);
-VOID GetResInfo(ULONG ROMAddr,USHORT ModeNo);
-VOID GetRAMDAC2DATA(ULONG ROMAddr,USHORT ModeNo);
-VOID GetCRT2Ptr(ULONG ROMAddr,USHORT ModeNo);
-VOID UnLockCRT2(USHORT BaseAddr);
-VOID SetCRT2ModeRegs(USHORT BaseAddr,USHORT ModeNo);


-VOID SetGroup1(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo,

- PHW_DEVICE_EXTENSION HwDeviceExtension);
-VOID SetCRT2Offset(USHORT Part1Port,ULONG ROMAddr);
-USHORT GetOffset(ULONG ROMAddr);
-USHORT GetColorDepth(ULONG ROMAddr);


-VOID SetCRT2FIFO(USHORT Part1Port,ULONG ROMAddr,USHORT ModeNo,

- PHW_DEVICE_EXTENSION HwDeviceExtension);
-USHORT GetVCLK(ULONG ROMAddr,USHORT ModeNo,
- PHW_DEVICE_EXTENSION HwDeviceExtension);
-USHORT GetVCLKPtr(ULONG ROMAddr,USHORT ModeNo);
-USHORT GetColorTh(ULONG ROMAddr);
-USHORT GetMCLK(ULONG ROMAddr);
-USHORT GetMCLKPtr(ULONG ROMAddr);
-USHORT GetDRAMType(ULONG ROMAddr);
-#ifndef CONFIG_FB_SIS_LINUXBIOS
-static USHORT CalcDelay(VOID);
-#endif
-USHORT GetVCLK2Ptr(ULONG ROMAddr,USHORT ModeNo);
-VOID SetCRT2Sync(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo);
-VOID GetCRT1Ptr(ULONG ROMAddr);
-VOID SetRegANDOR(USHORT Port,USHORT Index,USHORT DataAND,USHORT DataOR);
-USHORT GetVGAHT2(VOID);
-VOID SetGroup2(USHORT BaseAddr,ULONG ROMAddr);
-VOID SetGroup3(USHORT BaseAddr);
-VOID SetGroup4(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo);
-VOID SetCRT2VCLK(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo);
-VOID SetGroup5(USHORT BaseAddr,ULONG ROMAddr);
-VOID EnableCRT2(VOID);
-VOID LoadDAC2(ULONG ROMAddr,USHORT Part5Port);
-VOID WriteDAC2(USHORT Pdata,USHORT dl, USHORT ah, USHORT al, USHORT dh);
-VOID LockCRT2(USHORT BaseAddr);
-VOID SetLockRegs(VOID);
-VOID EnableBridge(USHORT BaseAddr);
-USHORT GetLockInfo(USHORT pattern);
-VOID GetVBInfo(USHORT BaseAddr,ULONG ROMAddr);
-BOOLEAN BridgeIsEnable(USHORT BaseAddr);
-BOOLEAN BridgeInSlave(VOID);
-BOOLEAN GetLCDResInfo(ULONG ROMAddr,USHORT P3d4);
-VOID PresetScratchregister(USHORT P3d4,PHW_DEVICE_EXTENSION HwDeviceExtension);
-BOOLEAN GetLCDDDCInfo(PHW_DEVICE_EXTENSION HwDeviceExtension);
-VOID SetTVSystem(PHW_DEVICE_EXTENSION HwDeviceExtension,ULONG ROMAddr);
-BOOLEAN GetSenseStatus(PHW_DEVICE_EXTENSION HwDeviceExtension,USHORT BaseAddr,ULONG ROMAddr);
-BOOLEAN Sense(USHORT Part4Port,USHORT inputbx,USHORT inputcx);
-BOOLEAN SenseLCD(PHW_DEVICE_EXTENSION HwDeviceExtension,USHORT Part4Port,ULONG ROMAddr);
-BOOLEAN TestMonitorType(USHORT d1,USHORT d2,USHORT d3);
-VOID WaitDisplay(VOID);
-BOOLEAN DetectMonitor(PHW_DEVICE_EXTENSION HwDeviceExtension);
-VOID LongWait(VOID);
-//VOID ClearALLBuffer(PHW_DEVICE_EXTENSION HwDeviceExtension);
-USHORT GetQueueConfig(VOID);
-VOID VBLongWait(VOID);
-USHORT GetVCLKLen(ULONG ROMAddr);
-BOOLEAN WaitVBRetrace(USHORT BaseAddr);
-VOID GetLVDSDesData(ULONG ROMAddr,USHORT ModeNo);
-VOID ModCRT1CRTC(ULONG ROMAddr,USHORT ModeNo);
-VOID SetCRT2ECLK(ULONG ROMAddr, USHORT ModeNo);
-VOID GetCRT2Data301(ULONG ROMAddr,USHORT ModeNo);
-VOID GetCRT2DataLVDS(ULONG ROMAddr,USHORT ModeNo);
-USHORT GetLVDSDesPtr(ULONG ROMAddr,USHORT ModeNo);


-VOID SetGroup1_301(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo,

- PHW_DEVICE_EXTENSION HwDeviceExtension);


-VOID SetGroup1_LVDS(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo,

- PHW_DEVICE_EXTENSION HwDeviceExtension);
-VOID SetTPData(VOID);
-BOOLEAN GetPanelID(VOID);


-BOOLEAN GetLVDSCRT1Ptr(ULONG ROMAddr,USHORT ModeNo);
-

-extern USHORT DRAMType[17][5];
-extern USHORT MDA_DAC[];
-extern USHORT CGA_DAC[];
-extern USHORT EGA_DAC[];
-extern USHORT VGA_DAC[];
-
-extern USHORT P3c4,P3d4,P3c0,P3ce,P3c2,P3ca,P3c6,P3c7,P3c8,P3c9,P3da;
-extern USHORT flag_clearbuffer; //0:no clear frame buffer 1:clear frame buffer
-extern int RAMType;
-extern int ModeIDOffset,StandTable,CRT1Table,ScreenOffset,VCLKData,MCLKData, ECLKData;
-extern int REFIndex,ModeType;
-extern USHORT VBInfo,LCDResInfo,LCDTypeInfo,LCDInfo;
-extern USHORT IF_DEF_LVDS,IF_DEF_TRUMPION;
-
-extern VOID SetMemoryClock(ULONG);
-extern VOID SetDRAMSize(PHW_DEVICE_EXTENSION);
-extern BOOLEAN SearchModeID(ULONG, USHORT);
-extern BOOLEAN CheckMemorySize(ULONG);
-extern VOID GetModePtr(ULONG, USHORT);
-extern BOOLEAN GetRatePtr(ULONG, USHORT);
-extern VOID SetSeqRegs(ULONG);
-extern VOID SetMiscRegs(ULONG);
-extern VOID SetCRTCRegs(ULONG);
-extern VOID SetATTRegs(ULONG);
-extern VOID SetGRCRegs(ULONG);
-extern VOID ClearExt1Regs(VOID);
-extern VOID SetSync(ULONG);
-extern VOID SetCRT1CRTC(ULONG);
-extern VOID SetCRT1Offset(ULONG);
-extern VOID SetCRT1FIFO(ULONG);
-extern VOID SetCRT1VCLK(ULONG);
-extern VOID LoadDAC(ULONG);
-extern VOID DisplayOn(VOID);
-extern VOID SetCRT1ModeRegs(ULONG, USHORT);
-extern VOID SetVCLKState(ULONG, USHORT);
-extern VOID WriteDAC(USHORT, USHORT, USHORT, USHORT);
-extern VOID ClearBuffer(PHW_DEVICE_EXTENSION);
-//extern VOID ClearDAC(ULONG);
-extern void ClearDAC(u16 port);
-extern BOOLEAN SiSSetMode(PHW_DEVICE_EXTENSION HwDeviceExtension,
- USHORT ModeNo);


-extern void SetReg1(u16 port, u16 index, u16 data);
-extern void SetReg3(u16 port, u16 data);
-extern void SetReg4(u16 port, unsigned long data);
-extern u8 GetReg1(u16 port, u16 index);
-extern u8 GetReg2(u16 port);
-extern u32 GetReg3(u16 port);

diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/sis_main.c linux/drivers/video/sis/sis_main.c
--- v2.4.14/linux/drivers/video/sis/sis_main.c Mon Nov 5 15:55:33 2001
+++ linux/drivers/video/sis/sis_main.c Fri Nov 9 14:11:14 2001


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

- * SiS 300/630/540 frame buffer device For Kernal 2.4.x
+ * SiS 300/630/540/315H/315 frame buffer device For Kernal 2.4.x
X *
X * This driver is partly based on the VBE 2.0 compliant graphic
X * boards framebuffer driver, which is
@@ -8,7 +8,7 @@


X *
X */
X

-#undef SISFBDEBUG
+//#undef SISFBDEBUG


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

@@ -27,10 +27,13 @@
X #include <linux/pci.h>
X #include <linux/vt_kern.h>
X #include <linux/capability.h>
-#include <linux/sisfb.h>
X #include <linux/fs.h>
+#include <linux/agp_backend.h>
+#include <linux/types.h>
+#include <linux/sisfb.h>
X
X #include <asm/io.h>
+#include <asm/mtrr.h>
X
X #include <video/fbcon.h>
X #include <video/fbcon-cfb8.h>
@@ -38,568 +41,543 @@
X #include <video/fbcon-cfb24.h>
X #include <video/fbcon-cfb32.h>
X
-#include "sis.h"
-#ifdef NOBIOS
-#include "bios.h"
-#endif
-
-/* ------------------- Constant Definitions ------------------------- */
-
-/* capabilities */
-#define TURBO_QUEUE_CAP 0x80
-#define HW_CURSOR_CAP 0x40
+#include "osdef.h"
+#include "vgatypes.h"
+#include "sis_main.h"
X
-/* VGA register Offsets */
-#define SEQ_ADR (0x14)
-#define SEQ_DATA (0x15)
-#define DAC_ADR (0x18)
-#define DAC_DATA (0x19)
-#define CRTC_ADR (0x24)
-#define CRTC_DATA (0x25)
+/* -------------------- Macro definitions ---------------------------- */
X
-#define DAC2_ADR 0x16 - 0x30
-#define DAC2_DATA 0x17 - 0x30
-
-
-/* SiS indexed register indexes */
-#define IND_SIS_PASSWORD (0x05)
-#define IND_SIS_DRAM_SIZE (0x14)
-#define IND_SIS_MODULE_ENABLE (0x1E)
-#define IND_SIS_PCI_ADDRESS_SET (0x20)
-#define IND_SIS_TURBOQUEUE_ADR (0x26)
-#define IND_SIS_TURBOQUEUE_SET (0x27)
-
-/* Sis register value */
-#define SIS_PASSWORD (0x86)
-
-#define SIS_2D_ENABLE (0x40)
+#ifdef SISFBDEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
X
-#define SIS_MEM_MAP_IO_ENABLE (0x01)
-#define SIS_PCI_ADDR_ENABLE (0x80)
+#define vgawb(reg,data) \
+ (outb(data, ivideo.vga_base+reg))
+#define vgaww(reg,data) \
+ (outw(data, ivideo.vga_base+reg))
+#define vgawl(reg,data) \
+ (outl(data, ivideo.vga_base+reg))
+#define vgarb(reg) \
+ (inb(ivideo.vga_base+reg))
X
-//#define MMIO_SIZE 0x10000 /* 64K MMIO capability */
-#define MAX_ROM_SCAN 0x10000
+/* --------------- Hardware Access Routines -------------------------- */
X
-#define RESERVED_MEM_SIZE_4M 0x400000 /* 4M */
-#define RESERVED_MEM_SIZE_8M 0x800000 /* 8M */
+void sisfb_set_reg1 (u16 port, u16 index, u16 data)
+{
+ outb ((u8) (index & 0xff), port);
+ port++;
+ outb ((u8) (data & 0xff), port);
+}
X
-/* Mode set stuff */
-#define DEFAULT_MODE 0 /* 640x480x8 */
-#define DEFAULT_LCDMODE 9 /* 800x600x8 */
-#define DEFAULT_TVMODE 9 /* 800x600x8 */


+void sisfb_set_reg3 (u16 port, u16 data)

+{
+ outb ((u8) (data & 0xff), port);
+}
X
-/* heap stuff */
-#define OH_ALLOC_SIZE 4000
-#define SENTINEL 0x7fffffff


+void sisfb_set_reg4 (u16 port, unsigned long data)

+{
+ outl ((u32) (data & 0xffffffff), port);
+}
X
-#define TURBO_QUEUE_AREA_SIZE 0x80000 /* 512K */
-#define HW_CURSOR_AREA_SIZE 0x1000 /* 4K */


+u8 sisfb_get_reg1 (u16 port, u16 index)

+{
+ u8 data;
X
-/* ------------------- Global Variables ----------------------------- */
+ outb ((u8) (index & 0xff), port);
+ port += 1;
+ data = inb (port);
+ return (data);
+}
X
-struct video_info ivideo;
-HW_DEVICE_EXTENSION HwExt={0,0,0,0,0,0};
+u8 sisfb_get_reg2 (u16 port)
+{
+ u8 data;
X
-struct GlyInfo {
- unsigned char ch;
- int fontwidth;
- int fontheight;
- u8 gmask[72];
- int ngmask;
-};
+ data = inb (port);
X
-/* Supported SiS Chips list */
-static struct board {
- u16 vendor, device;
- const char *name;
-} dev_list[] = {
- {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300, "SIS 300"},
- {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, "SIS 540"},
- {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, "SIS 630"},
- {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_730_VGA, "SIS 730"},
- {0, 0, NULL}
-};
+ return (data);
+}
X
-/* card parameters */
-unsigned long rom_base;
-unsigned long rom_vbase;
-
-/* mode */
-static int video_type = FB_TYPE_PACKED_PIXELS;
-static int video_linelength;
-static int video_cmap_len;
-static int sisfb_off = 0;
-static int crt1off = 0;
-
-static struct fb_var_screeninfo default_var = {
- 0, 0, 0, 0,
- 0, 0,
- 0,
- 0,
- {0, 8, 0},
- {0, 8, 0},
- {0, 8, 0},
- {0, 0, 0},
- 0,
- FB_ACTIVATE_NOW, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,
- FB_VMODE_NONINTERLACED,
- {0, 0, 0, 0, 0, 0}
-};
+u32 sisfb_get_reg3 (u16 port)
+{
+ u32 data;
X
-static struct display disp;
-static struct fb_info fb_info;
-static struct {
- u16 blue, green, red, pad;
-} palette[256];
-static union {
-#ifdef FBCON_HAS_CFB16
- u16 cfb16[16];
-#endif
-#ifdef FBCON_HAS_CFB24
- u32 cfb24[16];
-#endif
-#ifdef FBCON_HAS_CFB32
- u32 cfb32[16];
-#endif
-} fbcon_cmap;
+ data = inl (port);
+ return (data);
+}
X
-static int inverse = 0;
-static int currcon = 0;
+/* --------------- Interface to BIOS code ---------------------------- */
X
-static struct display_switch sisfb_sw;


+BOOLEAN sisfb_query_VGA_config_space (PSIS_HW_DEVICE_INFO psishw_ext,
+ unsigned long offset, unsigned long set,
+ unsigned long *value)

+{
+ static struct pci_dev *pdev = NULL;
+ static unsigned char init = 0, valid_pdev = 0;
X
-static u8 caps = 0;
-static unsigned long MMIO_SIZE = 0;
-
-/* ModeSet stuff */
-unsigned char uDispType = 0;
-int mode_idx = -1;
-u8 mode_no = 0;
-u8 rate_idx = 0;
-
-static const struct _sisbios_mode {
- char name[15];
- u8 mode_no;
- u16 xres;
- u16 yres;
- u16 bpp;
- u16 rate_idx;
- u16 cols;
- u16 rows;
-} sisbios_mode[] = {
- {"640x480x8", 0x2E, 640, 480, 8, 1, 80, 30},
- {"640x480x16", 0x44, 640, 480, 16, 1, 80, 30},
- {"640x480x32", 0x62, 640, 480, 32, 1, 80, 30},
- {"720x480x8", 0x31, 720, 480, 8, 1, 90, 30}, /* NTSC TV */
- {"720x480x16", 0x33, 720, 480, 16, 1, 90, 30},
- {"720x480x32", 0x35, 720, 480, 32, 1, 90, 30},
- {"720x576x8", 0x32, 720, 576, 8, 1, 90, 36}, /* PAL TV */
- {"720x576x16", 0x34, 720, 576, 16, 1, 90, 36},
- {"720x576x32", 0x36, 720, 576, 32, 1, 90, 36},
- {"800x600x8", 0x30, 800, 600, 8, 2, 100, 37},
- {"800x600x16", 0x47, 800, 600, 16, 2, 100, 37},
- {"800x600x32", 0x63, 800, 600, 32, 2, 100, 37},
- {"1024x768x8", 0x38, 1024, 768, 8, 2, 128, 48},
- {"1024x768x16", 0x4A, 1024, 768, 16, 2, 128, 48},
- {"1024x768x32", 0x64, 1024, 768, 32, 2, 128, 48},
- {"1280x1024x8", 0x3A, 1280, 1024, 8, 2, 160, 64},
- {"1280x1024x16", 0x4D, 1280, 1024, 16, 2, 160, 64},
- {"1280x1024x32", 0x65, 1280, 1024, 32, 2, 160, 64},
- {"1600x1200x8", 0x3C, 1600, 1200, 8, 1, 200, 75},
- {"1600x1200x16", 0x3D, 1600, 1200, 16, 1, 200, 75},
- {"1600x1200x32", 0x66, 1600, 1200, 32, 1, 200, 75},
- {"1920x1440x8", 0x68, 1920, 1440, 8, 1, 240, 75},
- {"1920x1440x16", 0x69, 1920, 1440, 16, 1, 240, 75},
- {"1920x1440x32", 0x6B, 1920, 1440, 32, 1, 240, 75},
- {"\0", 0x00, 0, 0, 0, 0, 0, 0}
-};
+ if (!set)
+ DPRINTK ("Get VGA offset 0x%lx\n", offset);
+ else
+ DPRINTK ("Set offset 0x%lx to 0x%lx\n", offset, *value);
X
-static struct _vrate {
- u16 idx;
- u16 xres;
- u16 yres;
- u16 refresh;
-} vrate[] = {
- {1, 640, 480, 60}, {2, 640, 480, 72}, {3, 640, 480, 75}, {4, 640, 480, 85},
- {5, 640, 480, 100}, {6, 640, 480, 120}, {7, 640, 480, 160}, {8, 640, 480, 200},
- {1, 720, 480, 60},
- {1, 720, 576, 50},
- {1, 800, 600, 56}, {2, 800, 600, 60}, {3, 800, 600, 72}, {4, 800, 600, 75},
- {5, 800, 600, 85}, {6, 800, 600, 100}, {7, 800, 600, 120}, {8, 800, 600, 160},
- {1, 1024, 768, 43}, {2, 1024, 768, 60}, {3, 1024, 768, 70}, {4, 1024, 768, 75},
- {5, 1024, 768, 85}, {6, 1024, 768, 100}, {7, 1024, 768, 120},
- {1, 1280, 1024, 43}, {2, 1280, 1024, 60}, {3, 1280, 1024, 75}, {4, 1280, 1024, 85},
- {1, 1600, 1200, 60}, {2, 1600, 1200, 65}, {3, 1600, 1200, 70}, {4, 1600, 1200, 75},
- {5, 1600, 1200, 85},
- {1, 1920, 1440, 60},
- {0, 0, 0, 0}
-};
+ if (!init) {
+ init = TRUE;
+ pci_for_each_dev (pdev) {
+ DPRINTK ("Current: 0x%x, target: 0x%x\n", pdev->device,
+ ivideo.chip_id);
+ if ((pdev->vendor == PCI_VENDOR_ID_SI)
+ && (pdev->device == ivideo.chip_id)) {
+ valid_pdev = TRUE;


+ break;
+ }
+ }
+ }

X
+ if (!valid_pdev) {
+ printk (KERN_DEBUG "Can't find SiS %d VGA device.\n",
+ ivideo.chip_id);
+ return FALSE;
+ }
X
-/* HEAP stuff */
+ if (set == 0)
+ pci_read_config_dword (pdev, offset, (u32 *) value);
+ else
+ pci_write_config_dword (pdev, offset, (u32) (*value));
X
-struct OH {
- struct OH *pohNext;
- struct OH *pohPrev;
- unsigned long ulOffset;
- unsigned long ulSize;
-};
+ return TRUE;
+}
X
-struct OHALLOC {
- struct OHALLOC *pohaNext;
- struct OH aoh[1];
-};


+BOOLEAN sisfb_query_north_bridge_space (PSIS_HW_DEVICE_INFO psishw_ext,
+ unsigned long offset, unsigned long set,
+ unsigned long *value)

+{
+ static struct pci_dev *pdev = NULL;
+ static unsigned char init = 0, valid_pdev = 0;
+ u16 nbridge_id = 0;
X
-struct HEAP {
- struct OH ohFree;
- struct OH ohUsed;
- struct OH *pohFreeList;
- struct OHALLOC *pohaChain;
+ if (!init) {
+ init = TRUE;
+ switch (ivideo.chip) {
+ case SIS_540:
+ nbridge_id = PCI_DEVICE_ID_SI_540;
+ break;
+ case SIS_630:
+ nbridge_id = PCI_DEVICE_ID_SI_630;
+ break;
+ case SIS_730:
+ nbridge_id = PCI_DEVICE_ID_SI_730;


+ break;
+ case SIS_550:

+ nbridge_id = PCI_DEVICE_ID_SI_550;
+ break;
+ default:
+ nbridge_id = 0;
+ break;
+ }
X
- unsigned long ulMaxFreeSize;
-};
+ pci_for_each_dev (pdev) {
+ DPRINTK ("Current: 0x%x, target: 0x%x\n", pdev->device,
+ ivideo.chip_id);
+ if ((pdev->vendor == PCI_VENDOR_ID_SI)
+ && (pdev->device == nbridge_id)) {
+ valid_pdev = TRUE;


+ break;
+ }
+ }
+ }

X
-struct HEAP heap;
-unsigned long heap_start;
-unsigned long heap_end;
-unsigned long heap_size;
+ if (!valid_pdev) {
+ printk (KERN_DEBUG "Can't find SiS %d North Bridge device.\n",
+ nbridge_id);
+ return FALSE;
+ }
X
-unsigned int tqueue_pos;
-unsigned long hwcursor_vbase;
+ if (set == 0)
+ pci_read_config_dword (pdev, offset, (u32 *) value);
+ else
+ pci_write_config_dword (pdev, offset, (u32) (*value));
X
+ return TRUE;
+}
X
-/* -------------------- Macro definitions --------------------------- */
+/* -------------------- Export functions ----------------------------- */
X
-#ifdef SISFBDEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif


+static void sis_get_glyph (SIS_GLYINFO * gly)

+{
+ struct display *p = &fb_display[currcon];
+ u16 c;
+ u8 *cdat;
+ int widthb;
+ u8 *gbuf = gly->gmask;
+ int size;
X
-#define vgawb(reg,data) \
- (outb(data, ivideo.vga_base+reg))
-#define vgaww(reg,data) \
- (outw(data, ivideo.vga_base+reg))
-#define vgawl(reg,data) \
- (outl(data, ivideo.vga_base+reg))
-#define vgarb(reg) \
- (inb(ivideo.vga_base+reg))
+ gly->fontheight = fontheight (p);
+ gly->fontwidth = fontwidth (p);
+ widthb = (fontwidth (p) + 7) / 8;
X
-/* ---------------------- Routine Prototype ------------------------- */
+ c = gly->ch & p->charmask;
+ if (fontwidth (p) <= 8)
+ cdat = p->fontdata + c * fontheight (p);
+ else
+ cdat = p->fontdata + (c * fontheight (p) << 1);
X
-/* Interface used by the world */
-int sisfb_setup(char *options);


-static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,

- struct fb_info *info);


-static int sisfb_get_var(struct fb_var_screeninfo *var, int con,

- struct fb_info *info);


-static int sisfb_set_var(struct fb_var_screeninfo *var, int con,

- struct fb_info *info);


-static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,

- struct fb_info *info);


-static int sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,

- struct fb_info *info);


-static int sisfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg, int con,

- struct fb_info *info);
+ size = fontheight (p) * widthb;
+ memcpy (gbuf, cdat, size);
+ gly->ngmask = size;
+}
X
-/* Interface to the low level console driver */
-int sisfb_init(void);
-static int sisfb_update_var(int con, struct fb_info *info);
-static int sisfb_switch(int con, struct fb_info *info);
-static void sisfb_blank(int blank, struct fb_info *info);


+void sis_dispinfo (struct ap_data *rec)

+{
+ rec->minfo.bpp = ivideo.video_bpp;
+ rec->minfo.xres = ivideo.video_width;
+ rec->minfo.yres = ivideo.video_height;
+ rec->minfo.v_xres = ivideo.video_vwidth;
+ rec->minfo.v_yres = ivideo.video_vheight;
+ rec->minfo.org_x = ivideo.org_x;
+ rec->minfo.org_y = ivideo.org_y;
+ rec->minfo.vrate = ivideo.refresh_rate;
+ rec->iobase = ivideo.vga_base - 0x30;
+ rec->mem_size = ivideo.video_size;
+ rec->disp_state = ivideo.disp_state;
+ rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
+ rec->hasVB = ivideo.hasVB;
+ rec->TV_type = ivideo.TV_type;
+ rec->TV_plug = ivideo.TV_plug;
+ rec->chip = ivideo.chip;
+}
X
-/* Internal routines */
-static void crtc_to_var(struct fb_var_screeninfo *var);
-static void sisfb_set_disp(int con, struct fb_var_screeninfo *var);
-static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green,
- unsigned *blue, unsigned *transp,
- struct fb_info *fb_info);
-static int sis_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *fb_info);
-static void do_install_cmap(int con, struct fb_info *info);
-static int do_set_var(struct fb_var_screeninfo *var, int isactive,
- struct fb_info *info);
+/* ------------------ Internal Routines ------------------------------ */
X
-/* set-mode routines */
-void SetReg1(u16 port, u16 index, u16 data);
-void SetReg3(u16 port, u16 data);
-void SetReg4(u16 port, unsigned long data);
-u8 GetReg1(u16 port, u16 index);
-u8 GetReg2(u16 port);
-u32 GetReg3(u16 port);
-extern BOOLEAN SiSSetMode(PHW_DEVICE_EXTENSION HwDeviceExtension,
- USHORT ModeNo);
-extern BOOLEAN SiSInit300(PHW_DEVICE_EXTENSION HwDeviceExtension);
-static void pre_setmode(void);
-static void post_setmode(void);
-static void search_mode(const char *name);
-static u8 search_refresh_rate(unsigned int rate);


+static void sisfb_search_mode (const char *name)

+{
+ int i = 0;

X
-/* heap routines */
-static int sisfb_heap_init(void);
-static struct OH *poh_new_node(void);
-static struct OH *poh_allocate(unsigned long size);
-static struct OH *poh_free(unsigned long base);
-static void delete_node(struct OH *poh);
-static void insert_node(struct OH *pohList, struct OH *poh);
-static void free_node(struct OH *poh);
+ if (name == NULL)
+ return;
X
-/* ---------------------- Internal Routines ------------------------- */
+ while (sisbios_mode[i].mode_no != 0) {
+ if (!strcmp (name, sisbios_mode[i].name)) {
+ sisfb_mode_idx = i;


+ break;
+ }
+ i++;
+ }

X
-inline static u32 RD32(unsigned char *base, s32 off)
-{
- return readl(base + off);
+ if (sisfb_mode_idx < 0)
+ DPRINTK ("Invalid user mode : %s\n", name);
X }
X
-inline static void WR32(unsigned char *base, s32 off, u32 v)
+static void sisfb_validate_mode (void)
X {
- writel(v, base + off);
-}


+ switch (ivideo.disp_state & DISPTYPE_DISP2) {

+ case DISPTYPE_LCD:
+// Eden Chen
+ switch (sishw_ext.ulCRT2LCDType) {
+ case LCD_1024x768:
+ if (sisbios_mode[sisfb_mode_idx].xres > 1024)
+ sisfb_mode_idx = -1;
+ break;
+ case LCD_1280x1024:
+ case LCD_1280x960:
+ if (sisbios_mode[sisfb_mode_idx].xres > 1280)
+ sisfb_mode_idx = -1;
+ break;
+ case LCD_2048x1536:
+ if (sisbios_mode[sisfb_mode_idx].xres > 2048)
+ sisfb_mode_idx = -1;
+ break;
+ case LCD_1920x1440:
+ if (sisbios_mode[sisfb_mode_idx].xres > 1920)
+ sisfb_mode_idx = -1;
+ break;
+ case LCD_1600x1200:
+ if (sisbios_mode[sisfb_mode_idx].xres > 1600)
+ sisfb_mode_idx = -1;
+ break;
+ case LCD_800x600:
+ if (sisbios_mode[sisfb_mode_idx].xres > 800)
+ sisfb_mode_idx = -1;
+ break;
+ case LCD_640x480:
+ if (sisbios_mode[sisfb_mode_idx].xres > 640)
+ sisfb_mode_idx = -1;
+ break;
+ default:
+ sisfb_mode_idx = -1;
+ }
+// ~Eden Chen
X
-inline static void WR16(unsigned char *base, s32 off, u16 v)
-{
- writew(v, base + off);
+ if (sisbios_mode[sisfb_mode_idx].xres == 720)
+ sisfb_mode_idx = -1;
+ break;
+ case DISPTYPE_TV:
+ switch (sisbios_mode[sisfb_mode_idx].xres) {
+ case 800:
+ case 640:


+ break;
+ case 720:

+ if (ivideo.TV_type == TVMODE_NTSC) {

+ if (sisbios_mode[sisfb_mode_idx].yres != 480)
+ sisfb_mode_idx = -1;


+ } else if (ivideo.TV_type == TVMODE_PAL) {

+ if (sisbios_mode[sisfb_mode_idx].yres != 576)
+ sisfb_mode_idx = -1;
+ }
+ break;
+ /*karl */
+ case 1024:


+ if (ivideo.TV_type == TVMODE_NTSC) {

+ if (sisbios_mode[sisfb_mode_idx].bpp == 32)
+ sisfb_mode_idx -= 1;
+ }
+ break;
+ default:
+ sisfb_mode_idx = -1;
+ }
+ break;
+ }
X }
X
-inline static void WR8(unsigned char *base, s32 off, u8 v)


+static u8 sisfb_search_refresh_rate (unsigned int rate)

X {
- writeb(v, base + off);
-}
+ u16 xres, yres;


+ int i = 0;

X
-inline static u32 regrl(s32 off)
-{
- return RD32(ivideo.mmio_vbase, off);
-}
+ xres = sisbios_mode[sisfb_mode_idx].xres;
+ yres = sisbios_mode[sisfb_mode_idx].yres;
X
-inline static void regwl(s32 off, u32 v)
-{
- WR32(ivideo.mmio_vbase, off, v);
-}
+ sisfb_rate_idx = 0;
+ while ((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
+ if ((sisfb_vrate[i].xres == xres)
+ && (sisfb_vrate[i].yres == yres)) {
+ if (sisfb_vrate[i].refresh == rate) {
+ sisfb_rate_idx = sisfb_vrate[i].idx;
+ break;
+ } else if (sisfb_vrate[i].refresh > rate) {
+ if ((sisfb_vrate[i].refresh - rate) <= 2) {
+ DPRINTK
+ ("Adjust rate from %d up to %d\n",
+ rate, sisfb_vrate[i].refresh);
+ sisfb_rate_idx = sisfb_vrate[i].idx;
+ ivideo.refresh_rate =
+ sisfb_vrate[i].refresh;
+ } else if (((rate - sisfb_vrate[i - 1].refresh) <= 2)
+ && (sisfb_vrate[i].idx != 1)) {
+ DPRINTK("Adjust rate from %d down to %d\n",
+ rate, sisfb_vrate[i - 1].refresh);
+ sisfb_rate_idx = sisfb_vrate[i - 1].idx;
+ ivideo.refresh_rate = sisfb_vrate[i - 1].refresh;


+ }
+ break;
+ }
+ }

+ i++;
+ }
+
+ if (sisfb_rate_idx > 0) {
+ return sisfb_rate_idx;
+ } else {
+ DPRINTK ("Unsupported rate %d for %dx%d mode\n", rate, xres,
+ yres);
+ return 0;
+ }
X
-inline static void regww(s32 off, u16 v)
-{
- WR16(ivideo.mmio_vbase, off, v);
X }
X
-inline static void regwb(s32 off, u8 v)
+static int sis_getcolreg (unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
+ unsigned *transp, struct fb_info *fb_info)
X {
- WR8(ivideo.mmio_vbase, off, v);
+ if (regno >= video_cmap_len)
+ return 1;
+
+ *red = palette[regno].red;
+ *green = palette[regno].green;
+ *blue = palette[regno].blue;
+ *transp = 0;
+ return 0;
X }
X
-/*
- * Get CRTC registers to set var
- */
-static void crtc_to_var(struct fb_var_screeninfo *var)
+static int sis_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *fb_info)
X {
- u16 VRE, VBE, VRS, VBS, VDE, VT;
- u16 HRE, HBE, HRS, HBS, HDE, HT;
- u8 uSRdata, uCRdata, uCRdata2, uCRdata3, uMRdata;
- int A, B, C, D, E, F, temp;
- double hrate, drate;
-
- vgawb(SEQ_ADR, 0x6);
- uSRdata = vgarb(SEQ_DATA);
X
- if (uSRdata & 0x20)
- var->vmode = FB_VMODE_INTERLACED;
- else
- var->vmode = FB_VMODE_NONINTERLACED;
+ if (regno >= video_cmap_len)
+ return 1;
X
- switch ((uSRdata & 0x1c) >> 2) {
- case 0:
- var->bits_per_pixel = 8;
- break;
- case 2:
- var->bits_per_pixel = 16;


- break;
- case 4:

- var->bits_per_pixel = 32;
- break;
- }
+ palette[regno].red = red;
+ palette[regno].green = green;
+ palette[regno].blue = blue;
X
- switch (var->bits_per_pixel) {
+ switch (ivideo.video_bpp) {
+#ifdef FBCON_HAS_CFB8
X case 8:
- var->red.length = 6;
- var->green.length = 6;
- var->blue.length = 6;
- video_cmap_len = 256;
- break;
- case 16: /* RGB 565 */
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = 0;
- var->transp.length = 0;
- video_cmap_len = 16;
+ vgawb (DAC_ADR, regno);
+ vgawb (DAC_DATA, red >> 10);
+ vgawb (DAC_DATA, green >> 10);
+ vgawb (DAC_DATA, blue >> 10);


+ if (ivideo.disp_state & DISPTYPE_DISP2) {

+ vgawb (DAC2_ADR, regno);
+ vgawb (DAC2_DATA, red >> 8);
+ vgawb (DAC2_DATA, green >> 8);
+ vgawb (DAC2_DATA, blue >> 8);
+ }
X
X break;
- case 24: /* RGB 888 */
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 0;
- var->transp.length = 0;
- video_cmap_len = 16;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 15:
+ case 16:
+ fbcon_cmap.cfb16[regno] =
+ ((red & 0xf800)) |
+ ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ fbcon_cmap.cfb24[regno] = (red << 16) | (green << 8) | (blue);
X break;
+#endif
+#ifdef FBCON_HAS_CFB32
X case 32:
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 24;
- var->transp.length = 8;
- video_cmap_len = 16;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
X break;
+#endif
X }
+ return 0;
+}
X
- vgawb(SEQ_ADR, 0xa);
- uSRdata = vgarb(SEQ_DATA);
-
- vgawb(CRTC_ADR, 0x6);
- uCRdata = vgarb(CRTC_DATA);
- vgawb(CRTC_ADR, 0x7);
- uCRdata2 = vgarb(CRTC_DATA);
- VT =
- (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x01) << 8) |
- ((u16) (uCRdata2 & 0x20) << 4) | ((u16) (uSRdata & 0x01) <<
- 10);
- A = VT + 2;
-
- vgawb(CRTC_ADR, 0x12);
- uCRdata = vgarb(CRTC_DATA);
- VDE =
- (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x02) << 7) |
- ((u16) (uCRdata2 & 0x40) << 3) | ((u16) (uSRdata & 0x02) << 9);
- E = VDE + 1;
-
- vgawb(CRTC_ADR, 0x10);
- uCRdata = vgarb(CRTC_DATA);
- VRS =
- (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x04) << 6) |
- ((u16) (uCRdata2 & 0x80) << 2) | ((u16) (uSRdata & 0x08) << 7);
- F = VRS + 1 - E;
-
- vgawb(CRTC_ADR, 0x15);
- uCRdata = vgarb(CRTC_DATA);
- vgawb(CRTC_ADR, 0x9);
- uCRdata3 = vgarb(CRTC_DATA);
- VBS =
- (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x08) << 5) |
- ((u16) (uCRdata3 & 0x20) << 4) | ((u16) (uSRdata & 0x04) << 8);
-
- vgawb(CRTC_ADR, 0x16);
- uCRdata = vgarb(CRTC_DATA);
- VBE = (uCRdata & 0xff) | ((u16) (uSRdata & 0x10) << 4);
- temp = VBE - ((E - 1) & 511);
- B = (temp > 0) ? temp : (temp + 512);
-
- vgawb(CRTC_ADR, 0x11);
- uCRdata = vgarb(CRTC_DATA);
- VRE = (uCRdata & 0x0f) | ((uSRdata & 0x20) >> 1);
- temp = VRE - ((E + F - 1) & 31);
- C = (temp > 0) ? temp : (temp + 32);
-
- D = B - F - C;
-
- var->yres = var->yres_virtual = E;
- var->upper_margin = D;
- var->lower_margin = F;
- var->vsync_len = C;
-
- vgawb(SEQ_ADR, 0xb);
- uSRdata = vgarb(SEQ_DATA);
-
- vgawb(CRTC_ADR, 0x0);
- uCRdata = vgarb(CRTC_DATA);
- HT = (uCRdata & 0xff) | ((u16) (uSRdata & 0x03) << 8);
- A = HT + 5;
-
- vgawb(CRTC_ADR, 0x1);
- uCRdata = vgarb(CRTC_DATA);
- HDE = (uCRdata & 0xff) | ((u16) (uSRdata & 0x0C) << 6);
- E = HDE + 1;


+static int sisfb_do_set_var (struct fb_var_screeninfo *var, int isactive,

+ struct fb_info *info)
+{
+ unsigned int htotal =
+ var->left_margin + var->xres + var->right_margin + var->hsync_len;
+ unsigned int vtotal =
+ var->upper_margin + var->yres + var->lower_margin + var->vsync_len;
+ double drate = 0, hrate = 0;
+ int found_mode = 0;
+ int old_mode;
X
- vgawb(CRTC_ADR, 0x4);
- uCRdata = vgarb(CRTC_DATA);
- HRS = (uCRdata & 0xff) | ((u16) (uSRdata & 0xC0) << 2);
- F = HRS - E - 3;
+ if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
+ vtotal <<= 1;
+ else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
+ vtotal <<= 2;
+ else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+ var->yres <<= 1;
X
- vgawb(CRTC_ADR, 0x2);
- uCRdata = vgarb(CRTC_DATA);
- HBS = (uCRdata & 0xff) | ((u16) (uSRdata & 0x30) << 4);
-
- vgawb(SEQ_ADR, 0xc);
- uSRdata = vgarb(SEQ_DATA);
- vgawb(CRTC_ADR, 0x3);
- uCRdata = vgarb(CRTC_DATA);
- vgawb(CRTC_ADR, 0x5);
- uCRdata2 = vgarb(CRTC_DATA);
- HBE =
- (uCRdata & 0x1f) | ((u16) (uCRdata2 & 0x80) >> 2) |
- ((u16) (uSRdata & 0x03) << 6);
- HRE = (uCRdata2 & 0x1f) | ((uSRdata & 0x04) << 3);
+ if (!htotal || !vtotal) {
+ DPRINTK ("Invalid 'var' Information!\n");
+ return -EINVAL;
+ }
X
- temp = HBE - ((E - 1) & 255);
- B = (temp > 0) ? temp : (temp + 256);
+ drate = 1E12 / var->pixclock;
+ hrate = drate / htotal;
+ ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
X
- temp = HRE - ((E + F + 3) & 63);
- C = (temp > 0) ? temp : (temp + 64);
+ DPRINTK ("Chagne mode to %dx%dx%d-%dMHz\n",
+ var->xres, var->yres, var->bits_per_pixel,
+ ivideo.refresh_rate);
+
+ old_mode = sisfb_mode_idx;
+ sisfb_mode_idx = 0;
+
+ while ((sisbios_mode[sisfb_mode_idx].mode_no != 0)
+ && (sisbios_mode[sisfb_mode_idx].xres <= var->xres)) {
+ if ((sisbios_mode[sisfb_mode_idx].xres == var->xres)
+ && (sisbios_mode[sisfb_mode_idx].yres == var->yres)
+ && (sisbios_mode[sisfb_mode_idx].bpp ==
+ var->bits_per_pixel)) {


+ sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;

+ found_mode = 1;
+ break;
+ }
+ sisfb_mode_idx++;
+ }
X
- D = B - F - C;
+ if (found_mode)
+ sisfb_validate_mode ();
+ else
+ sisfb_mode_idx = -1;
X
- var->xres = var->xres_virtual = E * 8;
- var->left_margin = D * 8;
- var->right_margin = F * 8;
- var->hsync_len = C * 8;
+ if (sisfb_mode_idx < 0) {
+ DPRINTK ("sisfb does not support mode %dx%d-%d\n", var->xres,
+ var->yres, var->bits_per_pixel);
+ sisfb_mode_idx = old_mode;
+ return -EINVAL;
+ }
X
- var->activate = FB_ACTIVATE_NOW;
+ if (sisfb_search_refresh_rate (ivideo.refresh_rate) == 0) {


+ sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;

+ ivideo.refresh_rate = 60;
+ }
X
- var->sync = 0;
+ if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
+ sisfb_pre_setmode ();
X
- uMRdata = vgarb(0x1C);
- if (uMRdata & 0x80)
- var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
- else
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
+// Eden Chen
+/*
+#ifdef CONFIG_FB_SIS_300
+ if (SiSSetMode(&sishw_ext, sisfb_mode_no)) {
+ DPRINTK("set mode[0x%x]: failed\n", sisfb_mode_no);


+ return -1;
+ }
+#endif

X
- if (uMRdata & 0x40)
- var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
- else
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
+#ifdef CONFIG_FB_SIS_315
+ if (SiSSetMode310(&sishw_ext, sisfb_mode_no)) {
+ DPRINTK("set mode[0x%x]: failed\n", sisfb_mode_no);
+ return -1;
+ }
X
- VT += 2;
- VT <<= 1;
- HT = (HT + 5) * 8;
+#endif
+*/


+ if (SiSSetMode (&sishw_ext, sisfb_mode_no) == 0) {
+ DPRINTK ("set mode[0x%x]: failed\n", sisfb_mode_no);

+ return -1;
+ }
+

+ vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+ vgawb (SEQ_DATA, SIS_PASSWORD);

+// ~Eden Chen
+ sisfb_post_setmode ();
+
+ DPRINTK ("Set New Mode : %dx%dx%d-%d \n",
+ sisbios_mode[sisfb_mode_idx].xres,
+ sisbios_mode[sisfb_mode_idx].yres,
+ sisbios_mode[sisfb_mode_idx].bpp, ivideo.refresh_rate);
+


+ ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
+ ivideo.video_vwidth = ivideo.video_width =

+ sisbios_mode[sisfb_mode_idx].xres;


+ ivideo.video_vheight = ivideo.video_height =

+ sisbios_mode[sisfb_mode_idx].yres;
+ ivideo.org_x = ivideo.org_y = 0;
+ video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
X
- hrate = (double) ivideo.refresh_rate * (double) VT / 2;
- drate = hrate * HT;
- var->pixclock = (u32) (1E12 / drate);
+ }
+ return 0;
X }
X
-static void sisfb_set_disp(int con, struct fb_var_screeninfo *var)


+static void sisfb_set_disp (int con, struct fb_var_screeninfo *var)

X {
X struct fb_fix_screeninfo fix;
X struct display *display;
X struct display_switch *sw;
- long flags;
+ u32 flags;
X
X if (con >= 0)
X display = &fb_display[con];
X else
- display = &disp; /* used during initialization */
+ display = &disp;
X
- sisfb_get_fix(&fix, con, 0);
+ sisfb_get_fix (&fix, con, 0);
X
X display->screen_base = ivideo.video_vbase;
X display->visual = fix.visual;
@@ -609,12 +587,11 @@
X display->ywrapstep = fix.ywrapstep;
X display->line_length = fix.line_length;
X display->next_line = fix.line_length;
- /*display->can_soft_blank = 1; */
X display->can_soft_blank = 0;
- display->inverse = inverse;
+ display->inverse = sisfb_inverse;
X display->var = *var;
X
- save_flags(flags);
+ save_flags (flags);
X switch (ivideo.video_bpp) {
X #ifdef FBCON_HAS_CFB8
X case 8:
@@ -644,852 +621,1380 @@
X sw = &fbcon_dummy;
X return;
X }
- memcpy(&sisfb_sw, sw, sizeof(*sw));
+ memcpy (&sisfb_sw, sw, sizeof (*sw));
X display->dispsw = &sisfb_sw;
- restore_flags(flags);
+ restore_flags (flags);
X
X display->scrollmode = SCROLL_YREDRAW;
X sisfb_sw.bmove = fbcon_redraw_bmove;
-
X }
X
-/*
- * Read a single color register and split it into colors/transparent.
- * Return != 0 for invalid regno.
- */
-static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
- unsigned *transp, struct fb_info *fb_info)
+static void sisfb_do_install_cmap (int con, struct fb_info *info)
X {
- if (regno >= video_cmap_len)
- return 1;
+ if (con != currcon)
+ return;
X
- *red = palette[regno].red;
- *green = palette[regno].green;
- *blue = palette[regno].blue;
- *transp = 0;
- return 0;
+ if (fb_display[con].cmap.len)
+ fb_set_cmap (&fb_display[con].cmap, 1, sis_setcolreg, info);
+ else
+ fb_set_cmap (fb_default_cmap (video_cmap_len), 1,
+ sis_setcolreg, info);
X }
X
-/*
- * Set a single color register. The values supplied are already
- * rounded down to the hardware's capabilities (according to the
- * entries in the var structure). Return != 0 for invalid regno.
- */
-static int sis_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
- unsigned transp, struct fb_info *fb_info)
-{
-
- if (regno >= video_cmap_len)
- return 1;
-
- palette[regno].red = red;
- palette[regno].green = green;
- palette[regno].blue = blue;
+/* --------------- Chip-dependent Routines --------------------------- */
X
- switch (ivideo.video_bpp) {
-#ifdef FBCON_HAS_CFB8
- case 8:
- vgawb(DAC_ADR, regno);
- vgawb(DAC_DATA, red >> 10);
- vgawb(DAC_DATA, green >> 10);
- vgawb(DAC_DATA, blue >> 10);
- if(uDispType & MASK_DISPTYPE_DISP2)
- {
- /* VB connected */
- vgawb(DAC2_ADR, regno);
- vgawb(DAC2_DATA, red >> 8);
- vgawb(DAC2_DATA, green >> 8);
- vgawb(DAC2_DATA, blue >> 8);
- }
+#ifdef CONFIG_FB_SIS_300 /* for SiS 300/630/540/730 */
+static int sisfb_get_dram_size_300 (void)
+{
+ struct pci_dev *pdev = NULL;
+ int pdev_valid = 0;
+ u8 pci_data, reg;
+ u16 nbridge_id;
X
+ switch (ivideo.chip) {
+ case SIS_540:
+ nbridge_id = PCI_DEVICE_ID_SI_540;
X break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 15:
- case 16:
- fbcon_cmap.cfb16[regno] =
- ((red & 0xf800)) |
- ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+ case SIS_630:
+ nbridge_id = PCI_DEVICE_ID_SI_630;
X break;
-#endif
-#ifdef FBCON_HAS_CFB24
- case 24:
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- fbcon_cmap.cfb24[regno] =
- (red << 16) | (green << 8) | (blue);
+ case SIS_730:
+ nbridge_id = PCI_DEVICE_ID_SI_730;
X break;
-#endif
-#ifdef FBCON_HAS_CFB32
- case 32:
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- fbcon_cmap.cfb32[regno] =
- (red << 16) | (green << 8) | (blue);
+ default:
+ nbridge_id = 0;
X break;
-#endif


X }
- return 0;
-}

X
-static void do_install_cmap(int con, struct fb_info *info)
-{
- if (con != currcon)
- return;
+ if (nbridge_id == 0) {
+ vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
+ ivideo.video_size =
+ ((unsigned
+ int) ((vgarb (SEQ_DATA) & SIS_DRAM_SIZE_MASK) + 1) << 20);
+ } else {
+ pci_for_each_dev (pdev) {
+ if ((pdev->vendor == PCI_VENDOR_ID_SI)
+ && (pdev->device == nbridge_id)) {
+ //&& (pdev->device == PCI_DEVICE_ID_SI_630)) {
+ pci_read_config_byte (pdev, IND_BRI_DRAM_STATUS,
+ &pci_data);
+ pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
+ ivideo.video_size =
+ (unsigned int) (1 << (pci_data + 21));
+ pdev_valid = 1;
X
- if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, 1, sis_setcolreg, info);
- else
- fb_set_cmap(fb_default_cmap(video_cmap_len), 1,
- sis_setcolreg, info);
+ reg = SIS_DATA_BUS_64 << 6;
+ vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
+ switch (pci_data) {
+ case BRI_DRAM_SIZE_2MB:
+ reg |= SIS_DRAM_SIZE_2MB;
+ break;
+ case BRI_DRAM_SIZE_4MB:
+ reg |= SIS_DRAM_SIZE_4MB;
+ break;
+ case BRI_DRAM_SIZE_8MB:
+ reg |= SIS_DRAM_SIZE_8MB;
+ break;
+ case BRI_DRAM_SIZE_16MB:
+ reg |= SIS_DRAM_SIZE_16MB;
+ break;
+ case BRI_DRAM_SIZE_32MB:
+ reg |= SIS_DRAM_SIZE_32MB;
+ break;
+ case BRI_DRAM_SIZE_64MB:
+ reg |= SIS_DRAM_SIZE_64MB;
+ break;
+ }
+ vgawb (SEQ_DATA, reg);


+ break;
+ }
+ }
+

+ if (!pdev_valid)


+ return -1;
+ }
+

+ return 0;
X }
X

-static int do_set_var(struct fb_var_screeninfo *var, int isactive,
- struct fb_info *info)
+static void sisfb_detect_VB_connect_300(void)
X {
- unsigned int htotal =
- var->left_margin + var->xres + var->right_margin +
- var->hsync_len;
- unsigned int vtotal =
- var->upper_margin + var->yres + var->lower_margin +
- var->vsync_len;
- double drate = 0, hrate = 0;
- int found_mode = 0;
- int old_mode;
+ u8 sr16, sr17, cr32, temp;
X
- if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
- vtotal <<= 1;
- else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
- vtotal <<= 2;
- else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
- var->yres <<= 1;
+ vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_17);
+ sr17 = vgarb (SEQ_DATA);
+ vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR32);
+ cr32 = vgarb (CRTC_DATA);
X
+ ivideo.TV_plug = ivideo.TV_type = 0;
+ if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) {
+ if ((sr17 & 0x01) && !sisfb_crt1off)
+ sisfb_crt1off = 0;
+ else {
+ if (sr17 & 0x0E)
+ sisfb_crt1off = 1;
+ else
+ sisfb_crt1off = 0;
+ }
X
- if (!htotal || !vtotal) {
- DPRINTK("Invalid 'var' Information!\n");
- return 1;
- }
+ if (sr17 & 0x08)
+ ivideo.disp_state = DISPTYPE_CRT2;
+ else if (sr17 & 0x02)
+ ivideo.disp_state = DISPTYPE_LCD;
+ else if (sr17 & 0x04) {
+ ivideo.disp_state = DISPTYPE_TV;
+ if (sr17 & 0x20)
+ ivideo.TV_plug = TVPLUG_SVIDEO;
+ else if (sr17 & 0x10)
+ ivideo.TV_plug = TVPLUG_COMPOSITE;
X
- drate = 1E12 / var->pixclock;
- hrate = drate / htotal;
- ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
+ vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_16);
+ sr16 = vgarb (SEQ_DATA);
+ if (sr16 & 0x20)
+ ivideo.TV_type = TVMODE_PAL;
+ else
+ ivideo.TV_type = TVMODE_NTSC;
+ } else
+ ivideo.disp_state = 0;
+ } else {
+ if ((cr32 & SIS_CRT1) && !sisfb_crt1off)
+ sisfb_crt1off = 0;
+ else {
+ if (cr32 & 0x5F)
+ sisfb_crt1off = 1;
+ else
+ sisfb_crt1off = 0;
+ }
X
- old_mode = mode_idx;
- mode_idx = 0;
+ if (cr32 & SIS_VB_CRT2)
+ ivideo.disp_state = DISPTYPE_CRT2;
+ else if (cr32 & SIS_VB_LCD)
+ ivideo.disp_state = DISPTYPE_LCD;
+ else if (cr32 & SIS_VB_TV) {
+ ivideo.disp_state = DISPTYPE_TV;
+ if (cr32 & SIS_VB_HIVISION) {
+ ivideo.TV_type = TVMODE_HIVISION;
+ ivideo.TV_plug = TVPLUG_SVIDEO;
+ } else if (cr32 & SIS_VB_SVIDEO)
+ ivideo.TV_plug = TVPLUG_SVIDEO;
+ else if (cr32 & SIS_VB_COMPOSITE)
+ ivideo.TV_plug = TVPLUG_COMPOSITE;
+ else if (cr32 & SIS_VB_SCART)
+ ivideo.TV_plug = TVPLUG_SCART;
X
- while ((sisbios_mode[mode_idx].mode_no != 0)
- && (sisbios_mode[mode_idx].xres <= var->xres)) {
- if ((sisbios_mode[mode_idx].xres == var->xres)
- && (sisbios_mode[mode_idx].yres == var->yres)
- && (sisbios_mode[mode_idx].bpp == var->bits_per_pixel)) {


- mode_no = sisbios_mode[mode_idx].mode_no;

- found_mode = 1;
- break;
- }
- mode_idx++;
+ if (ivideo.TV_type == 0) {
+ // Eden Chen
+ //temp = *((u8 *)(sishw_ext.VirtualRomBase+0x52));
+ //if (temp&0x40) {
+ // temp=*((u8 *)(sishw_ext.VirtualRomBase+0x53));
+ //} else {
+ vgawb (SEQ_ADR, IND_SIS_POWER_ON_TRAP);
+ temp = vgarb (SEQ_DATA);
+ //}
+ // ~Eden Chen
+ if (temp & 0x01)
+ ivideo.TV_type = TVMODE_PAL;
+ else
+ ivideo.TV_type = TVMODE_NTSC;
+ }
+ } else
+ ivideo.disp_state = 0;
X }
+}
X
- if(found_mode)
- {


- switch(uDispType & MASK_DISPTYPE_DISP2)
- {

- case MASK_DISPTYPE_LCD:
- switch(HwExt.usLCDType)
- {
- case LCD1024:

- if(var->xres > 1024)
- found_mode = 0;


- break;
- case LCD1280:

- if(var->xres > 1280)
- found_mode = 0;


- break;
- case LCD2048:

- if(var->xres > 2048)
- found_mode = 0;
+static void sisfb_get_VB_type_300 (void)
+{
+ u8 reg;
+
+ if (ivideo.chip != SIS_300) {
+ if (!sisfb_has_VB_300 ()) {
+ vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR37);


+ reg = vgarb (CRTC_DATA);

+
+ switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {
+ case SIS_EXTERNAL_CHIP_SIS301:
+ ivideo.hasVB = HASVB_301;
X break;
- case LCD1920:
- if(var->xres > 1920)
- found_mode = 0;
+ case SIS_EXTERNAL_CHIP_LVDS:
+ ivideo.hasVB = HASVB_LVDS;
X break;
- case LCD1600:
- if(var->xres > 1600)
- found_mode = 0;
+ case SIS_EXTERNAL_CHIP_TRUMPION:
+ ivideo.hasVB = HASVB_TRUMPION;
X break;
- case LCD800:
- if(var->xres > 800)
- found_mode = 0;
+ case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
+ ivideo.hasVB = HASVB_LVDS_CHRONTEL;
X break;
- case LCD640:
- if(var->xres > 640)
- found_mode = 0;
+ case SIS_EXTERNAL_CHIP_CHRONTEL:
+ ivideo.hasVB = HASVB_CHRONTEL;
X break;
X default:
- found_mode = 0;
- }
- if(var->xres == 720) /* mode only for TV */
- found_mode = 0;

- break;
- case MASK_DISPTYPE_TV:

- switch(var->xres)


- {
- case 800:
- case 640:

X break;


- case 720:
- if(ivideo.TV_type == TVMODE_NTSC)
- {
- if(sisbios_mode[mode_idx].yres != 480)

- found_mode = 0;


- }
- else if(ivideo.TV_type == TVMODE_PAL)
- {
- if(sisbios_mode[mode_idx].yres != 576)

- found_mode = 0;
+ }
+ }
+ } else {
+ sisfb_has_VB_300 ();
+ }
+
+ //sishw_ext.hasVB = ivideo.hasVB;
+}
+
+static int sisfb_has_VB_300 (void)


+{
+ // Eden Chen

+ //u8 sr38, sr39, vb_chipid;
+ u8 vb_chipid;
+
+ //vgawb(SEQ_ADR, IND_SIS_POWER_ON_TRAP);
+ //sr38 = vgarb(SEQ_DATA);
+ //vgawb(SEQ_ADR, IND_SIS_POWER_ON_TRAP2);
+ //sr39 = vgarb(SEQ_DATA);
+ vgawb (VB_PART4_ADR, 0x0);
+ vb_chipid = vgarb (VB_PART4_DATA);
+
+ switch (vb_chipid) {
+ case 0x01:
+ ivideo.hasVB = HASVB_301;
+ break;
+ case 0x02:
+ ivideo.hasVB = HASVB_302;
+ break;
+ case 0x03:
+ ivideo.hasVB = HASVB_303;
+ break;
+ default:
+ ivideo.hasVB = HASVB_NONE;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+#endif /* CONFIG_FB_SIS_300 */
+
+#ifdef CONFIG_FB_SIS_315 /* for SiS 315H/315 */
+static int sisfb_get_dram_size_315 (void)
+{
+#ifdef LINUXBIOS
+ struct pci_dev *pdev = NULL;
+ int pdev_valid = 0;
+ u8 pci_data;
+#endif
+ u8 reg = 0;
+
+ if (ivideo.chip == SIS_550) {
+#ifdef LINUXBIOS
+ pci_for_each_dev (pdev) {
+ if ((pdev->vendor == PCI_VENDOR_ID_SI)
+ && (pdev->device == PCI_DEVICE_ID_SI_550)) {
+ pci_read_config_byte (pdev, IND_BRI_DRAM_STATUS,
+ &pci_data);
+ pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
+ ivideo.video_size =
+ (unsigned int) (1 << (pci_data + 21));
+ pdev_valid = 1;
+
+ vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
+ reg = vgarb (SEQ_DATA) & 0xC0;
+
+ switch (pci_data) {
+ //case BRI_DRAM_SIZE_2MB:
+ // reg |= (SIS315_DRAM_SIZE_2MB << 4); break;
+ case BRI_DRAM_SIZE_4MB:
+ reg |= SIS550_DRAM_SIZE_4MB;
+ break;
+ case BRI_DRAM_SIZE_8MB:
+ reg |= SIS550_DRAM_SIZE_8MB;
+ break;
+ case BRI_DRAM_SIZE_16MB:
+ reg |= SIS550_DRAM_SIZE_16MB;
+ break;
+ case BRI_DRAM_SIZE_32MB:
+ reg |= SIS550_DRAM_SIZE_32MB;
+ break;
+ case BRI_DRAM_SIZE_64MB:
+ reg |= SIS550_DRAM_SIZE_64MB;
+ break;
+ /* case BRI_DRAM_SIZE_128MB:
+ reg |= (SIS315_DRAM_SIZE_128MB << 4); break; */
X }
+
+ /* TODO : set Dual channel and bus width bits here */
+
+ vgawb (SEQ_DATA, reg);
X break;


- default:
- /* illegal mode */

- found_mode = 0;
X }
+ }
+
+ if (!pdev_valid)
+ return -1;
+#else
+ vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);


+ reg = vgarb (SEQ_DATA);

+ switch (reg & SIS550_DRAM_SIZE_MASK) {
+ case SIS550_DRAM_SIZE_4MB:
+ ivideo.video_size = 0x400000;
+ break;
+ case SIS550_DRAM_SIZE_8MB:
+ ivideo.video_size = 0x800000;
+ break;
+ case SIS550_DRAM_SIZE_16MB:
+ ivideo.video_size = 0x1000000;
+ break;
+ case SIS550_DRAM_SIZE_24MB:
+ ivideo.video_size = 0x1800000;
+ break;
+ case SIS550_DRAM_SIZE_32MB:
+ ivideo.video_size = 0x2000000;
+ break;
+ case SIS550_DRAM_SIZE_64MB:
+ ivideo.video_size = 0x4000000;
+ break;
+ case SIS550_DRAM_SIZE_96MB:
+ ivideo.video_size = 0x6000000;
+ break;
+ case SIS550_DRAM_SIZE_128MB:
+ ivideo.video_size = 0x8000000;
+ break;
+ case SIS550_DRAM_SIZE_256MB:
+ ivideo.video_size = 0x10000000;
+ break;
+ default:
+ return -1;
+ }
+#endif
+ return 0;
+ } else {
+ vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);


+ reg = vgarb (SEQ_DATA);

+ switch ((reg & SIS315_DRAM_SIZE_MASK) >> 4) {
+ case SIS315_DRAM_SIZE_2MB:
+ ivideo.video_size = 0x200000;
+ break;
+ case SIS315_DRAM_SIZE_4MB:
+ ivideo.video_size = 0x400000;
+ break;
+ case SIS315_DRAM_SIZE_8MB:
+ ivideo.video_size = 0x800000;
+ break;
+ case SIS315_DRAM_SIZE_16MB:
+ ivideo.video_size = 0x1000000;
X break;
+ case SIS315_DRAM_SIZE_32MB:
+ ivideo.video_size = 0x2000000;
+ break;
+ case SIS315_DRAM_SIZE_64MB:
+ ivideo.video_size = 0x4000000;
+ break;
+ case SIS315_DRAM_SIZE_128MB:
+ ivideo.video_size = 0x8000000;
+ break;
+ default:


+ return -1;
+ }
+ }
+

+ reg &= SIS315_DUAL_CHANNEL_MASK;
+ reg >>= 2;
+ switch (reg) {
+ case SIS315_SINGLE_CHANNEL_2_RANK:
+ ivideo.video_size <<= 1;
+ break;
+ case SIS315_DUAL_CHANNEL_1_RANK:
+ ivideo.video_size <<= 1;
+ break;
+ }
+


+ return 0;
+}
+

+static void sisfb_detect_VB_connect_315 (void)
+{
+ u8 cr32, temp;
+
+ vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR32);
+ cr32 = vgarb (CRTC_DATA);
+
+ ivideo.TV_plug = ivideo.TV_type = 0;
+ if ((cr32 & SIS_CRT1) && !sisfb_crt1off)
+ sisfb_crt1off = 0;
+ else {
+ if (cr32 & 0x5F)
+ sisfb_crt1off = 1;
+ else


+ sisfb_crt1off = 0;
+ }
+

+ if (cr32 & SIS_VB_CRT2)
+ ivideo.disp_state = DISPTYPE_CRT2;
+ else if (cr32 & SIS_VB_LCD)
+ ivideo.disp_state = DISPTYPE_LCD;
+ else if (cr32 & SIS_VB_TV) {
+ ivideo.disp_state = DISPTYPE_TV;
+
+ if (cr32 & SIS_VB_HIVISION) {
+ ivideo.TV_type = TVMODE_HIVISION;
+ ivideo.TV_plug = TVPLUG_SVIDEO;
+ } else if (cr32 & SIS_VB_SVIDEO)
+ ivideo.TV_plug = TVPLUG_SVIDEO;
+ else if (cr32 & SIS_VB_COMPOSITE)
+ ivideo.TV_plug = TVPLUG_COMPOSITE;
+ else if (cr32 & SIS_VB_SCART)
+ ivideo.TV_plug = TVPLUG_SCART;
+
+ if (ivideo.TV_type == 0) {
+ vgawb (SEQ_ADR, IND_SIS_POWER_ON_TRAP);
+ temp = vgarb (SEQ_DATA);
+


+ if (temp & 0x01)

+ ivideo.TV_type = TVMODE_PAL;
+ else
+ ivideo.TV_type = TVMODE_NTSC;
X }
+ } else
+ ivideo.disp_state = 0;
+}
+
+static void sisfb_get_VB_type_315 (void)
+{
+ u8 vb_chipid;
+
+ vgawb (VB_PART4_ADR, 0x0);
+ vb_chipid = vgarb (VB_PART4_DATA);
+
+ switch (vb_chipid) {
+ case 0x01:
+ ivideo.hasVB = HASVB_301;
+ break;
+ case 0x02:
+ ivideo.hasVB = HASVB_302;
+ break;
+ case 0x03:
+ ivideo.hasVB = HASVB_303;
+ break;
+ default:
+ ivideo.hasVB = HASVB_NONE;
X }
+ // Eden Chen
+ //sishw_ext.hasVB = ivideo.hasVB;


+ // ~Eden Chen
+}

+#endif /* CONFIG_FB_SIS_315 */
+
+/* --------------------- Heap Routines ------------------------------- */
+
+static int sisfb_heap_init (void)
+{
+ SIS_OH *poh;
+ u8 temp = 0;
+#ifdef CONFIG_FB_SIS_315
+ int agp_enabled = 1;
+ u32 agp_size;
+ unsigned long *cmdq_baseport = 0;
+ unsigned long *read_port = 0;
+ unsigned long *write_port = 0;
+ SIS_CMDTYPE cmd_type;
+#ifndef AGPOFF
+ agp_kern_info *agp_info;
+ agp_memory *agp;
+ u32 agp_phys;
+#endif
+#endif


+ /*karl:10/01/2001 */
+ if (!sisfb_mem) {

X
- if (!found_mode) {
- printk("sisfb does not support mode %dx%d-%d\n", var->xres,
- var->yres, var->bits_per_pixel);
- mode_idx = old_mode;
- return 1;
+ if (ivideo.video_size > 0x800000)
+ sisfb_heap_start =
+ (unsigned long) ivideo.video_vbase + 0x800000;
+ else
+ sisfb_heap_start =
+ (unsigned long) ivideo.video_vbase + 0x400000;
+ } else
+ sisfb_heap_start =
+ (unsigned long) (ivideo.video_vbase + sisfb_mem * 0x100000);
+
+ sisfb_heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;
+ sisfb_heap_size = sisfb_heap_end - sisfb_heap_start;
+
+#ifdef CONFIG_FB_SIS_315
+
+ cmdq_baseport =
+ (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_PHYBASE);
+ write_port =
+ (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_WRITEPORT);
+ read_port = (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_READPORT);
+
+ DPRINTK ("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport,
+ read_port, write_port);
+
+ agp_size = COMMAND_QUEUE_AREA_SIZE;
+
+#ifndef AGPOFF
+
+ agp_info = vmalloc (sizeof (agp_kern_info));
+ memset ((void *) agp_info, 0x00, sizeof (agp_kern_info));
+ agp_copy_info (agp_info);
+
+ agp_backend_acquire ();
+
+ agp =
+ agp_allocate_memory (COMMAND_QUEUE_AREA_SIZE / PAGE_SIZE,
+ AGP_NORMAL_MEMORY);
+ if (agp == NULL) {
+ DPRINTK ("Allocate AGP buffer failed.\n");
+ agp_enabled = 0;
+ } else {
+ if (agp_bind_memory (agp, agp->pg_start) != 0) {
+ DPRINTK ("AGP : can not bind memory\n");
+ agp_enabled = 0;
+ } else {
+ agp_enable (0);
+ }
X }
X
- if (search_refresh_rate(ivideo.refresh_rate) == 0) {
- /* not supported rate */


- rate_idx = sisbios_mode[mode_idx].rate_idx;

- ivideo.refresh_rate = 60;
- }
+#else
+ agp_enabled = 0;
+#endif
+ if (agp_enabled)
+ cmd_type = AGP_CMD_QUEUE;
+ else if (sisfb_heap_size >= COMMAND_QUEUE_AREA_SIZE)
+ cmd_type = VM_CMD_QUEUE;
+ else
+ cmd_type = MMIO_CMD;
X
- if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
- pre_setmode();
+ switch (agp_size) {
+ case 0x80000:
+ temp = SIS_CMD_QUEUE_SIZE_512k;
+ break;
+ case 0x100000:
+ temp = SIS_CMD_QUEUE_SIZE_1M;
+ break;
+ case 0x200000:
+ temp = SIS_CMD_QUEUE_SIZE_2M;
+ break;
+ case 0x400000:
+ temp = SIS_CMD_QUEUE_SIZE_4M;
+ break;
+ }
X

- if (SiSSetMode(&HwExt, mode_no)) {
- DPRINTK("sisfb: set mode[0x%x]: failed\n",

- mode_no);
- return 1;
- }
+ switch (cmd_type) {
+ case AGP_CMD_QUEUE:
+#ifndef AGPOFF
+ DPRINTK ("AGP buffer base:0x%lx, offset:0x%x, size is %dK\n",
+ agp_info->aper_base, agp->physical, agp_size / 1024);
X
- post_setmode();
+ agp_phys = agp_info->aper_base + agp->physical;
X
- printk(KERN_DEBUG "Current Mode: %dx%dx%d-%d \n", sisbios_mode[mode_idx].xres,
- sisbios_mode[mode_idx].yres, sisbios_mode[mode_idx].bpp, ivideo.refresh_rate);
+ vgawb (CRTC_ADR, IND_SIS_AGP_IO_PAD);
+ vgawb (CRTC_DATA, 0);
+ vgawb (CRTC_DATA, SIS_AGP_2X);


X
- ivideo.video_bpp = sisbios_mode[mode_idx].bpp;
- ivideo.video_vwidth = ivideo.video_width = sisbios_mode[mode_idx].xres;
- ivideo.video_vheight = ivideo.video_height = sisbios_mode[mode_idx].yres;

- ivideo.org_x = ivideo.org_y = 0;
- video_linelength =


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

echo 'End of part 083'
echo 'File patch-2.4.15 is continued in part 084'
echo "084" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:03 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part087

#!/bin/sh -x
# this is part 087 of a 115 - part archive


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

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

+ k++, next_block++) {
+ if (DQUOT_PREALLOC_BLOCK(inode, 1))
+ break;


+ /* Writer: ->i_prealloc* */

+ if (*prealloc_block + *prealloc_count != next_block ||
+ ext3_set_bit (j + k, bh->b_data)) {


+ /* Writer: end */

+ DQUOT_FREE_BLOCK(inode, 1);
+ break;
+ }
+ (*prealloc_count)++;


+ /* Writer: end */
+ }

+ /*
+ * As soon as we go for per-group spinlocks we'll need these
+ * done inside the loop above.
+ */
+ gdp->bg_free_blocks_count =
+ cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) -
+ (k - 1));
+ es->s_free_blocks_count =
+ cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) -
+ (k - 1));
+ ext3_debug ("Preallocated a further %lu bits.\n",
+ (k - 1));
+ }
+#endif
+
+ j = tmp;
+
+ BUFFER_TRACE(bh, "journal_dirty_metadata for bitmap block");


+ err = ext3_journal_dirty_metadata(handle, bh);
+ if (!fatal) fatal = err;
+

+ if (j >= le32_to_cpu(es->s_blocks_count)) {
+ ext3_error (sb, "ext3_new_block",
+ "block(%d) >= blocks count(%d) - "
+ "block_group = %d, es == %p ",j,
+ le32_to_cpu(es->s_blocks_count), i, es);


+ goto out;
+ }
+

+ /*
+ * It is up to the caller to add the new buffer to a journal
+ * list of some description. We don't know in advance whether
+ * the caller wants to use it as metadata or data.
+ */
+
+ ext3_debug ("allocating block %d. "
+ "Goal hits %d of %d.\n", j, goal_hits, goal_attempts);
+
+ gdp->bg_free_blocks_count =
+ cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - 1);
+ es->s_free_blocks_count =
+ cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - 1);
+
+ BUFFER_TRACE(bh2, "journal_dirty_metadata for group descriptor");
+ err = ext3_journal_dirty_metadata(handle, bh2);


+ if (!fatal) fatal = err;
+

+ BUFFER_TRACE(bh, "journal_dirty_metadata for superblock");
+ err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);


+ if (!fatal) fatal = err;

+
+ sb->s_dirt = 1;

+ if (fatal)
+ goto out;
+
+ unlock_super (sb);
+ *errp = 0;
+ return j;
+
+io_error:
+ *errp = -EIO;
+out:


+ if (fatal) {
+ *errp = fatal;

+ ext3_std_error(sb, fatal);
+ }


+ unlock_super (sb);
+ return 0;
+
+}

+
+unsigned long ext3_count_free_blocks (struct super_block * sb)
+{
+#ifdef EXT3FS_DEBUG


+ struct ext3_super_block * es;

+ unsigned long desc_count, bitmap_count, x;
+ int bitmap_nr;


+ struct ext3_group_desc * gdp;

+ int i;


+
+ lock_super (sb);
+ es = sb->u.ext3_sb.s_es;

+ desc_count = 0;
+ bitmap_count = 0;
+ gdp = NULL;
+ for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
+ gdp = ext3_get_group_desc (sb, i, NULL);
+ if (!gdp)
+ continue;
+ desc_count += le16_to_cpu(gdp->bg_free_blocks_count);


+ bitmap_nr = load_block_bitmap (sb, i);
+ if (bitmap_nr < 0)

+ continue;
+
+ x = ext3_count_free (sb->u.ext3_sb.s_block_bitmap[bitmap_nr],
+ sb->s_blocksize);
+ printk ("group %d: stored = %d, counted = %lu\n",
+ i, le16_to_cpu(gdp->bg_free_blocks_count), x);
+ bitmap_count += x;
+ }
+ printk("ext3_count_free_blocks: stored = %lu, computed = %lu, %lu\n",
+ le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count);
+ unlock_super (sb);
+ return bitmap_count;
+#else
+ return le32_to_cpu(sb->u.ext3_sb.s_es->s_free_blocks_count);
+#endif
+}
+
+static inline int block_in_use (unsigned long block,
+ struct super_block * sb,
+ unsigned char * map)
+{
+ return ext3_test_bit ((block -
+ le32_to_cpu(sb->u.ext3_sb.s_es->s_first_data_block)) %
+ EXT3_BLOCKS_PER_GROUP(sb), map);
+}
+
+static inline int test_root(int a, int b)
+{
+ if (a == 0)
+ return 1;
+ while (1) {
+ if (a == 1)
+ return 1;
+ if (a % b)
+ return 0;
+ a = a / b;
+ }
+}
+
+int ext3_group_sparse(int group)
+{
+ return (test_root(group, 3) || test_root(group, 5) ||
+ test_root(group, 7));
+}
+
+/**
+ * ext3_bg_has_super - number of blocks used by the superblock in group
+ * @sb: superblock for filesystem
+ * @group: group number to check
+ *
+ * Return the number of blocks used by the superblock (primary or backup)
+ * in this group. Currently this will be only 0 or 1.
+ */
+int ext3_bg_has_super(struct super_block *sb, int group)
+{
+ if (EXT3_HAS_RO_COMPAT_FEATURE(sb,EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)&&
+ !ext3_group_sparse(group))
+ return 0;


+ return 1;
+}
+

+/**
+ * ext3_bg_num_gdb - number of blocks used by the group table in group
+ * @sb: superblock for filesystem
+ * @group: group number to check
+ *
+ * Return the number of blocks used by the group descriptor table
+ * (primary or backup) in this group. In the future there may be a
+ * different number of descriptor blocks in each group.
+ */
+unsigned long ext3_bg_num_gdb(struct super_block *sb, int group)
+{
+ if (EXT3_HAS_RO_COMPAT_FEATURE(sb,EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)&&
+ !ext3_group_sparse(group))
+ return 0;
+ return EXT3_SB(sb)->s_gdb_count;
+}
+
+#ifdef CONFIG_EXT3_CHECK
+/* Called at mount-time, super-block is locked */
+void ext3_check_blocks_bitmap (struct super_block * sb)
+{
+ struct buffer_head * bh;


+ struct ext3_super_block * es;

+ unsigned long desc_count, bitmap_count, x, j;
+ unsigned long desc_blocks;
+ int bitmap_nr;


+ struct ext3_group_desc * gdp;

+ int i;
+


+ es = sb->u.ext3_sb.s_es;

+ desc_count = 0;
+ bitmap_count = 0;
+ gdp = NULL;
+ for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
+ gdp = ext3_get_group_desc (sb, i, NULL);
+ if (!gdp)
+ continue;
+ desc_count += le16_to_cpu(gdp->bg_free_blocks_count);


+ bitmap_nr = load_block_bitmap (sb, i);
+ if (bitmap_nr < 0)

+ continue;
+
+ bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
+
+ if (ext3_bg_has_super(sb, i) && !ext3_test_bit(0, bh->b_data))
+ ext3_error(sb, __FUNCTION__,
+ "Superblock in group %d is marked free", i);
+
+ desc_blocks = ext3_bg_num_gdb(sb, i);
+ for (j = 0; j < desc_blocks; j++)
+ if (!ext3_test_bit(j + 1, bh->b_data))
+ ext3_error(sb, __FUNCTION__,
+ "Descriptor block #%ld in group "
+ "%d is marked free", j, i);
+
+ if (!block_in_use (le32_to_cpu(gdp->bg_block_bitmap),
+ sb, bh->b_data))
+ ext3_error (sb, "ext3_check_blocks_bitmap",
+ "Block bitmap for group %d is marked free",
+ i);
+
+ if (!block_in_use (le32_to_cpu(gdp->bg_inode_bitmap),
+ sb, bh->b_data))
+ ext3_error (sb, "ext3_check_blocks_bitmap",
+ "Inode bitmap for group %d is marked free",
+ i);
+
+ for (j = 0; j < sb->u.ext3_sb.s_itb_per_group; j++)
+ if (!block_in_use (le32_to_cpu(gdp->bg_inode_table) + j,
+ sb, bh->b_data))
+ ext3_error (sb, "ext3_check_blocks_bitmap",
+ "Block #%d of the inode table in "
+ "group %d is marked free", j, i);
+
+ x = ext3_count_free (bh, sb->s_blocksize);
+ if (le16_to_cpu(gdp->bg_free_blocks_count) != x)
+ ext3_error (sb, "ext3_check_blocks_bitmap",
+ "Wrong free blocks count for group %d, "
+ "stored = %d, counted = %lu", i,
+ le16_to_cpu(gdp->bg_free_blocks_count), x);
+ bitmap_count += x;
+ }
+ if (le32_to_cpu(es->s_free_blocks_count) != bitmap_count)
+ ext3_error (sb, "ext3_check_blocks_bitmap",
+ "Wrong free blocks count in super block, "
+ "stored = %lu, counted = %lu",
+ (unsigned long)le32_to_cpu(es->s_free_blocks_count),
+ bitmap_count);
+}
+#endif
diff -u --recursive --new-file v2.4.14/linux/fs/ext3/bitmap.c linux/fs/ext3/bitmap.c
--- v2.4.14/linux/fs/ext3/bitmap.c Wed Dec 31 16:00:00 1969
+++ linux/fs/ext3/bitmap.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,26 @@
+/*
+ * linux/fs/ext3/bitmap.c


+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (ca...@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)

+ */
+
+#include <linux/fs.h>
+
+
+static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
+
+unsigned long ext3_count_free (struct buffer_head * map, unsigned int numchars)
+{
+ unsigned int i;
+ unsigned long sum = 0;
+
+ if (!map)
+ return (0);
+ for (i = 0; i < numchars; i++)
+ sum += nibblemap[map->b_data[i] & 0xf] +
+ nibblemap[(map->b_data[i] >> 4) & 0xf];
+ return (sum);
+}
diff -u --recursive --new-file v2.4.14/linux/fs/ext3/dir.c linux/fs/ext3/dir.c
--- v2.4.14/linux/fs/ext3/dir.c Wed Dec 31 16:00:00 1969
+++ linux/fs/ext3/dir.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,190 @@
+/*
+ * linux/fs/ext3/dir.c


+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (ca...@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *

+ * from
+ *

+ * linux/fs/minix/dir.c
+ *


+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *

+ * ext3 directory handling functions
+ *


+ * Big-endian to little-endian byte-swapping/bitmaps by
+ * David S. Miller (da...@caip.rutgers.edu), 1995
+ */
+

+#include <linux/fs.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+

+static unsigned char ext3_filetype_table[] = {
+ DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
+};
+
+static int ext3_readdir(struct file *, void *, filldir_t);
+
+struct file_operations ext3_dir_operations = {
+ read: generic_read_dir,
+ readdir: ext3_readdir, /* BKL held */
+ ioctl: ext3_ioctl, /* BKL held */
+ fsync: ext3_sync_file, /* BKL held */
+};
+
+int ext3_check_dir_entry (const char * function, struct inode * dir,
+ struct ext3_dir_entry_2 * de,


+ struct buffer_head * bh,

+ unsigned long offset)
+{
+ const char * error_msg = NULL;
+ const int rlen = le16_to_cpu(de->rec_len);
+
+ if (rlen < EXT3_DIR_REC_LEN(1))
+ error_msg = "rec_len is smaller than minimal";
+ else if (rlen % 4 != 0)
+ error_msg = "rec_len % 4 != 0";
+ else if (rlen < EXT3_DIR_REC_LEN(de->name_len))
+ error_msg = "rec_len is too small for name_len";
+ else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
+ error_msg = "directory entry across blocks";
+ else if (le32_to_cpu(de->inode) >
+ le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count))
+ error_msg = "inode out of bounds";
+
+ if (error_msg != NULL)
+ ext3_error (dir->i_sb, function,
+ "bad entry in directory #%lu: %s - "
+ "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
+ dir->i_ino, error_msg, offset,
+ (unsigned long) le32_to_cpu(de->inode),
+ rlen, de->name_len);
+ return error_msg == NULL ? 1 : 0;
+}
+
+static int ext3_readdir(struct file * filp,
+ void * dirent, filldir_t filldir)
+{
+ int error = 0;
+ unsigned long offset, blk;
+ int i, num, stored;
+ struct buffer_head * bh, * tmp, * bha[16];


+ struct ext3_dir_entry_2 * de;

+ struct super_block * sb;

+ int err;
+ struct inode *inode = filp->f_dentry->d_inode;


+
+ sb = inode->i_sb;
+

+ stored = 0;
+ bh = NULL;
+ offset = filp->f_pos & (sb->s_blocksize - 1);
+
+ while (!error && !stored && filp->f_pos < inode->i_size) {
+ blk = (filp->f_pos) >> EXT3_BLOCK_SIZE_BITS(sb);
+ bh = ext3_bread (0, inode, blk, 0, &err);
+ if (!bh) {
+ ext3_error (sb, "ext3_readdir",


+ "directory #%lu contains a hole at offset %lu",

+ inode->i_ino, (unsigned long)filp->f_pos);
+ filp->f_pos += sb->s_blocksize - offset;
+ continue;
+ }
+
+ /*
+ * Do the readahead
+ */
+ if (!offset) {
+ for (i = 16 >> (EXT3_BLOCK_SIZE_BITS(sb) - 9), num = 0;
+ i > 0; i--) {
+ tmp = ext3_getblk (NULL, inode, ++blk, 0, &err);
+ if (tmp && !buffer_uptodate(tmp) &&
+ !buffer_locked(tmp))
+ bha[num++] = tmp;
+ else
+ brelse (tmp);
+ }
+ if (num) {
+ ll_rw_block (READA, num, bha);
+ for (i = 0; i < num; i++)
+ brelse (bha[i]);
+ }
+ }
+
+revalidate:
+ /* If the dir block has changed since the last call to
+ * readdir(2), then we might be pointing to an invalid
+ * dirent right now. Scan from the start of the block
+ * to make sure. */
+ if (filp->f_version != inode->i_version) {
+ for (i = 0; i < sb->s_blocksize && i < offset; ) {


+ de = (struct ext3_dir_entry_2 *)

+ (bh->b_data + i);
+ /* It's too expensive to do a full
+ * dirent test each time round this
+ * loop, but we do have to test at
+ * least that it is non-zero. A
+ * failure will be detected in the
+ * dirent test below. */
+ if (le16_to_cpu(de->rec_len) <
+ EXT3_DIR_REC_LEN(1))
+ break;


+ i += le16_to_cpu(de->rec_len);
+ }

+ offset = i;
+ filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
+ | offset;
+ filp->f_version = inode->i_version;
+ }
+
+ while (!error && filp->f_pos < inode->i_size
+ && offset < sb->s_blocksize) {
+ de = (struct ext3_dir_entry_2 *) (bh->b_data + offset);
+ if (!ext3_check_dir_entry ("ext3_readdir", inode, de,
+ bh, offset)) {
+ /* On error, skip the f_pos to the
+ next block. */
+ filp->f_pos = (filp->f_pos |
+ (sb->s_blocksize - 1)) + 1;
+ brelse (bh);
+ return stored;


+ }
+ offset += le16_to_cpu(de->rec_len);

+ if (le32_to_cpu(de->inode)) {
+ /* We might block in the next section
+ * if the data destination is
+ * currently swapped out. So, use a
+ * version stamp to detect whether or
+ * not the directory has been modified
+ * during the copy operation.
+ */
+ unsigned long version = filp->f_version;
+ unsigned char d_type = DT_UNKNOWN;
+
+ if (EXT3_HAS_INCOMPAT_FEATURE(sb,
+ EXT3_FEATURE_INCOMPAT_FILETYPE)
+ && de->file_type < EXT3_FT_MAX)
+ d_type =
+ ext3_filetype_table[de->file_type];
+ error = filldir(dirent, de->name,
+ de->name_len,
+ filp->f_pos,
+ le32_to_cpu(de->inode),
+ d_type);
+ if (error)
+ break;
+ if (version != filp->f_version)
+ goto revalidate;
+ stored ++;
+ }
+ filp->f_pos += le16_to_cpu(de->rec_len);
+ }
+ offset = 0;
+ brelse (bh);
+ }
+ UPDATE_ATIME(inode);
+ return 0;
+}
diff -u --recursive --new-file v2.4.14/linux/fs/ext3/file.c linux/fs/ext3/file.c
--- v2.4.14/linux/fs/ext3/file.c Wed Dec 31 16:00:00 1969
+++ linux/fs/ext3/file.c Thu Nov 15 13:37:55 2001
@@ -0,0 +1,94 @@
+/*
+ * linux/fs/ext3/file.c


+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (ca...@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *

+ * from
+ *

+ * linux/fs/minix/file.c
+ *


+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *

+ * ext3 fs regular file handling primitives
+ *
+ * 64-bit file support on 64-bit platforms by Jakub Jelinek
+ * (j...@sunsite.ms.mff.cuni.cz)
+ */
+
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/locks.h>


+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/ext3_jbd.h>

+#include <linux/smp_lock.h>
+
+/*
+ * Called when an inode is released. Note that this is different
+ * from ext3_file_open: open gets called at every open, but release
+ * gets called only when /all/ the files are closed.
+ */
+static int ext3_release_file (struct inode * inode, struct file * filp)
+{
+ if (filp->f_mode & FMODE_WRITE)
+ ext3_discard_prealloc (inode);


+ return 0;
+}
+

+/*
+ * Called when an inode is about to be opened.
+ * We use this to disallow opening RW large files on 32bit systems if
+ * the caller didn't specify O_LARGEFILE. On 64bit systems we force
+ * on this flag in sys_open.
+ */
+static int ext3_open_file (struct inode * inode, struct file * filp)
+{
+ if (!(filp->f_flags & O_LARGEFILE) &&
+ inode->i_size > 0x7FFFFFFFLL)
+ return -EFBIG;


+ return 0;
+}
+

+/*
+ * ext3_file_write().
+ *
+ * Most things are done in ext3_prepare_write() and ext3_commit_write().
+ */
+
+static ssize_t
+ext3_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+
+ /*
+ * Nasty: if the file is subject to synchronous writes then we need
+ * to force generic_osync_inode() to call ext3_write_inode().
+ * We do that by marking the inode dirty. This adds much more
+ * computational expense than we need, but we're going to sync
+ * anyway.
+ */
+ if (IS_SYNC(inode) || (file->f_flags & O_SYNC))
+ mark_inode_dirty(inode);
+
+ return generic_file_write(file, buf, count, ppos);
+}
+
+struct file_operations ext3_file_operations = {
+ llseek: generic_file_llseek, /* BKL held */
+ read: generic_file_read, /* BKL not held. Don't need */
+ write: ext3_file_write, /* BKL not held. Don't need */
+ ioctl: ext3_ioctl, /* BKL held */
+ mmap: generic_file_mmap,
+ open: ext3_open_file, /* BKL not held. Don't need */
+ release: ext3_release_file, /* BKL not held. Don't need */
+ fsync: ext3_sync_file, /* BKL held */
+};
+
+struct inode_operations ext3_file_inode_operations = {
+ truncate: ext3_truncate, /* BKL held */
+ setattr: ext3_setattr, /* BKL held */
+};
+
diff -u --recursive --new-file v2.4.14/linux/fs/ext3/fsync.c linux/fs/ext3/fsync.c
--- v2.4.14/linux/fs/ext3/fsync.c Wed Dec 31 16:00:00 1969
+++ linux/fs/ext3/fsync.c Tue Nov 20 21:34:13 2001
@@ -0,0 +1,70 @@
+/*
+ * linux/fs/ext3/fsync.c
+ *
+ * Copyright (C) 1993 Stephen Tweedie (s...@redhat.com)
+ * from
+ * Copyright (C) 1992 Remy Card (ca...@masi.ibp.fr)


+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)

+ * from
+ * linux/fs/minix/truncate.c Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * ext3fs fsync primitive
+ *


+ * Big-endian to little-endian byte-swapping/bitmaps by
+ * David S. Miller (da...@caip.rutgers.edu), 1995
+ *

+ * Removed unnecessary code duplication for little endian machines
+ * and excessive __inline__s.
+ * Andi Kleen, 1997
+ *
+ * Major simplications and cleanup - we only need to do the metadata, because
+ * we can depend on generic_block_fdatasync() to sync the data blocks.
+ */
+


+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/ext3_jbd.h>

+#include <linux/jbd.h>
+#include <linux/smp_lock.h>
+
+/*
+ * akpm: A new design for ext3_sync_file().
+ *
+ * This is only called from sys_fsync(), sys_fdatasync() and sys_msync().
+ * There cannot be a transaction open by this task. (AKPM: quotas?)
+ * Another task could have dirtied this inode. Its data can be in any
+ * state in the journalling system.
+ *
+ * What we do is just kick off a commit and wait on it. This will snapshot the
+ * inode to disk.
+ *
+ * Note that there is a serious optimisation we can make here: if the current
+ * inode is not part of j_running_transaction or j_committing_transaction
+ * then we have nothing to do. That would require implementation of t_ilist,
+ * which isn't too hard.
+ */
+
+int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync)
+{
+ struct inode *inode = dentry->d_inode;
+ int ret;
+
+ J_ASSERT(ext3_journal_current_handle() == 0);
+
+ /*
+ * fsync_inode_buffers() just walks i_dirty_buffers and waits
+ * on them. It's a no-op for full data journalling because
+ * i_dirty_buffers will be ampty.
+ * Really, we only need to start I/O on the dirty buffers -
+ * we'll end up waiting on them in commit.
+ */
+ ret = fsync_inode_buffers(inode);
+ ret |= fsync_inode_data_buffers(inode);
+
+ ext3_force_commit(inode->i_sb);


+
+ return ret;
+}

diff -u --recursive --new-file v2.4.14/linux/fs/ext3/ialloc.c linux/fs/ext3/ialloc.c
--- v2.4.14/linux/fs/ext3/ialloc.c Wed Dec 31 16:00:00 1969
+++ linux/fs/ext3/ialloc.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,664 @@
+/*
+ * linux/fs/ext3/ialloc.c


+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (ca...@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *

+ * BSD ufs-inspired inode and directory allocation by
+ * Stephen Tweedie (s...@redhat.com), 1993


+ * Big-endian to little-endian byte-swapping/bitmaps by
+ * David S. Miller (da...@caip.rutgers.edu), 1995
+ */
+

+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/ext3_jbd.h>

+#include <linux/stat.h>
+#include <linux/string.h>


+#include <linux/locks.h>
+#include <linux/quotaops.h>
+

+#include <asm/bitops.h>
+#include <asm/byteorder.h>
+
+/*
+ * ialloc.c contains the inodes allocation and deallocation routines
+ */
+
+/*
+ * The free inodes are managed by bitmaps. A file system contains several


+ * blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap
+ * block for inodes, N blocks for the inode table and data blocks.
+ *
+ * The file system contains group descriptors which are located after the
+ * super block. Each descriptor contains the number of the bitmap block and
+ * the free blocks count in the block. The descriptors are loaded in memory
+ * when a file system is mounted (see ext3_read_super).
+ */
+
+

+/*
+ * Read the inode allocation bitmap for a given block_group, reading
+ * into the specified slot in the superblock's bitmap cache.


+ *
+ * Return >=0 on success or a -ve error code.
+ */

+static int read_inode_bitmap (struct super_block * sb,
+ unsigned long block_group,
+ unsigned int bitmap_nr)


+{
+ struct ext3_group_desc * gdp;
+ struct buffer_head * bh = NULL;

+ int retval = 0;


+
+ gdp = ext3_get_group_desc (sb, block_group, NULL);
+ if (!gdp) {

+ retval = -EIO;
+ goto error_out;
+ }


+ bh = bread (sb->s_dev,

+ le32_to_cpu(gdp->bg_inode_bitmap), sb->s_blocksize);
+ if (!bh) {
+ ext3_error (sb, "read_inode_bitmap",
+ "Cannot read inode bitmap - "
+ "block_group = %lu, inode_bitmap = %lu",
+ block_group, (unsigned long) gdp->bg_inode_bitmap);


+ retval = -EIO;
+ }
+ /*
+ * On IO error, just leave a zero in the superblock's block pointer for
+ * this group. The IO will be retried next time.
+ */
+error_out:

+ sb->u.ext3_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
+ sb->u.ext3_sb.s_inode_bitmap[bitmap_nr] = bh;


+ return retval;
+}
+
+/*

+ * load_inode_bitmap loads the inode bitmap for a blocks group


+ *
+ * It maintains a cache for the last bitmaps loaded. This cache is managed
+ * with a LRU algorithm.
+ *
+ * Notes:
+ * 1/ There is one cache per mounted file system.
+ * 2/ If the file system contains less than EXT3_MAX_GROUP_LOADED groups,
+ * this function reads the bitmap without maintaining a LRU cache.
+ *
+ * Return the slot used to store the bitmap, or a -ve error code.
+ */

+static int load_inode_bitmap (struct super_block * sb,


+ unsigned int block_group)
+{

+ struct ext3_sb_info *sbi = EXT3_SB(sb);

+ unsigned long inode_bitmap_number;
+ struct buffer_head * inode_bitmap;


+ int i, j, retval = 0;
+

+ if (block_group >= sbi->s_groups_count)

+ ext3_panic (sb, "load_inode_bitmap",


+ "block_group >= groups_count - "
+ "block_group = %d, groups_count = %lu",

+ block_group, sbi->s_groups_count);


+ if (sbi->s_loaded_inode_bitmaps > 0 &&
+ sbi->s_inode_bitmap_number[0] == block_group &&

+ sbi->s_inode_bitmap[0] != NULL)
+ return 0;
+ if (sbi->s_groups_count <= EXT3_MAX_GROUP_LOADED) {
+ if (sbi->s_inode_bitmap[block_group]) {
+ if (sbi->s_inode_bitmap_number[block_group] !=
+ block_group)
+ ext3_panic(sb, "load_inode_bitmap",


+ "block_group != inode_bitmap_number");

+ return block_group;
+ }
+ retval = read_inode_bitmap(sb, block_group, block_group);


+ if (retval < 0)
+ return retval;
+ return block_group;
+ }
+

+ for (i = 0; i < sbi->s_loaded_inode_bitmaps &&

+ sbi->s_inode_bitmap_number[i] != block_group; i++)
+ /* do nothing */;
+ if (i < sbi->s_loaded_inode_bitmaps &&
+ sbi->s_inode_bitmap_number[i] == block_group) {
+ inode_bitmap_number = sbi->s_inode_bitmap_number[i];
+ inode_bitmap = sbi->s_inode_bitmap[i];


+ for (j = i; j > 0; j--) {

+ sbi->s_inode_bitmap_number[j] =
+ sbi->s_inode_bitmap_number[j - 1];
+ sbi->s_inode_bitmap[j] = sbi->s_inode_bitmap[j - 1];
+ }
+ sbi->s_inode_bitmap_number[0] = inode_bitmap_number;
+ sbi->s_inode_bitmap[0] = inode_bitmap;
+
+ /*
+ * There's still one special case here --- if inode_bitmap == 0


+ * then our last attempt to read the bitmap failed and we have
+ * just ended up caching that failure. Try again to read it.
+ */

+ if (!inode_bitmap)
+ retval = read_inode_bitmap (sb, block_group, 0);
+ } else {
+ if (sbi->s_loaded_inode_bitmaps < EXT3_MAX_GROUP_LOADED)


+ sbi->s_loaded_inode_bitmaps++;
+ else

+ brelse(sbi->s_inode_bitmap[EXT3_MAX_GROUP_LOADED - 1]);
+ for (j = sbi->s_loaded_inode_bitmaps - 1; j > 0; j--) {
+ sbi->s_inode_bitmap_number[j] =
+ sbi->s_inode_bitmap_number[j - 1];
+ sbi->s_inode_bitmap[j] = sbi->s_inode_bitmap[j - 1];
+ }
+ retval = read_inode_bitmap (sb, block_group, 0);


+ }
+ return retval;
+}
+
+/*

+ * NOTE! When we get the inode, we're the only people
+ * that have access to it, and as such there are no
+ * race conditions we have to worry about. The inode
+ * is not on the hash-lists, and it cannot be reached
+ * through the filesystem because the directory entry
+ * has been deleted earlier.
+ *
+ * HOWEVER: we must make sure that we get no aliases,
+ * which means that we have to call "clear_inode()"
+ * _before_ we mark the inode not in use in the inode
+ * bitmaps. Otherwise a newly created file might use
+ * the same inode number (not actually the same pointer
+ * though), and then we'd have two inodes sharing the
+ * same inode number and space on the harddisk.
+ */
+void ext3_free_inode (handle_t *handle, struct inode * inode)
+{
+ struct super_block * sb = inode->i_sb;
+ int is_directory;
+ unsigned long ino;
+ struct buffer_head * bh;


+ struct buffer_head * bh2;

+ unsigned long block_group;
+ unsigned long bit;

+ int bitmap_nr;


+ struct ext3_group_desc * gdp;
+ struct ext3_super_block * es;

+ int fatal = 0, err;
+

+ if (!inode->i_dev) {
+ printk ("ext3_free_inode: inode has no device\n");
+ return;
+ }
+ if (atomic_read(&inode->i_count) > 1) {
+ printk ("ext3_free_inode: inode has count=%d\n",
+ atomic_read(&inode->i_count));
+ return;
+ }
+ if (inode->i_nlink) {
+ printk ("ext3_free_inode: inode has nlink=%d\n",
+ inode->i_nlink);
+ return;
+ }
+ if (!sb) {
+ printk("ext3_free_inode: inode on nonexistent device\n");
+ return;
+ }
+
+ ino = inode->i_ino;
+ ext3_debug ("freeing inode %lu\n", ino);
+
+ /*
+ * Note: we must free any quota before locking the superblock,
+ * as writing the quota to disk may need the lock as well.
+ */
+ DQUOT_INIT(inode);
+ DQUOT_FREE_INODE(inode);
+ DQUOT_DROP(inode);
+
+ is_directory = S_ISDIR(inode->i_mode);
+
+ /* Do this BEFORE marking the inode not in use or returning an error */
+ clear_inode (inode);


+
+ lock_super (sb);
+ es = sb->u.ext3_sb.s_es;

+ if (ino < EXT3_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
+ ext3_error (sb, "ext3_free_inode",
+ "reserved or nonexistent inode %lu", ino);
+ goto error_return;
+ }
+ block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb);
+ bit = (ino - 1) % EXT3_INODES_PER_GROUP(sb);
+ bitmap_nr = load_inode_bitmap (sb, block_group);


+ if (bitmap_nr < 0)
+ goto error_return;
+

+ bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr];
+
+ BUFFER_TRACE(bh, "get_write_access");
+ fatal = ext3_journal_get_write_access(handle, bh);
+ if (fatal)
+ goto error_return;
+
+ /* Ok, now we can actually update the inode bitmaps.. */
+ if (!ext3_clear_bit (bit, bh->b_data))
+ ext3_error (sb, "ext3_free_inode",
+ "bit already cleared for inode %lu", ino);
+ else {
+ gdp = ext3_get_group_desc (sb, block_group, &bh2);


+
+ BUFFER_TRACE(bh2, "get_write_access");
+ fatal = ext3_journal_get_write_access(handle, bh2);

+ if (fatal) goto error_return;
+
+ BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get write access");


+ fatal = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);

+ if (fatal) goto error_return;
+
+ if (gdp) {
+ gdp->bg_free_inodes_count = cpu_to_le16(
+ le16_to_cpu(gdp->bg_free_inodes_count) + 1);
+ if (is_directory)
+ gdp->bg_used_dirs_count = cpu_to_le16(
+ le16_to_cpu(gdp->bg_used_dirs_count) - 1);
+ }
+ BUFFER_TRACE(bh2, "call ext3_journal_dirty_metadata");
+ err = ext3_journal_dirty_metadata(handle, bh2);


+ if (!fatal) fatal = err;

+ es->s_free_inodes_count =
+ cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
+ BUFFER_TRACE(sb->u.ext3_sb.s_sbh,
+ "call ext3_journal_dirty_metadata");
+ err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);


+ if (!fatal) fatal = err;
+ }

+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
+ err = ext3_journal_dirty_metadata(handle, bh);
+ if (!fatal)
+ fatal = err;


+ sb->s_dirt = 1;
+error_return:

+ ext3_std_error(sb, fatal);
+ unlock_super(sb);
+}
+
+/*
+ * There are two policies for allocating an inode. If the new inode is
+ * a directory, then a forward search is made for a block group with both
+ * free space and a low directory-to-inode ratio; if that fails, then of
+ * the groups with above-average free space, that group with the fewest
+ * directories already is chosen.
+ *
+ * For other inodes, search forward from the parent directory's block
+ * group to find a free inode.
+ */
+struct inode * ext3_new_inode (handle_t *handle,
+ const struct inode * dir, int mode)
+{


+ struct super_block * sb;

+ struct buffer_head * bh;


+ struct buffer_head * bh2;

+ int i, j, avefreei;


+ struct inode * inode;

+ int bitmap_nr;


+ struct ext3_group_desc * gdp;

+ struct ext3_group_desc * tmp;


+ struct ext3_super_block * es;

+ int err = 0;
+
+ /* Cannot create files in a deleted directory */
+ if (!dir || !dir->i_nlink)
+ return ERR_PTR(-EPERM);


+
+ sb = dir->i_sb;

+ inode = new_inode(sb);
+ if (!inode)
+ return ERR_PTR(-ENOMEM);
+ init_rwsem(&inode->u.ext3_i.truncate_sem);


+
+ lock_super (sb);
+ es = sb->u.ext3_sb.s_es;

+repeat:
+ gdp = NULL;


+ i = 0;
+

+ if (S_ISDIR(mode)) {
+ avefreei = le32_to_cpu(es->s_free_inodes_count) /
+ sb->u.ext3_sb.s_groups_count;
+ if (!gdp) {
+ for (j = 0; j < sb->u.ext3_sb.s_groups_count; j++) {
+ struct buffer_head *temp_buffer;
+ tmp = ext3_get_group_desc (sb, j, &temp_buffer);
+ if (tmp &&
+ le16_to_cpu(tmp->bg_free_inodes_count) &&
+ le16_to_cpu(tmp->bg_free_inodes_count) >=
+ avefreei) {
+ if (!gdp || (le16_to_cpu(tmp->bg_free_blocks_count) >
+ le16_to_cpu(gdp->bg_free_blocks_count))) {
+ i = j;
+ gdp = tmp;
+ bh2 = temp_buffer;
+ }
+ }
+ }
+ }
+ } else {


+ /*
+ * Try to place the inode in its parent directory
+ */

+ i = dir->u.ext3_i.i_block_group;
+ tmp = ext3_get_group_desc (sb, i, &bh2);
+ if (tmp && le16_to_cpu(tmp->bg_free_inodes_count))
+ gdp = tmp;
+ else


+ {
+ /*
+ * Use a quadratic hash to find a group with a
+ * free inode
+ */

+ for (j = 1; j < sb->u.ext3_sb.s_groups_count; j <<= 1) {
+ i += j;


+ if (i >= sb->u.ext3_sb.s_groups_count)

+ i -= sb->u.ext3_sb.s_groups_count;
+ tmp = ext3_get_group_desc (sb, i, &bh2);
+ if (tmp &&
+ le16_to_cpu(tmp->bg_free_inodes_count)) {
+ gdp = tmp;


+ break;
+ }
+ }
+ }

+ if (!gdp) {


+ /*
+ * That failed: try linear search for a free inode
+ */

+ i = dir->u.ext3_i.i_block_group + 1;
+ for (j = 2; j < sb->u.ext3_sb.s_groups_count; j++) {
+ if (++i >= sb->u.ext3_sb.s_groups_count)
+ i = 0;
+ tmp = ext3_get_group_desc (sb, i, &bh2);
+ if (tmp &&
+ le16_to_cpu(tmp->bg_free_inodes_count)) {
+ gdp = tmp;


+ break;
+ }
+ }
+ }
+ }

+
+ err = -ENOSPC;
+ if (!gdp)
+ goto fail;
+
+ err = -EIO;
+ bitmap_nr = load_inode_bitmap (sb, i);
+ if (bitmap_nr < 0)
+ goto fail;
+
+ bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr];
+
+ if ((j = ext3_find_first_zero_bit ((unsigned long *) bh->b_data,
+ EXT3_INODES_PER_GROUP(sb))) <
+ EXT3_INODES_PER_GROUP(sb)) {
+ BUFFER_TRACE(bh, "get_write_access");
+ err = ext3_journal_get_write_access(handle, bh);
+ if (err) goto fail;
+
+ if (ext3_set_bit (j, bh->b_data)) {
+ ext3_error (sb, "ext3_new_inode",
+ "bit already set for inode %d", j);
+ goto repeat;
+ }
+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
+ err = ext3_journal_dirty_metadata(handle, bh);
+ if (err) goto fail;
+ } else {
+ if (le16_to_cpu(gdp->bg_free_inodes_count) != 0) {
+ ext3_error (sb, "ext3_new_inode",


+ "Free inodes count corrupted in group %d",

+ i);


+ /* Is it really ENOSPC? */
+ err = -ENOSPC;
+ if (sb->s_flags & MS_RDONLY)
+ goto fail;
+

+ BUFFER_TRACE(bh2, "get_write_access");
+ err = ext3_journal_get_write_access(handle, bh2);
+ if (err) goto fail;
+ gdp->bg_free_inodes_count = 0;
+ BUFFER_TRACE(bh2, "call ext3_journal_dirty_metadata");
+ err = ext3_journal_dirty_metadata(handle, bh2);
+ if (err) goto fail;
+ }
+ goto repeat;
+ }
+ j += i * EXT3_INODES_PER_GROUP(sb) + 1;
+ if (j < EXT3_FIRST_INO(sb) || j > le32_to_cpu(es->s_inodes_count)) {
+ ext3_error (sb, "ext3_new_inode",
+ "reserved inode or inode > inodes count - "
+ "block_group = %d,inode=%d", i, j);
+ err = -EIO;


+ goto fail;
+ }
+

+ BUFFER_TRACE(bh2, "get_write_access");
+ err = ext3_journal_get_write_access(handle, bh2);
+ if (err) goto fail;
+ gdp->bg_free_inodes_count =
+ cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
+ if (S_ISDIR(mode))
+ gdp->bg_used_dirs_count =
+ cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
+ BUFFER_TRACE(bh2, "call ext3_journal_dirty_metadata");
+ err = ext3_journal_dirty_metadata(handle, bh2);
+ if (err) goto fail;


+
+ BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
+ err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);

+ if (err) goto fail;
+ es->s_free_inodes_count =
+ cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1);
+ BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "call ext3_journal_dirty_metadata");
+ err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);


+ sb->s_dirt = 1;

+ if (err) goto fail;
+
+ inode->i_uid = current->fsuid;
+ if (test_opt (sb, GRPID))
+ inode->i_gid = dir->i_gid;
+ else if (dir->i_mode & S_ISGID) {
+ inode->i_gid = dir->i_gid;
+ if (S_ISDIR(mode))
+ mode |= S_ISGID;
+ } else
+ inode->i_gid = current->fsgid;
+ inode->i_mode = mode;
+
+ inode->i_ino = j;
+ /* This is the optimal IO size (for stat), not the fs block size */


+ inode->i_blksize = PAGE_SIZE;

+ inode->i_blocks = 0;

+ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->u.ext3_i.i_flags = dir->u.ext3_i.i_flags & ~EXT3_INDEX_FL;
+ if (S_ISLNK(mode))
+ inode->u.ext3_i.i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL);
+#ifdef EXT3_FRAGMENTS
+ inode->u.ext3_i.i_faddr = 0;
+ inode->u.ext3_i.i_frag_no = 0;
+ inode->u.ext3_i.i_frag_size = 0;
+#endif
+ inode->u.ext3_i.i_file_acl = 0;
+ inode->u.ext3_i.i_dir_acl = 0;
+ inode->u.ext3_i.i_dtime = 0;
+ INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);


+#ifdef EXT3_PREALLOCATE
+ inode->u.ext3_i.i_prealloc_count = 0;
+#endif

+ inode->u.ext3_i.i_block_group = i;
+
+ if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL)


+ inode->i_flags |= S_SYNC;

+ if (IS_SYNC(inode))
+ handle->h_sync = 1;

+ insert_inode_hash(inode);
+ inode->i_generation = event++;
+
+ inode->u.ext3_i.i_state = EXT3_STATE_NEW;


+ err = ext3_mark_inode_dirty(handle, inode);

+ if (err) goto fail;
+
+ unlock_super (sb);
+ if(DQUOT_ALLOC_INODE(inode)) {
+ DQUOT_DROP(inode);
+ inode->i_flags |= S_NOQUOTA;


+ inode->i_nlink = 0;

+ iput(inode);
+ return ERR_PTR(-EDQUOT);
+ }
+ ext3_debug ("allocating inode %lu\n", inode->i_ino);
+ return inode;
+
+fail:
+ unlock_super(sb);
+ iput(inode);
+ ext3_std_error(sb, err);
+ return ERR_PTR(err);
+}
+
+/* Verify that we are loading a valid orphan from disk */
+struct inode *ext3_orphan_get (struct super_block * sb, ino_t ino)
+{
+ ino_t max_ino = le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count);
+ unsigned long block_group;
+ int bit;
+ int bitmap_nr;
+ struct buffer_head *bh;
+ struct inode *inode = NULL;
+
+ /* Error cases - e2fsck has already cleaned up for us */
+ if (ino > max_ino) {
+ ext3_warning(sb, __FUNCTION__,
+ "bad orphan ino %ld! e2fsck was run?\n", ino);


+ return NULL;
+ }
+

+ block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb);
+ bit = (ino - 1) % EXT3_INODES_PER_GROUP(sb);
+ if ((bitmap_nr = load_inode_bitmap(sb, block_group)) < 0 ||
+ !(bh = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr])) {
+ ext3_warning(sb, __FUNCTION__,
+ "inode bitmap error for orphan %ld\n", ino);


+ return NULL;
+ }
+

+ /* Having the inode bit set should be a 100% indicator that this
+ * is a valid orphan (no e2fsck run on fs). Orphans also include
+ * inodes that were being truncated, so we can't check i_nlink==0.
+ */
+ if (!ext3_test_bit(bit, bh->b_data) || !(inode = iget(sb, ino)) ||
+ is_bad_inode(inode) || NEXT_ORPHAN(inode) > max_ino) {
+ ext3_warning(sb, __FUNCTION__,
+ "bad orphan inode %ld! e2fsck was run?\n", ino);
+ printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%ld) = %d\n",
+ bit, bh->b_blocknr, ext3_test_bit(bit, bh->b_data));
+ printk(KERN_NOTICE "inode=%p\n", inode);
+ if (inode) {
+ printk(KERN_NOTICE "is_bad_inode(inode)=%d\n",
+ is_bad_inode(inode));
+ printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%d\n",
+ NEXT_ORPHAN(inode));
+ printk(KERN_NOTICE "max_ino=%ld\n", max_ino);
+ }
+ /* Avoid freeing blocks if we got a bad deleted inode */
+ if (inode && inode->i_nlink == 0)


+ inode->i_blocks = 0;

+ iput(inode);


+ return NULL;
+ }
+

+ return inode;
+}
+
+unsigned long ext3_count_free_inodes (struct super_block * sb)
+{
+#ifdef EXT3FS_DEBUG


+ struct ext3_super_block * es;

+ unsigned long desc_count, bitmap_count, x;
+ int bitmap_nr;


+ struct ext3_group_desc * gdp;

+ int i;


+
+ lock_super (sb);
+ es = sb->u.ext3_sb.s_es;

+ desc_count = 0;
+ bitmap_count = 0;
+ gdp = NULL;
+ for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
+ gdp = ext3_get_group_desc (sb, i, NULL);
+ if (!gdp)
+ continue;
+ desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
+ bitmap_nr = load_inode_bitmap (sb, i);
+ if (bitmap_nr < 0)
+ continue;
+
+ x = ext3_count_free (sb->u.ext3_sb.s_inode_bitmap[bitmap_nr],
+ EXT3_INODES_PER_GROUP(sb) / 8);
+ printk ("group %d: stored = %d, counted = %lu\n",
+ i, le16_to_cpu(gdp->bg_free_inodes_count), x);
+ bitmap_count += x;
+ }
+ printk("ext3_count_free_inodes: stored = %lu, computed = %lu, %lu\n",
+ le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count);
+ unlock_super (sb);
+ return desc_count;
+#else
+ return le32_to_cpu(sb->u.ext3_sb.s_es->s_free_inodes_count);
+#endif
+}
+
+#ifdef CONFIG_EXT3_CHECK
+/* Called at mount-time, super-block is locked */
+void ext3_check_inodes_bitmap (struct super_block * sb)
+{


+ struct ext3_super_block * es;

+ unsigned long desc_count, bitmap_count, x;
+ int bitmap_nr;


+ struct ext3_group_desc * gdp;

+ int i;
+


+ es = sb->u.ext3_sb.s_es;

+ desc_count = 0;
+ bitmap_count = 0;
+ gdp = NULL;
+ for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
+ gdp = ext3_get_group_desc (sb, i, NULL);
+ if (!gdp)
+ continue;
+ desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
+ bitmap_nr = load_inode_bitmap (sb, i);
+ if (bitmap_nr < 0)
+ continue;
+
+ x = ext3_count_free (sb->u.ext3_sb.s_inode_bitmap[bitmap_nr],
+ EXT3_INODES_PER_GROUP(sb) / 8);
+ if (le16_to_cpu(gdp->bg_free_inodes_count) != x)
+ ext3_error (sb, "ext3_check_inodes_bitmap",
+ "Wrong free inodes count in group %d, "
+ "stored = %d, counted = %lu", i,
+ le16_to_cpu(gdp->bg_free_inodes_count), x);
+ bitmap_count += x;
+ }
+ if (le32_to_cpu(es->s_free_inodes_count) != bitmap_count)
+ ext3_error (sb, "ext3_check_inodes_bitmap",
+ "Wrong free inodes count in super block, "
+ "stored = %lu, counted = %lu",
+ (unsigned long)le32_to_cpu(es->s_free_inodes_count),
+ bitmap_count);
+}
+#endif
diff -u --recursive --new-file v2.4.14/linux/fs/ext3/inode.c linux/fs/ext3/inode.c
--- v2.4.14/linux/fs/ext3/inode.c Wed Dec 31 16:00:00 1969
+++ linux/fs/ext3/inode.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,2672 @@
+/*
+ * linux/fs/ext3/inode.c


+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (ca...@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *

+ * from
+ *
+ * linux/fs/minix/inode.c

+ *


+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *

+ * Goal-directed block allocation by Stephen Tweedie
+ * (s...@redhat.com), 1993, 1998


+ * Big-endian to little-endian byte-swapping/bitmaps by
+ * David S. Miller (da...@caip.rutgers.edu), 1995

+ * 64-bit file support on 64-bit platforms by Jakub Jelinek
+ * (j...@sunsite.ms.mff.cuni.cz)
+ *
+ * Assorted race fixes, rewrite of ext3_get_block() by Al Viro, 2000


+ */
+
+#include <linux/fs.h>
+#include <linux/sched.h>

+#include <linux/ext3_jbd.h>
+#include <linux/jbd.h>
+#include <linux/locks.h>
+#include <linux/smp_lock.h>
+#include <linux/highuid.h>
+#include <linux/quotaops.h>
+#include <linux/module.h>
+
+
+/*
+ * SEARCH_FROM_ZERO forces each block allocation to search from the start
+ * of the filesystem. This is to force rapid reallocation of recently-freed
+ * blocks. The file fragmentation is horrendous.
+ */
+#undef SEARCH_FROM_ZERO
+
+/* The ext3 forget function must perform a revoke if we are freeing data
+ * which has been journaled. Metadata (eg. indirect blocks) must be
+ * revoked in all cases.
+ *
+ * "bh" may be NULL: a metadata block may have been freed from memory
+ * but there may still be a record of it in the journal, and that record
+ * still needs to be revoked.
+ */
+
+static int ext3_forget(handle_t *handle, int is_metadata,
+ struct inode *inode, struct buffer_head *bh,
+ int blocknr)
+{
+ int err;
+
+ BUFFER_TRACE(bh, "enter");
+
+ jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
+ "data mode %lx\n",
+ bh, is_metadata, inode->i_mode,
+ test_opt(inode->i_sb, DATA_FLAGS));
+
+ /* Never use the revoke function if we are doing full data
+ * journaling: there is no need to, and a V1 superblock won't
+ * support it. Otherwise, only skip the revoke on un-journaled
+ * data blocks. */
+
+ if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA ||
+ (!is_metadata && !ext3_should_journal_data(inode))) {
+ if (bh) {
+ BUFFER_TRACE(bh, "call journal_forget");
+ ext3_journal_forget(handle, bh);
+ }


+ return 0;
+ }
+
+ /*

+ * data!=journal && (is_metadata || should_journal_data(inode))
+ */
+ BUFFER_TRACE(bh, "call ext3_journal_revoke");
+ err = ext3_journal_revoke(handle, blocknr, bh);
+ if (err)
+ ext3_abort(inode->i_sb, __FUNCTION__,
+ "error %d when attempting revoke", err);
+ BUFFER_TRACE(bh, "exit");
+ return err;
+}
+
+/*
+ * Truncate transactions can be complex and absolutely huge. So we need to
+ * be able to restart the transaction at a conventient checkpoint to make
+ * sure we don't overflow the journal.
+ *
+ * start_transaction gets us a new handle for a truncate transaction,
+ * and extend_transaction tries to extend the existing one a bit. If
+ * extend fails, we need to propagate the failure up and restart the
+ * transaction in the top-level truncate loop. --sct
+ */
+
+static handle_t *start_transaction(struct inode *inode)
+{
+ long needed;
+ handle_t *result;
+
+ needed = inode->i_blocks;
+ if (needed > EXT3_MAX_TRANS_DATA)
+ needed = EXT3_MAX_TRANS_DATA;
+
+ result = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS + needed);
+ if (!IS_ERR(result))
+ return result;
+
+ ext3_std_error(inode->i_sb, PTR_ERR(result));
+ return result;
+}
+
+/*
+ * Try to extend this transaction for the purposes of truncation.
+ *
+ * Returns 0 if we managed to create more room. If we can't create more
+ * room, and the transaction must be restarted we return 1.
+ */
+static int try_to_extend_transaction(handle_t *handle, struct inode *inode)
+{
+ long needed;
+
+ if (handle->h_buffer_credits > EXT3_RESERVE_TRANS_BLOCKS)
+ return 0;
+ needed = inode->i_blocks;
+ if (needed > EXT3_MAX_TRANS_DATA)
+ needed = EXT3_MAX_TRANS_DATA;
+ if (!ext3_journal_extend(handle, EXT3_RESERVE_TRANS_BLOCKS + needed))
+ return 0;
+ return 1;
+}
+
+/*
+ * Restart the transaction associated with *handle. This does a commit,
+ * so before we call here everything must be consistently dirtied against
+ * this transaction.
+ */
+static int ext3_journal_test_restart(handle_t *handle, struct inode *inode)
+{
+ long needed = inode->i_blocks;
+ if (needed > EXT3_MAX_TRANS_DATA)
+ needed = EXT3_MAX_TRANS_DATA;
+ jbd_debug(2, "restarting handle %p\n", handle);
+ return ext3_journal_restart(handle, EXT3_DATA_TRANS_BLOCKS + needed);
+}
+
+/*
+ * Called at each iput()
+ */
+void ext3_put_inode (struct inode * inode)
+{
+ ext3_discard_prealloc (inode);
+}
+
+/*
+ * Called at the last iput() if i_nlink is zero.
+ */
+void ext3_delete_inode (struct inode * inode)
+{
+ handle_t *handle;
+
+ if (is_bad_inode(inode) ||
+ inode->i_ino == EXT3_ACL_IDX_INO ||


+ inode->i_ino == EXT3_ACL_DATA_INO)

+ goto no_delete;
+
+ lock_kernel();
+ handle = start_transaction(inode);
+ if (IS_ERR(handle)) {
+ /* If we're going to skip the normal cleanup, we still
+ * need to make sure that the in-core orphan linked list
+ * is properly cleaned up. */
+ ext3_orphan_del(NULL, inode);
+
+ ext3_std_error(inode->i_sb, PTR_ERR(handle));
+ unlock_kernel();
+ goto no_delete;
+ }
+

+ if (IS_SYNC(inode))
+ handle->h_sync = 1;

+ inode->i_size = 0;

+ if (inode->i_blocks)
+ ext3_truncate(inode);
+ /*
+ * Kill off the orphan record which ext3_truncate created.
+ * AKPM: I think this can be inside the above `if'.
+ * Note that ext3_orphan_del() has to be able to cope with the
+ * deletion of a non-existent orphan - this is because we don't
+ * know if ext3_truncate() actually created an orphan record.
+ * (Well, we could do this if we need to, but heck - it works)
+ */
+ ext3_orphan_del(handle, inode);
+ inode->u.ext3_i.i_dtime = CURRENT_TIME;
+
+ /*
+ * One subtle ordering requirement: if anything has gone wrong
+ * (transaction abort, IO errors, whatever), then we can still
+ * do these next steps (the fs will already have been marked as
+ * having errors), but we can't free the inode if the mark_dirty
+ * fails.
+ */
+ if (ext3_mark_inode_dirty(handle, inode))
+ /* If that failed, just do the required in-core inode clear. */
+ clear_inode(inode);
+ else
+ ext3_free_inode(handle, inode);
+ ext3_journal_stop(handle, inode);
+ unlock_kernel();
+ return;
+no_delete:
+ clear_inode(inode); /* We must guarantee clearing of inode... */
+}
+
+void ext3_discard_prealloc (struct inode * inode)
+{
+#ifdef EXT3_PREALLOCATE
+ lock_kernel();


+ /* Writer: ->i_prealloc* */

+ if (inode->u.ext3_i.i_prealloc_count) {
+ unsigned short total = inode->u.ext3_i.i_prealloc_count;
+ unsigned long block = inode->u.ext3_i.i_prealloc_block;


+ inode->u.ext3_i.i_prealloc_count = 0;

+ inode->u.ext3_i.i_prealloc_block = 0;


+ /* Writer: end */

+ ext3_free_blocks (inode, block, total);
+ }
+ unlock_kernel();
+#endif
+}
+
+static int ext3_alloc_block (handle_t *handle,
+ struct inode * inode, unsigned long goal, int *err)
+{
+#ifdef EXT3FS_DEBUG
+ static unsigned long alloc_hits = 0, alloc_attempts = 0;
+#endif
+ unsigned long result;
+
+#ifdef EXT3_PREALLOCATE


+ /* Writer: ->i_prealloc* */

+ if (inode->u.ext3_i.i_prealloc_count &&
+ (goal == inode->u.ext3_i.i_prealloc_block ||
+ goal + 1 == inode->u.ext3_i.i_prealloc_block))
+ {
+ result = inode->u.ext3_i.i_prealloc_block++;
+ inode->u.ext3_i.i_prealloc_count--;


+ /* Writer: end */

+ ext3_debug ("preallocation hit (%lu/%lu).\n",
+ ++alloc_hits, ++alloc_attempts);
+ } else {
+ ext3_discard_prealloc (inode);
+ ext3_debug ("preallocation miss (%lu/%lu).\n",
+ alloc_hits, ++alloc_attempts);
+ if (S_ISREG(inode->i_mode))
+ result = ext3_new_block (inode, goal,
+ &inode->u.ext3_i.i_prealloc_count,
+ &inode->u.ext3_i.i_prealloc_block, err);
+ else
+ result = ext3_new_block (inode, goal, 0, 0, err);
+ /*
+ * AKPM: this is somewhat sticky. I'm not surprised it was
+ * disabled in 2.2's ext3. Need to integrate b_committed_data
+ * guarding with preallocation, if indeed preallocation is
+ * effective.
+ */
+ }
+#else
+ result = ext3_new_block (handle, inode, goal, 0, 0, err);
+#endif
+ return result;
+}
+
+
+typedef struct {
+ u32 *p;
+ u32 key;
+ struct buffer_head *bh;
+} Indirect;
+
+static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v)
+{
+ p->key = *(p->p = v);
+ p->bh = bh;
+}
+
+static inline int verify_chain(Indirect *from, Indirect *to)
+{
+ while (from <= to && from->key == *from->p)
+ from++;
+ return (from > to);
+}
+
+/**
+ * ext3_block_to_path - parse the block number into array of offsets
+ * @inode: inode in question (we are only interested in its superblock)
+ * @i_block: block number to be parsed
+ * @offsets: array to store the offsets in
+ *
+ * To store the locations of file's data ext3 uses a data structure common
+ * for UNIX filesystems - tree of pointers anchored in the inode, with
+ * data blocks at leaves and indirect blocks in intermediate nodes.
+ * This function translates the block number into path in that tree -
+ * return value is the path length and @offsets[n] is the offset of
+ * pointer to (n+1)th node in the nth one. If @block is out of range
+ * (negative or too large) warning is printed and zero returned.
+ *
+ * Note: function doesn't find node addresses, so no IO is needed. All
+ * we need to know is the capacity of indirect blocks (taken from the
+ * inode->i_sb).
+ */
+
+/*
+ * Portability note: the last comparison (check that we fit into triple
+ * indirect block) is spelled differently, because otherwise on an
+ * architecture with 32-bit longs and 8Kb pages we might get into trouble
+ * if our filesystem had 8Kb blocks. We might use long long, but that would
+ * kill us on x86. Oh, well, at least the sign propagation does not matter -
+ * i_block would have to be negative in the very beginning, so we would not
+ * get there at all.
+ */
+
+static int ext3_block_to_path(struct inode *inode, long i_block, int offsets[4])
+{
+ int ptrs = EXT3_ADDR_PER_BLOCK(inode->i_sb);
+ int ptrs_bits = EXT3_ADDR_PER_BLOCK_BITS(inode->i_sb);
+ const long direct_blocks = EXT3_NDIR_BLOCKS,
+ indirect_blocks = ptrs,
+ double_blocks = (1 << (ptrs_bits * 2));
+ int n = 0;
+
+ if (i_block < 0) {
+ ext3_warning (inode->i_sb, "ext3_block_to_path", "block < 0");
+ } else if (i_block < direct_blocks) {
+ offsets[n++] = i_block;
+ } else if ( (i_block -= direct_blocks) < indirect_blocks) {
+ offsets[n++] = EXT3_IND_BLOCK;
+ offsets[n++] = i_block;
+ } else if ((i_block -= indirect_blocks) < double_blocks) {
+ offsets[n++] = EXT3_DIND_BLOCK;
+ offsets[n++] = i_block >> ptrs_bits;
+ offsets[n++] = i_block & (ptrs - 1);
+ } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) {
+ offsets[n++] = EXT3_TIND_BLOCK;
+ offsets[n++] = i_block >> (ptrs_bits * 2);
+ offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1);
+ offsets[n++] = i_block & (ptrs - 1);
+ } else {
+ ext3_warning (inode->i_sb, "ext3_block_to_path", "block > big");
+ }
+ return n;
+}
+
+/**
+ * ext3_get_branch - read the chain of indirect blocks leading to data


+ * @inode: inode in question

+ * @depth: depth of the chain (1 - direct pointer, etc.)
+ * @offsets: offsets of pointers in inode/indirect blocks
+ * @chain: place to store the result
+ * @err: here we store the error value
+ *
+ * Function fills the array of triples <key, p, bh> and returns %NULL
+ * if everything went OK or the pointer to the last filled triple
+ * (incomplete one) otherwise. Upon the return chain[i].key contains
+ * the number of (i+1)-th block in the chain (as it is stored in memory,
+ * i.e. little-endian 32-bit), chain[i].p contains the address of that
+ * number (it points into struct inode for i==0 and into the bh->b_data
+ * for i>0) and chain[i].bh points to the buffer_head of i-th indirect
+ * block for i>0 and NULL for i==0. In other words, it holds the block
+ * numbers of the chain, addresses they were taken from (and where we can
+ * verify that chain did not change) and buffer_heads hosting these
+ * numbers.
+ *
+ * Function stops when it stumbles upon zero pointer (absent block)
+ * (pointer to last triple returned, *@err == 0)
+ * or when it gets an IO error reading an indirect block
+ * (ditto, *@err == -EIO)
+ * or when it notices that chain had been changed while it was reading
+ * (ditto, *@err == -EAGAIN)
+ * or when it reads all @depth-1 indirect blocks successfully and finds
+ * the whole chain, all way to the data (returns %NULL, *err == 0).
+ */
+static Indirect *ext3_get_branch(struct inode *inode, int depth, int *offsets,
+ Indirect chain[4], int *err)
+{
+ kdev_t dev = inode->i_dev;
+ int blocksize = inode->i_sb->s_blocksize;
+ Indirect *p = chain;


+ struct buffer_head *bh;
+

+ *err = 0;
+ /* i_data is not going away, no lock needed */
+ add_chain (chain, NULL, inode->u.ext3_i.i_data + *offsets);
+ if (!p->key)
+ goto no_block;
+ while (--depth) {
+ bh = bread(dev, le32_to_cpu(p->key), blocksize);
+ if (!bh)
+ goto failure;
+ /* Reader: pointers */
+ if (!verify_chain(chain, p))
+ goto changed;
+ add_chain(++p, bh, (u32*)bh->b_data + *++offsets);
+ /* Reader: end */
+ if (!p->key)
+ goto no_block;


+ }
+ return NULL;
+

+changed:
+ *err = -EAGAIN;
+ goto no_block;
+failure:
+ *err = -EIO;
+no_block:
+ return p;
+}
+
+/**
+ * ext3_find_near - find a place for allocation with sufficient locality
+ * @inode: owner
+ * @ind: descriptor of indirect block.
+ *
+ * This function returns the prefered place for block allocation.
+ * It is used when heuristic for sequential allocation fails.
+ * Rules are:
+ * + if there is a block to the left of our position - allocate near it.
+ * + if pointer will live in indirect block - allocate near that block.
+ * + if pointer will live in inode - allocate in the same
+ * cylinder group.
+ * Caller must make sure that @ind is valid and will stay that way.
+ */
+
+static inline unsigned long ext3_find_near(struct inode *inode, Indirect *ind)
+{
+ u32 *start = ind->bh ? (u32*) ind->bh->b_data : inode->u.ext3_i.i_data;
+ u32 *p;
+
+ /* Try to find previous block */
+ for (p = ind->p - 1; p >= start; p--)
+ if (*p)
+ return le32_to_cpu(*p);
+
+ /* No such thing, so let's try location of indirect block */
+ if (ind->bh)
+ return ind->bh->b_blocknr;
+
+ /*
+ * It is going to be refered from inode itself? OK, just put it into
+ * the same cylinder group then.
+ */
+ return (inode->u.ext3_i.i_block_group *
+ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
+ le32_to_cpu(inode->i_sb->u.ext3_sb.s_es->s_first_data_block);
+}
+
+/**
+ * ext3_find_goal - find a prefered place for allocation.
+ * @inode: owner
+ * @block: block we want


+ * @chain: chain of indirect blocks

+ * @partial: pointer to the last triple within a chain
+ * @goal: place to store the result.
+ *
+ * Normally this function find the prefered place for block allocation,
+ * stores it in *@goal and returns zero. If the branch had been changed
+ * under us we return -EAGAIN.
+ */
+
+static int ext3_find_goal(struct inode *inode, long block, Indirect chain[4],
+ Indirect *partial, unsigned long *goal)
+{
+ /* Writer: ->i_next_alloc* */
+ if (block == inode->u.ext3_i.i_next_alloc_block + 1) {
+ inode->u.ext3_i.i_next_alloc_block++;
+ inode->u.ext3_i.i_next_alloc_goal++;
+ }


+#ifdef SEARCH_FROM_ZERO
+ inode->u.ext3_i.i_next_alloc_block = 0;
+ inode->u.ext3_i.i_next_alloc_goal = 0;
+#endif

+ /* Writer: end */

+ /* Reader: pointers, ->i_next_alloc* */
+ if (verify_chain(chain, partial)) {
+ /*
+ * try the heuristic for sequential allocation,
+ * failing that at least try to get decent locality.
+ */
+ if (block == inode->u.ext3_i.i_next_alloc_block)
+ *goal = inode->u.ext3_i.i_next_alloc_goal;
+ if (!*goal)
+ *goal = ext3_find_near(inode, partial);
+#ifdef SEARCH_FROM_ZERO
+ *goal = 0;
+#endif
+ return 0;
+ }
+ /* Reader: end */
+ return -EAGAIN;
+}
+
+/**
+ * ext3_alloc_branch - allocate and set up a chain of blocks.
+ * @inode: owner
+ * @num: depth of the chain (number of blocks to allocate)
+ * @offsets: offsets (in the blocks) to store the pointers to next.
+ * @branch: place to store the chain in.
+ *
+ * This function allocates @num blocks, zeroes out all but the last one,
+ * links them into chain and (if we are synchronous) writes them to disk.
+ * In other words, it prepares a branch that can be spliced onto the
+ * inode. It stores the information about that chain in the branch[], in
+ * the same format as ext3_get_branch() would do. We are calling it after
+ * we had read the existing part of chain and partial points to the last
+ * triple of that (one with zero ->key). Upon the exit we have the same
+ * picture as after the successful ext3_get_block(), excpet that in one
+ * place chain is disconnected - *branch->p is still zero (we did not
+ * set the last link), but branch->key contains the number that should
+ * be placed into *branch->p to fill that gap.
+ *
+ * If allocation fails we free all blocks we've allocated (and forget
+ * their buffer_heads) and return the error value the from failed
+ * ext3_alloc_block() (normally -ENOSPC). Otherwise we set the chain
+ * as described above and return 0.
+ */
+
+static int ext3_alloc_branch(handle_t *handle, struct inode *inode,
+ int num,
+ unsigned long goal,
+ int *offsets,
+ Indirect *branch)
+{
+ int blocksize = inode->i_sb->s_blocksize;
+ int n = 0, keys = 0;


+ int err = 0;

+ int i;
+ int parent = ext3_alloc_block(handle, inode, goal, &err);
+
+ branch[0].key = cpu_to_le32(parent);
+ if (parent) {
+ for (n = 1; n < num; n++) {
+ struct buffer_head *bh;
+ /* Allocate the next block */
+ int nr = ext3_alloc_block(handle, inode, parent, &err);
+ if (!nr)
+ break;
+ branch[n].key = cpu_to_le32(nr);
+ keys = n+1;
+
+ /*
+ * Get buffer_head for parent block, zero it out
+ * and set the pointer to new one, then send
+ * parent to disk.
+ */
+ bh = getblk(inode->i_dev, parent, blocksize);


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

echo 'End of part 087'
echo 'File patch-2.4.15 is continued in part 088'
echo "088" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 3:59:53 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part077

#!/bin/sh -x
# this is part 077 of a 115 - part archive


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

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

+
+ if ((VCLK >= 0) && (VCLK < 135))
+ data2 = 0x03;
+ if ((VCLK >= 135) && (VCLK < 160))
+ data2 = 0x02;
+ if ((VCLK >= 160) && (VCLK < 260))
+ data2 = 0x01;
+ if (VCLK > 260)
+ data2 = 0x00;
+ /* disable 24bit palette RAM gamma correction */
+
+ if (HwDeviceExtension->jChipType == SIS_540) {
+ if ((VCLK == 203) || (VCLK < 234))
+ data2 = 0x02;
+ }
+ SiS_SetRegANDOR (SiS_P3c4, 0x07, 0xFC, data2);
+}
+
+void
+SiS_LoadDAC (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex)
+{


+ USHORT data, data2;
+ USHORT time, i, j, k;
+ USHORT m, n, o;
+ USHORT si, di, bx, dl;
+ USHORT al, ah, dh;

+ USHORT *table = NULL;


+
+ if (ModeNo <= 0x13)

+ data = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ else
+ data = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+
+ data = data & DACInfoFlag;


+ time = 64;
+ if (data == 0x00)
+ table = SiS_MDA_DAC;
+ if (data == 0x08)
+ table = SiS_CGA_DAC;
+ if (data == 0x10)
+ table = SiS_EGA_DAC;
+ if (data == 0x18) {
+ time = 256;
+ table = SiS_VGA_DAC;
+ }
+ if (time == 256)
+ j = 16;
+ else
+ j = time;
+

+ SiS_SetReg3 (SiS_P3c6, 0xFF);
+ SiS_SetReg3 (SiS_P3c8, 0x00);
+


+ for (i = 0; i < j; i++) {
+ data = table[i];

+ for (k = 0; k < 3; k++) {
+ data2 = 0;


+ if (data & 0x01)
+ data2 = 0x2A;

+ if (data & 0x02)
+ data2 = data2 + 0x15;
+ SiS_SetReg3 (SiS_P3c9, data2);


+ data = data >> 2;

+ }
+ }
+


+ if (time == 256) {
+ for (i = 16; i < 32; i++) {
+ data = table[i];

+ for (k = 0; k < 3; k++)
+ SiS_SetReg3 (SiS_P3c9, data);


+ }
+ si = 32;
+ for (m = 0; m < 9; m++) {
+ di = si;
+ bx = si + 0x04;
+ dl = 0;
+ for (n = 0; n < 3; n++) {
+ for (o = 0; o < 5; o++) {
+ dh = table[si];
+ ah = table[di];
+ al = table[bx];
+ si++;

+ SiS_WriteDAC (dl, ah, al, dh);


+ } /* for 5 */
+ si = si - 2;
+ for (o = 0; o < 3; o++) {
+ dh = table[bx];
+ ah = table[di];

+ al = table[si];
+ si--;
+ SiS_WriteDAC (dl, ah, al, dh);


+ } /* for 3 */
+ dl++;
+ } /* for 3 */
+ si = si + 5;

+ } /* for 9 */
+ }
+}
+
+void
+SiS_WriteDAC (USHORT dl, USHORT ah, USHORT al, USHORT dh)
+{
+ USHORT temp;


+ USHORT bh, bl;
+
+ bh = ah;
+ bl = al;
+ if (dl != 0) {
+ temp = bh;
+ bh = dh;
+ dh = temp;
+ if (dl == 1) {
+ temp = bl;
+ bl = dh;
+ dh = temp;

+ } else {


+ temp = bl;
+ bl = bh;
+ bh = temp;
+ }
+ }

+ SiS_SetReg3 (SiS_P3c9, (USHORT) dh);
+ SiS_SetReg3 (SiS_P3c9, (USHORT) bh);
+ SiS_SetReg3 (SiS_P3c9, (USHORT) bl);
+}
+
+void
+SiS_ClearBuffer (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT ModeNo)
+{
+ PVOID VideoMemoryAddress =
+ (PVOID) HwDeviceExtension->pjVideoMemoryAddress;
+ ULONG AdapterMemorySize = (ULONG) HwDeviceExtension->ulVideoMemorySize;
+ PUSHORT pBuffer;
+ int i;
+
+ if (SiS_ModeType >= ModeEGA) {
+ if (ModeNo > 0x13) {
+ SiS_SetMemory (VideoMemoryAddress, AdapterMemorySize,
+ 0);
+ } else {
+ pBuffer = VideoMemoryAddress;
+ for (i = 0; i < 0x4000; i++)
+ pBuffer[i] = 0x0000;
+ }
+ } else {
+ pBuffer = VideoMemoryAddress;
+ if (SiS_ModeType == ModeCGA) {
+ for (i = 0; i < 0x4000; i++)
+ pBuffer[i] = 0x0720;
+ } else {
+ for (i = 0; i < 0x4000; i++)
+ pBuffer[i] = 0x0000;


+ }
+ }
+}
+
+void

+SiS_DisplayOn (void)
+{
+
+ SiS_SetRegANDOR (SiS_P3c4, 0x01, 0xDF, 0x00);
+}
+
+void
+SiS_DisplayOff (void)
+{
+
+ SiS_SetRegANDOR (SiS_P3c4, 0x01, 0xDF, 0x20);
+}
+
+/* ========================================== */
+/* SR CRTC GR */
+void
+SiS_SetReg1 (USHORT port, USHORT index, USHORT data)
+{
+ OutPortByte (port, index);
+ OutPortByte (port + 1, data);
+
+ /*
+ _asm
+ {
+ mov dx, port
+ mov ax, index
+ mov bx, data
+ out dx, al
+ mov ax, bx
+ inc dx
+ out dx, al
+ }
+ */
+
+}
+
+/* ========================================== */
+/* AR(3C0) */
+void
+SiS_SetReg2 (USHORT port, USHORT index, USHORT data)
+{
+
+ InPortByte (port + 0x3da - 0x3c0);
+ OutPortByte (SiS_P3c0, index);
+ OutPortByte (SiS_P3c0, data);
+ OutPortByte (SiS_P3c0, 0x20);
+
+ /*
+ _asm
+ {
+ mov dx, port
+ mov cx, index
+ mov bx, data
+
+ add dx, 3dah-3c0h
+ in al, dx
+
+ mov ax, cx
+ mov dx, 3c0h
+ out dx, al
+ mov ax, bx
+ out dx, al
+
+ mov ax, 20h
+ out dx, al
+ }
+ */
+
+}
+
+/* ========================================== */
+void
+SiS_SetReg3 (USHORT port, USHORT data)
+{
+
+ OutPortByte (port, data);
+
+ /*
+ _asm
+ {
+ mov dx, port
+ mov ax, data
+ out dx, al
+
+ }
+ */
+
+}
+
+/* ========================================== */
+void
+SiS_SetReg4 (USHORT port, ULONG data)
+{
+
+ OutPortLong (port, data);
+
+ /*
+ _asm
+ {
+ mov dx, port ;; port
+ mov eax, data ;; data
+ out dx, eax
+
+ }
+ */
+}
+
+/* ========================================= */
+UCHAR SiS_GetReg1 (USHORT port, USHORT index)


+{
+ UCHAR data;
+

+ OutPortByte (port, index);
+ data = InPortByte (port + 1);
+
+ /*
+ _asm
+ {
+ mov dx, port ;; port
+ mov ax, index ;; index
+
+ out dx, al
+ mov ax, bx
+ inc dx
+ xor eax, eax
+ in al, dx
+ mov data, al
+ }
+ */
+ return (data);
+}
+
+/* ========================================== */
+UCHAR SiS_GetReg2 (USHORT port)


+{
+ UCHAR data;
+

+ data = InPortByte (port);
+
+ /*
+ _asm
+ {
+ mov dx, port ;; port
+ xor eax, eax
+ in al, dx
+ mov data, al
+ }
+ */
+ return (data);
+}
+
+/* ========================================== */
+ULONG SiS_GetReg3 (USHORT port)
+{
+ ULONG data;
+
+ data = InPortLong (port);
+
+ /*
+ _asm
+ {
+ mov dx, port ;; port
+ xor eax, eax
+ in eax, dx
+ mov data, eax
+ }
+ */
+ return (data);
+}
+
+/* ========================================== */
+void
+SiS_ClearDAC (ULONG port)


+{
+ int i;
+

+ OutPortByte (port, 0);
+ port++;
+ for (i = 0; i < 256 * 3; i++) {
+ OutPortByte (port, 0);
+ }
+
+}
+
+/*========================================== */
+
+void
+SiS_SetInterlace (ULONG ROMAddr, USHORT ModeNo, USHORT RefreshRateTableIndex)
+{
+ ULONG Temp;
+ USHORT data, Temp2;
+
+ Temp = (ULONG) SiS_GetReg1 (SiS_P3d4, 0x01);
+ Temp++;
+ Temp = Temp * 8;
+
+ if (Temp == 1024)
+ data = 0x0035;
+ else if (Temp == 1280)
+ data = 0x0048;
+ else


+ data = 0x0000;
+

+ Temp2 = SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+ Temp2 &= InterlaceMode;
+ if (Temp2 == 0)


+ data = 0x0000;
+

+ SiS_SetReg1 (SiS_P3d4, 0x19, data);
+
+ Temp = (ULONG) SiS_GetReg1 (SiS_P3d4, 0x1A);
+ Temp2 = (USHORT) (Temp & 0xFC);
+ SiS_SetReg1 (SiS_P3d4, 0x1A, (USHORT) Temp);
+
+ Temp = (ULONG) SiS_GetReg1 (SiS_P3c4, 0x0f);
+ Temp2 = (USHORT) Temp & 0xBF;
+ if (ModeNo == 0x37)
+ Temp2 = Temp2 | 0x40;
+ SiS_SetReg1 (SiS_P3d4, 0x1A, (USHORT) Temp2);
+}
+
+void
+SiS_SetCRT1FIFO (ULONG ROMAddr, USHORT ModeNo,


+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+

+ USHORT data;
+
+ data = SiS_GetReg1 (SiS_P3c4, 0x3D);
+ data &= 0xfe;
+ SiS_SetReg1 (SiS_P3c4, 0x3D, data); /* diable auto-threshold */
+ if (ModeNo > 0x13) {
+ SiS_SetReg1 (SiS_P3c4, 0x08, 0x34);
+ data = SiS_GetReg1 (SiS_P3c4, 0x09);
+ data &= 0xF0;
+ SiS_SetReg1 (SiS_P3c4, 0x09, data);
+
+ data = SiS_GetReg1 (SiS_P3c4, 0x3D);
+ data |= 0x01;
+ SiS_SetReg1 (SiS_P3c4, 0x3D, data);
+ } else {
+ SiS_SetReg1 (SiS_P3c4, 0x08, 0xAE);
+ data = SiS_GetReg1 (SiS_P3c4, 0x09);
+ data &= 0xF0;
+ SiS_SetReg1 (SiS_P3c4, 0x09, data);
+ }
+
+}
+
+USHORT
+SiS_CalcDelay (ULONG ROMAddr, USHORT key)
+{
+ USHORT data, data2, temp0, temp1;
+ UCHAR ThLowA[] = { 61, 3, 52, 5, 68, 7, 100, 11,
+ 43, 3, 42, 5, 54, 7, 78, 11,
+ 34, 3, 37, 5, 47, 7, 67, 11
+ };
+ UCHAR ThLowB[] = { 81, 4, 72, 6, 88, 8, 120, 12,
+ 55, 4, 54, 6, 66, 8, 90, 12,
+ 42, 4, 45, 6, 55, 8, 75, 12
+ };
+ UCHAR ThTiming[] = { 1, 2, 2, 3, 0, 1, 1, 2 };


+
+ data = SiS_GetReg1 (SiS_P3c4, 0x16);

+ data = data >> 6;
+ data2 = SiS_GetReg1 (SiS_P3c4, 0x14);
+ data2 = (data2 >> 4) & 0x0C;
+ data = data | data2;
+ data = data < 1;
+ if (key == 0) {
+ temp0 = (USHORT) ThLowA[data];
+ temp1 = (USHORT) ThLowA[data + 1];
+ } else {
+ temp0 = (USHORT) ThLowB[data];
+ temp1 = (USHORT) ThLowB[data + 1];
+ }
+
+ data2 = 0;
+ data = SiS_GetReg1 (SiS_P3c4, 0x18);
+ if (data & 0x02)
+ data2 = data2 | 0x01;
+ if (data & 0x20)


+ data2 = data2 | 0x02;

+ if (data & 0x40)
+ data2 = data2 | 0x04;
+
+ data = temp1 * ThTiming[data2] + temp0;
+ return (data);
+}
+
+void
+SiS_SetCRT1FIFO2 (ULONG ROMAddr, USHORT ModeNo,


+ PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT RefreshRateTableIndex)
+{

+ USHORT i, index, data, VCLK, data2, MCLK, colorth = 0;
+ USHORT ah, bl, B;
+ ULONG eax;
+ USHORT ThresholdLow = 0;
+ UCHAR FQBQData[] = { 0x01, 0x21, 0x41, 0x61, 0x81,
+ 0x31, 0x51, 0x71, 0x91, 0xb1,
+ 0x00, 0x20, 0x40, 0x60, 0x80,
+ 0x30, 0x50, 0x70, 0x90, 0xb0, 0xFF
+ };
+


+ if (ModeNo >= 0x13) {

+ index = SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+ if (HwDeviceExtension->jChipType < SIS_315H) { /* for300 serial */


+ index = index & 0x3F;
+ }

+ VCLK = SiS_VCLKData[index].CLOCK; /* Get VCLK */
+ index = SiS_GetReg1 (SiS_P3c4, 0x1A);
+ index = index & 07;
+ MCLK = SiS_MCLKData[index].CLOCK; /* Get MCLK */
+ data2 = SiS_ModeType - 0x02;
+ switch (data2) {
+ case 0:

+ colorth = 1;


+ break;
+ case 1:

+ colorth = 2;


+ break;
+ case 2:

+ colorth = 4;


+ break;
+ case 3:

+ colorth = 4;


+ break;
+ case 4:

+ colorth = 6;


+ break;
+ case 5:

+ colorth = 8;
+ break;
+ }
+
+ i = 0;
+ do {
+ B =
+ (SiS_CalcDelay2 (ROMAddr, FQBQData[i]) * VCLK *
+ colorth);
+ bl = B / (16 * MCLK);
+ if (B == bl * 16 * MCLK) {
+ bl = bl + 1;
+ } else {
+ bl = bl + 1;
+ }
+
+ if (bl > 0x13) {
+ if (FQBQData[i + 1] == 0xFF) {
+ ThresholdLow = 0x13;


+ break;
+ }
+ i++;

+ } else {
+ ThresholdLow = bl;
+ break;
+ }
+ } while (FQBQData[i] != 0xFF);
+ } else {
+ ThresholdLow = 0x02;
+ }
+
+ data2 = FQBQData[i];
+ data2 = (data2 & 0xf0) >> 4;
+ data2 = data2 << 24;


+
+ SiS_SetReg4 (0xcf8, 0x80000050);
+ eax = SiS_GetReg3 (0xcfc);

+ eax = eax & 0x0f0ffffff;
+ eax = eax | data2;
+ SiS_SetReg4 (0xcfc, eax);
+
+ ah = ThresholdLow;
+ ah = ah << 4;
+ ah = ah | 0x0f;
+ SiS_SetReg1 (SiS_P3c4, 0x08, ah);
+
+ data = ThresholdLow;
+ data = data & 0x10;
+ data = data << 1;
+ SiS_SetRegANDOR (SiS_P3c4, 0x0F, 0xDF, data);
+ SiS_SetReg1 (SiS_P3c4, 0x3B, 0x09);
+
+ data = ThresholdLow + 3;
+ if (data > 0x0f)
+ data = 0x0f;
+ SiS_SetRegANDOR (SiS_P3c4, 0x09, 0x80, data);
+}
+
+USHORT
+SiS_CalcDelay2 (ULONG ROMAddr, UCHAR key)
+{
+ USHORT data, index;


+ UCHAR LatencyFactor[] = { 97, 88, 86, 79, 77, 00, /*; 64 bit BQ=2 */
+ 00, 87, 85, 78, 76, 54, /*; 64 bit BQ=1 */
+ 97, 88, 86, 79, 77, 00, /*; 128 bit BQ=2 */
+ 00, 79, 77, 70, 68, 48, /*; 128 bit BQ=1 */
+ 80, 72, 69, 63, 61, 00, /*; 64 bit BQ=2 */
+ 00, 70, 68, 61, 59, 37, /*; 64 bit BQ=1 */
+ 86, 77, 75, 68, 66, 00, /*; 128 bit BQ=2 */
+ 00, 68, 66, 59, 57, 37
+ }; /*; 128 bit BQ=1 */
+

+ index = (key & 0xE0) >> 5;
+ if (key & 0x10)
+ index = index + 6;
+ if (!(key & 0x01))
+ index = index + 24;


+ data = SiS_GetReg1 (SiS_P3c4, 0x14);

+ if (data & 0x0080)
+ index = index + 12;
+


+ data = LatencyFactor[index];

+ return (data);
+}
+
+void
+SiS_CRT2AutoThreshold (USHORT BaseAddr)
+{
+ USHORT temp1;
+ USHORT Part1Port;
+ Part1Port = BaseAddr + SIS_CRT2_PORT_04;
+ temp1 = SiS_GetReg1 (SiS_Part1Port, 0x1);
+ temp1 |= 0x40;
+ SiS_SetReg1 (SiS_Part1Port, 0x1, temp1);
+}
+
+/* ============= ynlai ============== */
+void
+SiS_DetectMonitor (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr)
+{
+ UCHAR DAC_TEST_PARMS[] = { 0x0F, 0x0F, 0x0F };
+ UCHAR DAC_CLR_PARMS[] = { 0x00, 0x00, 0x00 };
+ USHORT SR1F;
+
+ SR1F = SiS_GetReg1 (SiS_P3c4, 0x1F);
+ SiS_SetRegANDOR (SiS_P3c4, 0x1F, 0xFF, 0x04);


+ if (SiS_IF_DEF_LVDS == 0) {

+ if (SiS_BridgeIsOn (BaseAddr)) {
+ SiS_SetReg1 (SiS_P3d4, 0x30, 0x41);
+ }
+ }
+ SiSSetMode (HwDeviceExtension, 0x03); /* InitMode */
+ SiS_SetReg3 (SiS_P3c6, 0xff);
+ SiS_ClearDAC (SiS_P3c8);
+ SiS_LongWait ();
+ SiS_LongWait ();
+ SiS_SetRegANDOR (SiS_P3d4, 0x32, 0xDF, 0x00);
+ if (SiS_TestMonitorType
+ (DAC_TEST_PARMS[0], DAC_TEST_PARMS[1], DAC_TEST_PARMS[2])) {
+ SiS_SetRegANDOR (SiS_P3d4, 0x32, 0xDF, 0x20);
+ }
+ if (SiS_TestMonitorType
+ (DAC_TEST_PARMS[0], DAC_TEST_PARMS[1], DAC_TEST_PARMS[2])) {
+ SiS_SetRegANDOR (SiS_P3d4, 0x32, 0xDF, 0x20);
+ }
+ SiS_TestMonitorType (DAC_CLR_PARMS[0], DAC_CLR_PARMS[1],
+ DAC_CLR_PARMS[2]);
+ SiS_SetReg1 (SiS_P3c4, 0x1F, SR1F);
+}
+
+USHORT
+SiS_TestMonitorType (UCHAR R_DAC, UCHAR G_DAC, UCHAR B_DAC)
+{
+ USHORT temp, tempbx;
+
+ tempbx = R_DAC * 0x4d + G_DAC * 0x97 + B_DAC * 0x1c;
+ if (tempbx > 0x80)
+ tempbx = tempbx + 0x100;
+ tempbx = (tempbx & 0xFF00) >> 8;
+ R_DAC = (UCHAR) tempbx;
+ G_DAC = (UCHAR) tempbx;
+ B_DAC = (UCHAR) tempbx;
+
+ SiS_SetReg3 (SiS_P3c8, 0x00);
+ SiS_SetReg3 (SiS_P3c9, R_DAC);
+ SiS_SetReg3 (SiS_P3c9, G_DAC);
+ SiS_SetReg3 (SiS_P3c9, B_DAC);
+ SiS_LongWait ();
+ temp = SiS_GetReg2 (SiS_P3c2);
+ if (temp & 0x10)


+ return (1);
+ else
+ return (0);
+}
+

+/* ---- test ----- */
+void
+SiS_GetSenseStatus (PSIS_HW_DEVICE_INFO HwDeviceExtension, ULONG ROMAddr)
+{
+ USHORT tempax = 0, tempbx, tempcx, temp;
+ USHORT P2reg0 = 0, SenseModeNo = 0, OutputSelect = *pSiS_OutputSelect;
+ USHORT ModeIdIndex, i;


+ USHORT BaseAddr = (USHORT) HwDeviceExtension->ulIOAddress;
+

+ if (SiS_IF_DEF_LVDS == 1) {

+ SiS_GetPanelID ();
+ temp = LCDSense;
+ temp = temp | SiS_SenseCHTV ();
+ tempbx = ~(LCDSense | AVIDEOSense | SVIDEOSense);
+ SiS_SetRegANDOR (SiS_P3d4, 0x32, tempbx, temp);
+ } else { /* for 301 */
+ if (SiS_IF_DEF_HiVision == 1) { /* for HiVision */
+ tempax = SiS_GetReg1 (SiS_P3c4, 0x38);
+ temp = tempax & 0x01;
+ tempax = SiS_GetReg1 (SiS_P3c4, 0x3A);
+ temp = temp | (tempax & 0x02);
+ SiS_SetRegANDOR (SiS_P3d4, 0x32, 0xA0, temp);
+ } else {
+ if (SiS_BridgeIsOn (BaseAddr)) {
+ P2reg0 = SiS_GetReg1 (SiS_Part2Port, 0x00);
+ if (!SiS_BridgeIsEnable
+ (BaseAddr, HwDeviceExtension)) {
+ SenseModeNo = 0x2e;
+ temp =
+ SiS_SearchModeID (ROMAddr,
+ SenseModeNo,
+ &ModeIdIndex);
+ SiS_SetFlag = 0x00;
+ SiS_ModeType = ModeVGA;
+ SiS_VBInfo =
+ SetCRT2ToRAMDAC | LoadDACFlag |
+ SetInSlaveMode;
+ SiS_SetCRT2Group301 (BaseAddr, ROMAddr,
+ SenseModeNo,
+ HwDeviceExtension);
+ for (i = 0; i < 20; i++) {


+ SiS_LongWait ();
+ }
+ }

+ SiS_SetReg1 (SiS_Part2Port, 0x00, 0x1c);
+ tempax = 0;
+ tempbx = *pSiS_RGBSenseData;
+ /*301b */
+ if (!(SiS_Is301B (BaseAddr))) {
+ tempbx = *pSiS_RGBSenseData2;


+ }
+ /*end 301b */

+ tempcx = 0x0E08;
+ if (SiS_Sense (SiS_Part4Port, tempbx, tempcx)) {
+ if (SiS_Sense
+ (SiS_Part4Port, tempbx, tempcx)) {
+ tempax = tempax | Monitor2Sense;
+ }
+ }
+
+ tempbx = *pSiS_YCSenseData;
+ /*301b */
+ if (!(SiS_Is301B (BaseAddr))) {
+ tempbx = *pSiS_YCSenseData2;
+ }
+ /*301b */
+ tempcx = 0x0604;
+ if (SiS_Sense (SiS_Part4Port, tempbx, tempcx)) {
+ if (SiS_Sense
+ (SiS_Part4Port, tempbx, tempcx)) {
+ tempax = tempax | SVIDEOSense;
+ }
+ }
+
+ if (OutputSelect & BoardTVType) {
+ tempbx = *pSiS_VideoSenseData;
+ /*301b */
+ if (!(SiS_Is301B (BaseAddr))) {
+ tempbx = *pSiS_VideoSenseData2;


+ }
+ /*end 301b */

+ tempcx = 0x0804;
+ if (SiS_Sense
+ (SiS_Part4Port, tempbx, tempcx)) {
+ if (SiS_Sense
+ (SiS_Part4Port, tempbx,
+ tempcx)) {
+ tempax =
+ tempax |
+ AVIDEOSense;
+ }
+ }
+ } else {
+ if (!(tempax & SVIDEOSense)) {
+ tempbx = *pSiS_VideoSenseData;
+ /*301b */
+ if (!(SiS_Is301B (BaseAddr))) {
+ tempbx =
+ *pSiS_VideoSenseData2;


+ }
+ /*end 301b */

+ tempcx = 0x0804;
+ if (SiS_Sense
+ (SiS_Part4Port, tempbx,
+ tempcx)) {
+ if (SiS_Sense
+ (SiS_Part4Port,
+ tempbx, tempcx)) {
+ tempax =
+ tempax |
+ AVIDEOSense;


+ }
+ }
+ }
+ }
+ }
+

+ if (SiS_SenseLCD (HwDeviceExtension)) {
+ tempax = tempax | LCDSense;
+ }
+
+ tempbx = 0;
+ tempcx = 0;
+ SiS_Sense (SiS_Part4Port, tempbx, tempcx);
+
+ SiS_SetRegANDOR (SiS_P3d4, 0x32, ~0xDF, tempax);
+ SiS_SetReg1 (SiS_Part2Port, 0x00, P2reg0);
+ if (!(P2reg0 & 0x20)) {
+ SiS_VBInfo = DisableCRT2Display;
+ SiS_SetCRT2Group301 (BaseAddr, ROMAddr,
+ SenseModeNo,
+ HwDeviceExtension);


+ }
+ }
+ }
+}
+

+BOOLEAN
+SiS_Sense (USHORT Part4Port, USHORT tempbx, USHORT tempcx)
+{
+ USHORT temp, i, tempch;
+
+ temp = tempbx & 0xFF;
+ SiS_SetReg1 (SiS_Part4Port, 0x11, temp);


+ temp = (tempbx & 0xFF00) >> 8;

+ temp = temp | (tempcx & 0x00FF);
+ SiS_SetRegANDOR (SiS_Part4Port, 0x10, ~0x1F, temp);
+
+ for (i = 0; i < 10; i++)
+ SiS_LongWait ();
+
+ tempch = (tempcx & 0x7F00) >> 8; /* ynlai [05/22/2001] */
+ temp = SiS_GetReg1 (SiS_Part4Port, 0x03);
+ temp = temp ^ (0x0E);
+ temp = temp & tempch; /* ynlai [05/22/2001] */
+ if (temp > 0)


+ return 1;
+ else
+ return 0;
+}
+

+USHORT
+SiS_SenseLCD (PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+/* USHORT SoftSetting; */
+ USHORT temp;
+
+ temp = SiS_GetPanelID ();
+ if (!temp)
+ temp = SiS_GetLCDDDCInfo (HwDeviceExtension);


+ return (temp);
+}
+

+BOOLEAN
+SiS_GetLCDDDCInfo (PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{
+ USHORT temp;
+ //add lcd sense
+ if (HwDeviceExtension->ulCRT2LCDType == LCD_UNKNOWN)
+ return 0;
+ else {
+ temp = (USHORT) HwDeviceExtension->ulCRT2LCDType;
+ SiS_SetReg1 (SiS_P3d4, 0x36, temp);


+ return 1;
+ }
+}
+

+BOOLEAN
+SiS_GetPanelID (void)
+{
+ USHORT PanelTypeTable[16] =
+ { SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType00,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType01,
+ SyncPP | PanelRGB18Bit | Panel800x600 | _PanelType02,
+ SyncNN | PanelRGB18Bit | Panel640x480 | _PanelType03,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType04,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType05,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType06,
+ SyncNN | PanelRGB24Bit | Panel1024x768 | _PanelType07,
+ SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType08,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType09,
+ SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType0A,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0B,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0C,
+ SyncNN | PanelRGB24Bit | Panel1024x768 | _PanelType0D,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0E,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0F


+ };
+ USHORT tempax, tempbx, temp;

+/* USHORT return_flag; */
+
+ tempax = SiS_GetReg1 (SiS_P3c4, 0x18);
+ tempbx = tempax & 0x0F;
+ if (!(tempax & 0x10)) {


+ if (SiS_IF_DEF_LVDS == 1) {

+ tempbx = 0;
+ temp = SiS_GetReg1 (SiS_P3c4, 0x38);
+ if (temp & 0x40)
+ tempbx = tempbx | 0x08;
+ if (temp & 0x20)
+ tempbx = tempbx | 0x02;


+ if (temp & 0x01)

+ tempbx = tempbx | 0x01;
+ temp = SiS_GetReg1 (SiS_P3c4, 0x39);
+ if (temp & 0x80)
+ tempbx = tempbx | 0x04;


+ } else {
+ return 0;
+ }
+ }
+

+ tempbx = tempbx << 1;

+ tempbx = PanelTypeTable[tempbx];
+ tempbx = tempbx | LCDSync;


+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_P3d4, 0x36, temp);
+ temp = (tempbx & 0xFF00) >> 8;
+ SiS_SetRegANDOR (SiS_P3d4, 0x37, ~(LCDSyncBit | LCDRGB18Bit), temp);


+ return 1;
+}
+

+USHORT
+SiS_SenseCHTV (void)
+{
+ USHORT temp, push0e, status;
+
+ status = 0;
+ push0e = SiS_GetCH7005 (0x0e);
+ push0e = (push0e << 8) | 0x0e;
+ SiS_SetCH7005 (0x0b0e);
+ SiS_SetCH7005 (0x0110);
+ SiS_SetCH7005 (0x0010);
+ temp = SiS_GetCH7005 (0x10);
+ if (temp & 0x08)
+ status = status | SVIDEOSense;


+ if (temp & 0x02)

+ status = status | AVIDEOSense;
+ SiS_SetCH7005 (push0e);
+ return (status);
+}
+
+/* ========================================== */
+#ifdef TC
+
+int
+INT1AReturnCode (union REGS regs)
+{
+ if (regs.x.cflag) {
+ /*printf("Error to find pci device!\n"); */


+ return 1;
+ }
+

+ switch (regs.h.ah) {
+ case 0:
+ return 0;
+ break;
+ case 0x81:
+ printf ("Function not support\n");
+ break;
+ case 0x83:
+ printf ("bad vendor id\n");
+ break;
+ case 0x86:
+ printf ("device not found\n");
+ break;
+ case 0x87:
+ printf ("bad register number\n");
+ break;
+ case 0x88:
+ printf ("set failed\n");
+ break;
+ case 0x89:
+ printf ("buffer too small");
+ break;


+ }
+ return 1;
+}
+

+unsigned
+FindPCIIOBase (unsigned index, unsigned deviceid)
+{
+ union REGS regs;
+
+ regs.h.ah = 0xb1; /*PCI_FUNCTION_ID */
+ regs.h.al = 0x02; /*FIND_PCI_DEVICE */
+ regs.x.cx = deviceid;
+ regs.x.dx = 0x1039;
+ regs.x.si = index; /* find n-th device */
+
+ int86 (0x1A, &regs, &regs);
+
+ if (INT1AReturnCode (regs) != 0)
+ return 0;
+
+/* regs.h.bh *//* bus number */
+/* regs.h.bl *//* device number */
+ regs.h.ah = 0xb1; /*PCI_FUNCTION_ID */
+ regs.h.al = 0x09; /*READ_CONFIG_WORD */
+ regs.x.cx = deviceid;
+ regs.x.dx = 0x1039;
+ regs.x.di = 0x18; /* register number */
+ int86 (0x1A, &regs, &regs);
+
+ if (INT1AReturnCode (regs) != 0)
+ return 0;
+ return regs.x.cx;
+}
+
+void
+main (int argc, char *argv[])
+/* void main() */
+{
+ SIS_HW_DEVICE_INFO HwDeviceExtension;
+ USHORT temp;
+ USHORT ModeNo;
+
+ /*HwDeviceExtension.pjVirtualRomBase =(PUCHAR) MK_FP(0xC000,0); */
+ /*HwDeviceExtension.pjVideoMemoryAddress = (PUCHAR)MK_FP(0xA000,0); */
+#ifdef CONFIG_FB_SIS_300
+ HwDeviceExtension.ulIOAddress =
+ (FindPCIIOBase (0, 0x6300) & 0xFF80) + 0x30;
+ HwDeviceExtension.jChipType = SIS_630;
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+// HwDeviceExtension.ulIOAddress = (FindPCIIOBase(0,0x5315)&0xFF80) + 0x30;
+// HwDeviceExtension.jChipType = SIS_550;
+ HwDeviceExtension.ulIOAddress =
+ (FindPCIIOBase (0, 0x325) & 0xFF80) + 0x30;
+ HwDeviceExtension.jChipType = SIS_315H;
+#endif
+ HwDeviceExtension.ujVBChipID = VB_CHIP_301;
+ strcpy (HwDeviceExtension.szVBIOSVer, "0.84");
+ HwDeviceExtension.bSkipDramSizing = FALSE;
+ HwDeviceExtension.ulVideoMemorySize = 0;
+ if (argc == 2) {
+ ModeNo = atoi (argv[1]);
+ } else {
+ ModeNo = 0x2e;
+ /*ModeNo=0x37; 1024x768x 4bpp */
+ /*ModeNo=0x38; 1024x768x 8bpp */
+ /*ModeNo=0x4A; 1024x768x 16bpp */
+ /*ModeNo=0x47; 800x600x 16bpp */
+ }
+ // SiSInit(&HwDeviceExtension);
+ SiSSetMode (&HwDeviceExtension, ModeNo);
+
+}
+#endif
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/init.h linux/drivers/video/sis/init.h
--- v2.4.14/linux/drivers/video/sis/init.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/sis/init.h Fri Nov 9 14:11:14 2001
@@ -0,0 +1,227 @@
+#ifndef _INIT_
+#define _INIT_


+
+#include "osdef.h"
+#include "initdef.h"
+#include "vgatypes.h"
+#include "vstruct.h"
+

+#include <linux/types.h>
+#include <asm/io.h>
+#include <linux/sisfb.h>
+
+
+USHORT SiS_DRAMType[17][5] = {
+ {0x0C, 0x0A, 0x02, 0x40, 0x39},
+ {0x0D, 0x0A, 0x01, 0x40, 0x48},
+ {0x0C, 0x09, 0x02, 0x20, 0x35},
+ {0x0D, 0x09, 0x01, 0x20, 0x44},
+ {0x0C, 0x08, 0x02, 0x10, 0x31},
+ {0x0D, 0x08, 0x01, 0x10, 0x40},
+ {0x0C, 0x0A, 0x01, 0x20, 0x34},
+ {0x0C, 0x09, 0x01, 0x08, 0x32},
+ {0x0B, 0x08, 0x02, 0x08, 0x21},
+ {0x0C, 0x08, 0x01, 0x08, 0x30},
+ {0x0A, 0x08, 0x02, 0x04, 0x11},
+ {0x0B, 0x0A, 0x01, 0x10, 0x28},
+ {0x09, 0x08, 0x02, 0x02, 0x01},
+ {0x0B, 0x09, 0x01, 0x08, 0x24},
+ {0x0B, 0x08, 0x01, 0x04, 0x20},
+ {0x0A, 0x08, 0x01, 0x02, 0x10},
+ {0x09, 0x08, 0x01, 0x01, 0x00}
+};
+
+USHORT SiS_SDRDRAM_TYPE[13][5] = {
+ {2, 12, 9, 64, 0x35},
+ {1, 13, 9, 64, 0x44},
+ {2, 12, 8, 32, 0x31},
+ {2, 11, 9, 32, 0x25},
+ {1, 12, 9, 32, 0x34},
+ {1, 13, 8, 32, 0x40},
+ {2, 11, 8, 16, 0x21},
+ {1, 12, 8, 16, 0x30},
+ {1, 11, 9, 16, 0x24},
+ {1, 11, 8, 8, 0x20},
+ {2, 9, 8, 4, 0x01},
+ {1, 10, 8, 4, 0x10},
+ {1, 9, 8, 2, 0x00}
+};
+
+USHORT SiS_DDRDRAM_TYPE[4][5] = {
+ {2, 12, 9, 64, 0x35},
+ {2, 12, 8, 32, 0x31},
+ {2, 11, 8, 16, 0x21},
+ {2, 9, 8, 4, 0x01}
+};
+
+UCHAR SiS_ChannelAB, SiS_DataBusWidth;
+
+USHORT SiS_MDA_DAC[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,


+ 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,

+ 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,


+ 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,

+ 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F
+};
+
+USHORT SiS_CGA_DAC[] = {
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
+ 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
+ 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
+ 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
+ 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F
+};
+
+USHORT SiS_EGA_DAC[] = {
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x05, 0x15,
+ 0x20, 0x30, 0x24, 0x34, 0x21, 0x31, 0x25, 0x35,
+ 0x08, 0x18, 0x0C, 0x1C, 0x09, 0x19, 0x0D, 0x1D,
+ 0x28, 0x38, 0x2C, 0x3C, 0x29, 0x39, 0x2D, 0x3D,
+ 0x02, 0x12, 0x06, 0x16, 0x03, 0x13, 0x07, 0x17,
+ 0x22, 0x32, 0x26, 0x36, 0x23, 0x33, 0x27, 0x37,
+ 0x0A, 0x1A, 0x0E, 0x1E, 0x0B, 0x1B, 0x0F, 0x1F,
+ 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F
+};
+
+USHORT SiS_VGA_DAC[] = {
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
+ 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
+ 0x00, 0x05, 0x08, 0x0B, 0x0E, 0x11, 0x14, 0x18,
+ 0x1C, 0x20, 0x24, 0x28, 0x2D, 0x32, 0x38, 0x3F,
+
+ 0x00, 0x10, 0x1F, 0x2F, 0x3F, 0x1F, 0x27, 0x2F,
+ 0x37, 0x3F, 0x2D, 0x31, 0x36, 0x3A, 0x3F, 0x00,
+ 0x07, 0x0E, 0x15, 0x1C, 0x0E, 0x11, 0x15, 0x18,
+ 0x1C, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x00, 0x04,
+ 0x08, 0x0C, 0x10, 0x08, 0x0A, 0x0C, 0x0E, 0x10,
+ 0x0B, 0x0C, 0x0D, 0x0F, 0x10
+};
+
+USHORT SiS_P3c4, SiS_P3d4, SiS_P3c0, SiS_P3ce, SiS_P3c2;
+USHORT SiS_P3ca, SiS_P3c6, SiS_P3c7, SiS_P3c8, SiS_P3c9, SiS_P3da;
+USHORT SiS_Part1Port, SiS_Part2Port;
+USHORT SiS_Part3Port, SiS_Part4Port, SiS_Part5Port;
+USHORT SiS_CRT1Mode;
+
+USHORT flag_clearbuffer; /*0: no clear frame buffer 1:clear frame buffer */
+int SiS_RAMType; /*int ModeIDOffset,StandTable,CRT1Table,ScreenOffset,REFIndex; */
+USHORT SiS_ModeType;
+USHORT SiS_IF_DEF_LVDS, SiS_IF_DEF_TRUMPION, SiS_IF_DEF_DSTN; /*add for dstn */
+USHORT SiS_IF_DEF_CH7005, SiS_IF_DEF_HiVision;
+USHORT SiS_VBInfo, SiS_LCDResInfo, SiS_LCDTypeInfo, SiS_LCDInfo, SiS_VBType; /*301b */
+USHORT SiS_SelectCRT2Rate;
+
+extern USHORT SiS_SetFlag;
+
+void SiS_SetMemoryClock (ULONG ROMAddr);
+void SiS_SetDRAMModeRegister (ULONG ROMAddr);
+void SiS_SetDRAMSize_310 (PSIS_HW_DEVICE_INFO);
+void SiS_SetDRAMSize_300 (PSIS_HW_DEVICE_INFO HwDeviceExtension);
+USHORT SiS_ChkBUSWidth_300 (ULONG FBAddress);
+UCHAR SiS_Get310DRAMType (ULONG ROMAddr);
+
+void SiS_Delay15us (ULONG);
+BOOLEAN SiS_SearchModeID (ULONG ROMAddr, USHORT ModeNo, USHORT * ModeIdIndex);
+BOOLEAN SiS_CheckMemorySize (ULONG ROMAddr,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT ModeNo, USHORT ModeIdIndex);
+UCHAR SiS_GetModePtr (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex);
+void SiS_SetSeqRegs (ULONG, USHORT StandTableIndex);
+void SiS_SetMiscRegs (ULONG, USHORT StandTableIndex);
+void SiS_SetCRTCRegs (ULONG, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT StandTableIndex);
+void SiS_SetATTRegs (ULONG, USHORT StandTableIndex);
+void SiS_SetGRCRegs (ULONG, USHORT StandTableIndex);
+void SiS_ClearExt1Regs (void);
+void SiS_SetSync (ULONG ROMAddr, USHORT RefreshRateTableIndex);
+void SiS_SetCRT1CRTC (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex);
+void SiS_SetCRT1VCLK (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ PSIS_HW_DEVICE_INFO, USHORT RefreshRateTableIndex);
+void SiS_SetVCLKState (ULONG ROMAddr, PSIS_HW_DEVICE_INFO, USHORT ModeNo,
+ USHORT RefreshRateTableIndex);
+void SiS_LoadDAC (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex);
+void SiS_DisplayOn (void);
+void SiS_SetCRT1ModeRegs (ULONG ROMAddr, PSIS_HW_DEVICE_INFO, USHORT ModeNo,
+ USHORT ModeIdIndex, USHORT RefreshRateTableIndex);
+void SiS_WriteDAC (USHORT, USHORT, USHORT, USHORT);
+void SiS_GetVBType (USHORT BaseAddr); /*301b */
+USHORT SiS_ChkBUSWidth (ULONG);
+USHORT SiS_GetModeIDLength (ULONG, USHORT);
+USHORT SiS_GetRefindexLength (ULONG, USHORT);
+void SiS_SetInterlace (ULONG ROMAddr, USHORT ModeNo,
+ USHORT RefreshRateTableIndex);
+USHORT SiS_CalcDelay2 (ULONG, UCHAR);
+USHORT SiS_CalcDelay (ULONG, USHORT);
+void SiS_Set_LVDS_TRUMPION (PSIS_HW_DEVICE_INFO HwDeviceExtension);
+void SiS_SetCRT1Offset (ULONG, USHORT, USHORT, USHORT, PSIS_HW_DEVICE_INFO);
+void SiS_SetCRT1FIFO (ULONG, USHORT, PSIS_HW_DEVICE_INFO);
+void SiS_SetCRT1FIFO2 (ULONG, USHORT ModeNo, PSIS_HW_DEVICE_INFO,
+ USHORT RefreshRateTableIndex);
+void SiS_CRT2AutoThreshold (USHORT BaseAddr);
+void SiS_ClearBuffer (PSIS_HW_DEVICE_INFO, USHORT ModeNo);
+void SiS_SetCRT1Group (ULONG ROMAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT ModeNo, USHORT ModeIdIndex);
+void SiS_DetectMonitor (PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr);
+void SiS_GetSenseStatus (PSIS_HW_DEVICE_INFO HwDeviceExtension, ULONG ROMAddr);
+USHORT SiS_TestMonitorType (UCHAR R_DAC, UCHAR G_DAC, UCHAR B_DAC);
+USHORT SiS_SenseCHTV (VOID);
+BOOLEAN SiS_Sense (USHORT Part4Port, USHORT tempbx, USHORT tempcx);
+BOOLEAN SiS_GetPanelID (VOID);
+BOOLEAN SiS_GetLCDDDCInfo (PSIS_HW_DEVICE_INFO);
+USHORT SiS_SenseLCD (PSIS_HW_DEVICE_INFO);
+
+extern BOOLEAN SiS_SetCRT2Group301 (USHORT BaseAddr, ULONG ROMAddr,
+ USHORT ModeNo,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+extern void SiS_PresetScratchregister (USHORT SiS_P3d4,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+extern void SiS_UnLockCRT2 (PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT BaseAddr);
+extern void SiS_LockCRT2 (PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT BaseAddr);
+extern BOOLEAN SiS_BridgeIsOn (USHORT BaseAddr);
+extern BOOLEAN SiS_BridgeIsEnable (USHORT BaseAddr, PSIS_HW_DEVICE_INFO);
+extern void SiS_SetTVSystem301 (VOID);
+extern BOOLEAN SiS_GetLCDDDCInfo301 (PSIS_HW_DEVICE_INFO HwDeviceExtension);
+extern BOOLEAN SiS_GetSenseStatus301 (PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT BaseAddr, ULONG ROMAddr);
+extern USHORT SiS_GetVCLKLen (ULONG ROMAddr,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+extern BOOLEAN SiS_SetCRT2Group302 (USHORT BaseAddr, ULONG ROMAddr,
+ USHORT ModeNo,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+extern void SiS_GetVBInfo301 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,


+ USHORT ModeIdIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);

+extern BOOLEAN SiS_GetLCDResInfo301 (ULONG ROMAddr, USHORT P3d4, USHORT ModeNo,
+ USHORT ModeIdIndex);
+extern USHORT SiS_VBInfo, LCDResInfo, LCDTypeInfo, LCDInfo;
+extern USHORT SiS_GetRatePtrCRT2 (ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex);
+extern void SiS_LongWait (VOID);
+extern void SiS_SetRegANDOR (USHORT Port, USHORT Index, USHORT DataAND,
+ USHORT DataOR);
+extern USHORT SiS_GetResInfo (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex);
+extern void SiS_SetCH7005 (USHORT tempax);
+extern USHORT SiS_GetCH7005 (USHORT tempax);


+extern BOOLEAN SiS_GetLVDSCRT1Ptr (ULONG ROMAddr, USHORT ModeNo,

+ USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex,


+ USHORT * ResInfo, USHORT * DisplayType);

+extern BOOLEAN SiS_GetLCDACRT1Ptr (ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex,


+ USHORT * ResInfo, USHORT * DisplayType);

+extern USHORT SiS_GetVCLK2Ptr (ULONG ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);


+extern BOOLEAN SiS_Is301B (USHORT BaseAddr); /*301b */

+
+#endif
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/init301.c linux/drivers/video/sis/init301.c
--- v2.4.14/linux/drivers/video/sis/init301.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/sis/init301.c Fri Nov 9 14:11:14 2001
@@ -0,0 +1,6001 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/init301.c,v 1.3 2000/12/02 01:16:16 dawes Exp $ */
+
+#include "init301.h"
+#ifdef CONFIG_FB_SIS_300
+#include "oem300.h"
+#endif
+#ifdef CONFIG_FB_SIS_315
+#include "oem310.h"
+#endif
+
+BOOLEAN
+SiS_SetCRT2Group301 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+{


+ USHORT ModeIdIndex;
+ USHORT RefreshRateTableIndex;
+

+ SiS_SetFlag = SiS_SetFlag | ProgrammingCRT2;

+ SiS_SearchModeID (ROMAddr, ModeNo, &ModeIdIndex);
+ SiS_SelectCRT2Rate = 4;
+ RefreshRateTableIndex =
+ SiS_GetRatePtrCRT2 (ROMAddr, ModeNo, ModeIdIndex);
+ SiS_SaveCRT2Info (ModeNo);
+ SiS_DisableBridge (HwDeviceExtension, BaseAddr);
+ SiS_UnLockCRT2 (HwDeviceExtension, BaseAddr);
+ SiS_SetCRT2ModeRegs (BaseAddr, ModeNo, HwDeviceExtension);
+ if (SiS_VBInfo & DisableCRT2Display) {
+ SiS_LockCRT2 (HwDeviceExtension, BaseAddr);
+ SiS_DisplayOn ();
+ return (FALSE);
+ }
+/* SetDefCRT2ExtRegs(BaseAddr); */
+ SiS_GetCRT2Data (ROMAddr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ /*301b */


+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))

+ && (SiS_VBInfo & SetCRT2ToLCDA)) {
+ SiS_GetLVDSDesData (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex);
+ }


+ /*end 301b */
+ if (SiS_IF_DEF_LVDS == 1) {

+ SiS_GetLVDSDesData (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex);
+ }
+
+ SiS_SetGroup1 (BaseAddr, ROMAddr, ModeNo, ModeIdIndex,
+ HwDeviceExtension, RefreshRateTableIndex);
+ /*301b */


+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))
+ && (SiS_VBInfo & SetCRT2ToLCDA) && (SiS_IF_DEF_LVDS == 0)) {

+ } else if (SiS_IF_DEF_LVDS == 0 && (!(SiS_VBInfo & SetCRT2ToLCDA))) {
+ SiS_SetGroup2 (BaseAddr, ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, HwDeviceExtension);
+ SiS_SetGroup3 (BaseAddr, ROMAddr, ModeNo, ModeIdIndex,
+ HwDeviceExtension);
+ SiS_SetGroup4 (BaseAddr, ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, HwDeviceExtension);
+ SiS_SetGroup5 (BaseAddr, ROMAddr, ModeNo, ModeIdIndex);
+ } else {
+ if (SiS_IF_DEF_CH7005 == 1) {
+ SiS_SetCHTVReg (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex);
+ }
+ SiS_ModCRT1CRTC (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex);
+ SiS_SetCRT2ECLK (ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, HwDeviceExtension);
+ }


+
+#ifdef CONFIG_FB_SIS_300
+ if ((HwDeviceExtension->jChipType == SIS_540) ||
+ (HwDeviceExtension->jChipType == SIS_630) ||
+ (HwDeviceExtension->jChipType == SIS_730) ||
+ (HwDeviceExtension->jChipType == SIS_300))

+ SiS_OEM300Setting (HwDeviceExtension, BaseAddr, ROMAddr,
+ ModeNo);
+
+#endif
+
+#ifdef CONFIG_FB_SIS_315


+ if ((HwDeviceExtension->jChipType == SIS_315H) || /* 05/02/01 ynlai for sis550 */
+ (HwDeviceExtension->jChipType == SIS_315PRO) ||

+ (HwDeviceExtension->jChipType == SIS_550) || /* 05/02/01 ynlai for 550 */


+ (HwDeviceExtension->jChipType == SIS_640) || /* 08/20/01 chiawen for 640/740 */

+ (HwDeviceExtension->jChipType == SIS_740)) { /* 09/03/01 chiawen for 640/740 */
+ SiS_OEM310Setting (HwDeviceExtension, BaseAddr, ROMAddr, ModeNo,
+ ModeIdIndex);
+ SiS_CRT2AutoThreshold (BaseAddr);
+ }
+#endif
+
+ SiS_EnableBridge (HwDeviceExtension, BaseAddr);
+ SiS_DisplayOn ();
+ SiS_LockCRT2 (HwDeviceExtension, BaseAddr);


+ return 1;
+}
+
+void

+SiS_SetGroup1 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT RefreshRateTableIndex)
+{
+ USHORT temp = 0, tempax = 0, tempbx = 0, tempcx = 0;
+ USHORT pushbx = 0, CRT1Index = 0;
+ USHORT modeflag, resinfo = 0;
+
+ if (ModeNo <= 0x13) {
+ } else {
+ CRT1Index = SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;


+ CRT1Index = CRT1Index & 0x3F;

+ resinfo = SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ }

+
+ /*301b */


+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))

+ && (SiS_VBInfo & SetCRT2ToLCDA)) {
+ } else {
+ SiS_SetCRT2Offset (SiS_Part1Port, ROMAddr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex, HwDeviceExtension);


+ if (HwDeviceExtension->jChipType < SIS_315H) /* 300 series */

+ SiS_SetCRT2FIFO (SiS_Part1Port, ROMAddr, ModeNo,
+ HwDeviceExtension);


+ else /* 310 series */

+ SiS_SetCRT2FIFO2 (SiS_Part1Port, ROMAddr, ModeNo,
+ HwDeviceExtension);
+
+ SiS_SetCRT2Sync (BaseAddr, ROMAddr, ModeNo,
+ RefreshRateTableIndex);


+ }
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }

+ /*301b */


+ if (((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B))

+ && (SiS_VBInfo & SetCRT2ToLCDA)) {
+ SiS_SetGroup1_LCDA (BaseAddr, ROMAddr, ModeNo, ModeIdIndex,
+ HwDeviceExtension, RefreshRateTableIndex);


+ }
+ /*end 301b */

+ else if (HwDeviceExtension->jChipType < SIS_315H) { /* 300 series */
+ temp = (SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
+ SiS_SetReg1 (SiS_Part1Port, 0x08, temp);
+ temp = (((SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
+ SiS_SetRegANDOR (SiS_Part1Port, 0x09, ~0x0F0, temp);
+
+ temp = (SiS_VGAHDE + 12) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
+ SiS_SetReg1 (SiS_Part1Port, 0x0A, temp);
+
+ pushbx = SiS_VGAHDE + 12; /* bx BTVGA@HRS 0x0B,0x0C */
+ tempcx = (SiS_VGAHT - SiS_VGAHDE) >> 2; /* cx */
+ tempbx = pushbx + tempcx;


+ tempcx = tempcx << 1;

+ tempcx = tempcx + tempbx;

+


+ if (SiS_IF_DEF_LVDS == 0) {

+ if (SiS_VBInfo & SetCRT2ToRAMDAC) {
+ tempbx = SiS_CRT1Table[CRT1Index].CR[4];


+ tempbx =
+ tempbx |

+ ((SiS_CRT1Table[CRT1Index].CR[14] & 0xC0) <<
+ 2);
+ tempbx = (tempbx - 1) << 3;
+ tempcx = SiS_CRT1Table[CRT1Index].CR[5];
+ tempcx = tempcx & 0x1F;
+ temp = SiS_CRT1Table[CRT1Index].CR[15];
+ temp = (temp & 0x04) << (6 - 2);
+ tempcx = ((tempcx | temp) - 1) << 3;
+ }
+ }
+ /*add for hardware request */
+ if ((SiS_VBInfo & SetCRT2ToTV) && (resinfo == 0x08)) {


+ if (SiS_VBInfo & SetPALTV) {

+ tempbx = 1040;
+ tempcx = 1042;
+ } else {
+ tempbx = 1040;
+ tempcx = 1042;
+ }
+ }
+


+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part1Port, 0x0B, temp);
+


+ } else { /* 310 series */
+

+ if (modeflag & HalfDCLK) { /* for low resolution mode */
+ temp = (SiS_VGAHT / 2 - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
+ SiS_SetReg1 (SiS_Part1Port, 0x08, temp);
+ temp = (((SiS_VGAHT / 2 - 1) & 0xFF00) >> 8) << 4;
+ SiS_SetRegANDOR (SiS_Part1Port, 0x09, ~0x0F0, temp);
+ temp = (SiS_VGAHDE / 2 + 16) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
+ SiS_SetReg1 (SiS_Part1Port, 0x0A, temp);
+
+ pushbx = SiS_VGAHDE / 2 + 16;
+ tempcx = ((SiS_VGAHT - SiS_VGAHDE) / 2) >> 2; /* cx */
+ tempbx = pushbx + tempcx; /* bx BTVGA@HRS 0x0B,0x0C */
+ tempcx = tempcx + tempbx;
+


+ if (SiS_IF_DEF_LVDS == 0) {

+ if (SiS_VBInfo & SetCRT2ToRAMDAC) {
+ tempbx = SiS_CRT1Table[CRT1Index].CR[4];


+ tempbx =
+ tempbx |

+ ((SiS_CRT1Table
+ [CRT1Index].CR[14] & 0xC0) << 2);
+ tempbx = (tempbx - 3) << 3; /*(VGAHRS-3)*8 */
+ tempcx = SiS_CRT1Table[CRT1Index].CR[5];
+ tempcx = tempcx & 0x1F;
+ temp = SiS_CRT1Table[CRT1Index].CR[15];
+ temp = (temp & 0x04) << (5 - 2); /*VGAHRE D[5] */
+ tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */
+ }
+ }
+ tempbx += 4;
+ tempcx += 4;
+ if (tempcx > (SiS_VGAHT / 2))
+ tempcx = SiS_VGAHT / 2;


+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part1Port, 0x0B, temp);
+
+ } else {
+ temp = (SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
+ SiS_SetReg1 (SiS_Part1Port, 0x08, temp);
+ temp = (((SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
+ SiS_SetRegANDOR (SiS_Part1Port, 0x09, ~0x0F0, temp);
+ temp = (SiS_VGAHDE + 16) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
+ SiS_SetReg1 (SiS_Part1Port, 0x0A, temp);
+
+ pushbx = SiS_VGAHDE + 16;
+ tempcx = (SiS_VGAHT - SiS_VGAHDE) >> 2; /* cx */
+ tempbx = pushbx + tempcx; /* bx BTVGA@HRS 0x0B,0x0C */
+ tempcx = tempcx + tempbx;
+


+ if (SiS_IF_DEF_LVDS == 0) {

+ if (SiS_VBInfo & SetCRT2ToRAMDAC) {
+ tempbx = SiS_CRT1Table[CRT1Index].CR[4];


+ tempbx =
+ tempbx |

+ ((SiS_CRT1Table
+ [CRT1Index].CR[14] & 0xC0) << 2);
+ tempbx = (tempbx - 3) << 3; /*(VGAHRS-3)*8 */
+ tempcx = SiS_CRT1Table[CRT1Index].CR[5];
+ tempcx = tempcx & 0x1F;
+ temp = SiS_CRT1Table[CRT1Index].CR[15];
+ temp = (temp & 0x04) << (5 - 2); /*VGAHRE D[5] */
+ tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */
+ tempbx += 16;
+ tempcx += 16;
+
+ }
+ }
+ if (tempcx > SiS_VGAHT)
+ tempcx = SiS_VGAHT;
+ /*add for hardware request */
+ if ((SiS_VBInfo & SetCRT2ToTV) && (resinfo == 0x08)) {


+ if (SiS_VBInfo & SetPALTV) {

+ tempbx = 1040;
+ tempcx = 1042;
+ } else {
+ tempbx = 1040;
+ tempcx = 1042;
+ }
+ }


+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part1Port, 0x0B, temp);
+ }
+
+ }
+
+ tempax = (tempax & 0x00FF) | (tempbx & 0xFF00);
+ tempbx = pushbx;
+ tempbx = (tempbx & 0x00FF) | ((tempbx & 0xFF00) << 4);
+ tempax = tempax | (tempbx & 0xFF00);


+ temp = (tempax & 0xFF00) >> 8;

+ SiS_SetReg1 (SiS_Part1Port, 0x0C, temp);


+ temp = tempcx & 0x00FF;

+ SiS_SetReg1 (SiS_Part1Port, 0x0D, temp);
+ tempcx = (SiS_VGAVT - 1);


+ temp = tempcx & 0x00FF;

+ if (SiS_IF_DEF_CH7005 == 1) {

+ if (SiS_VBInfo & 0x0C) {
+ temp--;
+ }
+ }
+ SiS_SetReg1 (SiS_Part1Port, 0x0E, temp);
+ tempbx = SiS_VGAVDE - 1;


+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part1Port, 0x0F, temp);
+ temp = ((tempbx & 0xFF00) << 3) >> 8;


+ temp = temp | ((tempcx & 0xFF00) >> 8);

+ SiS_SetReg1 (SiS_Part1Port, 0x12, temp);
+
+ tempax = SiS_VGAVDE;
+ tempbx = SiS_VGAVDE;
+ tempcx = SiS_VGAVT;
+ tempbx = (SiS_VGAVT + SiS_VGAVDE) >> 1; /* BTVGA2VRS 0x10,0x11 */
+ tempcx = ((SiS_VGAVT - SiS_VGAVDE) >> 4) + tempbx + 1; /* BTVGA2VRE 0x11 */


+ if (SiS_IF_DEF_LVDS == 0) {

+ if (SiS_VBInfo & SetCRT2ToRAMDAC) {
+ tempbx = SiS_CRT1Table[CRT1Index].CR[8];
+ temp = SiS_CRT1Table[CRT1Index].CR[7];
+ if (temp & 0x04)


+ tempbx = tempbx | 0x0100;

+ if (temp & 0x080)


+ tempbx = tempbx | 0x0200;

+ temp = SiS_CRT1Table[CRT1Index].CR[13];
+ if (temp & 0x08)
+ tempbx = tempbx | 0x0400;
+ temp = SiS_CRT1Table[CRT1Index].CR[9];
+ tempcx = (tempcx & 0xFF00) | (temp & 0x00FF);
+ }
+ }


+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part1Port, 0x10, temp);
+ temp = ((tempbx & 0xFF00) >> 8) << 4;
+ temp = ((tempcx & 0x000F) | (temp));
+ SiS_SetReg1 (SiS_Part1Port, 0x11, temp);


+ if (SiS_IF_DEF_LVDS == 0) {

+ temp = 0x20;


+ if (SiS_LCDResInfo == Panel1280x1024)

+ temp = 0x20;


+ if (SiS_LCDResInfo == Panel1280x960)

+ temp = 0x24;


+ if (SiS_VBInfo & SetCRT2ToTV)

+ temp = 0x08;
+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) {


+ if (SiS_VBInfo & SetInSlaveMode)

+ temp = 0x2c;
+ else
+ temp = 0x20;
+ }
+ } else {
+ temp = 0x20;
+ }
+ if (HwDeviceExtension->jChipType < SIS_315H) /* 300 series */
+ SiS_SetRegANDOR (SiS_Part1Port, 0x13, ~0x03C, temp);


+ else { /* 310 series */
+

+ temp >>= 2;
+ temp = 0x11; /* ynlai 05/30/2001 for delay compenation */
+ SiS_SetReg1 (SiS_Part1Port, 0x2D, temp);
+ /*SiS_SetRegANDOR(SiS_Part1Port,0x2D,~0x00F,temp); */
+ SiS_SetRegAND (SiS_Part1Port, 0x13, 0xEF); /* BDirectLCD=0 for lcd ?? */
+ tempax = 0;
+
+ if (modeflag & DoubleScanMode)
+ tempax |= 0x80;


+ if (modeflag & HalfDCLK)

+ tempax |= 0x40;
+ SiS_SetRegANDOR (SiS_Part1Port, 0x2C, ~0x0C0, tempax);
+
+ }
+
+ if (SiS_IF_DEF_LVDS == 0) { /* 301 */
+ SiS_SetGroup1_301 (BaseAddr, ROMAddr, ModeNo, ModeIdIndex,
+ HwDeviceExtension, RefreshRateTableIndex);


+ } else { /* LVDS */

+ SiS_SetGroup1_LVDS (BaseAddr, ROMAddr, ModeNo, ModeIdIndex,
+ HwDeviceExtension, RefreshRateTableIndex);
+ }
+}
+
+void
+SiS_SetGroup1_301 (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT RefreshRateTableIndex)
+{
+ USHORT push1, push2;
+ USHORT tempax, tempbx, tempcx, temp;
+ USHORT resinfo, modeflag;
+ USHORT CRT1Index;


+
+ if (ModeNo <= 0x13) {

+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+ resinfo = SiS_SModeIDTable[ModeIdIndex].St_ResInfo;

+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */

+ resinfo = SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;

+ CRT1Index = SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;


+ CRT1Index = CRT1Index & 0x3F;
+ }

+
+ if (!(SiS_VBInfo & SetInSlaveMode)) {
+ return;
+ }
+ tempax = 0xFFFF;


+ if (!(SiS_VBInfo & SetCRT2ToTV)) {
+ tempax = SiS_GetVGAHT2 ();

+ }
+ if (modeflag & Charx8Dot)
+ tempcx = 0x08;
+ else
+ tempcx = 0x09;
+ if (tempax >= SiS_VGAHT) {
+ tempax = SiS_VGAHT;


+ }
+ if (modeflag & HalfDCLK) {

+ tempax = tempax >> 1;
+ }

+ tempax = (tempax / tempcx) - 5;
+ tempbx = tempax;
+ temp = 0xFF; /* set MAX HT */


+ SiS_SetReg1 (SiS_Part1Port, 0x03, temp);
+

+ tempax = SiS_VGAHDE; /* 0x04 Horizontal Display End */


+ if (modeflag & HalfDCLK)

+ tempax = tempax >> 1;

+ tempax = (tempax / tempcx) - 1;
+ tempbx = tempbx | ((tempax & 0x00FF) << 8);
+ temp = tempax & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x04, temp);


+
+ temp = (tempbx & 0xFF00) >> 8;

+ if (SiS_VBInfo & SetCRT2ToTV) {

+ temp = temp + 2;

+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) {

+ if (resinfo == 7)

+ temp = temp - 2;
+ }
+ }
+ SiS_SetReg1 (SiS_Part1Port, 0x05, temp); /* 0x05 Horizontal Display Start */
+ SiS_SetReg1 (SiS_Part1Port, 0x06, 0x03); /* 0x06 Horizontal Blank end */
+ /* 0x07 horizontal Retrace Start */
+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) {
+ temp = (tempbx & 0x00FF) - 1;


+ if (!(modeflag & HalfDCLK)) {

+ temp = temp - 6;


+ if (SiS_SetFlag & TVSimuMode) {

+ temp = temp - 4;
+ if (ModeNo > 0x13)
+ temp = temp - 10;
+ }
+ }
+ } else {
+ tempcx = tempbx & 0x00FF;
+ tempbx = (tempbx & 0xFF00) >> 8;
+ tempcx = (tempcx + tempbx) >> 1;
+ temp = (tempcx & 0x00FF) + 2;


+ if (SiS_VBInfo & SetCRT2ToTV) {

+ temp = temp - 1;


+ if (!(modeflag & HalfDCLK)) {

+ if ((modeflag & Charx8Dot)) {
+ temp = temp + 4;
+ if (SiS_VGAHDE >= 800) {
+ temp = temp - 6;
+ }
+ }
+ }
+ } else {
+ if (!(modeflag & HalfDCLK)) {
+ temp = temp - 4;


+ if (SiS_LCDResInfo != Panel1280x960) {

+ if (SiS_VGAHDE >= 800) {
+ temp = temp - 7;


+ if (SiS_ModeType == ModeEGA) {

+ if (SiS_VGAVDE == 1024) {
+ temp =
+ temp + 15;
+ if
+ (SiS_LCDResInfo
+ !=
+ Panel1280x1024)
+ {
+ temp =
+ temp
+ + 7;
+ }
+ }
+ }
+ if (SiS_VGAHDE >= 1280) {
+ if (SiS_LCDResInfo !=
+ Panel1280x960) {
+ if (SiS_LCDInfo
+ &
+ LCDNonExpanding)
+ {
+ temp =
+ temp
+ +
+ 28;


+ }
+ }
+ }
+ }
+ }
+ }

+ }
+ }
+
+ SiS_SetReg1 (SiS_Part1Port, 0x07, temp); /* 0x07 Horizontal Retrace Start */
+ SiS_SetReg1 (SiS_Part1Port, 0x08, 0); /* 0x08 Horizontal Retrace End */
+


+ if (SiS_VBInfo & SetCRT2ToTV) {

+ if (SiS_SetFlag & TVSimuMode) {
+ if ((ModeNo == 0x06) || (ModeNo == 0x10)
+ || (ModeNo == 0x11) || (ModeNo == 0x13)
+ || (ModeNo == 0x0F)) {
+ SiS_SetReg1 (SiS_Part1Port, 0x07, 0x5b);
+ SiS_SetReg1 (SiS_Part1Port, 0x08, 0x03);
+ }
+ if ((ModeNo == 0x00) || (ModeNo == 0x01)) {
+ if (SiS_VBInfo & SetNTSCTV) {
+ SiS_SetReg1 (SiS_Part1Port, 0x07, 0x2A);
+ SiS_SetReg1 (SiS_Part1Port, 0x08, 0x61);
+ } else {
+ SiS_SetReg1 (SiS_Part1Port, 0x07, 0x2A);
+ SiS_SetReg1 (SiS_Part1Port, 0x08, 0x41);
+ SiS_SetReg1 (SiS_Part1Port, 0x0C, 0xF0);
+ }
+ }
+ if ((ModeNo == 0x02) || (ModeNo == 0x03)
+ || (ModeNo == 0x07)) {
+ if (SiS_VBInfo & SetNTSCTV) {
+ SiS_SetReg1 (SiS_Part1Port, 0x07, 0x54);
+ SiS_SetReg1 (SiS_Part1Port, 0x08, 0x00);
+ } else {
+ SiS_SetReg1 (SiS_Part1Port, 0x07, 0x55);
+ SiS_SetReg1 (SiS_Part1Port, 0x08, 0x00);
+ SiS_SetReg1 (SiS_Part1Port, 0x0C, 0xF0);
+ }
+ }
+ if ((ModeNo == 0x04) || (ModeNo == 0x05)
+ || (ModeNo == 0x0D) || (ModeNo == 0x50)) {
+ if (SiS_VBInfo & SetNTSCTV) {
+ SiS_SetReg1 (SiS_Part1Port, 0x07, 0x30);
+ SiS_SetReg1 (SiS_Part1Port, 0x08, 0x03);
+ } else {
+ SiS_SetReg1 (SiS_Part1Port, 0x07, 0x2f);
+ SiS_SetReg1 (SiS_Part1Port, 0x08, 0x02);


+ }
+ }
+ }
+ }
+

+ SiS_SetReg1 (SiS_Part1Port, 0x18, 0x03); /* 0x18 SR08 */
+ SiS_SetRegANDOR (SiS_Part1Port, 0x19, 0xF0, 0x00);
+ SiS_SetReg1 (SiS_Part1Port, 0x09, 0xFF); /* 0x09 Set Max VT */
+
+ tempbx = SiS_VGAVT;
+ push1 = tempbx;
+ tempcx = 0x121;
+ tempbx = SiS_VGAVDE; /* 0x0E Virtical Display End */
+ if (tempbx == 357)
+ tempbx = 350;
+ if (tempbx == 360)
+ tempbx = 350;
+ if (tempbx == 375)
+ tempbx = 350;
+ if (tempbx == 405)
+ tempbx = 400;
+ if (tempbx == 420)
+ tempbx = 400;
+ if (tempbx == 525)
+ tempbx = 480;
+ push2 = tempbx;


+ if (SiS_VBInfo & SetCRT2ToLCD) {

+ if (SiS_LCDResInfo == Panel1024x768) {


+ if (!(SiS_SetFlag & LCDVESATiming)) {

+ if (tempbx == 350)
+ tempbx = tempbx + 5;
+ if (tempbx == 480)
+ tempbx = tempbx + 5;
+ }
+ }
+ }


+ tempbx--;
+ temp = tempbx & 0x00FF;
+ tempbx--;
+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part1Port, 0x10, temp); /* 0x10 vertical Blank Start */
+ tempbx = push2;


+ tempbx--;
+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part1Port, 0x0E, temp);
+ if (tempbx & 0x0100) {
+ tempcx = tempcx | 0x0002;
+ }
+ tempax = 0x000B;


+ if (modeflag & DoubleScanMode) {

+ tempax = tempax | 0x08000;
+ }
+ if (tempbx & 0x0200) {
+ tempcx = tempcx | 0x0040;


+ }
+
+ temp = (tempax & 0xFF00) >> 8;

+ SiS_SetReg1 (SiS_Part1Port, 0x0B, temp);
+ if (tempbx & 0x0400) {
+ tempcx = tempcx | 0x0600;
+ }
+ SiS_SetReg1 (SiS_Part1Port, 0x11, 0x00); /* 0x11 Vertival Blank End */
+
+ tempax = push1;
+ tempax = tempax - tempbx; /* 0x0C Vertical Retrace Start */


+ tempax = tempax >> 2;

+ push1 = tempax; /* push ax */
+
+ if (resinfo != 0x09) {


+ tempax = tempax << 1;

+ tempbx = tempax + tempbx;
+ }
+ if (SiS_VBInfo & SetCRT2ToHiVisionTV) {
+ tempbx = tempbx - 10;
+ } else {


+ if (SiS_SetFlag & TVSimuMode) {

+ if (SiS_VBInfo & SetPALTV) {

+ tempbx = tempbx + 40;
+ }
+ }
+ }
+ tempax = push1;


+ tempax = tempax >> 2;

+ tempax++;


+ tempax = tempax + tempbx;

+ push1 = tempax; /* push ax */
+ if ((SiS_VBInfo & SetPALTV)) {
+ if (tempbx <= 513) {
+ if (tempax >= 513) {
+ tempbx = 513;
+ }
+ }
+ }


+ temp = (tempbx & 0x00FF);

+ SiS_SetReg1 (SiS_Part1Port, 0x0C, temp);


+ tempbx--;
+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part1Port, 0x10, temp);
+ if (tempbx & 0x0100) {
+ tempcx = tempcx | 0x0008;
+ }
+ if (tempbx & 0x0200) {
+ SiS_SetRegANDOR (SiS_Part1Port, 0x0B, 0x0FF, 0x20);
+ }
+ tempbx++;
+ if (tempbx & 0x0100) {
+ tempcx = tempcx | 0x0004;
+ }
+ if (tempbx & 0x0200) {
+ tempcx = tempcx | 0x0080;
+ }
+ if (tempbx & 0x0400) {
+ tempcx = tempcx | 0x0C00;
+ }
+
+ tempbx = push1; /* pop ax */


+ temp = tempbx & 0x00FF;

+ temp = temp & 0x0F;

+ SiS_SetReg1 (SiS_Part1Port, 0x0D, temp); /* 0x0D vertical Retrace End */
+ if (tempbx & 0x0010) {
+ tempcx = tempcx | 0x2000;


+ }
+
+ temp = tempcx & 0x00FF;

+ SiS_SetReg1 (SiS_Part1Port, 0x0A, temp); /* 0x0A CR07 */
+ temp = (tempcx & 0x0FF00) >> 8;
+ SiS_SetReg1 (SiS_Part1Port, 0x17, temp); /* 0x17 SR0A */
+ tempax = modeflag;


+ temp = (tempax & 0xFF00) >> 8;
+

+ temp = (temp >> 1) & 0x09;
+ SiS_SetReg1 (SiS_Part1Port, 0x16, temp); /* 0x16 SR01 */
+ SiS_SetReg1 (SiS_Part1Port, 0x0F, 0); /* 0x0F CR14 */
+ SiS_SetReg1 (SiS_Part1Port, 0x12, 0); /* 0x12 CR17 */


+ if (SiS_LCDInfo & LCDRGB18Bit)

+ temp = 0x80;
+ else
+ temp = 0x00;
+ SiS_SetReg1 (SiS_Part1Port, 0x1A, temp); /* 0x1A SR0E */
+ return;
+}
+
+void
+SiS_SetGroup1_LVDS (USHORT BaseAddr, ULONG ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT RefreshRateTableIndex)
+{
+ USHORT modeflag, resinfo;
+ USHORT push1, push2, tempax, tempbx, tempcx, temp, pushcx;
+ ULONG tempeax = 0, tempebx, tempecx, tempvcfact = 0;
+


+ if (ModeNo <= 0x13) {
+ modeflag = SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */

+ resinfo = SiS_SModeIDTable[ModeIdIndex].St_ResInfo;

+ } else {
+ modeflag = SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */

+ resinfo = SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ }

+
+ tempax = SiS_LCDHDES;
+ tempbx = SiS_HDE;
+ tempcx = SiS_HT;

+ tempcx = tempcx - tempbx; /* HT-HDE */


+ if (SiS_LCDInfo & LCDNonExpanding) {

+ if (SiS_LCDResInfo == Panel800x600)
+ tempbx = 800;


+ if (SiS_LCDResInfo == Panel1024x768)

+ tempbx = 1024;
+ }
+ push1 = tempax;


+ tempax = tempax + tempbx; /* lcdhdee */
+ tempbx = SiS_HT;
+ if (tempax >= tempbx) {
+ tempax = tempax - tempbx;
+ }
+ push2 = tempax;
+ /* push ax lcdhdee */
+ tempcx = tempcx >> 2; /* temp */
+ tempcx = tempcx + tempax; /* lcdhrs */
+ if (tempcx >= tempbx) {
+ tempcx = tempcx - tempbx;
+ }
+ /* v ah,cl */
+ tempax = tempcx;
+ tempax = tempax >> 3; /* BPLHRS */
+ temp = tempax & 0x00FF;
+ SiS_SetReg1 (SiS_Part1Port, 0x14, temp); /* Part1_14h */
+ temp = (tempax & 0x00FF) + 10;
+ temp = temp & 0x01F;
+ temp = temp | (((tempcx & 0x00ff) & 0x07) << 5);
+ SiS_SetReg1 (SiS_Part1Port, 0x15, temp); /* Part1_15h */
+ tempbx = push2; /* lcdhdee */

+ tempcx = push1; /* lcdhdes */


+ temp = (tempcx & 0x00FF);

+ temp = temp & 0x07; /* BPLHDESKEW */

+ SiS_SetReg1 (SiS_Part1Port, 0x1A, temp); /* Part1_1Ah */
+ tempcx = tempcx >> 3; /* BPLHDES */


+ temp = (tempcx & 0x00FF);

+ SiS_SetReg1 (SiS_Part1Port, 0x16, temp); /* Part1_16h */
+ if (tempbx & 0x07)
+ tempbx = tempbx + 8;

+ tempbx = tempbx >> 3; /* BPLHDEE */


+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part1Port, 0x17, temp); /* Part1_17h */

+


+ tempcx = SiS_VGAVT;
+ tempbx = SiS_VGAVDE;
+ tempcx = tempcx - tempbx; /* GAVT-VGAVDE */
+ tempbx = SiS_LCDVDES; /* VGAVDES */
+ push1 = tempbx; /* push bx temppush1 */

+ if (SiS_IF_DEF_TRUMPION == 0) {

+ if (SiS_IF_DEF_CH7005 == 1) {
+ if (SiS_VBInfo & SetCRT2ToTV) {

+ tempax = SiS_VGAVDE;


+ }
+ }
+ if (SiS_VBInfo & SetCRT2ToLCD) {

+ if (SiS_LCDResInfo == Panel800x600)

+ tempax = 600;


+ if (SiS_LCDResInfo == Panel1024x768)

+ tempax = 768;
+ }
+ } else


+ tempax = SiS_VGAVDE;
+ tempbx = tempbx + tempax;
+ tempax = SiS_VT; /* VT */
+ if (tempbx >= SiS_VT) {
+ tempbx = tempbx - tempax;
+ }
+ push2 = tempbx; /* push bx temppush2 */
+ tempcx = tempcx >> 1;
+ tempbx = tempbx + tempcx;
+ tempbx++; /* BPLVRS */
+ if (tempbx >= tempax) {

+ tempbx = tempbx - tempax;


+ }
+ temp = tempbx & 0x00FF;

+ SiS_SetReg1 (SiS_Part1Port, 0x18, temp); /* Part1_18h */
+ tempcx = tempcx >> 3;
+ tempcx = tempcx + tempbx;
+ tempcx++; /* BPLVRE */

+ temp = tempcx & 0x00FF;

+ temp = temp & 0x0F;

+ SiS_SetRegANDOR (SiS_Part1Port, 0x19, ~0x00F, temp); /* Part1_19h */

+ temp = (tempbx & 0xFF00) >> 8;

+ temp = temp & 0x07;
+ temp = temp << 3; /* BPLDESKEW =0 */
+ tempbx = SiS_VGAVDE;

+ if (tempbx != SiS_VDE) {

+ temp = temp | 0x40;
+ }


+ if (SiS_SetFlag & EnableLVDSDDA) {
+ temp = temp | 0x40;

+ }


+ if (SiS_LCDInfo & LCDRGB18Bit) {

+ temp = temp | 0x80;
+ }
+ SiS_SetRegANDOR (SiS_Part1Port, 0x1A, 0x07, temp); /* Part1_1Ah */
+

+ tempecx = SiS_VGAVT;
+ tempebx = SiS_VDE;


+ tempeax = SiS_VGAVDE;
+ tempecx = tempecx - tempeax; /* VGAVT-VGAVDE */

+ tempeax = tempeax << 6;


+ temp = (USHORT) (tempeax % tempebx);

+ tempeax = tempeax / tempebx;
+ if (temp != 0) {
+ tempeax++;
+ }
+ tempebx = tempeax; /* BPLVCFACT */

+ if (SiS_SetFlag & EnableLVDSDDA) {

+ tempebx = tempebx & 0x003F;
+ }
+ temp = (USHORT) (tempebx & 0x00FF);
+ SiS_SetReg1 (SiS_Part1Port, 0x1E, temp); /* Part1_1Eh */
+
+ /*add for 301b different 301 */


+ if ((SiS_VBType & VB_SIS301B) || (SiS_VBType & VB_SIS302B)) {

+ tempecx = SiS_VGAVT;
+ tempebx = SiS_VDE;


+ tempeax = SiS_VGAVDE;
+ tempecx = tempecx - tempeax; /* VGAVT-VGAVDE */
+ tempeax = tempeax << 18;
+ temp = (USHORT) (tempeax % tempebx);
+ tempeax = tempeax / tempebx;
+ if (temp != 0) {
+ tempeax++;
+ }
+ tempebx = tempeax; /* BPLVCFACT */
+ tempvcfact = tempeax; /*301b */
+ temp = (USHORT) (tempebx & 0x00FF);
+ SiS_SetReg1 (SiS_Part1Port, 0x37, temp);
+ temp = (USHORT) ((tempebx & 0x00FF00) >> 8);
+ SiS_SetReg1 (SiS_Part1Port, 0x36, temp);
+ temp = (USHORT) ((tempebx & 0x00030000) >> 16);
+ if (SiS_VDE == SiS_VGAVDE) {
+ temp = temp | 0x04;
+ }
+
+ SiS_SetReg1 (SiS_Part1Port, 0x35, temp);
+ }

+ /*end for 301b */
+


+ tempbx = push2; /* p bx temppush2 BPLVDEE */
+ tempcx = push1; /* pop cx temppush1 NPLVDES */
+ push1 = (USHORT) (tempeax & 0xFFFF);

+ if (!(SiS_VBInfo & SetInSlaveMode)) {

+ if (SiS_LCDResInfo == Panel800x600) {

+ if (resinfo == 7)
+ tempcx++;

+ } else {
+ if (SiS_LCDResInfo == Panel1024x768) {
+ if (resinfo == 8)
+ tempcx++;
+ }
+ }
+ }
+


+ temp = (tempbx & 0xFF00) >> 8;

+ temp = temp & 0x07;


+ temp = temp << 3;

+ temp = temp | (((tempcx & 0xFF00) >> 8) & 0x07);
+ SiS_SetReg1 (SiS_Part1Port, 0x1D, temp); /* Part1_1Dh */

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

echo 'End of part 077'
echo 'File patch-2.4.15 is continued in part 078'
echo "078" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:06 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part090

#!/bin/sh -x
# this is part 090 of a 115 - part archive


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

if test "$Scheck" != 090; 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.4.15'
else
echo 'x - continuing with patch-2.4.15'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.4.15' &&
+{

+ if (*value) {
+ printk(KERN_NOTICE "EXT3-fs: Invalid %s argument: %s\n",
+ option, value);


+ return -1;
+ }
+ return 0;
+}
+

+static int want_numeric(char *value, char *option, unsigned long *number)
+{
+ if (want_value(value, option))
+ return -1;
+ *number = simple_strtoul(value, &value, 0);
+ if (want_null_value(value, option))
+ return -1;


+ return 0;
+}
+
+/*

+ * This function has been shamelessly adapted from the msdos fs
+ */
+static int parse_options (char * options, unsigned long * sb_block,
+ struct ext3_sb_info *sbi,
+ unsigned long * inum,
+ int is_remount)
+{
+ unsigned long *mount_options = &sbi->s_mount_opt;
+ uid_t *resuid = &sbi->s_resuid;
+ gid_t *resgid = &sbi->s_resgid;
+ char * this_char;
+ char * value;
+
+ if (!options)
+ return 1;
+ for (this_char = strtok (options, ",");
+ this_char != NULL;
+ this_char = strtok (NULL, ",")) {
+ if ((value = strchr (this_char, '=')) != NULL)
+ *value++ = 0;
+ if (!strcmp (this_char, "bsddf"))
+ clear_opt (*mount_options, MINIX_DF);
+ else if (!strcmp (this_char, "nouid32")) {
+ set_opt (*mount_options, NO_UID32);
+ }
+ else if (!strcmp (this_char, "abort"))
+ set_opt (*mount_options, ABORT);
+ else if (!strcmp (this_char, "check")) {
+ if (!value || !*value || !strcmp (value, "none"))
+ clear_opt (*mount_options, CHECK);
+ else
+#ifdef CONFIG_EXT3_CHECK
+ set_opt (*mount_options, CHECK);
+#else
+ printk(KERN_ERR
+ "EXT3 Check option not supported\n");
+#endif
+ }
+ else if (!strcmp (this_char, "debug"))
+ set_opt (*mount_options, DEBUG);
+ else if (!strcmp (this_char, "errors")) {
+ if (want_value(value, "errors"))
+ return 0;
+ if (!strcmp (value, "continue")) {
+ clear_opt (*mount_options, ERRORS_RO);
+ clear_opt (*mount_options, ERRORS_PANIC);
+ set_opt (*mount_options, ERRORS_CONT);
+ }
+ else if (!strcmp (value, "remount-ro")) {
+ clear_opt (*mount_options, ERRORS_CONT);
+ clear_opt (*mount_options, ERRORS_PANIC);
+ set_opt (*mount_options, ERRORS_RO);
+ }
+ else if (!strcmp (value, "panic")) {
+ clear_opt (*mount_options, ERRORS_CONT);
+ clear_opt (*mount_options, ERRORS_RO);
+ set_opt (*mount_options, ERRORS_PANIC);
+ }
+ else {
+ printk (KERN_ERR
+ "EXT3-fs: Invalid errors option: %s\n",
+ value);


+ return 0;
+ }
+ }

+ else if (!strcmp (this_char, "grpid") ||
+ !strcmp (this_char, "bsdgroups"))
+ set_opt (*mount_options, GRPID);
+ else if (!strcmp (this_char, "minixdf"))
+ set_opt (*mount_options, MINIX_DF);
+ else if (!strcmp (this_char, "nocheck"))
+ clear_opt (*mount_options, CHECK);
+ else if (!strcmp (this_char, "nogrpid") ||
+ !strcmp (this_char, "sysvgroups"))
+ clear_opt (*mount_options, GRPID);
+ else if (!strcmp (this_char, "resgid")) {
+ unsigned long v;
+ if (want_numeric(value, "resgid", &v))
+ return 0;
+ *resgid = v;
+ }
+ else if (!strcmp (this_char, "resuid")) {
+ unsigned long v;
+ if (want_numeric(value, "resuid", &v))
+ return 0;
+ *resuid = v;
+ }
+ else if (!strcmp (this_char, "sb")) {
+ if (want_numeric(value, "sb", sb_block))
+ return 0;
+ }
+#ifdef CONFIG_JBD_DEBUG
+ else if (!strcmp (this_char, "ro-after")) {
+ unsigned long v;
+ if (want_numeric(value, "ro-after", &v))
+ return 0;
+ ext3_ro_after = v;
+ }
+#endif
+ /* Silently ignore the quota options */
+ else if (!strcmp (this_char, "grpquota")
+ || !strcmp (this_char, "noquota")
+ || !strcmp (this_char, "quota")
+ || !strcmp (this_char, "usrquota"))
+ /* Don't do anything ;-) */ ;
+ else if (!strcmp (this_char, "journal")) {
+ /* @@@ FIXME */
+ /* Eventually we will want to be able to create
+ a journal file here. For now, only allow the
+ user to specify an existing inode to be the
+ journal file. */
+ if (is_remount) {
+ printk(KERN_ERR "EXT3-fs: cannot specify "
+ "journal on remount\n");


+ return 0;
+ }
+

+ if (want_value(value, "journal"))
+ return 0;
+ if (!strcmp (value, "update"))
+ set_opt (*mount_options, UPDATE_JOURNAL);
+ else if (want_numeric(value, "journal", inum))
+ return 0;
+ }
+ else if (!strcmp (this_char, "noload"))
+ set_opt (*mount_options, NOLOAD);
+ else if (!strcmp (this_char, "data")) {
+ int data_opt = 0;
+
+ if (want_value(value, "data"))
+ return 0;
+ if (!strcmp (value, "journal"))
+ data_opt = EXT3_MOUNT_JOURNAL_DATA;
+ else if (!strcmp (value, "ordered"))
+ data_opt = EXT3_MOUNT_ORDERED_DATA;
+ else if (!strcmp (value, "writeback"))
+ data_opt = EXT3_MOUNT_WRITEBACK_DATA;
+ else {
+ printk (KERN_ERR
+ "EXT3-fs: Invalid data option: %s\n",
+ value);
+ return 0;
+ }
+ if (is_remount) {
+ if ((*mount_options & EXT3_MOUNT_DATA_FLAGS) !=
+ data_opt) {
+ printk(KERN_ERR
+ "EXT3-fs: cannot change data "
+ "mode on remount\n");
+ return 0;
+ }
+ } else {
+ *mount_options &= ~EXT3_MOUNT_DATA_FLAGS;
+ *mount_options |= data_opt;
+ }
+ } else {
+ printk (KERN_ERR
+ "EXT3-fs: Unrecognized mount option %s\n",
+ this_char);


+ return 0;
+ }
+ }

+ return 1;
+}
+

+static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
+ int read_only)


+{
+ struct ext3_sb_info *sbi = EXT3_SB(sb);

+ int res = 0;
+
+ if (le32_to_cpu(es->s_rev_level) > EXT3_MAX_SUPP_REV) {
+ printk (KERN_ERR "EXT3-fs warning: revision level too high, "
+ "forcing read-only mode\n");
+ res = MS_RDONLY;
+ }
+ if (read_only)
+ return res;
+ if (!(sbi->s_mount_state & EXT3_VALID_FS))
+ printk (KERN_WARNING "EXT3-fs warning: mounting unchecked fs, "
+ "running e2fsck is recommended\n");
+ else if ((sbi->s_mount_state & EXT3_ERROR_FS))
+ printk (KERN_WARNING
+ "EXT3-fs warning: mounting fs with errors, "
+ "running e2fsck is recommended\n");
+ else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 &&
+ le16_to_cpu(es->s_mnt_count) >=
+ (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count))
+ printk (KERN_WARNING
+ "EXT3-fs warning: maximal mount count reached, "
+ "running e2fsck is recommended\n");
+ else if (le32_to_cpu(es->s_checkinterval) &&
+ (le32_to_cpu(es->s_lastcheck) +
+ le32_to_cpu(es->s_checkinterval) <= CURRENT_TIME))
+ printk (KERN_WARNING
+ "EXT3-fs warning: checktime reached, "
+ "running e2fsck is recommended\n");
+#if 0
+ /* @@@ We _will_ want to clear the valid bit if we find
+ inconsistencies, to force a fsck at reboot. But for
+ a plain journaled filesystem we can keep it set as
+ valid forever! :) */
+ es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT3_VALID_FS);
+#endif
+ if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
+ es->s_max_mnt_count =
+ (__s16) cpu_to_le16(EXT3_DFL_MAX_MNT_COUNT);
+ es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
+ es->s_mtime = cpu_to_le32(CURRENT_TIME);
+ ext3_update_dynamic_rev(sb);
+ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
+ ext3_commit_super (sb, es, 1);
+ if (test_opt (sb, DEBUG))
+ printk (KERN_INFO
+ "[EXT3 FS %s, %s, bs=%lu, gc=%lu, "
+ "bpg=%lu, ipg=%lu, mo=%04lx]\n",
+ EXT3FS_VERSION, EXT3FS_DATE, sb->s_blocksize,
+ sbi->s_groups_count,
+ EXT3_BLOCKS_PER_GROUP(sb),
+ EXT3_INODES_PER_GROUP(sb),
+ sbi->s_mount_opt);
+ printk(KERN_INFO "EXT3 FS " EXT3FS_VERSION ", " EXT3FS_DATE " on %s, ",
+ bdevname(sb->s_dev));
+ if (EXT3_SB(sb)->s_journal->j_inode == NULL) {
+ printk("external journal on %s\n",
+ bdevname(EXT3_SB(sb)->s_journal->j_dev));
+ } else {
+ printk("internal journal\n");
+ }
+#ifdef CONFIG_EXT3_CHECK
+ if (test_opt (sb, CHECK)) {
+ ext3_check_blocks_bitmap (sb);
+ ext3_check_inodes_bitmap (sb);
+ }
+#endif
+ setup_ro_after(sb);
+ return res;
+}
+
+static int ext3_check_descriptors (struct super_block * sb)


+{
+ struct ext3_sb_info *sbi = EXT3_SB(sb);

+ unsigned long block = le32_to_cpu(sbi->s_es->s_first_data_block);
+ struct ext3_group_desc * gdp = NULL;
+ int desc_block = 0;
+ int i;
+
+ ext3_debug ("Checking group descriptors");
+
+ for (i = 0; i < sbi->s_groups_count; i++)
+ {
+ if ((i % EXT3_DESC_PER_BLOCK(sb)) == 0)


+ gdp = (struct ext3_group_desc *)

+ sbi->s_group_desc[desc_block++]->b_data;
+ if (le32_to_cpu(gdp->bg_block_bitmap) < block ||
+ le32_to_cpu(gdp->bg_block_bitmap) >=
+ block + EXT3_BLOCKS_PER_GROUP(sb))
+ {
+ ext3_error (sb, "ext3_check_descriptors",


+ "Block bitmap for group %d"

+ " not in group (block %lu)!",
+ i, (unsigned long)
+ le32_to_cpu(gdp->bg_block_bitmap));
+ return 0;
+ }
+ if (le32_to_cpu(gdp->bg_inode_bitmap) < block ||
+ le32_to_cpu(gdp->bg_inode_bitmap) >=
+ block + EXT3_BLOCKS_PER_GROUP(sb))
+ {
+ ext3_error (sb, "ext3_check_descriptors",


+ "Inode bitmap for group %d"

+ " not in group (block %lu)!",
+ i, (unsigned long)
+ le32_to_cpu(gdp->bg_inode_bitmap));
+ return 0;
+ }
+ if (le32_to_cpu(gdp->bg_inode_table) < block ||
+ le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >=
+ block + EXT3_BLOCKS_PER_GROUP(sb))
+ {
+ ext3_error (sb, "ext3_check_descriptors",
+ "Inode table for group %d"
+ " not in group (block %lu)!",
+ i, (unsigned long)
+ le32_to_cpu(gdp->bg_inode_table));
+ return 0;
+ }
+ block += EXT3_BLOCKS_PER_GROUP(sb);
+ gdp++;
+ }


+ return 1;
+}
+

+
+/* ext3_orphan_cleanup() walks a singly-linked list of inodes (starting at
+ * the superblock) which were deleted from all directories, but held open by
+ * a process at the time of a crash. We walk the list and try to delete these
+ * inodes at recovery time (only with a read-write filesystem).
+ *
+ * In order to keep the orphan inode chain consistent during traversal (in
+ * case of crash during recovery), we link each inode into the superblock
+ * orphan list_head and handle it the same way as an inode deletion during
+ * normal operation (which journals the operations for us).
+ *
+ * We only do an iget() and an iput() on each inode, which is very safe if we
+ * accidentally point at an in-use or already deleted inode. The worst that
+ * can happen in this case is that we get a "bit already cleared" message from
+ * ext3_free_inode(). The only reason we would point at a wrong inode is if
+ * e2fsck was run on this filesystem, and it must have already done the orphan
+ * inode cleanup for us, so we can safely abort without any further action.
+ */
+static void ext3_orphan_cleanup (struct super_block * sb,
+ struct ext3_super_block * es)
+{
+ unsigned int s_flags = sb->s_flags;
+ int nr_orphans = 0, nr_truncates = 0;
+ if (!es->s_last_orphan) {
+ jbd_debug(4, "no orphan inodes to clean up\n");
+ return;
+ }
+
+ if (s_flags & MS_RDONLY) {
+ printk(KERN_INFO "EXT3-fs: %s: orphan cleanup on readonly fs\n",
+ bdevname(sb->s_dev));
+ sb->s_flags &= ~MS_RDONLY;
+ }
+
+ if (sb->u.ext3_sb.s_mount_state & EXT3_ERROR_FS) {
+ if (es->s_last_orphan)
+ jbd_debug(1, "Errors on filesystem, "
+ "clearing orphan list.\n");
+ es->s_last_orphan = 0;
+ jbd_debug(1, "Skipping orphan recovery on fs with errors.\n");
+ return;
+ }
+
+ while (es->s_last_orphan) {


+ struct inode *inode;
+

+ if (!(inode =
+ ext3_orphan_get(sb, le32_to_cpu(es->s_last_orphan)))) {
+ es->s_last_orphan = 0;
+ break;
+ }
+
+ list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan);
+ if (inode->i_nlink) {
+ printk(KERN_DEBUG __FUNCTION__
+ ": truncating inode %ld to %Ld bytes\n",
+ inode->i_ino, inode->i_size);
+ jbd_debug(2, "truncating inode %ld to %Ld bytes\n",
+ inode->i_ino, inode->i_size);
+ ext3_truncate(inode);
+ nr_truncates++;
+ } else {
+ printk(KERN_DEBUG __FUNCTION__
+ ": deleting unreferenced inode %ld\n",
+ inode->i_ino);
+ jbd_debug(2, "deleting unreferenced inode %ld\n",
+ inode->i_ino);
+ nr_orphans++;
+ }
+ iput(inode); /* The delete magic happens here! */
+ }
+
+#define PLURAL(x) (x), ((x)==1) ? "" : "s"
+
+ if (nr_orphans)
+ printk(KERN_INFO "EXT3-fs: %s: %d orphan inode%s deleted\n",
+ bdevname(sb->s_dev), PLURAL(nr_orphans));
+ if (nr_truncates)
+ printk(KERN_INFO "EXT3-fs: %s: %d truncate%s cleaned up\n",
+ bdevname(sb->s_dev), PLURAL(nr_truncates));
+ sb->s_flags = s_flags; /* Restore MS_RDONLY status */
+}
+
+#define log2(n) ffz(~(n))
+
+/*
+ * Maximal file size. There is a direct, and {,double-,triple-}indirect
+ * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
+ * We need to be 1 filesystem block less than the 2^32 sector limit.
+ */
+static loff_t ext3_max_size(int bits)
+{
+ loff_t res = EXT3_NDIR_BLOCKS;
+ res += 1LL << (bits-2);
+ res += 1LL << (2*(bits-2));
+ res += 1LL << (3*(bits-2));
+ res <<= bits;
+ if (res > (512LL << 32) - (1 << bits))
+ res = (512LL << 32) - (1 << bits);
+ return res;
+}
+
+struct super_block * ext3_read_super (struct super_block * sb, void * data,
+ int silent)
+{


+ struct buffer_head * bh;

+ struct ext3_super_block *es = 0;


+ struct ext3_sb_info *sbi = EXT3_SB(sb);

+ unsigned long sb_block = 1;
+ unsigned long logic_sb_block = 1;
+ unsigned long offset = 0;
+ unsigned long journal_inum = 0;
+ kdev_t dev = sb->s_dev;
+ int blocksize;
+ int hblock;
+ int db_count;
+ int i;
+ int needs_recovery;
+
+#ifdef CONFIG_JBD_DEBUG
+ ext3_ro_after = 0;
+#endif
+ /*
+ * See what the current blocksize for the device is, and
+ * use that as the blocksize. Otherwise (or if the blocksize
+ * is smaller than the default) use the default.
+ * This is important for devices that have a hardware
+ * sectorsize that is larger than the default.
+ */
+ blocksize = EXT3_MIN_BLOCK_SIZE;
+ hblock = get_hardsect_size(dev);
+ if (blocksize < hblock)
+ blocksize = hblock;
+
+ sbi->s_mount_opt = 0;
+ sbi->s_resuid = EXT3_DEF_RESUID;
+ sbi->s_resgid = EXT3_DEF_RESGID;
+ if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
+ sb->s_dev = 0;


+ goto out_fail;
+ }
+

+ set_blocksize (dev, blocksize);
+
+ /*
+ * The ext3 superblock will not be buffer aligned for other than 1kB
+ * block sizes. We need to calculate the offset from buffer start.
+ */
+ if (blocksize != EXT3_MIN_BLOCK_SIZE) {
+ logic_sb_block = (sb_block * EXT3_MIN_BLOCK_SIZE) / blocksize;
+ offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;
+ }
+
+ if (!(bh = bread (dev, logic_sb_block, blocksize))) {
+ printk (KERN_ERR "EXT3-fs: unable to read superblock\n");
+ goto out_fail;
+ }
+ /*
+ * Note: s_es must be initialized as soon as possible because
+ * some ext3 macro-instructions depend on its value
+ */
+ es = (struct ext3_super_block *) (((char *)bh->b_data) + offset);
+ sbi->s_es = es;
+ sb->s_magic = le16_to_cpu(es->s_magic);
+ if (sb->s_magic != EXT3_SUPER_MAGIC) {
+ if (!silent)
+ printk(KERN_ERR
+ "VFS: Can't find ext3 filesystem on dev %s.\n",
+ bdevname(dev));
+ goto failed_mount;
+ }
+ if (le32_to_cpu(es->s_rev_level) == EXT3_GOOD_OLD_REV &&
+ (EXT3_HAS_COMPAT_FEATURE(sb, ~0U) ||
+ EXT3_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
+ EXT3_HAS_INCOMPAT_FEATURE(sb, ~0U)))
+ printk(KERN_WARNING
+ "EXT3-fs warning: feature flags set on rev 0 fs, "
+ "running e2fsck is recommended\n");
+ /*
+ * Check feature flags regardless of the revision level, since we
+ * previously didn't change the revision level when setting the flags,
+ * so there is a chance incompat flags are set on a rev 0 filesystem.
+ */
+ if ((i = EXT3_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP))) {
+ printk(KERN_ERR "EXT3-fs: %s: couldn't mount because of "
+ "unsupported optional features (%x).\n",
+ bdevname(dev), i);
+ goto failed_mount;
+ }
+ if (!(sb->s_flags & MS_RDONLY) &&
+ (i = EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP))){
+ printk(KERN_ERR "EXT3-fs: %s: couldn't mount RDWR because of "
+ "unsupported optional features (%x).\n",
+ bdevname(dev), i);
+ goto failed_mount;
+ }
+ sb->s_blocksize_bits = le32_to_cpu(es->s_log_block_size) + 10;
+ sb->s_blocksize = 1 << sb->s_blocksize_bits;
+
+ if (sb->s_blocksize < EXT3_MIN_BLOCK_SIZE ||
+ sb->s_blocksize > EXT3_MAX_BLOCK_SIZE) {
+ printk(KERN_ERR
+ "EXT3-fs: Unsupported filesystem blocksize %d on %s.\n",
+ blocksize, bdevname(dev));
+ goto failed_mount;
+ }
+
+ sb->s_maxbytes = ext3_max_size(sb->s_blocksize_bits);
+
+ if (sb->s_blocksize != blocksize) {
+ blocksize = sb->s_blocksize;
+
+ /*
+ * Make sure the blocksize for the filesystem is larger
+ * than the hardware sectorsize for the machine.
+ */
+ if (sb->s_blocksize < hblock) {
+ printk(KERN_ERR "EXT3-fs: blocksize %d too small for "
+ "device blocksize %d.\n", blocksize, hblock);
+ goto failed_mount;
+ }
+
+ brelse (bh);
+ set_blocksize (dev, sb->s_blocksize);
+ logic_sb_block = (sb_block * EXT3_MIN_BLOCK_SIZE) / blocksize;
+ offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;
+ bh = bread (dev, logic_sb_block, blocksize);
+ if (!bh) {
+ printk(KERN_ERR
+ "EXT3-fs: Can't read superblock on 2nd try.\n");
+ return NULL;
+ }
+ es = (struct ext3_super_block *)(((char *)bh->b_data) + offset);
+ sbi->s_es = es;
+ if (es->s_magic != le16_to_cpu(EXT3_SUPER_MAGIC)) {
+ printk (KERN_ERR
+ "EXT3-fs: Magic mismatch, very weird !\n");
+ goto failed_mount;
+ }
+ }
+
+ if (le32_to_cpu(es->s_rev_level) == EXT3_GOOD_OLD_REV) {
+ sbi->s_inode_size = EXT3_GOOD_OLD_INODE_SIZE;
+ sbi->s_first_ino = EXT3_GOOD_OLD_FIRST_INO;
+ } else {
+ sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
+ sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
+ if (sbi->s_inode_size != EXT3_GOOD_OLD_INODE_SIZE) {
+ printk (KERN_ERR
+ "EXT3-fs: unsupported inode size: %d\n",
+ sbi->s_inode_size);
+ goto failed_mount;
+ }
+ }
+ sbi->s_frag_size = EXT3_MIN_FRAG_SIZE <<
+ le32_to_cpu(es->s_log_frag_size);
+ if (blocksize != sbi->s_frag_size) {
+ printk(KERN_ERR
+ "EXT3-fs: fragsize %lu != blocksize %u (unsupported)\n",
+ sbi->s_frag_size, blocksize);
+ goto failed_mount;
+ }
+ sbi->s_frags_per_block = 1;
+ sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
+ sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
+ sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
+ sbi->s_inodes_per_block = blocksize / EXT3_INODE_SIZE(sb);
+ sbi->s_itb_per_group = sbi->s_inodes_per_group /sbi->s_inodes_per_block;
+ sbi->s_desc_per_block = blocksize / sizeof(struct ext3_group_desc);
+ sbi->s_sbh = bh;
+ if (sbi->s_resuid == EXT3_DEF_RESUID)
+ sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
+ if (sbi->s_resgid == EXT3_DEF_RESGID)
+ sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
+ sbi->s_mount_state = le16_to_cpu(es->s_state);
+ sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb));
+ sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb));
+
+ if (sbi->s_blocks_per_group > blocksize * 8) {
+ printk (KERN_ERR
+ "EXT3-fs: #blocks per group too big: %lu\n",
+ sbi->s_blocks_per_group);
+ goto failed_mount;
+ }
+ if (sbi->s_frags_per_group > blocksize * 8) {
+ printk (KERN_ERR
+ "EXT3-fs: #fragments per group too big: %lu\n",
+ sbi->s_frags_per_group);
+ goto failed_mount;
+ }
+ if (sbi->s_inodes_per_group > blocksize * 8) {
+ printk (KERN_ERR
+ "EXT3-fs: #inodes per group too big: %lu\n",
+ sbi->s_inodes_per_group);
+ goto failed_mount;
+ }
+
+ sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
+ le32_to_cpu(es->s_first_data_block) +
+ EXT3_BLOCKS_PER_GROUP(sb) - 1) /
+ EXT3_BLOCKS_PER_GROUP(sb);
+ db_count = (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) /
+ EXT3_DESC_PER_BLOCK(sb);
+ sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
+ GFP_KERNEL);
+ if (sbi->s_group_desc == NULL) {
+ printk (KERN_ERR "EXT3-fs: not enough memory\n");
+ goto failed_mount;
+ }
+ for (i = 0; i < db_count; i++) {
+ sbi->s_group_desc[i] = bread(dev, logic_sb_block + i + 1,
+ blocksize);
+ if (!sbi->s_group_desc[i]) {
+ printk (KERN_ERR "EXT3-fs: "
+ "can't read group descriptor %d\n", i);
+ db_count = i;
+ goto failed_mount2;
+ }
+ }
+ if (!ext3_check_descriptors (sb)) {
+ printk (KERN_ERR "EXT3-fs: group descriptors corrupted !\n");
+ goto failed_mount2;
+ }
+ for (i = 0; i < EXT3_MAX_GROUP_LOADED; i++) {
+ sbi->s_inode_bitmap_number[i] = 0;
+ sbi->s_inode_bitmap[i] = NULL;
+ sbi->s_block_bitmap_number[i] = 0;
+ sbi->s_block_bitmap[i] = NULL;
+ }
+ sbi->s_loaded_inode_bitmaps = 0;
+ sbi->s_loaded_block_bitmaps = 0;
+ sbi->s_gdb_count = db_count;
+ /*
+ * set up enough so that it can read an inode
+ */
+ sb->s_op = &ext3_sops;
+ INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
+
+ sb->s_root = 0;
+
+ needs_recovery = (es->s_last_orphan != 0 ||
+ EXT3_HAS_INCOMPAT_FEATURE(sb,
+ EXT3_FEATURE_INCOMPAT_RECOVER));
+
+ /*
+ * The first inode we look at is the journal inode. Don't try
+ * root first: it may be modified in the journal!
+ */
+ if (!test_opt(sb, NOLOAD) &&
+ EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
+ if (ext3_load_journal(sb, es))
+ goto failed_mount2;
+ } else if (journal_inum) {
+ if (ext3_create_journal(sb, es, journal_inum))
+ goto failed_mount2;
+ } else {
+ if (!silent)
+ printk (KERN_ERR
+ "ext3: No journal on filesystem on %s\n",
+ bdevname(dev));
+ goto failed_mount2;
+ }
+
+ /* We have now updated the journal if required, so we can
+ * validate the data journaling mode. */
+ switch (test_opt(sb, DATA_FLAGS)) {
+ case 0:
+ /* No mode set, assume a default based on the journal
+ capabilities: ORDERED_DATA if the journal can
+ cope, else JOURNAL_DATA */
+ if (journal_check_available_features
+ (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE))
+ set_opt(sbi->s_mount_opt, ORDERED_DATA);
+ else
+ set_opt(sbi->s_mount_opt, JOURNAL_DATA);
+ break;
+
+ case EXT3_MOUNT_ORDERED_DATA:
+ case EXT3_MOUNT_WRITEBACK_DATA:
+ if (!journal_check_available_features
+ (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) {
+ printk(KERN_ERR "EXT3-fs: Journal does not support "
+ "requested data journaling mode\n");
+ goto failed_mount3;
+ }


+ default:
+ break;
+ }
+

+ /*
+ * The journal_load will have done any necessary log recovery,
+ * so we can safely mount the rest of the filesystem now.
+ */
+
+ sb->s_root = d_alloc_root(iget(sb, EXT3_ROOT_INO));
+ if (!sb->s_root || !S_ISDIR(sb->s_root->d_inode->i_mode) ||
+ !sb->s_root->d_inode->i_blocks || !sb->s_root->d_inode->i_size) {
+ if (sb->s_root) {
+ dput(sb->s_root);
+ sb->s_root = NULL;
+ printk(KERN_ERR
+ "EXT3-fs: corrupt root inode, run e2fsck\n");
+ } else
+ printk(KERN_ERR "EXT3-fs: get root inode failed\n");
+ goto failed_mount3;
+ }
+
+ ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);
+ /*
+ * akpm: core read_super() calls in here with the superblock locked.
+ * That deadlocks, because orphan cleanup needs to lock the superblock
+ * in numerous places. Here we just pop the lock - it's relatively
+ * harmless, because we are now ready to accept write_super() requests,
+ * and aviro says that's the only reason for hanging onto the
+ * superblock lock.
+ */
+ EXT3_SB(sb)->s_mount_state |= EXT3_ORPHAN_FS;
+ unlock_super(sb); /* akpm: sigh */
+ ext3_orphan_cleanup(sb, es);
+ lock_super(sb);
+ EXT3_SB(sb)->s_mount_state &= ~EXT3_ORPHAN_FS;
+ if (needs_recovery)
+ printk (KERN_INFO "EXT3-fs: recovery complete.\n");
+ ext3_mark_recovery_complete(sb, es);
+ printk (KERN_INFO "EXT3-fs: mounted filesystem with %s data mode.\n",
+ test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA ? "journal":
+ test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
+ "writeback");
+
+ return sb;
+
+failed_mount3:
+ journal_destroy(sbi->s_journal);
+failed_mount2:
+ for (i = 0; i < db_count; i++)


+ brelse(sbi->s_group_desc[i]);
+ kfree(sbi->s_group_desc);

+failed_mount:
+ ext3_blkdev_remove(sbi);
+ brelse(bh);
+out_fail:


+ return NULL;
+}
+

+static journal_t *ext3_get_journal(struct super_block *sb, int journal_inum)
+{
+ struct inode *journal_inode;
+ journal_t *journal;
+
+ /* First, test for the existence of a valid inode on disk. Bad
+ * things happen if we iget() an unused inode, as the subsequent
+ * iput() will try to delete it. */
+
+ journal_inode = iget(sb, journal_inum);
+ if (!journal_inode) {
+ printk(KERN_ERR "EXT3-fs: no journal found.\n");
+ return NULL;
+ }
+ if (!journal_inode->i_nlink) {
+ make_bad_inode(journal_inode);
+ iput(journal_inode);
+ printk(KERN_ERR "EXT3-fs: journal inode is deleted.\n");


+ return NULL;
+ }
+

+ jbd_debug(2, "Journal inode found at %p: %Ld bytes\n",
+ journal_inode, journal_inode->i_size);
+ if (is_bad_inode(journal_inode) || !S_ISREG(journal_inode->i_mode)) {
+ printk(KERN_ERR "EXT3-fs: invalid journal inode.\n");
+ iput(journal_inode);


+ return NULL;
+ }
+

+ journal = journal_init_inode(journal_inode);
+ if (!journal)
+ iput(journal_inode);
+ return journal;
+}
+
+static journal_t *ext3_get_dev_journal(struct super_block *sb,
+ int dev)
+{


+ struct buffer_head * bh;

+ journal_t *journal;
+ int start;
+ int len;
+ int hblock, blocksize;
+ unsigned long sb_block;
+ unsigned long offset;
+ kdev_t journal_dev = to_kdev_t(dev);


+ struct ext3_super_block * es;

+ struct block_device *bdev;
+

+ bdev = ext3_blkdev_get(journal_dev);


+ if (bdev == NULL)

+ return NULL;
+
+ blocksize = sb->s_blocksize;
+ hblock = get_hardsect_size(journal_dev);
+ if (blocksize < hblock) {
+ printk(KERN_ERR
+ "EXT3-fs: blocksize too small for journal device.\n");
+ goto out_bdev;
+ }
+
+ sb_block = EXT3_MIN_BLOCK_SIZE / blocksize;
+ offset = EXT3_MIN_BLOCK_SIZE % blocksize;
+ set_blocksize(dev, blocksize);
+ if (!(bh = bread(dev, sb_block, blocksize))) {
+ printk(KERN_ERR "EXT3-fs: couldn't read superblock of "
+ "external journal\n");
+ goto out_bdev;
+ }
+
+ es = (struct ext3_super_block *) (((char *)bh->b_data) + offset);
+ if ((le16_to_cpu(es->s_magic) != EXT3_SUPER_MAGIC) ||
+ !(le32_to_cpu(es->s_feature_incompat) &
+ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+ printk(KERN_ERR "EXT3-fs: external journal has "
+ "bad superblock\n");
+ brelse(bh);
+ goto out_bdev;
+ }
+
+ if (memcmp(EXT3_SB(sb)->s_es->s_journal_uuid, es->s_uuid, 16)) {
+ printk(KERN_ERR "EXT3-fs: journal UUID does not match\n");
+ brelse(bh);
+ goto out_bdev;
+ }
+
+ len = le32_to_cpu(es->s_blocks_count);
+ start = sb_block + 1;
+ brelse(bh); /* we're done with the superblock */
+
+ journal = journal_init_dev(journal_dev, sb->s_dev,
+ start, len, blocksize);
+ if (!journal) {
+ printk(KERN_ERR "EXT3-fs: failed to create device journal\n");
+ goto out_bdev;
+ }
+ ll_rw_block(READ, 1, &journal->j_sb_buffer);
+ wait_on_buffer(journal->j_sb_buffer);
+ if (!buffer_uptodate(journal->j_sb_buffer)) {
+ printk(KERN_ERR "EXT3-fs: I/O error on journal device\n");
+ goto out_journal;
+ }
+ if (ntohl(journal->j_superblock->s_nr_users) != 1) {
+ printk(KERN_ERR "EXT3-fs: External journal has more than one "
+ "user (unsupported) - %d\n",
+ ntohl(journal->j_superblock->s_nr_users));
+ goto out_journal;
+ }
+ EXT3_SB(sb)->journal_bdev = bdev;
+ return journal;
+out_journal:
+ journal_destroy(journal);
+out_bdev:
+ ext3_blkdev_put(bdev);


+ return NULL;
+}
+

+static int ext3_load_journal(struct super_block * sb,


+ struct ext3_super_block * es)

+{
+ journal_t *journal;
+ int journal_inum = le32_to_cpu(es->s_journal_inum);
+ int journal_dev = le32_to_cpu(es->s_journal_dev);
+ int err;
+ int really_read_only;
+
+ really_read_only = is_read_only(sb->s_dev);
+
+ /*
+ * Are we loading a blank journal or performing recovery after a
+ * crash? For recovery, we need to check in advance whether we
+ * can get read-write access to the device.
+ */
+
+ if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER)) {


+ if (sb->s_flags & MS_RDONLY) {

+ printk(KERN_INFO "EXT3-fs: INFO: recovery "
+ "required on readonly filesystem.\n");
+ if (really_read_only) {
+ printk(KERN_ERR "EXT3-fs: write access "
+ "unavailable, cannot proceed.\n");
+ return -EROFS;
+ }
+ printk (KERN_INFO "EXT3-fs: write access will "
+ "be enabled during recovery.\n");
+ }
+ }
+
+ if (journal_inum && journal_dev) {
+ printk(KERN_ERR "EXT3-fs: filesystem has both journal "
+ "and inode journals!\n");
+ return -EINVAL;
+ }
+
+ if (journal_inum) {
+ if (!(journal = ext3_get_journal(sb, journal_inum)))
+ return -EINVAL;
+ } else {
+ if (!(journal = ext3_get_dev_journal(sb, journal_dev)))
+ return -EINVAL;
+ }
+
+
+ if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) {
+ err = journal_update_format(journal);
+ if (err) {
+ printk(KERN_ERR "EXT3-fs: error updating journal.\n");
+ journal_destroy(journal);


+ return err;
+ }
+ }
+

+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER))
+ journal_wipe(journal, !really_read_only);
+
+ err = journal_load(journal);
+ if (err) {
+ printk(KERN_ERR "EXT3-fs: error loading journal.\n");
+ journal_destroy(journal);


+ return err;
+ }
+

+ EXT3_SB(sb)->s_journal = journal;
+ ext3_clear_journal_err(sb, es);


+ return 0;
+}
+

+static int ext3_create_journal(struct super_block * sb,


+ struct ext3_super_block * es,

+ int journal_inum)


+{
+ journal_t *journal;
+

+ if (sb->s_flags & MS_RDONLY) {

+ printk(KERN_ERR "EXT3-fs: readonly filesystem when trying to "
+ "create journal.\n");


+ return -EROFS;
+ }
+

+ if (!(journal = ext3_get_journal(sb, journal_inum)))
+ return -EINVAL;
+
+ printk(KERN_INFO "EXT3-fs: creating new journal on inode %d\n",
+ journal_inum);
+
+ if (journal_create(journal)) {
+ printk(KERN_ERR "EXT3-fs: error creating journal.\n");
+ journal_destroy(journal);


+ return -EIO;
+ }
+

+ EXT3_SB(sb)->s_journal = journal;
+
+ ext3_update_dynamic_rev(sb);
+ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
+ EXT3_SET_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL);
+
+ es->s_journal_inum = cpu_to_le32(journal_inum);


+ sb->s_dirt = 1;
+

+ /* Make sure we flush the recovery flag to disk. */


+ ext3_commit_super(sb, es, 1);
+

+ return 0;
+}
+

+static void ext3_commit_super (struct super_block * sb,
+ struct ext3_super_block * es,
+ int sync)

+{
+ es->s_wtime = cpu_to_le32(CURRENT_TIME);
+ BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "marking dirty");
+ mark_buffer_dirty(sb->u.ext3_sb.s_sbh);
+ if (sync) {
+ ll_rw_block(WRITE, 1, &sb->u.ext3_sb.s_sbh);
+ wait_on_buffer(sb->u.ext3_sb.s_sbh);
+ }
+}
+
+
+/*
+ * Have we just finished recovery? If so, and if we are mounting (or
+ * remounting) the filesystem readonly, then we will end up with a
+ * consistent fs on disk. Record that fact.
+ */


+static void ext3_mark_recovery_complete(struct super_block * sb,
+ struct ext3_super_block * es)

+{
+ journal_flush(EXT3_SB(sb)->s_journal);
+ if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) &&
+ sb->s_flags & MS_RDONLY) {
+ EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
+ sb->s_dirt = 0;


+ ext3_commit_super(sb, es, 1);
+ }
+}
+

+/*
+ * If we are mounting (or read-write remounting) a filesystem whose journal
+ * has recorded an error from a previous lifetime, move that error to the
+ * main filesystem now.
+ */


+static void ext3_clear_journal_err(struct super_block * sb,
+ struct ext3_super_block * es)

+{
+ journal_t *journal;
+ int j_errno;
+ const char *errstr;
+
+ journal = EXT3_SB(sb)->s_journal;
+
+ /*
+ * Now check for any error status which may have been recorded in the
+ * journal by a prior ext3_error() or ext3_abort()
+ */
+
+ j_errno = journal_errno(journal);
+ if (j_errno) {


+ char nbuf[16];
+

+ errstr = ext3_decode_error(sb, j_errno, nbuf);
+ ext3_warning(sb, __FUNCTION__, "Filesystem error recorded "
+ "from previous mount: %s", errstr);
+ ext3_warning(sb, __FUNCTION__, "Marking fs in need of "
+ "filesystem check.");
+

+ sb->u.ext3_sb.s_mount_state |= EXT3_ERROR_FS;

+ es->s_state |= cpu_to_le16(EXT3_ERROR_FS);
+ ext3_commit_super (sb, es, 1);
+
+ journal_clear_err(journal);
+ }
+}
+
+/*
+ * Force the running and committing transactions to commit,
+ * and wait on the commit.
+ */
+int ext3_force_commit(struct super_block *sb)
+{
+ journal_t *journal;
+ int ret;


+
+ if (sb->s_flags & MS_RDONLY)

+ return 0;
+
+ journal = EXT3_SB(sb)->s_journal;
+ sb->s_dirt = 0;
+ lock_kernel(); /* important: lock down j_running_transaction */
+ ret = ext3_journal_force_commit(journal);
+ unlock_kernel();


+ return ret;
+}
+

+/*
+ * Ext3 always journals updates to the superblock itself, so we don't
+ * have to propagate any other updates to the superblock on disk at this
+ * point. Just start an async writeback to get the buffers on their way
+ * to the disk.
+ *
+ * This implicitly triggers the writebehind on sync().
+ */
+
+static int do_sync_supers = 0;
+MODULE_PARM(do_sync_supers, "i");
+MODULE_PARM_DESC(do_sync_supers, "Write superblocks synchronously");
+
+void ext3_write_super (struct super_block * sb)
+{
+ tid_t target;
+
+ if (down_trylock(&sb->s_lock) == 0)
+ BUG(); /* aviro detector */
+ sb->s_dirt = 0;
+ target = log_start_commit(EXT3_SB(sb)->s_journal, NULL);
+
+ if (do_sync_supers) {
+ unlock_super(sb);
+ log_wait_commit(EXT3_SB(sb)->s_journal, target);
+ lock_super(sb);
+ }
+}
+
+/*
+ * LVM calls this function before a (read-only) snapshot is created. This
+ * gives us a chance to flush the journal completely and mark the fs clean.
+ */
+void ext3_write_super_lockfs(struct super_block *sb)
+{
+ sb->s_dirt = 0;
+
+ lock_kernel(); /* 2.4.5 forgot to do this for us */


+ if (!(sb->s_flags & MS_RDONLY)) {

+ journal_t *journal = EXT3_SB(sb)->s_journal;
+
+ /* Now we set up the journal barrier. */


+ journal_lock_updates(journal);
+ journal_flush(journal);
+

+ /* Journal blocked and flushed, clear needs_recovery flag. */
+ EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
+ ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1);
+ }
+ unlock_kernel();
+}
+
+/*
+ * Called by LVM after the snapshot is done. We need to reset the RECOVER
+ * flag here, even though the filesystem is not technically dirty yet.
+ */
+void ext3_unlockfs(struct super_block *sb)
+{


+ if (!(sb->s_flags & MS_RDONLY)) {

+ lock_kernel();
+ lock_super(sb);
+ /* Reser the needs_recovery flag before the fs is unlocked. */
+ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
+ ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1);
+ unlock_super(sb);
+ journal_unlock_updates(EXT3_SB(sb)->s_journal);
+ unlock_kernel();
+ }
+}
+
+int ext3_remount (struct super_block * sb, int * flags, char * data)


+{
+ struct ext3_super_block * es;

+ struct ext3_sb_info *sbi = EXT3_SB(sb);

+ unsigned long tmp;
+
+ clear_ro_after(sb);
+
+ /*
+ * Allow the "check" option to be passed as a remount option.
+ */
+ if (!parse_options(data, &tmp, sbi, &tmp, 1))
+ return -EINVAL;
+
+ if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
+ ext3_abort(sb, __FUNCTION__, "Abort forced by user");
+
+ es = sbi->s_es;
+
+ if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
+ if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
+ return -EROFS;
+
+ if (*flags & MS_RDONLY) {
+ /*
+ * First of all, the unconditional stuff we have to do
+ * to disable replay of the journal when we next remount
+ */


+ sb->s_flags |= MS_RDONLY;
+

+ /*
+ * OK, test if we are remounting a valid rw partition
+ * readonly, and if so set the rdonly flag and then
+ * mark the partition as valid again.
+ */
+ if (!(es->s_state & cpu_to_le16(EXT3_VALID_FS)) &&
+ (sbi->s_mount_state & EXT3_VALID_FS))
+ es->s_state = cpu_to_le16(sbi->s_mount_state);
+
+ ext3_mark_recovery_complete(sb, es);
+ } else {
+ int ret;
+ if ((ret = EXT3_HAS_RO_COMPAT_FEATURE(sb,
+ ~EXT3_FEATURE_RO_COMPAT_SUPP))) {
+ printk(KERN_WARNING "EXT3-fs: %s: couldn't "
+ "remount RDWR because of unsupported "
+ "optional features (%x).\n",
+ bdevname(sb->s_dev), ret);
+ return -EROFS;
+ }
+ /*
+ * Mounting a RDONLY partition read-write, so reread
+ * and store the current valid flag. (It may have
+ * been changed by e2fsck since we originally mounted
+ * the partition.)
+ */
+ ext3_clear_journal_err(sb, es);
+ sbi->s_mount_state = le16_to_cpu(es->s_state);
+ if (!ext3_setup_super (sb, es, 0))
+ sb->s_flags &= ~MS_RDONLY;
+ }
+ }
+ setup_ro_after(sb);


+ return 0;
+}
+

+int ext3_statfs (struct super_block * sb, struct statfs * buf)


+{
+ struct ext3_super_block *es = EXT3_SB(sb)->s_es;

+ unsigned long overhead;
+ int i;
+
+ if (test_opt (sb, MINIX_DF))
+ overhead = 0;
+ else {
+ /*
+ * Compute the overhead (FS structures)
+ */
+
+ /*
+ * All of the blocks before first_data_block are
+ * overhead
+ */
+ overhead = le32_to_cpu(es->s_first_data_block);
+
+ /*
+ * Add the overhead attributed to the superblock and
+ * block group descriptors. If the sparse superblocks
+ * feature is turned on, then not all groups have this.
+ */
+ for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++)
+ overhead += ext3_bg_has_super(sb, i) +
+ ext3_bg_num_gdb(sb, i);
+
+ /*
+ * Every block group has an inode bitmap, a block
+ * bitmap, and an inode table.
+ */
+ overhead += (EXT3_SB(sb)->s_groups_count *
+ (2 + EXT3_SB(sb)->s_itb_per_group));
+ }
+
+ buf->f_type = EXT3_SUPER_MAGIC;
+ buf->f_bsize = sb->s_blocksize;
+ buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
+ buf->f_bfree = ext3_count_free_blocks (sb);
+ buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
+ if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
+ buf->f_bavail = 0;
+ buf->f_files = le32_to_cpu(es->s_inodes_count);
+ buf->f_ffree = ext3_count_free_inodes (sb);
+ buf->f_namelen = EXT3_NAME_LEN;


+ return 0;
+}
+

+static DECLARE_FSTYPE_DEV(ext3_fs_type, "ext3", ext3_read_super);
+
+static int __init init_ext3_fs(void)
+{
+ return register_filesystem(&ext3_fs_type);
+}
+
+static void __exit exit_ext3_fs(void)
+{
+ unregister_filesystem(&ext3_fs_type);
+}
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_LICENSE("GPL");
+module_init(init_ext3_fs)
+module_exit(exit_ext3_fs)
diff -u --recursive --new-file v2.4.14/linux/fs/ext3/symlink.c linux/fs/ext3/symlink.c
--- v2.4.14/linux/fs/ext3/symlink.c Wed Dec 31 16:00:00 1969
+++ linux/fs/ext3/symlink.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,39 @@
+/*
+ * linux/fs/ext3/symlink.c
+ *
+ * Only fast symlinks left here - the rest is done by generic code. AV, 1999


+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (ca...@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * from
+ *

+ * linux/fs/minix/symlink.c


+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *

+ * ext3 symlink handling code


+ */
+
+#include <linux/fs.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+

+static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+ char *s = (char *)dentry->d_inode->u.ext3_i.i_data;
+ return vfs_readlink(dentry, buffer, buflen, s);
+}
+
+static int ext3_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ char *s = (char *)dentry->d_inode->u.ext3_i.i_data;
+ return vfs_follow_link(nd, s);
+}
+
+struct inode_operations ext3_fast_symlink_inode_operations = {
+ readlink: ext3_readlink, /* BKL not held. Don't need */
+ follow_link: ext3_follow_link, /* BKL not held. Don't need */
+};
diff -u --recursive --new-file v2.4.14/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v2.4.14/linux/fs/fat/inode.c Tue Oct 23 22:48:53 2001
+++ linux/fs/fat/inode.c Tue Nov 20 14:15:26 2001
@@ -123,6 +123,8 @@
X if (i->i_location != i_pos)
X continue;
X inode = igrab(i->i_fat_inode);
+ if (inode)
+ break;
X }
X spin_unlock(&fat_inode_lock);
X return inode;
diff -u --recursive --new-file v2.4.14/linux/fs/freevxfs/vxfs_subr.c linux/fs/freevxfs/vxfs_subr.c
--- v2.4.14/linux/fs/freevxfs/vxfs_subr.c Mon May 21 12:31:06 2001
+++ linux/fs/freevxfs/vxfs_subr.c Fri Nov 9 14:25:35 2001
@@ -45,7 +45,8 @@
X
X struct address_space_operations vxfs_aops = {
X .readpage = vxfs_readpage,
- .bmap = vxfs_bmap
+ .bmap = vxfs_bmap,
+ .sync_page = block_sync_page,
X };
X
X
diff -u --recursive --new-file v2.4.14/linux/fs/inode.c linux/fs/inode.c
--- v2.4.14/linux/fs/inode.c Tue Oct 9 17:06:53 2001
+++ linux/fs/inode.c Thu Nov 22 10:38:31 2001
@@ -66,7 +66,7 @@
X * NOTE! You also have to own the lock if you change
X * the i_state of an inode while it is in use..
X */
-spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
X
X /*
X * Statistics gathering..
@@ -404,6 +404,8 @@
X spin_lock(&sb_lock);
X sb = sb_entry(super_blocks.next);
X for (; nr_inodes && sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) {
+ if (list_empty(&sb->s_dirty))
+ continue;
X spin_unlock(&sb_lock);
X nr_inodes = try_to_sync_unused_list(&sb->s_dirty, nr_inodes);
X spin_lock(&sb_lock);
@@ -569,8 +571,7 @@
X continue;
X invalidate_inode_buffers(inode);
X if (!atomic_read(&inode->i_count)) {
- list_del(&inode->i_hash);
- INIT_LIST_HEAD(&inode->i_hash);
+ list_del_init(&inode->i_hash);
X list_del(&inode->i_list);
X list_add(&inode->i_list, dispose);
X inode->i_state |= I_FREEING;
@@ -678,11 +679,11 @@
X entry = entry->prev;
X inode = INODE(tmp);
X if (inode->i_state & (I_FREEING|I_CLEAR|I_LOCK))
- BUG();
+ continue;
X if (!CAN_UNUSE(inode))
X continue;
X if (atomic_read(&inode->i_count))
- BUG();
+ continue;
X list_del(tmp);
X list_del(&inode->i_hash);
X INIT_LIST_HEAD(&inode->i_hash);
@@ -957,8 +958,6 @@
X */
X inode = NULL;
X spin_unlock(&inode_lock);
- if (inode)
- wait_on_inode(inode);
X return inode;
X }
X
@@ -1029,13 +1028,14 @@
X void iput(struct inode *inode)
X {
X if (inode) {


+ struct super_block *sb = inode->i_sb;

X struct super_operations *op = NULL;
X
X if (inode->i_state == I_CLEAR)
X BUG();
X
- if (inode->i_sb && inode->i_sb->s_op)
- op = inode->i_sb->s_op;
+ if (sb && sb->s_op)
+ op = sb->s_op;
X if (op && op->put_inode)
X op->put_inode(inode);
X
@@ -1065,7 +1065,7 @@
X if (inode->i_state != I_CLEAR)
X BUG();
X } else {
- if (!list_empty(&inode->i_hash)) {
+ if (!list_empty(&inode->i_hash) && sb && sb->s_root) {
X if (!(inode->i_state & (I_DIRTY|I_LOCK))) {
X list_del(&inode->i_list);
X list_add(&inode->i_list, &inode_unused);
@@ -1074,9 +1074,8 @@
X spin_unlock(&inode_lock);
X return;
X } else {
- /* magic nfs path */
- list_del(&inode->i_list);
- INIT_LIST_HEAD(&inode->i_list);
+ list_del_init(&inode->i_list);
+ list_del_init(&inode->i_hash);
X inode->i_state|=I_FREEING;
X inodes_stat.nr_inodes--;
X spin_unlock(&inode_lock);
@@ -1210,9 +1209,9 @@
X
X if (!sb->dq_op)
X return; /* nothing to do */
-
X /* We have to be protected against other CPUs */
- spin_lock(&inode_lock);
+ lock_kernel(); /* This lock is for quota code */
+ spin_lock(&inode_lock); /* This lock is for inodes code */
X
X list_for_each(act_head, &inode_in_use) {
X inode = list_entry(act_head, struct inode, i_list);
@@ -1235,6 +1234,7 @@
X remove_inode_dquot_ref(inode, type, &tofree_head);
X }
X spin_unlock(&inode_lock);
+ unlock_kernel();
X
X put_dquot_list(&tofree_head);
X }
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/Makefile linux/fs/intermezzo/Makefile
--- v2.4.14/linux/fs/intermezzo/Makefile Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/Makefile Sun Nov 11 10:20:21 2001
@@ -0,0 +1,12 @@
+#
+# Makefile 1.00 Peter Braam <br...@clusterfs.com>
+#
+
+O_TARGET := intermezzo.o
+
+obj-y := journal_reiserfs.o cache.o journal.o presto.o vfs.o psdev.o upcall.o methods.o sysctl.o dcache.o dir.o super.o journal_ext2.o journal_ext3.o journal_xfs.o inode.o file.o journal_obdfs.o
+
+


+obj-m := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make

diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/cache.c linux/fs/intermezzo/cache.c
--- v2.4.14/linux/fs/intermezzo/cache.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/cache.c Sun Nov 11 10:20:21 2001


@@ -0,0 +1,256 @@
+/*
+ *

+ *
+ * Copyright (C) 2000 Stelias Computing, Inc.
+ * Copyright (C) 2000 Red Hat, Inc.
+ *


+ *
+ */
+

+#define __NO_VERSION__
+#include <linux/module.h>
+#include <stdarg.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/sched.h>


+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/locks.h>

+#include <linux/blkdev.h>
+#include <linux/init.h>
+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+
+/*
+ This file contains the routines associated with managing a
+ cache of files for InterMezzo. These caches have two reqs:
+ - need to be found fast so they are hashed by the device,
+ with an attempt to have collision chains of length 1.
+ The methods for the cache are set up in methods.
+*/
+
+/* the intent of this hash is to have collision chains of length 1 */
+#define CACHES_BITS 8
+#define CACHES_SIZE (1 << CACHES_BITS)
+#define CACHES_MASK CACHES_SIZE - 1
+static struct list_head presto_caches[CACHES_SIZE];
+
+static inline int presto_cache_hash(kdev_t dev)
+{
+ return (CACHES_MASK) & ((0x000F & (dev)) + ((0x0F00 & (dev)) >>8));
+}
+
+inline void presto_cache_add(struct presto_cache *cache, kdev_t dev)
+{
+ list_add(&cache->cache_chain,
+ &presto_caches[presto_cache_hash(dev)]);
+ cache->cache_dev = dev;
+}
+
+inline void presto_init_cache_hash(void)
+{
+ int i;
+ for ( i = 0; i < CACHES_SIZE; i++ ) {
+ INIT_LIST_HEAD(&presto_caches[i]);
+ }
+}
+
+/* map a device to a cache */
+struct presto_cache *presto_find_cache(kdev_t dev)
+{
+ struct presto_cache *cache;
+ struct list_head *lh, *tmp;
+
+ lh = tmp = &(presto_caches[presto_cache_hash(dev)]);
+ while ( (tmp = lh->next) != lh ) {
+ cache = list_entry(tmp, struct presto_cache, cache_chain);
+ if ( cache->cache_dev == dev ) {
+ return cache;
+ }
+ }


+ return NULL;
+}
+
+

+/* map an inode to a cache */
+struct presto_cache *presto_get_cache(struct inode *inode)
+{
+ struct presto_cache *cache;
+
+ /* find the correct presto_cache here, based on the device */
+ cache = presto_find_cache(inode->i_dev);
+ if ( !cache ) {
+ printk("WARNING: no presto cache for dev %x, ino %ld\n",
+ inode->i_dev, inode->i_ino);
+ EXIT;
+ return NULL;
+ }
+ return cache;
+}
+
+
+/* list cache mount points for ioctl's or /proc/fs/intermezzo/mounts */
+int presto_sprint_mounts(char *buf, int buflen, int minor)
+{
+ int len = 0;
+ int i;
+ struct list_head *head, *tmp;
+ struct presto_cache *cache;
+
+ buf[0] = '\0';
+ for (i=0 ; i<CACHES_SIZE ; i++) {
+ head = tmp = &presto_caches[i];
+ while ( (tmp = tmp->next) != head ) {
+ cache = list_entry(tmp, struct presto_cache,
+ cache_chain);
+ if ( !cache->cache_root_fileset || !cache->cache_mtpt)
+ continue;
+ if ((minor != -1) &&
+ (cache->cache_psdev->uc_minor != minor))
+ continue;
+ if ( strlen(cache->cache_root_fileset) +
+ strlen(cache->cache_mtpt) +
+ strlen(cache->cache_psdev->uc_devname) +
+ 4 > buflen - len)
+ break;
+ len += sprintf(buf + len, "%s %s %s\n",
+ cache->cache_root_fileset,
+ cache->cache_mtpt,
+ cache->cache_psdev->uc_devname);
+ }
+ }
+
+ buf[buflen-1] = '\0';
+ CDEBUG(D_SUPER, "%s\n", buf);
+ return len;
+}
+
+#ifdef CONFIG_KREINT
+/* get mount point by volname
+ Arthur Ma, 2000.12.25
+ */
+int presto_get_mount (char *buf, int buflen, char *volname)
+{
+ int i;
+ struct list_head *head, *tmp;
+ struct presto_cache *cache = NULL;
+ char *path = "";
+
+ buf[0] = '\0';
+ for (i=0 ; i<CACHES_SIZE ; i++) {
+ head = tmp = &presto_caches[i];
+ while ( (tmp = tmp->next) != head ) {
+ cache = list_entry(tmp, struct presto_cache,
+ cache_chain);
+ if ( !cache->cache_root_fileset || !cache->cache_mtpt)
+ continue;
+ if ( strcmp(cache->cache_root_fileset, volname) == 0)
+ break;
+ }
+ }
+ if (cache != NULL)
+ path = cache->cache_mtpt;
+ strncpy (buf, path, buflen);
+ return strlen (buf);
+}
+#endif
+
+/* another debugging routine: check fs is InterMezzo fs */
+int presto_ispresto(struct inode *inode)
+{
+ struct presto_cache *cache;
+
+ if ( !inode )
+ return 0;
+ cache = presto_get_cache(inode);
+ if ( !cache )
+ return 0;
+ return (inode->i_dev == cache->cache_dev);
+}
+
+/* setup a cache structure when we need one */
+struct presto_cache *presto_init_cache(void)
+{
+ struct presto_cache *cache;
+
+ /* make a presto_cache structure for the hash */
+ PRESTO_ALLOC(cache, struct presto_cache *, sizeof(struct presto_cache));
+ if ( cache ) {
+ memset(cache, 0, sizeof(struct presto_cache));
+ INIT_LIST_HEAD(&cache->cache_chain);
+ INIT_LIST_HEAD(&cache->cache_fset_list);
+ }
+ cache->cache_lock = SPIN_LOCK_UNLOCKED;
+ cache->cache_reserved = 0;
+ return cache;
+}
+
+
+/* free a cache structure and all of the memory it is pointing to */
+inline void presto_free_cache(struct presto_cache *cache)
+{
+ if (!cache)
+ return;
+
+ list_del(&cache->cache_chain);
+ if (cache->cache_mtpt)
+ PRESTO_FREE(cache->cache_mtpt, strlen(cache->cache_mtpt) + 1);
+ if (cache->cache_type)
+ PRESTO_FREE(cache->cache_type, strlen(cache->cache_type) + 1);
+ if (cache->cache_root_fileset)
+ PRESTO_FREE(cache->cache_root_fileset, strlen(cache->cache_root_fileset) + 1);
+
+ PRESTO_FREE(cache, sizeof(struct presto_cache));
+}
+
+int presto_reserve_space(struct presto_cache *cache, loff_t req)
+{
+ struct filter_fs *filter;
+ loff_t avail;
+ struct super_block *sb = cache->cache_sb;
+ filter = cache->cache_filter;
+ if (!filter ) {
+ EXIT;
+ return 0;
+ }
+ if (!filter->o_trops ) {
+ EXIT;
+ return 0;
+ }
+ if (!filter->o_trops->tr_avail ) {
+ EXIT;
+ return 0;
+ }
+ avail = filter->o_trops->tr_avail(cache, sb);
+ CDEBUG(D_SUPER, "ESC::%ld +++> %ld \n", (long) cache->cache_reserved,
+ (long) (cache->cache_reserved + req));
+ CDEBUG(D_SUPER, "ESC::Avail::%ld \n", (long) avail);
+ spin_lock(&cache->cache_lock);
+ if (req + cache->cache_reserved > avail) {
+ spin_unlock(&cache->cache_lock);
+ EXIT;
+ return -ENOSPC;
+ }
+ cache->cache_reserved += req;
+ spin_unlock(&cache->cache_lock);


+
+ return 0;
+}
+

+void presto_release_space(struct presto_cache *cache, loff_t req)
+{
+ CDEBUG(D_SUPER, "ESC::%ld ---> %ld \n", (long) cache->cache_reserved,
+ (long) (cache->cache_reserved - req));
+ spin_lock(&cache->cache_lock);
+ cache->cache_reserved -= req;
+ spin_unlock(&cache->cache_lock);
+}
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/dcache.c linux/fs/intermezzo/dcache.c
--- v2.4.14/linux/fs/intermezzo/dcache.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/dcache.c Tue Nov 13 09:20:56 2001
@@ -0,0 +1,139 @@
+/*
+ * Directory operations for InterMezzo filesystem
+ * Original version: (C) 1996 P. Braam and M. Callahan
+ * Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University
+ *
+ * Stelias encourages users to contribute improvements to
+ * the InterMezzo project. Contact Peter Braam (co...@stelias.com).
+ */
+
+#define __NO_VERSION__
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/locks.h>
+#include <linux/slab.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/string.h>
+
+#include <linux/intermezzo_fs.h>
+
+static int presto_dentry_revalidate(struct dentry *de, int );
+static kmem_cache_t * presto_dentry_slab;
+
+/* called when a cache lookup succeeds */
+static int presto_dentry_revalidate(struct dentry *de, int flag)
+{
+ struct inode *inode = de->d_inode;
+ ENTRY;
+ if (!inode) {
+ EXIT;
+ return 1;
+ }
+ if (is_bad_inode(inode)) {
+ EXIT;


+ return 0;
+ }
+

+ if ( S_ISDIR(inode->i_mode) ) {
+ EXIT;
+ return (presto_chk(de, PRESTO_DATA) &&
+ (presto_chk(de, PRESTO_ATTR)));
+ } else {
+ EXIT;
+ return presto_chk(de, PRESTO_ATTR);
+ }
+}
+
+static void presto_d_release(struct dentry *dentry)
+{
+ if (!presto_d2d(dentry)) {
+ /* This should really only happen in the case of a dentry
+ * with no inode. */
+ return;
+ }
+
+ presto_d2d(dentry)->dd_count--;
+
+ if (! presto_d2d(dentry)->dd_count) {
+ kmem_cache_free(presto_dentry_slab, presto_d2d(dentry));
+ dentry->d_fsdata = NULL;
+ }
+}
+
+struct dentry_operations presto_dentry_ops =
+{
+ d_revalidate: presto_dentry_revalidate,
+ d_release: presto_d_release
+};
+
+
+// XXX THIS DEPENDS ON THE KERNEL LOCK!
+
+void presto_set_dd(struct dentry * dentry)
+{
+ ENTRY;
+ if (dentry == NULL)
+ BUG();
+
+ if (dentry->d_fsdata) {
+ printk("VERY BAD: dentry: %p\n", dentry);
+ if (dentry->d_inode)
+ printk(" inode: %ld\n", dentry->d_inode->i_ino);
+ EXIT;
+ return;
+ }
+
+ if (dentry->d_inode == NULL) {
+ dentry->d_fsdata = kmem_cache_alloc(presto_dentry_slab,
+ SLAB_KERNEL);
+ memset(dentry->d_fsdata, 0, sizeof(struct presto_dentry_data));
+ presto_d2d(dentry)->dd_count = 1;
+ EXIT;
+ return;
+ }
+
+ /* If there's already a dentry for this inode, share the data */
+ if (dentry->d_alias.next != &dentry->d_inode->i_dentry ||
+ dentry->d_alias.prev != &dentry->d_inode->i_dentry) {
+ struct dentry *de;
+
+ if (dentry->d_alias.next != &dentry->d_inode->i_dentry)
+ de = list_entry(dentry->d_alias.next, struct dentry,
+ d_alias);
+ else
+ de = list_entry(dentry->d_alias.prev, struct dentry,
+ d_alias);
+
+ dentry->d_fsdata = de->d_fsdata;
+ presto_d2d(dentry)->dd_count++;
+ EXIT;
+ return;
+ }
+
+ dentry->d_fsdata = kmem_cache_alloc(presto_dentry_slab, SLAB_KERNEL);
+ memset(dentry->d_fsdata, 0, sizeof(struct presto_dentry_data));
+ presto_d2d(dentry)->dd_count = 1;
+ EXIT;
+ return;
+}
+
+void presto_init_ddata_cache(void)
+{
+ ENTRY;
+ presto_dentry_slab =
+ kmem_cache_create("presto_cache",
+ sizeof(struct presto_dentry_data), 0,
+ SLAB_HWCACHE_ALIGN, NULL,
+ NULL);
+ EXIT;
+}
+
+void presto_cleanup_ddata_cache(void)
+{
+ kmem_cache_destroy(presto_dentry_slab);
+}
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/dir.c linux/fs/intermezzo/dir.c
--- v2.4.14/linux/fs/intermezzo/dir.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/dir.c Tue Nov 13 09:20:56 2001
@@ -0,0 +1,893 @@
+/*
+ *
+ *
+ * Copyright (C) 2000 Stelias Computing, Inc.
+ * Copyright (C) 2000 Red Hat, Inc.
+ * Copyright (C) 2000 Tacitus Systems
+ * Copyright (C) 2000 Peter J. Braam


+ *
+ */
+

+
+#include <stdarg.h>
+
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/smp_lock.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/sched.h>


+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/locks.h>

+#include <linux/blkdev.h>
+#include <linux/init.h>
+#define __NO_VERSION__
+#include <linux/module.h>
+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+
+static inline void presto_relock_sem(struct inode *dir)
+{
+ /* the lock from sys_mkdir / lookup_create */
+ down(&dir->i_sem);
+ /* the rest is done by the do_{create,mkdir, ...} */


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

echo 'End of part 090'
echo 'File patch-2.4.15 is continued in part 091'
echo "091" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:07 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part091

#!/bin/sh -x
# this is part 091 of a 115 - part archive


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

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

+static inline void presto_relock_other(struct inode *dir)
+{
+ /* vfs_mkdir locks */
+ down(&dir->i_zombie);
+ lock_kernel();
+}
+
+static inline void presto_fulllock(struct inode *dir)

+{
+ /* the lock from sys_mkdir / lookup_create */
+ down(&dir->i_sem);

+ /* vfs_mkdir locks */
+ down(&dir->i_zombie);
+ lock_kernel();
+}
+
+static inline void presto_unlock(struct inode *dir)
+{
+ /* vfs_mkdir locks */
+ unlock_kernel();
+ up(&dir->i_zombie);


+ /* the lock from sys_mkdir / lookup_create */

+ up(&dir->i_sem);
+}
+
+
+/*
+ * these are initialized in super.c
+ */
+extern int presto_permission(struct inode *inode, int mask);
+int presto_ilookup_uid = 0;
+
+extern int presto_prep(struct dentry *, struct presto_cache **,
+ struct presto_file_set **);
+
+static int dentry2id(struct dentry *dentry, ino_t *id, unsigned int *generation)
+{
+ char *tmpname;
+ char *next;


+ int error = 0;

+
+ ENTRY;
+ if (dentry->d_name.len > EXT2_NAME_LEN) {
+ EXIT;


+ return -ENAMETOOLONG;
+ }
+

+ /* prefix is 7 characters: '...ino:' */
+ if ( dentry->d_name.len < 7 ||
+ memcmp(dentry->d_name.name, PRESTO_ILOOKUP_MAGIC, 7) != 0 ) {
+ EXIT;
+ return 1;
+ }
+
+ PRESTO_ALLOC(tmpname, char *, dentry->d_name.len - 7 + 1);
+ if ( !tmpname ) {
+ EXIT;
+ return -ENOMEM;
+ }
+
+ memcpy(tmpname, dentry->d_name.name + 7, dentry->d_name.len - 7);
+ *(tmpname + dentry->d_name.len) = '\0';
+
+ /* name is of the form <inode number>:<generation> */
+ *id = simple_strtoul(tmpname, &next, 0);
+ if ( *next == PRESTO_ILOOKUP_SEP ) {
+ *generation = simple_strtoul(next + 1, 0, 0);
+ CDEBUG(D_INODE, "INO to find = %s\n", tmpname);
+ CDEBUG(D_INODE, "Id = %lx (%lu), generation %x (%d)\n",
+ *id, *id, *generation, *generation);
+ } else
+ error = 1;
+
+ PRESTO_FREE(tmpname, dentry->d_name.len - 7 + 1);
+ EXIT;


+ return error;
+}
+

+static int presto_opendir_upcall(int minor, struct dentry *de,
+ struct dentry *root, int async)
+{
+ int rc;
+ char *path, *buffer;
+ int pathlen;
+
+ PRESTO_ALLOC(buffer, char *, PAGE_SIZE);
+ if ( !buffer ) {
+ printk("PRESTO: out of memory!\n");
+ return ENOMEM;
+ }
+ path = presto_path(de, root, buffer, PAGE_SIZE);
+ pathlen = MYPATHLEN(buffer, path);
+ CDEBUG(D_INODE, "path: %*s, len %d\n", pathlen, path, pathlen);
+ rc = lento_opendir(minor, pathlen, path, async);
+ PRESTO_FREE(buffer, PAGE_SIZE);
+ return rc;
+}
+
+inline int presto_can_ilookup(void)
+{
+ return (current->euid == presto_ilookup_uid ||
+ capable(CAP_DAC_READ_SEARCH));
+}
+
+struct dentry *presto_ilookup(struct inode *dir, struct dentry *dentry,
+ ino_t ino, unsigned int generation)
+{
+ struct inode *inode;
+ int error;
+
+ ENTRY;
+
+ /* if we can't ilookup, forbid anything with this name to
+ * avoid any security issues/name clashes.
+ */
+ if ( !presto_can_ilookup() ) {
+ CDEBUG(D_CACHE, "ilookup denied: euid %u, ilookup_uid %u\n",
+ current->euid, presto_ilookup_uid);
+ EXIT;
+ return ERR_PTR(-EPERM);
+ }


+ inode = iget(dir->i_sb, ino);

+ if (!inode || is_bad_inode(inode)) {
+ CDEBUG(D_PIOCTL, "fatal: invalid inode %ld (%s).\n",
+ ino, inode ? inode->i_nlink ? "bad inode" :
+ "no links" : "NULL");
+ error = -ENOENT;
+ EXIT;
+ goto cleanup_iput;
+ } else if (inode->i_nlink == 0) {
+ /* This is quite evil, but we have little choice. If we were
+ * to iput() again with i_nlink == 0, delete_inode would get
+ * called again, which ext3 really Does Not Like. */
+ atomic_dec(&inode->i_count);
+ EXIT;
+ return ERR_PTR(-ENOENT);
+ }
+
+ /* We need to make sure we have the right inode (by checking the
+ * generation) so we don't write into the wrong file (old inode was
+ * deleted and then a new one was created with the same number).
+ */
+ if (inode->i_generation != generation) {
+ CDEBUG(D_PIOCTL, "fatal: bad generation %u (want %u)\n",
+ inode->i_generation, generation);
+ error = -ENOENT;
+ EXIT;
+ goto cleanup_iput;
+ }
+
+ d_instantiate(dentry, inode);
+ dentry->d_flags |= DCACHE_NFSD_DISCONNECTED; /* NFS hack */
+


+ EXIT;
+ return NULL;
+

+cleanup_iput:
+ if (inode)
+ iput(inode);
+ return ERR_PTR(error);
+}
+
+
+struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry)
+{
+ int rc = 0;
+ struct dentry *de;
+ struct presto_cache *cache;
+ struct presto_file_set *fset;
+ int error;
+ int minor;
+ ino_t ino;
+ unsigned int generation;
+
+ ENTRY;
+ CDEBUG(D_CACHE, "calling presto_prep on dentry %p\n", dentry);
+ error = presto_prep(dentry->d_parent, &cache, &fset);
+ if ( error ) {
+ EXIT;
+ return ERR_PTR(error);
+ }
+ minor = presto_c2m(cache);
+
+ CDEBUG(D_CACHE, "dir ino: %ld, name: %*s\n",
+ dir->i_ino, dentry->d_name.len, dentry->d_name.name);
+ if ( ISLENTO(minor) )
+ CDEBUG(D_CACHE, "We are lento\n");
+
+ rc = dentry2id(dentry, &ino, &generation);
+ CDEBUG(D_CACHE, "dentry2id returned %d\n", rc);
+ if ( rc < 0 ) {
+ EXIT;
+ goto exit;
+ }
+
+ if ( rc == 0 ) {
+ de = presto_ilookup(dir, dentry, ino, generation);
+ } else {
+ struct inode_operations *iops = filter_c2cdiops(cache->cache_filter);
+ rc = 0;
+ /* recursively do a cache lookup in dir */
+ if (iops && iops->lookup)
+ de = iops->lookup(dir, dentry);
+ else {
+ printk("filesystem has no lookup\n");
+ EXIT;
+ goto exit;
+ }
+ }
+ /* XXX this needs some work to handle returning de if we get it */
+ filter_setup_dentry_ops(cache->cache_filter,
+ dentry->d_op, &presto_dentry_ops);
+ dentry->d_op = filter_c2udops(cache->cache_filter);
+ if ( IS_ERR(de) ) {
+ rc = PTR_ERR(de);
+ CDEBUG(D_CACHE, "dentry lookup error %d\n", rc);
+ EXIT;
+ goto exit;
+ }
+
+ presto_set_dd(dentry);
+
+ /* some file systems set the methods in lookup, not in
+ read_inode, as a result we should set the methods here
+ as well as in read_inode
+ */
+ if (dentry->d_inode) {
+ presto_set_ops(dentry->d_inode, cache->cache_filter);
+ }
+ EXIT;
+exit:
+ return ERR_PTR(rc);
+}
+
+int presto_setattr(struct dentry *de, struct iattr *iattr)
+{
+ int error;
+ struct presto_cache *cache;
+ struct presto_file_set *fset;
+ struct lento_vfs_context info = { 0, 0, 0 };
+
+ ENTRY;
+ error = presto_prep(de, &cache, &fset);
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ if (!iattr->ia_valid)
+ CDEBUG(D_INODE, "presto_setattr: iattr is not valid\n");
+
+ CDEBUG(D_INODE, "valid %#x, mode %#o, uid %u, gid %u, size %Lu, "
+ "atime %lu mtime %lu ctime %lu flags %d\n",
+ iattr->ia_valid, iattr->ia_mode, iattr->ia_uid, iattr->ia_gid,
+ iattr->ia_size, iattr->ia_atime, iattr->ia_mtime,
+ iattr->ia_ctime, iattr->ia_attr_flags);
+
+ if ( presto_get_permit(de->d_inode) < 0 ) {
+ EXIT;


+ return -EROFS;
+ }
+

+ if (!ISLENTO(presto_c2m(cache)))
+ info.flags = LENTO_FL_KML;
+ info.flags |= LENTO_FL_IGNORE_TIME;
+ error = presto_do_setattr(fset, de, iattr, &info);
+ presto_put_permit(de->d_inode);
+ return error;
+}
+
+/*
+ * Now the meat: the fs operations that require journaling
+ *
+ *
+ * XXX: some of these need modifications for hierarchical filesets
+ */
+
+int presto_prep(struct dentry *dentry, struct presto_cache **cache,
+ struct presto_file_set **fset)
+{
+ *fset = presto_fset(dentry);
+ if ( !*fset ) {
+ CDEBUG(D_INODE, "No file set for dentry at %p\n", dentry);


+ return -EROFS;
+ }
+

+ *cache = (*fset)->fset_cache;
+ if ( !*cache ) {
+ printk("PRESTO: BAD, BAD: cannot find cache\n");
+ return -EBADF;
+ }
+
+ CDEBUG(D_PIOCTL, "---> cache flags %x, fset flags %x\n",
+ (*cache)->cache_flags, (*fset)->fset_flags);
+ if( presto_is_read_only(*fset) ) {
+ printk("PRESTO: cannot modify read-only fileset, minor %d.\n",
+ presto_c2m(*cache));
+ return -EROFS;
+ }


+ return 0;
+}
+

+static int presto_create(struct inode * dir, struct dentry * dentry, int mode)
+{
+ int error;
+ struct presto_cache *cache;
+ struct dentry *parent = dentry->d_parent;
+ struct lento_vfs_context info;
+ struct presto_file_set *fset;
+
+ ENTRY;
+ error = presto_prep(dentry->d_parent, &cache, &fset);
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+ presto_unlock(dir);
+
+ /* Does blocking and non-blocking behavious need to be
+ checked for. Without blocking (return 1), the permit
+ was acquired without reintegration
+ */
+ if ( presto_get_permit(dir) < 0 ) {
+ EXIT;
+ presto_fulllock(dir);


+ return -EROFS;
+ }
+

+ presto_relock_sem(dir);
+ parent = dentry->d_parent;
+ memset(&info, 0, sizeof(info));
+ if (!ISLENTO(presto_c2m(cache)))
+ info.flags = LENTO_FL_KML;
+ info.flags |= LENTO_FL_IGNORE_TIME;
+ error = presto_do_create(fset, parent, dentry, mode, &info);
+ presto_relock_other(dir);
+ presto_put_permit(dir);
+ EXIT;


+ return error;
+}
+

+static int presto_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *new_dentry)
+{
+ int error;
+ struct presto_cache *cache, *new_cache;
+ struct presto_file_set *fset, *new_fset;
+ struct dentry *parent = new_dentry->d_parent;
+ struct lento_vfs_context info;
+
+ ENTRY;
+ error = presto_prep(old_dentry, &cache, &fset);
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ error = presto_prep(new_dentry->d_parent, &new_cache, &new_fset);
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ if (fset != new_fset) {
+ EXIT;
+ return -EXDEV;
+ }
+
+ presto_unlock(dir);
+ if ( presto_get_permit(old_dentry->d_inode) < 0 ) {
+ EXIT;
+ presto_fulllock(dir);


+ return -EROFS;
+ }
+

+ if ( presto_get_permit(dir) < 0 ) {
+ EXIT;
+ presto_fulllock(dir);


+ return -EROFS;
+ }
+

+ presto_relock_sem(dir);
+ parent = new_dentry->d_parent;
+
+ memset(&info, 0, sizeof(info));
+ if (!ISLENTO(presto_c2m(cache)))
+ info.flags = LENTO_FL_KML;
+ info.flags |= LENTO_FL_IGNORE_TIME;
+ error = presto_do_link(fset, old_dentry, parent,
+ new_dentry, &info);
+ presto_relock_other(dir);
+ presto_put_permit(dir);
+ presto_put_permit(old_dentry->d_inode);


+ return error;
+}
+

+static int presto_mkdir(struct inode * dir, struct dentry * dentry, int mode)
+{
+ int error;
+ struct presto_file_set *fset;
+ struct presto_cache *cache;
+ struct dentry *parent = dentry->d_parent;
+ struct lento_vfs_context info;
+
+ ENTRY;
+
+ error = presto_prep(dentry->d_parent, &cache, &fset);
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ presto_unlock(dir);
+
+ if ( presto_get_permit(dir) < 0 ) {
+ EXIT;
+ presto_fulllock(dir);


+ return -EROFS;
+ }
+

+ memset(&info, 0, sizeof(info));
+ if (!ISLENTO(presto_c2m(cache)))
+ info.flags = LENTO_FL_KML;
+ info.flags |= LENTO_FL_IGNORE_TIME;
+
+ presto_relock_sem(dir);
+ parent = dentry->d_parent;
+ error = presto_do_mkdir(fset, parent, dentry, mode, &info);
+ presto_relock_other(dir);
+ presto_put_permit(dir);


+ return error;
+}
+

+
+static int presto_symlink(struct inode *dir, struct dentry *dentry,
+ const char *name)
+{
+ int error;
+ struct presto_cache *cache;
+ struct presto_file_set *fset;
+ struct dentry *parent = dentry->d_parent;
+ struct lento_vfs_context info;
+
+ ENTRY;
+ error = presto_prep(dentry->d_parent, &cache, &fset);
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ presto_unlock(dir);
+ if ( presto_get_permit(dir) < 0 ) {
+ EXIT;
+ presto_fulllock(dir);


+ return -EROFS;
+ }
+

+ presto_relock_sem(dir);
+ parent = dentry->d_parent;
+ memset(&info, 0, sizeof(info));
+ if (!ISLENTO(presto_c2m(cache)))
+ info.flags = LENTO_FL_KML;
+ info.flags |= LENTO_FL_IGNORE_TIME;
+ error = presto_do_symlink(fset, parent, dentry, name, &info);
+ presto_relock_other(dir);
+ presto_put_permit(dir);


+ return error;
+}
+

+int presto_unlink(struct inode *dir, struct dentry *dentry)
+{
+ int error;
+ struct presto_cache *cache;
+ struct presto_file_set *fset;
+ struct dentry *parent = dentry->d_parent;
+ struct lento_vfs_context info;
+
+ ENTRY;
+ error = presto_prep(dentry->d_parent, &cache, &fset);
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ presto_unlock(dir);
+ if ( presto_get_permit(dir) < 0 ) {
+ EXIT;
+ presto_fulllock(dir);


+ return -EROFS;
+ }
+

+ presto_relock_sem(dir);
+ parent = dentry->d_parent;
+ memset(&info, 0, sizeof(info));
+ if (!ISLENTO(presto_c2m(cache)))
+ info.flags = LENTO_FL_KML;
+ info.flags |= LENTO_FL_IGNORE_TIME;
+ error = presto_do_unlink(fset, parent, dentry, &info);
+ presto_relock_other(dir);
+ presto_put_permit(dir);


+ return error;
+}
+

+static int presto_rmdir(struct inode *dir, struct dentry *dentry)
+{
+ int error;
+ struct presto_cache *cache;
+ struct presto_file_set *fset;
+ struct dentry *parent = dentry->d_parent;
+ struct lento_vfs_context info;
+
+ ENTRY;
+ CDEBUG(D_FILE, "prepping presto\n");
+ error = presto_prep(dentry->d_parent, &cache, &fset);
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ CDEBUG(D_FILE, "unlocking\n");
+ /* We need to dget() before the dput in double_unlock, to ensure we
+ * still have dentry references. double_lock doesn't do dget for us.
+ */
+ unlock_kernel();
+ if (d_unhashed(dentry))
+ d_rehash(dentry);
+ double_up(&dir->i_zombie, &dentry->d_inode->i_zombie);
+ double_up(&dir->i_sem, &dentry->d_inode->i_sem);
+
+ CDEBUG(D_FILE, "getting permit\n");
+ if ( presto_get_permit(parent->d_inode) < 0 ) {
+ EXIT;
+ double_down(&dir->i_sem, &dentry->d_inode->i_sem);
+ double_down(&dir->i_zombie, &dentry->d_inode->i_zombie);
+
+ lock_kernel();
+ return -EROFS;
+ }
+ CDEBUG(D_FILE, "locking\n");
+
+ double_down(&dir->i_sem, &dentry->d_inode->i_sem);
+ parent = dentry->d_parent;
+ memset(&info, 0, sizeof(info));
+ if (!ISLENTO(presto_c2m(cache)))
+ info.flags = LENTO_FL_KML;
+ info.flags |= LENTO_FL_IGNORE_TIME;
+ error = presto_do_rmdir(fset, parent, dentry, &info);
+ presto_put_permit(parent->d_inode);
+ lock_kernel();
+ EXIT;


+ return error;
+}
+

+static int presto_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev)
+{
+ int error;
+ struct presto_cache *cache;
+ struct presto_file_set *fset;
+ struct dentry *parent = dentry->d_parent;
+ struct lento_vfs_context info;
+
+ ENTRY;
+ error = presto_prep(dentry->d_parent, &cache, &fset);
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ presto_unlock(dir);
+ if ( presto_get_permit(dir) < 0 ) {
+ EXIT;
+ presto_fulllock(dir);


+ return -EROFS;
+ }
+

+ presto_relock_sem(dir);
+ parent = dentry->d_parent;
+ memset(&info, 0, sizeof(info));
+ if (!ISLENTO(presto_c2m(cache)))
+ info.flags = LENTO_FL_KML;
+ info.flags |= LENTO_FL_IGNORE_TIME;
+ error = presto_do_mknod(fset, parent, dentry, mode, rdev, &info);
+ presto_relock_other(dir);
+ presto_put_permit(dir);
+ EXIT;


+ return error;
+}
+

+inline void presto_triple_unlock(struct inode *old_dir, struct inode *new_dir,
+ struct dentry *old_dentry,
+ struct dentry *new_dentry, int triple)
+{
+ /* rename_dir case */
+ if (S_ISDIR(old_dentry->d_inode->i_mode)) {
+ if (triple) {
+ triple_up(&old_dir->i_zombie,
+ &new_dir->i_zombie,
+ &new_dentry->d_inode->i_zombie);
+ } else {
+ double_up(&old_dir->i_zombie,
+ &new_dir->i_zombie);
+ }
+ up(&old_dir->i_sb->s_vfs_rename_sem);
+ } else /* this case is rename_other */
+ double_up(&old_dir->i_zombie, &new_dir->i_zombie);
+ /* done by do_rename */
+ unlock_kernel();
+ double_up(&old_dir->i_sem, &new_dir->i_sem);
+}
+
+inline void presto_triple_fulllock(struct inode *old_dir,
+ struct inode *new_dir,
+ struct dentry *old_dentry,
+ struct dentry *new_dentry, int triple)
+{
+ /* done by do_rename */
+ double_down(&old_dir->i_sem, &new_dir->i_sem);
+ lock_kernel();
+ /* rename_dir case */
+ if (S_ISDIR(old_dentry->d_inode->i_mode)) {
+ down(&old_dir->i_sb->s_vfs_rename_sem);
+ if (triple) {
+ triple_down(&old_dir->i_zombie,
+ &new_dir->i_zombie,
+ &new_dentry->d_inode->i_zombie);
+ } else {
+ double_down(&old_dir->i_zombie,
+ &new_dir->i_zombie);
+ }
+ } else /* this case is rename_other */
+ double_down(&old_dir->i_zombie, &new_dir->i_zombie);
+}
+
+inline void presto_triple_relock_sem(struct inode *old_dir,
+ struct inode *new_dir,
+ struct dentry *old_dentry,
+ struct dentry *new_dentry, int triple)
+{
+ /* done by do_rename */
+ double_down(&old_dir->i_sem, &new_dir->i_sem);
+ lock_kernel();
+}
+
+inline void presto_triple_relock_other(struct inode *old_dir,
+ struct inode *new_dir,
+ struct dentry *old_dentry,
+ struct dentry *new_dentry, int triple)
+{
+ /* rename_dir case */
+ if (S_ISDIR(old_dentry->d_inode->i_mode)) {
+ down(&old_dir->i_sb->s_vfs_rename_sem);
+ if (triple) {
+ triple_down(&old_dir->i_zombie,
+ &new_dir->i_zombie,
+ &new_dentry->d_inode->i_zombie);
+ } else {
+ double_down(&old_dir->i_zombie,
+ &new_dir->i_zombie);
+ }
+ } else /* this case is rename_other */
+ double_down(&old_dir->i_zombie, &new_dir->i_zombie);
+}
+
+
+// XXX this can be optimized: renamtes across filesets only require
+// multiple KML records, but can locally be executed normally.
+int presto_rename(struct inode *old_dir, struct dentry *old_dentry,


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

+ int error;
+ struct presto_cache *cache, *new_cache;
+ struct presto_file_set *fset, *new_fset;
+ struct lento_vfs_context info;
+ struct dentry *old_parent = old_dentry->d_parent;
+ struct dentry *new_parent = new_dentry->d_parent;
+ int triple;
+
+ ENTRY;
+ error = presto_prep(old_dentry, &cache, &fset);
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+ error = presto_prep(new_parent, &new_cache, &new_fset);
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ if ( fset != new_fset ) {
+ EXIT;
+ return -EXDEV;
+ }
+
+ /* We need to do dget before the dput in double_unlock, to ensure we
+ * still have dentry references. double_lock doesn't do dget for us.
+ */
+
+ triple = (S_ISDIR(old_dentry->d_inode->i_mode) && new_dentry->d_inode)?
+ 1:0;
+
+ presto_triple_unlock(old_dir, new_dir, old_dentry, new_dentry, triple);
+
+ if ( presto_get_permit(old_dir) < 0 ) {
+ EXIT;
+ presto_triple_fulllock(old_dir, new_dir, old_dentry, new_dentry, triple);
+ return -EROFS;
+ }
+ if ( presto_get_permit(new_dir) < 0 ) {
+ EXIT;
+ presto_triple_fulllock(old_dir, new_dir, old_dentry, new_dentry, triple);

+ return -EROFS;
+ }
+

+ presto_triple_relock_sem(old_dir, new_dir, old_dentry, new_dentry, triple);
+ memset(&info, 0, sizeof(info));
+ if (!ISLENTO(presto_c2m(cache)))
+ info.flags = LENTO_FL_KML;
+ info.flags |= LENTO_FL_IGNORE_TIME;
+ error = presto_do_rename(fset, old_parent, old_dentry, new_parent,
+ new_dentry, &info);
+ presto_triple_relock_other(old_dir, new_dir, old_dentry, new_dentry, triple);
+
+ presto_put_permit(new_dir);
+ presto_put_permit(old_dir);


+ return error;
+}
+

+/* basically this allows the ilookup processes access to all files for
+ * reading, while not making ilookup totally insecure. This could all
+ * go away if we could set the CAP_DAC_READ_SEARCH capability for the client.
+ */
+/* If posix acls are available, the underlying cache fs will export the
+ * appropriate permission function. Thus we do not worry here about ACLs
+ * or EAs. -SHP
+ */
+int presto_permission(struct inode *inode, int mask)
+{
+ unsigned short mode = inode->i_mode;
+ struct presto_cache *cache;
+ int rc;
+
+ ENTRY;
+ if ( presto_can_ilookup() && !(mask & S_IWOTH)) {
+ CDEBUG(D_CACHE, "ilookup on %ld OK\n", inode->i_ino);
+ EXIT;
+ return 0;
+ }
+


+ cache = presto_get_cache(inode);
+

+ if ( cache ) {

+ /* we only override the file/dir permission operations */
+ struct inode_operations *fiops = filter_c2cfiops(cache->cache_filter);
+ struct inode_operations *diops = filter_c2cdiops(cache->cache_filter);
+
+ if ( S_ISREG(mode) && fiops && fiops->permission ) {
+ EXIT;
+ return fiops->permission(inode, mask);
+ }
+ if ( S_ISDIR(mode) && diops && diops->permission ) {
+ EXIT;
+ return diops->permission(inode, mask);
+ }
+ }
+
+ /* The cache filesystem doesn't have its own permission function,
+ * but we don't want to duplicate the VFS code here. In order
+ * to avoid looping from permission calling this function again,
+ * we temporarily override the permission operation while we call
+ * the VFS permission function.
+ */
+ inode->i_op->permission = NULL;
+ rc = permission(inode, mask);
+ inode->i_op->permission = &presto_permission;
+
+ EXIT;
+ return rc;
+}
+
+
+static int presto_dir_open(struct inode *inode, struct file *file)
+{
+ int rc = 0;
+ struct dentry *de = file->f_dentry;
+ struct file_operations *fops;
+ struct presto_cache *cache;
+ struct presto_file_set *fset;
+ int minor;
+ int error;
+
+ ENTRY;
+
+ error = presto_prep(file->f_dentry, &cache, &fset);
+ if ( error ) {
+ EXIT;
+ make_bad_inode(inode);
+ return error;
+ }
+ minor = presto_c2m(cache);
+
+ CDEBUG(D_CACHE, "minor %d, DATA_OK: %d, ino: %ld\n",
+ minor, presto_chk(de, PRESTO_DATA), inode->i_ino);
+
+ if ( ISLENTO(minor) )
+ goto cache;
+
+ if ( !presto_chk(de, PRESTO_DATA) ) {
+ CDEBUG(D_CACHE, "doing lento_opendir\n");
+ rc = presto_opendir_upcall(minor, file->f_dentry, fset->fset_mtpt, SYNCHRONOUS);
+ }
+
+ if ( rc ) {
+ printk("presto_dir_open: DATA_OK: %d, ino: %ld, error %d\n",
+ presto_chk(de, PRESTO_DATA), inode->i_ino, rc);
+ return rc ;
+ }
+
+ cache:
+ fops = filter_c2cdfops(cache->cache_filter);
+ if ( fops->open ) {
+ rc = fops->open(inode, file);
+ }
+ presto_set(de, PRESTO_DATA | PRESTO_ATTR);
+ CDEBUG(D_CACHE, "returns %d, data %d, attr %d\n", rc,
+ presto_chk(de, PRESTO_DATA), presto_chk(de, PRESTO_ATTR));


+ return 0;
+}
+

+struct file_operations presto_dir_fops = {
+ open: presto_dir_open
+};
+
+struct inode_operations presto_dir_iops = {
+ create: presto_create,
+ lookup: presto_lookup,
+ link: presto_link,
+ unlink: presto_unlink,
+ symlink: presto_symlink,
+ mkdir: presto_mkdir,
+ rmdir: presto_rmdir,
+ mknod: presto_mknod,
+ rename: presto_rename,
+ permission: presto_permission,
+ setattr: presto_setattr,
+#ifdef CONFIG_FS_EXT_ATTR
+ set_ext_attr: presto_set_ext_attr,
+#endif
+
+};
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/ext_attr.c linux/fs/intermezzo/ext_attr.c
--- v2.4.14/linux/fs/intermezzo/ext_attr.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/ext_attr.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,196 @@
+/*
+ * Extended attribute handling for presto.
+ *
+ * Copyright (C) 2001. All rights reserved.
+ * Shirish H. Phatak
+ * Tacit Networks, Inc.


+ *
+ */
+
+#define __NO_VERSION__
+#include <linux/module.h>

+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>


+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/locks.h>

+#include <linux/unistd.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+


+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/locks.h>

+#include <linux/string.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/segment.h>
+#include <linux/smp_lock.h>


+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>

+#include <linux/intermezzo_kml.h>
+
+
+#ifdef CONFIG_FS_EXT_ATTR
+#include <linux/ext_attr.h>
+
+extern inline void presto_debug_fail_blkdev(struct presto_file_set *fset,
+ unsigned long value);
+
+extern int presto_prep(struct dentry *, struct presto_cache **,
+ struct presto_file_set **);
+
+
+/* VFS interface */
+/* XXX! Fixme test for user defined attributes */
+int presto_set_ext_attr(struct inode *inode,
+ const char *name, void *buffer,
+ size_t buffer_len, int flags)
+{
+ int error;
+ struct presto_cache *cache;
+ struct presto_file_set *fset;
+ struct lento_vfs_context info;
+ struct dentry *dentry;
+ int minor = presto_i2m(inode);
+ char *buf = NULL;
+
+ ENTRY;
+ if (minor < 0) {
+ EXIT;


+ return -1;
+ }
+

+ if ( ISLENTO(minor) ) {
+ EXIT;
+ return -EINVAL;
+ }
+
+ /* BAD...vfs should really pass down the dentry to use, especially
+ * since every other operation in iops does. But for now
+ * we do a reverse mapping from inode to the first dentry
+ */
+ if (list_empty(&inode->i_dentry)) {
+ printk("No alias for inode %d\n", (int) inode->i_ino);
+ EXIT;
+ return -EINVAL;
+ }
+
+ dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);
+
+ error = presto_prep(dentry, &cache, &fset);
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ if ((buffer != NULL) && (buffer_len != 0)) {
+ /* If buffer is a user space pointer copy it to kernel space
+ * and reset the flag. We do this since the journal functions need
+ * access to the contents of the buffer, and the file system
+ * does not care. When we actually invoke the function, we remove
+ * the EXT_ATTR_FLAG_USER flag.
+ *
+ * XXX:Check if the "fs does not care" assertion is always true -SHP
+ * (works for ext3)
+ */
+ if (flags & EXT_ATTR_FLAG_USER) {
+ PRESTO_ALLOC(buf, char *, buffer_len);
+ if (!buf) {
+ printk("InterMezzo: out of memory!!!\n");
+ return -ENOMEM;
+ }
+ error = copy_from_user(buf, buffer, buffer_len);
+ if (error)
+ return error;
+ } else
+ buf = buffer;
+ } else
+ buf = buffer;
+
+ if ( presto_get_permit(inode) < 0 ) {
+ EXIT;
+ if (buffer_len && (flags & EXT_ATTR_FLAG_USER))
+ PRESTO_FREE(buf, buffer_len);


+ return -EROFS;
+ }
+

+ /* Simulate presto_setup_info */
+ memset(&info, 0, sizeof(info));
+ /* For now redundant..but we keep it around just in case */
+ info.flags = LENTO_FL_IGNORE_TIME;
+ if (!ISLENTO(cache->cache_psdev->uc_minor))
+ info.flags |= LENTO_FL_KML;
+
+ /* We pass in the kernel space pointer and reset the
+ * EXT_ATTR_FLAG_USER flag.
+ * See comments above.
+ */
+ /* Note that mode is already set by VFS so we send in a NULL */
+ error = presto_do_set_ext_attr(fset, dentry, name, buf,
+ buffer_len, flags & ~EXT_ATTR_FLAG_USER,
+ NULL, &info);
+ presto_put_permit(inode);
+
+ if (buffer_len && (flags & EXT_ATTR_FLAG_USER))
+ PRESTO_FREE(buf, buffer_len);
+ EXIT;


+ return error;
+}
+

+/* Lento Interface */
+/* XXX: ignore flags? We should be forcing these operations through? -SHP*/
+int lento_set_ext_attr(const char *path, const char *name,
+ void *buffer, size_t buffer_len, int flags, mode_t mode,
+ struct lento_vfs_context *info)
+{
+ int error;
+ char * pathname;
+ struct nameidata nd;
+ struct dentry *dentry;
+ struct presto_file_set *fset;
+
+ ENTRY;
+ lock_kernel();
+
+ pathname=getname(path);
+ error = PTR_ERR(pathname);
+ if (IS_ERR(pathname)) {
+ EXIT;
+ goto exit;
+ }
+
+ /* Note that ext_attrs apply to both files and directories..*/
+ error=presto_walk(pathname,&nd);
+ if (error)
+ goto exit;
+ dentry = nd.dentry;
+
+ fset = presto_fset(dentry);
+ error = -EINVAL;
+ if ( !fset ) {
+ printk("No fileset!\n");
+ EXIT;
+ goto exit_dentry;
+ }
+
+ if (buffer==NULL) buffer_len=0;
+
+ error = presto_do_set_ext_attr(fset, dentry, name, buffer,
+ buffer_len, flags, &mode, info);
+exit_dentry:
+ path_release(&nd);
+exit_path:
+ putname(pathname);
+exit:
+ unlock_kernel();


+ return error;
+}
+

+#endif /*CONFIG_FS_EXT_ATTR*/
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/file.c linux/fs/intermezzo/file.c
--- v2.4.14/linux/fs/intermezzo/file.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/file.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,426 @@
+/*
+ *


+ * Copyright (C) 2000 Stelias Computing, Inc.
+ * Copyright (C) 2000 Red Hat, Inc.

+ * Copyright (C) 2000 TurboLinux, Inc.
+ * Copyright (C) 2000 Los Alamos National Laboratory.


+ * Copyright (C) 2000 Tacitus Systems
+ * Copyright (C) 2000 Peter J. Braam

+ * Copyright (C) 2001 Mountain View Data, Inc.
+ * Copyright (C) 2001 Cluster File Systems, Inc.
+ *
+ * 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.


+ *
+ */
+
+
+#include <stdarg.h>
+
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>

+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/sched.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/locks.h>
+#include <linux/blkdev.h>
+#include <linux/init.h>

+#include <linux/smp_lock.h>


+#define __NO_VERSION__
+#include <linux/module.h>
+
+#include <linux/intermezzo_fs.h>

+#include <linux/intermezzo_kml.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+#include <linux/fsfilter.h>
+/*
+ * these are initialized in super.c
+ */
+extern int presto_permission(struct inode *inode, int mask);
+extern int presto_opendir_upcall(int minor, struct dentry *de, int async);
+
+extern int presto_prep(struct dentry *, struct presto_cache **,
+ struct presto_file_set **);
+
+
+#if 0
+static int presto_open_upcall(int minor, struct dentry *de)
+{
+ int rc;
+ char *path, *buffer;
+ int pathlen;
+
+ PRESTO_ALLOC(buffer, char *, PAGE_SIZE);
+ if ( !buffer ) {
+ printk("PRESTO: out of memory!\n");
+ return ENOMEM;
+ }
+ path = presto_path(de, buffer, PAGE_SIZE);
+ pathlen = MYPATHLEN(buffer, path);
+ rc = lento_open(minor, pathlen, path);
+ PRESTO_FREE(buffer, PAGE_SIZE);
+ return rc;
+}
+#endif
+
+
+static int presto_file_open(struct inode *inode, struct file *file)
+{
+ int rc = 0;
+ struct file_operations *fops;
+ struct presto_cache *cache;
+ struct presto_file_data *fdata;
+ int writable = (file->f_flags & (O_RDWR | O_WRONLY));
+ int minor;
+ int i;
+
+ ENTRY;
+


+ cache = presto_get_cache(inode);
+ if ( !cache ) {

+ printk("PRESTO: BAD, BAD: cannot find cache\n");
+ EXIT;
+ return -EBADF;
+ }
+
+ minor = presto_c2m(cache);
+
+ CDEBUG(D_CACHE, "presto_file_open: DATA_OK: %d, ino: %ld\n",
+ presto_chk(file->f_dentry, PRESTO_DATA), inode->i_ino);
+
+ if ( ISLENTO(minor) )
+ goto cache;
+
+ if ( file->f_flags & O_RDWR || file->f_flags & O_WRONLY) {
+ CDEBUG(D_CACHE, "presto_file_open: calling presto_get_permit\n");
+ /* lock needed to protect permit_count manipulations -SHP */
+ if ( presto_get_permit(inode) < 0 ) {
+ EXIT;
+ return -EROFS;
+ }
+ presto_put_permit(inode);
+ }
+
+ /* XXX name space synchronization here for data/streaming on demand?*/
+ /* XXX Lento can make us wait here for backfetches to complete */
+#if 0
+ if ( !presto_chk(file->f_dentry, PRESTO_DATA) ||
+ !presto_has_all_data(file->f_dentry->d_inode) ) {
+ CDEBUG(D_CACHE, "presto_file_open: presto_open_upcall\n");
+ rc = presto_open_upcall(minor, file->f_dentry);
+ }
+
+#endif
+ rc = 0;
+ cache:
+ fops = filter_c2cffops(cache->cache_filter);
+ if ( fops->open ) {
+ CDEBUG(D_CACHE, "presto_file_open: calling fs open\n");
+ rc = fops->open(inode, file);
+ }
+ if (rc) {
+ EXIT;
+ return rc;
+ }
+
+ CDEBUG(D_CACHE, "presto_file_open: setting DATA, ATTR\n");
+ if( ISLENTO(minor) )
+ presto_set(file->f_dentry, PRESTO_ATTR );
+ else
+ presto_set(file->f_dentry, PRESTO_ATTR | PRESTO_DATA);
+
+ if (writable) {
+ PRESTO_ALLOC(fdata, struct presto_file_data *, sizeof(*fdata));
+ if (!fdata) {
+ EXIT;
+ return -ENOMEM;
+ }
+ /* we believe that on open the kernel lock
+ assures that only one process will do this allocation */
+ fdata->fd_do_lml = 0;
+ fdata->fd_fsuid = current->fsuid;
+ fdata->fd_fsgid = current->fsgid;
+ fdata->fd_mode = file->f_dentry->d_inode->i_mode;
+ fdata->fd_ngroups = current->ngroups;
+ for (i=0 ; i<current->ngroups ; i++)
+ fdata->fd_groups[i] = current->groups[i];
+ fdata->fd_bytes_written = 0; /*when open,written data is zero*/
+ file->private_data = fdata;
+ } else {
+ file->private_data = NULL;
+ }
+


+ return 0;
+}
+

+static int presto_file_release(struct inode *inode, struct file *file)
+{
+ struct rec_info rec;
+ int rc;
+ int writable = (file->f_flags & (O_RDWR | O_WRONLY));
+ struct file_operations *fops;
+ struct presto_cache *cache;
+ struct presto_file_set *fset;
+ void *handle;
+ struct presto_file_data *fdata =
+ (struct presto_file_data *)file->private_data;
+
+ ENTRY;
+ rc = presto_prep(file->f_dentry, &cache, &fset);
+ if ( rc ) {
+ EXIT;
+ return rc;
+ }
+
+ fops = filter_c2cffops(cache->cache_filter);
+ rc = fops->release(inode, file);
+
+ CDEBUG(D_CACHE, "islento = %d (minor %d), writable = %d, rc %d, data %p\n",
+ ISLENTO(cache->cache_psdev->uc_minor),
+ cache->cache_psdev->uc_minor,
+ writable, rc, fdata);
+
+ if (fdata && fdata->fd_do_lml) {
+ CDEBUG(D_CACHE, "LML at %lld\n", fdata->fd_lml_offset);
+ }
+
+ /* don't journal close if file couldn't have been written to */
+ /* if (!ISLENTO(cache->cache_prestominor) && !rc && writable) {*/
+ if (fdata && fdata->fd_do_lml &&
+ !rc && writable && (! ISLENTO(cache->cache_psdev->uc_minor))) {
+ struct presto_version new_ver;
+
+ presto_getversion(&new_ver, inode);
+
+ /* XXX: remove when lento gets file granularity cd */
+ /* Lock needed to protect permit_count manipulations -SHP */
+ if ( presto_get_permit(inode) < 0 ) {
+ EXIT;
+ return -EROFS;
+ }
+ CDEBUG(D_CACHE, "presto_file_release: writing journal\n");
+
+ rc = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);
+ if (rc) {
+ presto_put_permit(inode);
+ EXIT;
+ return rc;
+ }
+ handle = presto_trans_start(fset, file->f_dentry->d_inode,
+ PRESTO_OP_RELEASE);
+ if ( IS_ERR(handle) ) {
+ printk("presto_release: no space for transaction\n");
+ presto_put_permit(inode);
+ return -ENOSPC;
+ }
+ rc = presto_journal_close(&rec, fset, file, file->f_dentry,
+ &new_ver);
+ if (rc) {
+ printk("presto_close: cannot journal close\n");
+ /* XXX oops here to get this bug */
+ *(int *)0 = 1;
+ presto_put_permit(inode);
+ return -ENOSPC;
+ }
+ presto_trans_commit(fset, handle);
+
+ /* cancel the LML record */
+ handle = presto_trans_start
+ (fset, inode, PRESTO_OP_WRITE);
+ if ( IS_ERR(handle) ) {
+ printk("presto_release: no space for clear\n");
+ presto_put_permit(inode);
+ return -ENOSPC;
+ }
+ rc = presto_clear_lml_close(fset,
+ fdata->fd_lml_offset);
+ if (rc < 0 ) {
+ /* XXX oops here to get this bug */
+ *(int *)0 = 1;
+ presto_put_permit(inode);
+ printk("presto_close: cannot journal close\n");
+ return -ENOSPC;
+ }
+ presto_trans_commit(fset, handle);
+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
+
+ presto_truncate_lml(fset);
+
+ presto_put_permit(inode);
+ }
+
+ if (!rc && fdata) {
+ PRESTO_FREE(fdata, sizeof(*fdata));
+ }
+ file->private_data = NULL;
+
+ EXIT;
+ return rc;
+}
+
+
+
+static void presto_apply_write_policy(struct file *file, struct presto_file_set *fset, loff_t res)
+{
+ struct presto_file_data *fdata = (struct presto_file_data *)file->private_data;
+ struct presto_cache *cache = fset->fset_cache;
+ struct presto_version new_file_ver;
+ int error;
+ struct rec_info rec;
+
+ /* Here we do a journal close after a fixed or a specified
+ amount of KBytes, currently a global parameter set with
+ sysctl. If files are open for a long time, this gives added
+ protection. (XXX todo: per cache, add ioctl, handle
+ journaling in a thread, add more options etc.)
+ */
+
+ if ( (fset->fset_flags & FSET_JCLOSE_ON_WRITE)
+ && (!ISLENTO(cache->cache_psdev->uc_minor))) {
+ fdata->fd_bytes_written += res;
+
+ if (fdata->fd_bytes_written >= fset->fset_file_maxio) {
+ presto_getversion(&new_file_ver, file->f_dentry->d_inode);
+ /* This is really heavy weight and should be fixed
+ ASAP. At most we should be recording the number
+ of bytes written and not locking the kernel,
+ wait for permits, etc, on the write path. SHP
+ */
+ lock_kernel();
+ if ( presto_get_permit(file->f_dentry->d_inode) < 0 ) {
+ EXIT;
+ /* we must be disconnected, not to worry */
+ return;
+ }
+ error = presto_journal_close
+ (&rec, fset, file, file->f_dentry, &new_file_ver);
+ presto_put_permit(file->f_dentry->d_inode);
+ unlock_kernel();
+ if ( error ) {
+ printk("presto_close: cannot journal close\n");
+ /* XXX these errors are really bad */
+ /* panic(); */
+ return;
+ }
+ fdata->fd_bytes_written = 0;
+ }
+ }
+}
+
+static ssize_t presto_file_write(struct file *file, const char *buf, size_t size,
+ loff_t *off)
+{
+ struct rec_info rec;
+ int error;
+ struct presto_cache *cache;
+ struct presto_file_set *fset;
+ struct file_operations *fops;
+ ssize_t res;
+ int do_lml_here;
+ void *handle = NULL;
+ unsigned long blocks;
+ struct presto_file_data *fdata;
+ loff_t res_size;
+
+ error = presto_prep(file->f_dentry, &cache, &fset);
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ blocks = (size >> file->f_dentry->d_inode->i_sb->s_blocksize_bits) + 1;
+ /* XXX 3 is for ext2 indirect blocks ... */
+ res_size = 2 * PRESTO_REQHIGH + ((blocks+3)
+ << file->f_dentry->d_inode->i_sb->s_blocksize_bits);
+
+ error = presto_reserve_space(fset->fset_cache, res_size);
+ CDEBUG(D_INODE, "Reserved %Ld for %d\n", res_size, size);
+ if ( error ) {
+ EXIT;
+ return -ENOSPC;
+ }
+
+ /* XXX lock something here */
+ CDEBUG(D_INODE, "islento %d, minor: %d\n", ISLENTO(cache->cache_psdev->uc_minor),
+ cache->cache_psdev->uc_minor);
+ read_lock(&fset->fset_lml.fd_lock);
+ fdata = (struct presto_file_data *)file->private_data;
+ do_lml_here = (!ISLENTO(cache->cache_psdev->uc_minor)) &&
+ size && (fdata->fd_do_lml == 0);
+
+ if (do_lml_here)
+ fdata->fd_do_lml = 1;
+ read_unlock(&fset->fset_lml.fd_lock);
+
+ /* XXX we have two choices:
+ - we do the transaction for the LML record BEFORE any write
+ transaction starts - that has the benefit that no other
+ short write can complete without the record being there.
+ The disadvantage is that even if no write happens we get
+ the LML record.
+ - we bundle the transaction with this write. In that case
+ we may not have an LML record is a short write goes through
+ before this one (can that actually happen?).
+ */
+ res = 0;
+ if (do_lml_here) {
+ /* handle different space reqs from file system below! */
+ handle = presto_trans_start(fset, file->f_dentry->d_inode,
+ PRESTO_OP_WRITE);
+ if ( IS_ERR(handle) ) {
+ presto_release_space(fset->fset_cache, res_size);
+ printk("presto_write: no space for transaction\n");
+ return -ENOSPC;
+ }
+ res = presto_journal_write(&rec, fset, file);
+ fdata->fd_lml_offset = rec.offset;
+ if ( res ) {
+ /* XXX oops here to get this bug */
+ /* *(int *)0 = 1; */
+ EXIT;
+ goto exit_write;
+ }
+
+ presto_trans_commit(fset, handle);
+ }
+
+ fops = filter_c2cffops(cache->cache_filter);
+ res = fops->write(file, buf, size, off);
+ if ( res != size ) {
+ CDEBUG(D_FILE, "file write returns short write: size %d, res %d\n", size, res);
+ }
+
+ if ( (res > 0) && fdata )
+ presto_apply_write_policy(file, fset, res);
+
+ exit_write:
+ presto_release_space(fset->fset_cache, res_size);

+ return res;
+}
+

+struct file_operations presto_file_fops = {
+ write: presto_file_write,
+ open: presto_file_open,
+ release: presto_file_release
+};
+
+struct inode_operations presto_file_iops = {
+ permission: presto_permission,
+ setattr: presto_setattr,
+#ifdef CONFIG_FS_EXT_ATTR
+ set_ext_attr: presto_set_ext_attr,
+#endif
+};
+
+
+
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/inode.c linux/fs/intermezzo/inode.c
--- v2.4.14/linux/fs/intermezzo/inode.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/inode.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,166 @@
+/*
+ * Super block/filesystem wide operations
+ *
+ * Copryright (C) 1996 Peter J. Braam <br...@maths.ox.ac.uk> and
+ * Michael Callahan <call...@maths.ox.ac.uk>
+ *
+ * Rewritten for Linux 2.1. Peter Braam <br...@cs.cmu.edu>
+ * Copyright (C) Carnegie Mellon University


+ */
+
+#define __NO_VERSION__
+#include <linux/module.h>

+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>


+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/locks.h>

+#include <linux/unistd.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+


+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/locks.h>

+#include <linux/string.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/segment.h>


+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+

+extern int presto_remount(struct super_block *, int *, char *);
+
+int presto_excluded_gid = PRESTO_EXCL_GID;
+
+extern int presto_prep(struct dentry *, struct presto_cache **,
+ struct presto_file_set **);
+extern void presto_free_cache(struct presto_cache *);
+
+
+void presto_set_ops(struct inode *inode, struct filter_fs *filter)
+{
+ ENTRY;
+ if (inode->i_gid == presto_excluded_gid ) {
+ EXIT;
+ CDEBUG(D_INODE, "excluded methods for %ld at %p, %p\n",
+ inode->i_ino, inode->i_op, inode->i_fop);
+ return;
+ }
+ if (S_ISREG(inode->i_mode)) {
+ if ( !filter_c2cfiops(filter) ) {
+ filter_setup_file_ops(filter,
+ inode, &presto_file_iops,
+ &presto_file_fops);
+ }
+ inode->i_op = filter_c2ufiops(filter);
+ inode->i_fop = filter_c2uffops(filter);
+ CDEBUG(D_INODE, "set file methods for %ld to %p\n",
+ inode->i_ino, inode->i_op);


+ } else if (S_ISDIR(inode->i_mode)) {

+ inode->i_op = filter_c2udiops(filter);
+ inode->i_fop = filter_c2udfops(filter);
+ CDEBUG(D_INODE, "set dir methods for %ld to %p lookup %p\n",
+ inode->i_ino, inode->i_op, inode->i_op->lookup);


+ } else if (S_ISLNK(inode->i_mode)) {

+ if ( !filter_c2csiops(filter)) {
+ filter_setup_symlink_ops(filter,
+ inode,
+ &presto_sym_iops,
+ &presto_sym_fops);
+ }
+ inode->i_op = filter_c2usiops(filter);
+ inode->i_fop = filter_c2usfops(filter);
+ CDEBUG(D_INODE, "set link methods for %ld to %p\n",
+ inode->i_ino, inode->i_op);
+ }
+ EXIT;
+}
+
+void presto_read_inode(struct inode *inode)


+{
+ struct presto_cache *cache;
+

+ cache = presto_get_cache(inode);
+ if ( !cache ) {

+ printk("PRESTO: BAD, BAD: cannot find cache\n");
+ make_bad_inode(inode);
+ return ;
+ }
+
+ filter_c2csops(cache->cache_filter)->read_inode(inode);
+
+ CDEBUG(D_INODE, "presto_read_inode: ino %ld, gid %d\n",
+ inode->i_ino, inode->i_gid);
+
+ // if (inode->i_gid == presto_excluded_gid)
+ // return;
+
+ presto_set_ops(inode, cache->cache_filter);
+ /* XXX handle special inodes here or not - probably not? */
+}
+
+void presto_put_super(struct super_block *sb)


+{
+ struct presto_cache *cache;

+ struct upc_comm *psdev;
+ struct super_operations *sops;
+ struct list_head *lh;
+
+ ENTRY;
+ cache = presto_find_cache(sb->s_dev);
+ if (!cache) {
+ EXIT;
+ goto exit;
+ }
+ psdev = &upc_comms[presto_c2m(cache)];
+
+ sops = filter_c2csops(cache->cache_filter);
+ if (sops->put_super)
+ sops->put_super(sb);
+
+ /* free any remaining async upcalls when the filesystem is unmounted */
+ lh = psdev->uc_pending.next;
+ while ( lh != &psdev->uc_pending) {
+ struct upc_req *req;
+ req = list_entry(lh, struct upc_req, rq_chain);
+
+ /* assignment must be here: we are about to free &lh */
+ lh = lh->next;
+ if ( ! (req->rq_flags & REQ_ASYNC) )
+ continue;
+ list_del(&(req->rq_chain));
+ PRESTO_FREE(req->rq_data, req->rq_bufsize);
+ PRESTO_FREE(req, sizeof(struct upc_req));
+ }
+
+ presto_free_cache(cache);
+
+exit:
+ CDEBUG(D_MALLOC, "after umount: kmem %ld, vmem %ld\n",
+ presto_kmemory, presto_vmemory);
+ MOD_DEC_USE_COUNT;


+ return ;
+}
+
+

+/* symlinks can be chowned */
+struct inode_operations presto_sym_iops = {
+ setattr: presto_setattr
+};
+
+/* NULL for now */
+struct file_operations presto_sym_fops;
+
+struct super_operations presto_super_ops = {
+ read_inode: presto_read_inode,
+ put_super: presto_put_super,
+ remount_fs: presto_remount
+};
+MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/journal.c linux/fs/intermezzo/journal.c
--- v2.4.14/linux/fs/intermezzo/journal.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/journal.c Tue Nov 13 09:20:56 2001
@@ -0,0 +1,2059 @@
+/*
+ * Intermezzo. (C) 1998 Peter J. Braam
+ *
+ * Support for journalling extended attributes
+ * (C) 2001 Shirish H. Phatak, Tacit Networks, Inc.
+ */
+
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/time.h>
+#include <linux/errno.h>
+#include <linux/locks.h>


+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/string.h>

+#include <linux/smp_lock.h>


+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>

+#include <linux/intermezzo_kml.h>
+
+static int presto_log(struct presto_file_set *fset, struct rec_info *rec,
+ const char *buf, size_t size,
+ const char *string1, int len1,
+ const char *string2, int len2,
+ const char *string3, int len3);
+
+/*
+ * reserve record space and/or atomically request state of the log
+ * rec will hold the location reserved record upon return
+ * this reservation will be placed in the queue
+ */
+static void presto_reserve_record(struct presto_file_set *fset,
+ struct presto_log_fd *fd,
+ struct rec_info *rec,
+ struct presto_reservation_data *rd)
+{
+ int chunked_record = 0;
+ ENTRY;
+
+ write_lock(&fd->fd_lock);
+ if ( rec->is_kml ) {
+ int chunk = 1 << fset->fset_chunkbits;
+ int chunk_mask = ~(chunk -1);
+ loff_t boundary;
+
+ boundary = (fd->fd_offset + chunk - 1) & chunk_mask;
+ if ( fd->fd_offset + rec->size >= boundary ) {
+ chunked_record = 1;
+ fd->fd_offset = boundary;
+ }
+ }
+
+ fd->fd_recno++;
+
+ /* this move the fd_offset back after truncation */
+ if ( list_empty(&fd->fd_reservations) &&
+ !chunked_record) {
+ fd->fd_offset = fd->fd_file->f_dentry->d_inode->i_size;
+ }
+
+ rec->offset = fd->fd_offset;
+ rec->recno = fd->fd_recno;
+
+ fd->fd_offset += rec->size;
+
+ /* add the reservation data to the end of the list */
+ list_add(&rd->ri_list, fd->fd_reservations.prev);
+ rd->ri_offset = rec->offset;
+ rd->ri_size = rec->size;
+ rd->ri_recno = rec->recno;
+
+ write_unlock(&fd->fd_lock);
+
+ EXIT;
+}
+
+static inline void presto_release_record(struct presto_log_fd *fd,
+ struct presto_reservation_data *rd)
+{
+ write_lock(&fd->fd_lock);
+ list_del(&rd->ri_list);
+ write_unlock(&fd->fd_lock);
+}
+
+static int presto_do_truncate(struct presto_file_set *fset,
+ struct dentry *dentry, loff_t length,
+ loff_t size_check)
+{
+ struct inode *inode = dentry->d_inode;
+ struct inode_operations *op;
+ int error;
+ struct iattr newattrs;
+
+ ENTRY;
+
+ /* Not pretty: "inode->i_size" shouldn't really be "loff_t". */
+ if ((off_t) length < 0)


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

echo 'End of part 091'
echo 'File patch-2.4.15 is continued in part 092'
echo "092" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:10 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part094

#!/bin/sh -x
# this is part 094 of a 115 - part archive


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

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

+ EXIT;
+ return 0;
+}
+

+static int unpack_mkdir (struct kml_mkdir *rec, char *buf,
+ int pos, int *rec_offs)
+{
+ char *p, *q;
+ int unpack_size = 88;
+ int pathlen;
+
+ ENTRY;
+ p = buf + pos;
+ p = dlogit (&rec->old_parentv, p, sizeof (struct presto_version));
+ p = dlogit (&rec->new_parentv, p, sizeof (struct presto_version));
+ p = dlogit (&rec->new_objectv, p, sizeof (struct presto_version));
+ p = dlogit (&rec->mode, p, sizeof (int));
+ p = dlogit (&rec->uid, p, sizeof (int));
+ p = dlogit (&rec->gid, p, sizeof (int));
+ p = dlogit (&pathlen, p, sizeof (int));
+
+ PRESTO_ALLOC(q, char *, pathlen + 1);
+ if (q == NULL) {


+ EXIT;
+ return -ENOMEM;
+ }
+

+ memcpy (q, p, pathlen);
+ q[pathlen] = '\0';
+ rec->path = q;
+ p += pathlen;
+
+ *rec_offs = pos + unpack_size + size_round(pathlen);


+ EXIT;
+ return 0;
+}
+

+#if 0
+static int unpack_endmark (struct kml_endmark *rec, char *buf,
+ int pos, int *rec_offs)
+{
+ char *p;
+ p = buf + pos;
+ p = dlogit (&rec->total, p, sizeof (int));
+
+ PRESTO_ALLOC (rec->kop, struct kml_kop_node *,
+ sizeof (struct kml_kop_node) * rec->total);
+ if (rec->kop == NULL) {


+ EXIT;
+ return -ENOMEM;
+ }
+

+ p = dlogit (rec->kop, p, sizeof (struct kml_kop_node) * rec->total);
+
+ *rec_offs = pos + sizeof (int) + sizeof (struct kml_kop_node) * rec->total;


+ return 0;
+}
+#endif

+
+static char *kml_version (struct presto_version *ver)
+{
+ static char buf[256];
+ sprintf (buf, "mt::%lld, ct::%lld, size::%lld",
+ ver->pv_mtime, ver->pv_ctime, ver->pv_size);
+ return buf;
+}
+
+static void print_kml_prefix (struct big_journal_prefix *head)
+{
+ int i;
+
+ CDEBUG (D_KML, " === KML PREFIX\n");
+ CDEBUG (D_KML, " len = %u\n", head->len);
+ CDEBUG (D_KML, " version = %u\n", head->version);
+ CDEBUG (D_KML, " pid = %u\n", head->pid);
+ CDEBUG (D_KML, " uid = %u\n", head->uid);
+ CDEBUG (D_KML, " fsuid = %u\n", head->fsuid);
+ CDEBUG (D_KML, " fsgid = %u\n", head->fsgid);
+ CDEBUG (D_KML, " opcode = %u\n", head->opcode);
+ CDEBUG (D_KML, " ngroup = %u", head->ngroups);
+ for (i = 0; i < head->ngroups; i++)
+ CDEBUG (D_KML, "%u ", head->groups[i]);
+ CDEBUG (D_KML, "\n");
+}
+
+static void print_kml_create (struct kml_create *rec)
+{
+ CDEBUG (D_KML, " === CREATE\n");
+ CDEBUG (D_KML, " path::%s\n", rec->path);
+ CDEBUG (D_KML, " new_objv::%s\n", kml_version (&rec->new_objectv));
+ CDEBUG (D_KML, " old_parv::%s\n", kml_version (&rec->old_parentv));
+ CDEBUG (D_KML, " new_parv::%s\n", kml_version (&rec->new_parentv));
+ CDEBUG (D_KML, " mode::%o\n", rec->mode);
+ CDEBUG (D_KML, " uid::%d\n", rec->uid);
+ CDEBUG (D_KML, " gid::%d\n", rec->gid);
+}
+
+static void print_kml_mkdir (struct kml_mkdir *rec)
+{
+ CDEBUG (D_KML, " === MKDIR\n");
+ CDEBUG (D_KML, " path::%s\n", rec->path);
+ CDEBUG (D_KML, " new_objv::%s\n", kml_version (&rec->new_objectv));
+ CDEBUG (D_KML, " old_parv::%s\n", kml_version (&rec->old_parentv));
+ CDEBUG (D_KML, " new_parv::%s\n", kml_version (&rec->new_parentv));
+ CDEBUG (D_KML, " mode::%o\n", rec->mode);
+ CDEBUG (D_KML, " uid::%d\n", rec->uid);
+ CDEBUG (D_KML, " gid::%d\n", rec->gid);
+}
+
+static void print_kml_unlink (struct kml_unlink *rec)
+{
+ CDEBUG (D_KML, " === UNLINK\n");
+ CDEBUG (D_KML, " path::%s/%s\n", rec->path, rec->name);
+ CDEBUG (D_KML, " old_tgtv::%s\n", kml_version (&rec->old_tgtv));
+ CDEBUG (D_KML, " old_parv::%s\n", kml_version (&rec->old_parentv));
+ CDEBUG (D_KML, " new_parv::%s\n", kml_version (&rec->new_parentv));
+}
+
+static void print_kml_rmdir (struct kml_rmdir *rec)
+{
+ CDEBUG (D_KML, " === RMDIR\n");
+ CDEBUG (D_KML, " path::%s/%s\n", rec->path, rec->name);
+ CDEBUG (D_KML, " old_tgtv::%s\n", kml_version (&rec->old_tgtv));
+ CDEBUG (D_KML, " old_parv::%s\n", kml_version (&rec->old_parentv));
+ CDEBUG (D_KML, " new_parv::%s\n", kml_version (&rec->new_parentv));
+}
+
+static void print_kml_close (struct kml_close *rec)
+{
+ CDEBUG (D_KML, " === CLOSE\n");
+ CDEBUG (D_KML, " mode::%o\n", rec->open_mode);
+ CDEBUG (D_KML, " uid::%d\n", rec->open_uid);
+ CDEBUG (D_KML, " gid::%d\n", rec->open_gid);
+ CDEBUG (D_KML, " path::%s\n", rec->path);
+ CDEBUG (D_KML, " new_objv::%s\n", kml_version (&rec->new_objectv));
+ CDEBUG (D_KML, " ino::%lld\n", rec->ino);
+ CDEBUG (D_KML, " gen::%u\n", rec->generation);
+}
+
+static void print_kml_symlink (struct kml_symlink *rec)
+{
+ CDEBUG (D_KML, " === SYMLINK\n");
+ CDEBUG (D_KML, " s-path::%s\n", rec->sourcepath);
+ CDEBUG (D_KML, " t-path::%s\n", rec->targetpath);
+ CDEBUG (D_KML, " old_parv::%s\n", kml_version (&rec->old_parentv));
+ CDEBUG (D_KML, " new_parv::%s\n", kml_version (&rec->new_parentv));
+ CDEBUG (D_KML, " new_objv::%s\n", kml_version (&rec->new_objectv));
+ CDEBUG (D_KML, " uid::%d\n", rec->uid);
+ CDEBUG (D_KML, " gid::%d\n", rec->gid);
+}
+
+static void print_kml_rename (struct kml_rename *rec)
+{
+ CDEBUG (D_KML, " === RENAME\n");
+ CDEBUG (D_KML, " s-path::%s\n", rec->sourcepath);
+ CDEBUG (D_KML, " t-path::%s\n", rec->targetpath);
+ CDEBUG (D_KML, " old_tgtv::%s\n", kml_version (&rec->old_tgtv));
+ CDEBUG (D_KML, " new_tgtv::%s\n", kml_version (&rec->new_tgtv));
+ CDEBUG (D_KML, " new_objv::%s\n", kml_version (&rec->new_objectv));
+ CDEBUG (D_KML, " old_objv::%s\n", kml_version (&rec->old_objectv));
+}
+
+static void print_kml_setattr (struct kml_setattr *rec)
+{
+ CDEBUG (D_KML, " === SETATTR\n");
+ CDEBUG (D_KML, " path::%s\n", rec->path);
+ CDEBUG (D_KML, " old_objv::%s\n", kml_version (&rec->old_objectv));
+ CDEBUG (D_KML, " valid::0x%x\n", rec->iattr.ia_valid);
+ CDEBUG (D_KML, " mode::%o\n", rec->iattr.ia_mode);
+ CDEBUG (D_KML, " uid::%d\n", rec->iattr.ia_uid);
+ CDEBUG (D_KML, " gid::%d\n", rec->iattr.ia_gid);
+ CDEBUG (D_KML, " size::%u\n", (u32) rec->iattr.ia_size);
+ CDEBUG (D_KML, " mtime::%u\n", (u32) rec->iattr.ia_mtime);
+ CDEBUG (D_KML, " ctime::%u\n", (u32) rec->iattr.ia_ctime);
+ CDEBUG (D_KML, " flags::%u\n", (u32) rec->iattr.ia_attr_flags);
+}
+
+static void print_kml_link (struct kml_link *rec)
+{
+ CDEBUG (D_KML, " === LINK\n");
+ CDEBUG (D_KML, " path::%s ==> %s\n", rec->sourcepath, rec->targetpath);
+ CDEBUG (D_KML, " old_parv::%s\n", kml_version (&rec->old_parentv));
+ CDEBUG (D_KML, " new_obj::%s\n", kml_version (&rec->new_objectv));
+ CDEBUG (D_KML, " new_parv::%s\n", kml_version (&rec->new_parentv));
+}
+
+static void print_kml_mknod (struct kml_mknod *rec)
+{
+ CDEBUG (D_KML, " === MKNOD\n");
+ CDEBUG (D_KML, " path::%s\n", rec->path);
+ CDEBUG (D_KML, " new_obj::%s\n", kml_version (&rec->new_objectv));
+ CDEBUG (D_KML, " old_parv::%s\n", kml_version (&rec->old_parentv));
+ CDEBUG (D_KML, " new_parv::%s\n", kml_version (&rec->new_parentv));
+ CDEBUG (D_KML, " mode::%o\n", rec->mode);
+ CDEBUG (D_KML, " uid::%d\n", rec->uid);
+ CDEBUG (D_KML, " gid::%d\n", rec->gid);
+ CDEBUG (D_KML, " major::%d\n", rec->major);
+ CDEBUG (D_KML, " minor::%d\n", rec->minor);
+}
+
+static void print_kml_open (struct kml_open *rec)
+{
+ CDEBUG (D_KML, " === OPEN\n");
+}
+
+#if 0
+static void print_kml_endmark (struct kml_endmark *rec)
+{
+ int i;
+ CDEBUG (D_KML, " === ENDMARK\n");
+ CDEBUG (D_KML, " total::%u\n", rec->total);
+ for (i = 0; i < rec->total; i++)
+ {
+ CDEBUG (D_KML, " recno=%ld::flag=%ld,op=%ld, i_ino=%ld, \
+ i_nlink=%ld\n", (long) rec->kop[i].kml_recno,
+ (long) rec->kop[i].kml_flag, (long) rec->kop[i].kml_op,
+ (long) rec->kop[i].i_ino, (long) rec->kop[i].i_nlink);
+ }
+}
+#endif
+
+static void print_kml_optimize (struct kml_optimize *rec)
+{
+ CDEBUG (D_KML, " === OPTIMIZE\n");
+ if (rec->kml_flag == KML_REC_DELETE)
+ CDEBUG (D_KML, " kml_flag::deleted\n");
+ else
+ CDEBUG (D_KML, " kml_flag::exist\n");
+ CDEBUG (D_KML, " kml_op::%u\n", rec->kml_op);
+ CDEBUG (D_KML, " i_nlink::%d\n", rec->i_nlink);
+ CDEBUG (D_KML, " i_ino::%u\n", rec->i_ino);
+}
+
+static void print_kml_suffix (struct journal_suffix *tail)
+{
+ CDEBUG (D_KML, " === KML SUFFIX\n");
+ CDEBUG (D_KML, " prevrec::%ld\n", tail->prevrec);
+ CDEBUG (D_KML, " recno::%ld\n", (long) tail->recno);
+ CDEBUG (D_KML, " time::%d\n", tail->time);
+ CDEBUG (D_KML, " len::%d\n", tail->len);
+}
+
+void kml_printrec (struct kml_rec *rec, int kml_printop)
+{
+ if (kml_printop & PRINT_KML_PREFIX)
+ print_kml_prefix (&rec->rec_head);
+ if (kml_printop & PRINT_KML_REC)
+ {
+ switch (rec->rec_head.opcode)
+ {
+ case KML_CREATE:
+ print_kml_create (&rec->rec_kml.create);
+ break;
+ case KML_MKDIR:
+ print_kml_mkdir (&rec->rec_kml.mkdir);
+ break;
+ case KML_UNLINK:
+ print_kml_unlink (&rec->rec_kml.unlink);
+ break;
+ case KML_RMDIR:
+ print_kml_rmdir (&rec->rec_kml.rmdir);
+ break;
+ case KML_CLOSE:
+ print_kml_close (&rec->rec_kml.close);
+ break;
+ case KML_SYMLINK:
+ print_kml_symlink (&rec->rec_kml.symlink);
+ break;
+ case KML_RENAME:
+ print_kml_rename (&rec->rec_kml.rename);
+ break;
+ case KML_SETATTR:
+ print_kml_setattr (&rec->rec_kml.setattr);
+ break;
+ case KML_LINK:
+ print_kml_link (&rec->rec_kml.link);
+ break;
+ case KML_OPEN:
+ print_kml_open (&rec->rec_kml.open);
+ break;
+ case KML_MKNOD:
+ print_kml_mknod (&rec->rec_kml.mknod);
+ break;
+#if 0
+ case KML_ENDMARK:
+ print_kml_endmark (&rec->rec_kml.endmark);
+#endif
+ break;
+ default:
+ CDEBUG (D_KML, " === BAD RECORD, opcode=%u\n",
+ rec->rec_head.opcode);
+ break;
+ }
+ }
+ if (kml_printop & PRINT_KML_SUFFIX)
+ print_kml_suffix (&rec->rec_tail);
+ if (kml_printop & PRINT_KML_OPTIMIZE)
+ print_kml_optimize (&rec->kml_optimize);
+}
+
+void kml_freerec (struct kml_rec *rec)
+{
+ char *sourcepath = NULL,
+ *targetpath = NULL;
+ switch (rec->rec_head.opcode)
+ {
+ case KML_CREATE:
+ sourcepath = rec->rec_kml.create.path;
+ break;
+ case KML_MKDIR:
+ sourcepath = rec->rec_kml.create.path;
+ break;
+ case KML_UNLINK:
+ sourcepath = rec->rec_kml.unlink.path;
+ targetpath = rec->rec_kml.unlink.name;
+ break;
+ case KML_RMDIR:
+ sourcepath = rec->rec_kml.rmdir.path;
+ targetpath = rec->rec_kml.rmdir.name;
+ break;
+ case KML_CLOSE:
+ sourcepath = rec->rec_kml.close.path;
+ break;
+ case KML_SYMLINK:
+ sourcepath = rec->rec_kml.symlink.sourcepath;
+ targetpath = rec->rec_kml.symlink.targetpath;
+ break;
+ case KML_RENAME:
+ sourcepath = rec->rec_kml.rename.sourcepath;
+ targetpath = rec->rec_kml.rename.targetpath;
+ break;
+ case KML_SETATTR:
+ sourcepath = rec->rec_kml.setattr.path;
+ break;
+ case KML_LINK:
+ sourcepath = rec->rec_kml.link.sourcepath;
+ targetpath = rec->rec_kml.link.targetpath;
+ break;
+ case KML_OPEN:
+ break;
+ case KML_MKNOD:
+ sourcepath = rec->rec_kml.mknod.path;
+ break;
+#if 0
+ case KML_ENDMARK:
+ PRESTO_FREE (rec->rec_kml.endmark.kop, sizeof (int) +
+ sizeof (struct kml_kop_node) *
+ rec->rec_kml.endmark.total);
+#endif
+ break;


+ default:
+ break;
+ }

+ if (sourcepath != NULL)
+ PRESTO_FREE (sourcepath, strlen (sourcepath) + 1);
+ if (targetpath != NULL)
+ PRESTO_FREE (targetpath, strlen (targetpath) + 1);
+}
+
+char *readrec (char *recbuf, int reclen, int pos, int *size)
+{
+ char *p = recbuf + pos;
+ *size = *((int *) p);
+ if (*size > (reclen - pos))
+ return NULL;


+ return p;
+}
+

+int kml_decoderec (char *buf, int pos, int buflen, int *size,
+ struct kml_rec **newrec)
+{
+ char *tmp;
+ int error;
+ tmp = readrec (buf, buflen, pos, size);
+ if (tmp == NULL)
+ return -EBADF;
+ error = kml_unpack (tmp, *size, pos, newrec);

+ return error;
+}
+

+#if 0
+static void fill_kmlrec_optimize (struct list_head *head,
+ struct kml_rec *optrec)
+{
+ struct kml_rec *kmlrec;
+ struct list_head *tmp;
+ struct kml_endmark *km;
+ struct kml_optimize *ko;
+ int n;
+
+ if (optrec->rec_kml.endmark.total == 0)
+ return;
+ n = optrec->rec_kml.endmark.total - 1;
+ tmp = head->prev;
+ km = &optrec->rec_kml.endmark;
+ while ( n >= 0 && tmp != head )
+ {
+ kmlrec = list_entry(tmp, struct kml_rec,
+ kml_optimize.kml_chains);
+ tmp = tmp->prev;
+ if (kmlrec->rec_tail.recno == km->kop[n].kml_recno)
+ {
+ ko = &kmlrec->kml_optimize;
+ ko->kml_flag = km->kop[n].kml_flag;
+ ko->kml_op = km->kop[n].kml_op;
+ ko->i_nlink = km->kop[n].i_nlink;
+ ko->i_ino = km->kop[n].i_ino;
+ n --;
+ }
+ }
+ if (n != -1)
+ CDEBUG (D_KML, "Yeah!!!, KML optimize error, recno=%d, n=%d\n",
+ optrec->rec_tail.recno, n);
+}
+#endif
+
+int decode_kmlrec (struct list_head *head, char *kml_buf, int buflen)
+{
+ struct kml_rec *rec;
+ int pos = 0, size;
+ int err;
+ while (pos < buflen) {
+ err = kml_decoderec (kml_buf, pos, buflen, &size, &rec);
+ if (err != 0)
+ break;
+#if 0
+ if (rec->rec_head.opcode == KML_ENDMARK) {
+ fill_kmlrec_optimize (head, rec);
+ mark_rec_deleted (rec);
+ }
+#endif
+ list_add_tail (&rec->kml_optimize.kml_chains, head);
+ pos += size;
+ }


+ return err;
+}
+

+int delete_kmlrec (struct list_head *head)
+{
+ struct kml_rec *rec;
+ struct list_head *tmp;
+
+ if (list_empty(head))
+ return 0;
+ tmp = head->next;
+ while ( tmp != head ) {
+ rec = list_entry(tmp, struct kml_rec,
+ kml_optimize.kml_chains);
+ tmp = tmp->next;
+ kml_freerec (rec);
+ }
+ INIT_LIST_HEAD(head);


+ return 0;
+}
+

+int print_allkmlrec (struct list_head *head, int printop)
+{
+ struct kml_rec *rec;
+ struct list_head *tmp;
+
+ if (list_empty(head))
+ return 0;
+ tmp = head->next;
+ while ( tmp != head ) {
+ rec = list_entry(tmp, struct kml_rec,
+ kml_optimize.kml_chains);
+ tmp = tmp->next;
+#if 0
+ if (printop & PRINT_KML_EXIST) {
+ if (is_deleted_node (rec))
+ continue;
+ }
+ else if (printop & PRINT_KML_DELETE) {
+ if (! is_deleted_node (rec))
+ continue;
+ }
+#endif
+ kml_printrec (rec, printop);
+ }
+ INIT_LIST_HEAD(head);


+ return 0;
+}
+

diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/kml_reint.c linux/fs/intermezzo/kml_reint.c
--- v2.4.14/linux/fs/intermezzo/kml_reint.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/kml_reint.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,411 @@
+/*
+ * KML REINT
+ *
+ * Copryright (C) 1996 Arthur Ma <arth...@mountainviewdata.com>
+ *
+ * Copyright (C) 2000 Mountainview Data, Inc.


+ */
+
+#define __NO_VERSION__
+#include <linux/module.h>

+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_kml.h>
+#include <linux/intermezzo_psdev.h>
+#include <linux/intermezzo_upcall.h>
+
+static void kmlreint_pre_secure (struct kml_rec *rec);
+static void kmlreint_post_secure (struct kml_rec *rec);
+
+static void kmlreint_pre_secure (struct kml_rec *rec)
+{
+ if (current->fsuid != current->uid)
+ CDEBUG (D_KML, "reint_kmlreint_pre_secure: cannot setfsuid\n");
+ if (current->fsgid != current->gid)
+ CDEBUG (D_KML, "reint_kmlreint_pre_secure: cannot setfsgid\n");
+ current->fsuid = rec->rec_head.uid;
+ current->fsgid = rec->rec_head.fsgid;
+}
+
+static void kmlreint_post_secure (struct kml_rec *rec)
+{
+ current->fsuid = current->uid;
+ current->fsgid = current->gid;
+ /* current->egid = current->gid; */
+ /* ????????????? */
+}
+
+static int reint_create (int slot_offset, struct kml_rec *rec)
+{
+ struct lento_vfs_context info;
+ struct kml_create *create = &rec->rec_kml.create;
+ mm_segment_t old_fs;


+ int error;
+
+ ENTRY;

+ kmlreint_pre_secure (rec);
+
+ info.slot_offset = slot_offset;
+ info.recno = rec->rec_tail.recno;
+ info.kml_offset = rec->rec_kml_offset;
+ info.flags = 0;
+
+ CDEBUG (D_KML, "=====REINT_CREATE::%s\n", create->path);
+ old_fs = get_fs();
+ set_fs (get_ds());
+ error = lento_create(create->path, create->mode, &info);
+ set_fs (old_fs);
+ kmlreint_post_secure (rec);
+
+ EXIT;


+ return error;
+}
+

+static int reint_open (int slot_offset, struct kml_rec *rec)


+{
+ return 0;
+}
+

+static int reint_mkdir (int slot_offset, struct kml_rec *rec)
+{
+ struct lento_vfs_context info;
+ struct kml_mkdir *mkdir = &rec->rec_kml.mkdir;
+ mm_segment_t old_fs;


+ int error;
+
+ ENTRY;

+ kmlreint_pre_secure (rec);
+
+ info.slot_offset = slot_offset;
+ info.recno = rec->rec_tail.recno;
+ info.kml_offset = rec->rec_kml_offset;
+ info.flags = 0;
+ old_fs = get_fs();
+ set_fs (get_ds());
+ error = lento_mkdir (mkdir->path, mkdir->mode, &info);
+ set_fs (old_fs);
+ kmlreint_post_secure (rec);
+
+ EXIT;


+ return error;
+}
+

+static int reint_rmdir (int slot_offset, struct kml_rec *rec)
+{
+ struct kml_rmdir *rmdir = &rec->rec_kml.rmdir;
+ struct lento_vfs_context info;
+ mm_segment_t old_fs;
+ char *name;


+ int error;
+
+ ENTRY;

+ kmlreint_pre_secure (rec);
+ name = bdup_printf ("%s/%s", rmdir->path, rmdir->name);


+ if (name == NULL)

+ {
+ kmlreint_post_secure (rec);


+ EXIT;
+ return -ENOMEM;
+ }

+ info.slot_offset = slot_offset;
+ info.recno = rec->rec_tail.recno;
+ info.kml_offset = rec->rec_kml_offset;
+ info.flags = 0;
+
+ old_fs = get_fs();
+ set_fs (get_ds());
+ error = lento_rmdir (name, &info);
+ set_fs (old_fs);
+
+ PRESTO_FREE (name, strlen (name) + 1);
+ kmlreint_post_secure (rec);


+ EXIT;
+ return error;
+}
+

+static int reint_link (int slot_offset, struct kml_rec *rec)
+{
+ struct kml_link *link = &rec->rec_kml.link;
+ struct lento_vfs_context info;
+ mm_segment_t old_fs;


+ int error;
+
+ ENTRY;

+ kmlreint_pre_secure (rec);
+
+ info.slot_offset = slot_offset;
+ info.recno = rec->rec_tail.recno;
+ info.kml_offset = rec->rec_kml_offset;
+ info.flags = 0;
+
+ old_fs = get_fs();
+ set_fs (get_ds());
+ error = lento_link (link->sourcepath, link->targetpath, &info);
+ set_fs (old_fs);
+ kmlreint_post_secure (rec);


+ EXIT;
+ return error;
+}
+

+static int reint_unlink (int slot_offset, struct kml_rec *rec)
+{
+ struct kml_unlink *unlink = &rec->rec_kml.unlink;
+ struct lento_vfs_context info;
+ mm_segment_t old_fs;
+ int error;
+ char *name;
+
+ ENTRY;
+ kmlreint_pre_secure (rec);
+ name = bdup_printf ("%s/%s", unlink->path, unlink->name);


+ if (name == NULL)

+ {
+ kmlreint_post_secure (rec);


+ EXIT;
+ return -ENOMEM;
+ }

+ info.slot_offset = slot_offset;
+ info.recno = rec->rec_tail.recno;
+ info.kml_offset = rec->rec_kml_offset;
+ info.flags = 0;
+
+ old_fs = get_fs();
+ set_fs (get_ds());
+ error = lento_unlink (name, &info);
+ set_fs (old_fs);
+ PRESTO_FREE (name, strlen (name));
+ kmlreint_post_secure (rec);
+
+ EXIT;


+ return error;
+}
+

+static int reint_symlink (int slot_offset, struct kml_rec *rec)
+{
+ struct kml_symlink *symlink = &rec->rec_kml.symlink;
+ struct lento_vfs_context info;
+ mm_segment_t old_fs;


+ int error;
+
+ ENTRY;

+ kmlreint_pre_secure (rec);
+
+ info.slot_offset = slot_offset;
+ info.recno = rec->rec_tail.recno;
+ info.kml_offset = rec->rec_kml_offset;
+ info.flags = 0;
+
+ old_fs = get_fs();
+ set_fs (get_ds());
+ error = lento_symlink (symlink->targetpath,
+ symlink->sourcepath, &info);
+ set_fs (old_fs);
+ kmlreint_post_secure (rec);


+ EXIT;
+ return error;
+}
+

+static int reint_rename (int slot_offset, struct kml_rec *rec)
+{
+ struct kml_rename *rename = &rec->rec_kml.rename;
+ struct lento_vfs_context info;
+ mm_segment_t old_fs;


+ int error;
+
+ ENTRY;

+ kmlreint_pre_secure (rec);
+
+ info.slot_offset = slot_offset;
+ info.recno = rec->rec_tail.recno;
+ info.kml_offset = rec->rec_kml_offset;
+ info.flags = 0;
+
+ old_fs = get_fs();
+ set_fs (get_ds());
+ error = lento_rename (rename->sourcepath, rename->targetpath, &info);
+ set_fs (old_fs);
+ kmlreint_post_secure (rec);
+
+ EXIT;


+ return error;
+}
+

+static int reint_setattr (int slot_offset, struct kml_rec *rec)
+{
+ struct kml_setattr *setattr = &rec->rec_kml.setattr;
+ struct lento_vfs_context info;
+ mm_segment_t old_fs;


+ int error;
+
+ ENTRY;

+ kmlreint_pre_secure (rec);
+
+ info.slot_offset = slot_offset;
+ info.recno = rec->rec_tail.recno;
+ info.kml_offset = rec->rec_kml_offset;
+ info.flags = setattr->iattr.ia_attr_flags;
+
+ old_fs = get_fs();
+ set_fs (get_ds());
+ error = lento_setattr (setattr->path, &setattr->iattr, &info);
+ set_fs (old_fs);
+ kmlreint_post_secure (rec);


+ EXIT;
+ return error;
+}
+

+static int reint_mknod (int slot_offset, struct kml_rec *rec)
+{
+ struct kml_mknod *mknod = &rec->rec_kml.mknod;
+ struct lento_vfs_context info;
+ mm_segment_t old_fs;


+ int error;
+
+ ENTRY;

+ kmlreint_pre_secure (rec);
+
+ info.slot_offset = slot_offset;
+ info.recno = rec->rec_tail.recno;
+ info.kml_offset = rec->rec_kml_offset;
+ info.flags = 0;
+
+ old_fs = get_fs();
+ set_fs (get_ds());
+ error = lento_mknod (mknod->path, mknod->mode,
+ MKDEV(mknod->major, mknod->minor), &info);
+ set_fs (old_fs);
+ kmlreint_post_secure (rec);


+ EXIT;
+ return error;
+}
+

+int kml_reint (char *mtpt, int slot_offset, struct kml_rec *rec)
+{


+ int error = 0;

+ switch (rec->rec_head.opcode)
+ {
+ case KML_CREATE:
+ error = reint_create (slot_offset, rec);
+ break;
+ case KML_OPEN:
+ error = reint_open (slot_offset, rec);
+ break;
+ case KML_CLOSE:
+ /* error = reint_close (slot_offset, rec);
+ force the system to return to lento */
+ error = KML_CLOSE_BACKFETCH;
+ break;
+ case KML_MKDIR:
+ error = reint_mkdir (slot_offset, rec);
+ break;
+ case KML_RMDIR:
+ error = reint_rmdir (slot_offset, rec);
+ break;
+ case KML_UNLINK:
+ error = reint_unlink (slot_offset, rec);
+ break;
+ case KML_LINK:
+ error = reint_link (slot_offset, rec);
+ break;
+ case KML_SYMLINK:
+ error = reint_symlink (slot_offset, rec);
+ break;
+ case KML_RENAME:
+ error = reint_rename (slot_offset, rec);
+ break;
+ case KML_SETATTR:
+ error = reint_setattr (slot_offset, rec);
+ break;
+ case KML_MKNOD:
+ error = reint_mknod (slot_offset, rec);
+ break;
+ default:
+ CDEBUG (D_KML, "wrong opcode::%d\n", rec->rec_head.opcode);
+ return -EBADF;
+ }
+ if (error != 0 && error != KML_CLOSE_BACKFETCH)
+ CDEBUG (D_KML, "KML_ERROR::error = %d\n", error);


+ return error;
+}
+

+/* return the old mtpt */
+/*
+struct fs_struct {
+ atomic_t count;
+ int umask;
+ struct dentry * root, * pwd;
+};
+*/
+static int do_set_fs_root (struct dentry *newroot,
+ struct dentry **old_root)
+{
+ struct dentry *de = current->fs->root;
+ current->fs->root = newroot;
+ if (old_root != (struct dentry **) NULL)
+ *old_root = de;


+ return 0;
+}
+

+static int set_system_mtpt (char *mtpt, struct dentry **old_root)
+{


+ struct nameidata nd;
+ struct dentry *dentry;

+ int error;
+
+ if (path_init(pathname, LOOKUP_PARENT, &nd))
+ error = path_walk(mtpt, &nd);
+ if (error) {
+ CDEBUG (D_KML, "Yean!!!!::Can't find mtpt::%s\n", mtpt);


+ return error;
+ }
+

+ dentry = nd.dentry;
+ error = do_set_fs_root (dentry, old_root);
+ path_release (&nd);


+ return error;
+}
+

+int kml_reintbuf (struct kml_fsdata *kml_fsdata,
+ char *mtpt, struct kml_rec **close_rec)
+{
+ struct kml_rec *rec = NULL;


+ struct list_head *head, *tmp;

+ struct dentry *old_root;


+ int error = 0;
+

+ head = &kml_fsdata->kml_reint_cache;
+ if (list_empty(head))
+ return 0;
+
+ if (kml_fsdata->kml_reint_current == NULL ||
+ kml_fsdata->kml_reint_current == head->next)
+ return 0;
+
+ error = set_system_mtpt (mtpt, &old_root);


+ if (error)
+ return error;
+

+ tmp = head->next;
+ while (error == 0 && tmp != head ) {
+ rec = list_entry(tmp, struct kml_rec, kml_optimize.kml_chains);
+ error = kml_reint (mtpt, rec->rec_kml_offset, rec);
+ tmp = tmp->next;
+ }
+
+ do_set_fs_root (old_root, NULL);
+
+ if (error == KML_CLOSE_BACKFETCH)
+ *close_rec = rec;
+ kml_fsdata->kml_reint_current = tmp;


+ return error;
+}
+

diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/kml_setup.c linux/fs/intermezzo/kml_setup.c
--- v2.4.14/linux/fs/intermezzo/kml_setup.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/kml_setup.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,59 @@
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <asm/uaccess.h>


+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+#include <linux/intermezzo_kml.h>
+

+int kml_init (struct presto_file_set *fset)
+{
+ struct kml_fsdata *data;
+
+ ENTRY;
+ PRESTO_ALLOC (data, struct kml_fsdata *, sizeof (struct kml_fsdata));
+ if (data == NULL) {


+ EXIT;
+ return -ENOMEM;
+ }

+ INIT_LIST_HEAD (&data->kml_reint_cache);
+ INIT_LIST_HEAD (&data->kml_kop_cache);
+
+ PRESTO_ALLOC (data->kml_buf, char *, KML_REINT_MAXBUF);
+ if (data->kml_buf == NULL) {
+ PRESTO_FREE (data, sizeof (struct kml_fsdata));


+ EXIT;
+ return -ENOMEM;
+ }
+

+ data->kml_maxsize = KML_REINT_MAXBUF;
+ data->kml_len = 0;
+ data->kml_reintpos = 0;
+ data->kml_count = 0;
+ fset->fset_kmldata = data;


+ EXIT;
+ return 0;
+}
+

+int kml_cleanup (struct presto_file_set *fset)
+{
+ struct kml_fsdata *data = fset->fset_kmldata;
+
+ if (data == NULL)
+ return 0;
+
+ fset->fset_kmldata = NULL;
+#if 0
+ kml_sop_cleanup (&data->kml_reint_cache);
+ kml_kop_cleanup (&data->kml_kop_cache);
+#endif
+ PRESTO_FREE (data->kml_buf, KML_REINT_MAXBUF);
+ PRESTO_FREE (data, sizeof (struct kml_fsdata));


+ return 0;
+}
+
+

diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/kml_utils.c linux/fs/intermezzo/kml_utils.c
--- v2.4.14/linux/fs/intermezzo/kml_utils.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/kml_utils.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,44 @@
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>


+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_kml.h>
+

+
+// dlogit -- oppsite to logit ()
+// return the sbuf + size;
+char *dlogit (void *tbuf, const void *sbuf, int size)
+{
+ char *ptr = (char *)sbuf;
+ memcpy(tbuf, ptr, size);
+ ptr += size;
+ return ptr;
+}
+
+static spinlock_t kml_lock = SPIN_LOCK_UNLOCKED;
+static char buf[1024];
+char * bdup_printf (char *format, ...)
+{
+ va_list args;
+ int i;
+ char *path;
+ long flags;
+
+ spin_lock_irqsave(&kml_lock, flags);
+ va_start(args, format);
+ i = vsprintf(buf, format, args); /* hopefully i < sizeof(buf) */
+ va_end(args);
+
+ PRESTO_ALLOC (path, char *, i + 1);
+ if (path == NULL)
+ return NULL;
+ strcpy (path, buf);
+
+ spin_unlock_irqrestore(&kml_lock, flags);
+ return path;
+}
+
+
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/methods.c linux/fs/intermezzo/methods.c
--- v2.4.14/linux/fs/intermezzo/methods.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/methods.c Tue Nov 13 09:20:56 2001
@@ -0,0 +1,461 @@


+/*
+ *
+ *
+ * Copyright (C) 2000 Stelias Computing, Inc.
+ * Copyright (C) 2000 Red Hat, Inc.

+ * Copyright (C) 2000 Mountain View Data, Inc.
+ *
+ * Extended Attribute Support
+ * Copyright (C) 2001 Shirish H. Phatak, Tacit Networks, Inc.
+ */
+


+#include <stdarg.h>
+
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/sched.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/locks.h>
+#include <linux/blkdev.h>
+#include <linux/init.h>

+#define __NO_VERSION__
+#include <linux/module.h>
+

+#include <linux/fsfilter.h>
+#include <linux/intermezzo_fs.h>
+
+
+int filter_print_entry = 0;
+int filter_debug = 0xfffffff;
+/*
+ * The function in this file are responsible for setting up the
+ * correct methods layered file systems like InterMezzo and snapfs
+ */
+
+
+static struct filter_fs filter_oppar[FILTER_FS_TYPES];
+
+/* get to the upper methods (intermezzo, snapfs) */
+inline struct super_operations *filter_c2usops(struct filter_fs *cache)
+{
+ return &cache->o_fops.filter_sops;
+}
+
+inline struct inode_operations *filter_c2udiops(struct filter_fs *cache)
+{
+ return &cache->o_fops.filter_dir_iops;
+}
+
+
+inline struct inode_operations *filter_c2ufiops(struct filter_fs *cache)
+{
+ return &cache->o_fops.filter_file_iops;
+}
+
+inline struct inode_operations *filter_c2usiops(struct filter_fs *cache)
+{
+ return &cache->o_fops.filter_sym_iops;
+}
+
+
+inline struct file_operations *filter_c2udfops(struct filter_fs *cache)
+{
+ return &cache->o_fops.filter_dir_fops;
+}
+
+inline struct file_operations *filter_c2uffops(struct filter_fs *cache)
+{
+ return &cache->o_fops.filter_file_fops;
+}
+
+inline struct file_operations *filter_c2usfops(struct filter_fs *cache)
+{
+ return &cache->o_fops.filter_sym_fops;
+}
+
+inline struct dentry_operations *filter_c2udops(struct filter_fs *cache)
+{
+ return &cache->o_fops.filter_dentry_ops;
+}
+
+/* get to the cache (lower) methods */
+inline struct super_operations *filter_c2csops(struct filter_fs *cache)
+{
+ return cache->o_caops.cache_sops;
+}
+
+inline struct inode_operations *filter_c2cdiops(struct filter_fs *cache)
+{
+ return cache->o_caops.cache_dir_iops;
+}
+
+inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache)
+{
+ return cache->o_caops.cache_file_iops;
+}
+
+inline struct inode_operations *filter_c2csiops(struct filter_fs *cache)
+{
+ return cache->o_caops.cache_sym_iops;
+}
+
+inline struct file_operations *filter_c2cdfops(struct filter_fs *cache)
+{
+ return cache->o_caops.cache_dir_fops;
+}
+
+inline struct file_operations *filter_c2cffops(struct filter_fs *cache)
+{
+ return cache->o_caops.cache_file_fops;
+}
+
+inline struct file_operations *filter_c2csfops(struct filter_fs *cache)
+{
+ return cache->o_caops.cache_sym_fops;
+}
+
+inline struct dentry_operations *filter_c2cdops(struct filter_fs *cache)
+{
+ return cache->o_caops.cache_dentry_ops;
+}
+
+
+void filter_setup_journal_ops(struct filter_fs *ops, char *cache_type)
+{
+ if ( strlen(cache_type) == strlen("ext2") &&
+ memcmp(cache_type, "ext2", strlen("ext2")) == 0 ) {
+#if CONFIG_EXT2_FS
+ ops->o_trops = &presto_ext2_journal_ops;
+#else
+ ops->o_trops = NULL;
+#endif
+ FDEBUG(D_SUPER, "ops at %p\n", ops);
+ }
+
+ if ( strlen(cache_type) == strlen("ext3") &&
+ memcmp(cache_type, "ext3", strlen("ext3")) == 0 ) {
+#if defined(CONFIG_EXT3_FS) || defined (CONFIG_EXT3_FS_MODULE)
+ ops->o_trops = &presto_ext3_journal_ops;
+#else
+ ops->o_trops = NULL;
+#endif
+ FDEBUG(D_SUPER, "ops at %p\n", ops);
+ }
+
+ if ( strlen(cache_type) == strlen("reiserfs") &&
+ memcmp(cache_type, "reiserfs", strlen("reiserfs")) == 0 ) {
+#if 0
+ /* #if defined(CONFIG_REISERFS_FS) || defined(CONFIG_REISERFS_FS_MODULE) */
+ ops->o_trops = &presto_reiserfs_journal_ops;
+#else
+ ops->o_trops = NULL;
+#endif
+ FDEBUG(D_SUPER, "ops at %p\n", ops);
+ }
+
+ if ( strlen(cache_type) == strlen("xfs") &&
+ memcmp(cache_type, "xfs", strlen("xfs")) == 0 ) {
+#if 0
+ //#if defined(CONFIG_XFS_FS) || defined (CONFIG_XFS_FS_MODULE)
+ ops->o_trops = &presto_xfs_journal_ops;
+#else
+ ops->o_trops = NULL;
+#endif
+ FDEBUG(D_SUPER, "ops at %p\n", ops);
+ }
+
+ if ( strlen(cache_type) == strlen("obdfs") &&
+ memcmp(cache_type, "obdfs", strlen("obdfs")) == 0 ) {
+#if defined(CONFIG_OBDFS_FS) || defined (CONFIG_OBDFS_FS_MODULE)
+ ops->o_trops = presto_obdfs_journal_ops;
+#else
+ ops->o_trops = NULL;
+#endif
+ FDEBUG(D_SUPER, "ops at %p\n", ops);
+ }
+}
+
+
+/* find the cache for this FS */
+struct filter_fs *filter_get_filter_fs(const char *cache_type)
+{
+ struct filter_fs *ops = NULL;
+ FENTRY;
+
+ if ( strlen(cache_type) == strlen("ext2") &&
+ memcmp(cache_type, "ext2", strlen("ext2")) == 0 ) {
+ ops = &filter_oppar[FILTER_FS_EXT2];
+ FDEBUG(D_SUPER, "ops at %p\n", ops);
+ }
+
+ if ( strlen(cache_type) == strlen("xfs") &&
+ memcmp(cache_type, "xfs", strlen("xfs")) == 0 ) {
+ ops = &filter_oppar[FILTER_FS_XFS];
+ FDEBUG(D_SUPER, "ops at %p\n", ops);
+ }
+
+ if ( strlen(cache_type) == strlen("ext3") &&
+ memcmp(cache_type, "ext3", strlen("ext3")) == 0 ) {
+ ops = &filter_oppar[FILTER_FS_EXT3];
+ FDEBUG(D_SUPER, "ops at %p\n", ops);
+ }
+ if ( strlen(cache_type) == strlen("reiserfs") &&
+ memcmp(cache_type, "reiserfs", strlen("reiserfs")) == 0 ) {
+ ops = &filter_oppar[FILTER_FS_REISERFS];
+ FDEBUG(D_SUPER, "ops at %p\n", ops);
+ }
+ if ( strlen(cache_type) == strlen("obdfs") &&
+ memcmp(cache_type, "obdfs", strlen("obdfs")) == 0 ) {
+ ops = &filter_oppar[FILTER_FS_OBDFS];
+ FDEBUG(D_SUPER, "ops at %p\n", ops);
+ }
+
+ if (ops == NULL) {
+ printk("prepare to die: unrecognized cache type for Filter\n");
+ }
+ return ops;
+ FEXIT;
+}
+
+
+/*
+ * Frobnicate the InterMezzo operations
+ * this establishes the link between the InterMezzo file system
+ * and the underlying file system used for the cache.
+ */
+
+void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *cache_sops, struct super_operations *filter_sops)
+{
+ /* Get ptr to the shared struct snapfs_ops structure. */
+ struct filter_ops *props = &cache->o_fops;
+ /* Get ptr to the shared struct cache_ops structure. */
+ struct cache_ops *caops = &cache->o_caops;
+
+ FENTRY;
+
+ if ( cache->o_flags & FILTER_DID_SUPER_OPS ) {
+ FEXIT;
+ return;
+ }
+ cache->o_flags |= FILTER_DID_SUPER_OPS;
+
+ /* Set the cache superblock operations to point to the
+ superblock operations of the underlying file system. */
+ caops->cache_sops = cache_sops;
+
+ /*
+ * Copy the cache (real fs) superblock ops to the "filter"
+ * superblock ops as defaults. Some will be changed below
+ */
+ memcpy(&props->filter_sops, cache_sops, sizeof(*cache_sops));
+
+ /* 'put_super' unconditionally is that of filter */
+ if (filter_sops->put_super) {
+ props->filter_sops.put_super = filter_sops->put_super;
+ }
+
+ if (cache_sops->read_inode) {
+ props->filter_sops.read_inode = filter_sops->read_inode;
+ FDEBUG(D_INODE, "setting filter_read_inode, cache_ops %p, cache %p, ri at %p\n",
+ cache, cache, props->filter_sops.read_inode);
+ }
+
+ if (cache_sops->remount_fs)
+ props->filter_sops.remount_fs = filter_sops->remount_fs;
+ FEXIT;
+}
+
+
+void filter_setup_dir_ops(struct filter_fs *cache, struct inode *inode, struct inode_operations *filter_iops, struct file_operations *filter_fops)
+{
+ struct inode_operations *cache_filter_iops;
+ struct inode_operations *cache_iops = inode->i_op;
+ struct file_operations *cache_fops = inode->i_fop;
+ FENTRY;
+
+ if ( cache->o_flags & FILTER_DID_DIR_OPS ) {
+ FEXIT;
+ return;
+ }
+ cache->o_flags |= FILTER_DID_DIR_OPS;
+
+ /* former ops become cache_ops */
+ cache->o_caops.cache_dir_iops = cache_iops;
+ cache->o_caops.cache_dir_fops = cache_fops;
+ FDEBUG(D_SUPER, "filter at %p, cache iops %p, iops %p\n",
+ cache, cache_iops, filter_c2udiops(cache));
+
+ /* setup our dir iops: copy and modify */
+ memcpy(filter_c2udiops(cache), cache_iops, sizeof(*cache_iops));
+
+ /* abbreviate */
+ cache_filter_iops = filter_c2udiops(cache);
+
+ /* methods that filter if cache filesystem has these ops */
+ if (cache_iops->lookup && filter_iops->lookup)
+ cache_filter_iops->lookup = filter_iops->lookup;
+ if (cache_iops->create && filter_iops->create)
+ cache_filter_iops->create = filter_iops->create;
+ if (cache_iops->link && filter_iops->link)
+ cache_filter_iops->link = filter_iops->link;
+ if (cache_iops->unlink && filter_iops->unlink)
+ cache_filter_iops->unlink = filter_iops->unlink;
+ if (cache_iops->mkdir && filter_iops->mkdir)
+ cache_filter_iops->mkdir = filter_iops->mkdir;
+ if (cache_iops->rmdir && filter_iops->rmdir)
+ cache_filter_iops->rmdir = filter_iops->rmdir;
+ if (cache_iops->symlink && filter_iops->symlink)
+ cache_filter_iops->symlink = filter_iops->symlink;
+ if (cache_iops->rename && filter_iops->rename)
+ cache_filter_iops->rename = filter_iops->rename;
+ if (cache_iops->mknod && filter_iops->mknod)
+ cache_filter_iops->mknod = filter_iops->mknod;
+ if (cache_iops->permission && filter_iops->permission)
+ cache_filter_iops->permission = filter_iops->permission;
+ if (cache_iops->getattr)
+ cache_filter_iops->getattr = filter_iops->getattr;
+ /* Some filesystems do not use a setattr method of their own
+ instead relying on inode_setattr/write_inode. We still need to
+ journal these so we make setattr an unconditional operation.
+ XXX: we should probably check for write_inode. SHP
+ */
+ /*if (cache_iops->setattr)*/
+ cache_filter_iops->setattr = filter_iops->setattr;
+#ifdef CONFIG_FS_EXT_ATTR
+ /* For now we assume that posix acls are handled through extended
+ * attributes. If this is not the case, we must explicitly trap
+ * posix_set_acl. SHP
+ */
+ if (cache_iops->set_ext_attr && filter_iops->set_ext_attr)
+ cache_filter_iops->set_ext_attr = filter_iops->set_ext_attr;
+#endif
+
+
+ /* copy dir fops */
+ memcpy(filter_c2udfops(cache), cache_fops, sizeof(*cache_fops));
+
+ /* unconditional filtering operations */
+ filter_c2udfops(cache)->open = filter_fops->open;
+
+ FEXIT;
+}
+
+
+void filter_setup_file_ops(struct filter_fs *cache, struct inode *inode, struct inode_operations *filter_iops, struct file_operations *filter_fops)
+{
+ struct inode_operations *pr_iops;
+ struct inode_operations *cache_iops = inode->i_op;
+ struct file_operations *cache_fops = inode->i_fop;
+ FENTRY;
+
+ if ( cache->o_flags & FILTER_DID_FILE_OPS ) {
+ FEXIT;
+ return;
+ }
+ cache->o_flags |= FILTER_DID_FILE_OPS;
+
+ /* steal the old ops */
+ /* former ops become cache_ops */
+ cache->o_caops.cache_file_iops = cache_iops;
+ cache->o_caops.cache_file_fops = cache_fops;
+
+ /* abbreviate */
+ pr_iops = filter_c2ufiops(cache);
+
+ /* setup our dir iops: copy and modify */
+ memcpy(pr_iops, cache_iops, sizeof(*cache_iops));
+
+ /* copy dir fops */
+ printk("*** cache file ops at %p\n", cache_fops);
+ memcpy(filter_c2uffops(cache), cache_fops, sizeof(*cache_fops));
+
+ /* assign */
+ /* See comments above in filter_setup_dir_ops. SHP */
+ /*if (cache_iops->setattr)*/
+ pr_iops->setattr = filter_iops->setattr;
+ if (cache_iops->getattr)
+ pr_iops->getattr = filter_iops->getattr;
+#ifdef CONFIG_FS_EXT_ATTR
+ /* For now we assume that posix acls are handled through extended
+ * attributes. If this is not the case, we must explicitly trap and
+ * posix_set_acl
+ */
+ if (cache_iops->set_ext_attr && filter_iops->set_ext_attr)
+ pr_iops->set_ext_attr = filter_iops->set_ext_attr;
+#endif
+
+
+ /* unconditional filtering operations */
+ filter_c2uffops(cache)->open = filter_fops->open;
+ filter_c2uffops(cache)->release = filter_fops->release;
+ filter_c2uffops(cache)->write = filter_fops->write;
+
+ FEXIT;
+}
+
+/* XXX in 2.3 there are "fast" and "slow" symlink ops for ext2 XXX */
+void filter_setup_symlink_ops(struct filter_fs *cache, struct inode *inode, struct inode_operations *filter_iops, struct file_operations *filter_fops)
+{
+ struct inode_operations *pr_iops;
+ struct inode_operations *cache_iops = inode->i_op;
+ struct file_operations *cache_fops = inode->i_fop;
+ FENTRY;
+
+ if ( cache->o_flags & FILTER_DID_SYMLINK_OPS ) {
+ FEXIT;
+ return;
+ }
+ cache->o_flags |= FILTER_DID_SYMLINK_OPS;
+
+ /* steal the old ops */
+ cache->o_caops.cache_sym_iops = cache_iops;
+ cache->o_caops.cache_sym_fops = cache_fops;
+
+ /* abbreviate */
+ pr_iops = filter_c2usiops(cache);
+
+ /* setup our dir iops: copy and modify */
+ memcpy(pr_iops, cache_iops, sizeof(*cache_iops));
+
+ /* See comments above in filter_setup_dir_ops. SHP */
+ /* if (cache_iops->setattr) */
+ pr_iops->setattr = filter_iops->setattr;
+ if (cache_iops->getattr)
+ pr_iops->getattr = filter_iops->getattr;
+
+ /* assign */
+ /* copy fops - careful for symlinks they might be NULL */
+ if ( cache_fops ) {
+ memcpy(filter_c2usfops(cache), cache_fops, sizeof(*cache_fops));
+ }
+
+ FEXIT;
+}
+
+void filter_setup_dentry_ops(struct filter_fs *cache,
+ struct dentry_operations *cache_dop,
+ struct dentry_operations *filter_dop)
+{
+ if ( cache->o_flags & FILTER_DID_DENTRY_OPS ) {
+ FEXIT;
+ return;
+ }
+ cache->o_flags |= FILTER_DID_DENTRY_OPS;
+
+ cache->o_caops.cache_dentry_ops = cache_dop;
+ memcpy(&cache->o_fops.filter_dentry_ops,
+ filter_dop, sizeof(*filter_dop));
+
+ if (cache_dop && cache_dop != filter_dop && cache_dop->d_revalidate){
+ printk("WARNING: filter overriding revalidation!\n");
+ }
+ return;
+}
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/presto.c linux/fs/intermezzo/presto.c
--- v2.4.14/linux/fs/intermezzo/presto.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/presto.c Tue Nov 13 09:20:56 2001
@@ -0,0 +1,1150 @@
+/*
+ * intermezzo.c
+ *
+ * This file implements basic routines supporting the semantics
+ *
+ * Author: Peter J. Braam <br...@cs.cmu.edu>
+ * Copyright (C) 1998 Stelias Computing Inc
+ * Copyright (C) 1999 Red Hat Inc.
+ *
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>


+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/errno.h>

+#include <linux/vmalloc.h>
+#include <linux/slab.h>


+#include <linux/locks.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>

+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+#include <linux/intermezzo_kml.h>
+

+extern int presto_init_last_rcvd_file(struct presto_file_set *);
+extern int presto_init_lml_file(struct presto_file_set *);
+extern int presto_init_kml_file(struct presto_file_set *);
+
+int presto_walk(const char *name, struct nameidata *nd)
+{
+ int err;
+ /* we do not follow symlinks to support symlink operations
+ correctly. The vfs should always hand us resolved dentries
+ so we should not be required to use LOOKUP_FOLLOW. At the
+ reintegrating end, lento again should be working with the
+ resolved pathname and not the symlink. SHP
+ XXX: This code implies that direct symlinks do not work. SHP
+ */
+ unsigned int flags = LOOKUP_POSITIVE;
+
+ ENTRY;
+ err = 0;
+ if (path_init(name, flags, nd))
+ err = path_walk(name, nd);


+ return err;
+}
+

+inline struct presto_dentry_data *presto_d2d(struct dentry *dentry)
+{
+ return (struct presto_dentry_data *)dentry->d_fsdata;
+}
+
+static inline struct presto_file_set *presto_dentry2fset(struct dentry *dentry)
+{
+ if (dentry->d_fsdata == NULL) {
+ printk("fucked dentry: %p\n", dentry);
+ BUG();
+ }
+ return presto_d2d(dentry)->dd_fset;
+}
+
+/* find the presto minor device for this inode */
+int presto_i2m(struct inode *inode)


+{
+ struct presto_cache *cache;

+ ENTRY;
+ cache = presto_get_cache(inode);
+ CDEBUG(D_PSDEV, "\n");


+ if ( !cache ) {

+ printk("PRESTO: BAD: cannot find cache for dev %d, ino %ld\n",
+ inode->i_dev, inode->i_ino);
+ EXIT;
+ return -1;
+ }
+ EXIT;
+ return cache->cache_psdev->uc_minor;
+}
+
+inline int presto_f2m(struct presto_file_set *fset)
+{
+ return fset->fset_cache->cache_psdev->uc_minor;
+
+}
+
+inline int presto_c2m(struct presto_cache *cache)
+{
+ return cache->cache_psdev->uc_minor;
+
+}
+
+int presto_has_all_data(struct inode *inode)
+{
+ ENTRY;
+
+ if ( (inode->i_size >> inode->i_sb->s_blocksize_bits) >
+ inode->i_blocks) {


+ EXIT;
+ return 0;
+ }

+ EXIT;
+ return 1;
+
+}
+

+/* find the fileset dentry for this dentry */
+struct presto_file_set *presto_fset(struct dentry *de)
+{
+ struct dentry *fsde;
+ ENTRY;
+ fsde = de;
+ for ( ; ; ) {
+ if ( presto_dentry2fset(fsde) ) {
+ EXIT;
+ return presto_dentry2fset(fsde);
+ }
+ /* are we at the cache "/" ?? */
+ if ( fsde->d_parent == fsde ) {
+ if ( !de->d_inode ) {
+ printk("Warning %*s has no fileset inode.\n",
+ de->d_name.len, de->d_name.name);
+ }
+ /* better to return a BAD thing */


+ EXIT;
+ return NULL;
+ }

+ fsde = fsde->d_parent;
+ }
+ /* not reached */


+ EXIT;
+ return NULL;
+}
+

+/* XXX check this out */
+struct presto_file_set *presto_path2fileset(const char *name)
+{
+ struct nameidata nd;
+ struct presto_file_set *fileset;
+ int error;
+ ENTRY;
+
+ error = presto_walk(name, &nd);
+ if (!error) {
+#if 0
+ error = do_revalidate(nd.dentry);
+#endif
+ if (!error)
+ fileset = presto_fset(nd.dentry);
+ path_release(&nd);
+ EXIT;
+ } else
+ fileset = ERR_PTR(error);
+
+ EXIT;
+ return fileset;
+}
+
+/* check a flag on this dentry or fset root. Semantics:
+ - most flags: test if it is set
+ - PRESTO_ATTR, PRESTO_DATA return 1 if PRESTO_FSETINSYNC is set
+*/
+int presto_chk(struct dentry *dentry, int flag)
+{
+ int minor;
+ struct presto_file_set *fset = presto_fset(dentry);
+
+ ENTRY;
+ minor = presto_i2m(dentry->d_inode);
+ if ( upc_comms[minor].uc_no_filter ) {
+ EXIT;
+ return ~0;
+ }
+
+ /* if the fileset is in sync DATA and ATTR are OK */
+ if ( fset &&
+ (flag == PRESTO_ATTR || flag == PRESTO_DATA) &&
+ (fset->fset_flags & FSET_INSYNC) ) {
+ CDEBUG(D_INODE, "fset in sync (ino %ld)!\n",
+ fset->fset_mtpt->d_inode->i_ino);
+ EXIT;
+ return 1;
+ }
+
+ EXIT;
+ return (presto_d2d(dentry)->dd_flags & flag);
+}
+
+/* set a bit in the dentry flags */
+void presto_set(struct dentry *dentry, int flag)
+{
+
+ ENTRY;
+ if ( dentry->d_inode ) {
+ CDEBUG(D_INODE, "SET ino %ld, flag %x\n",
+ dentry->d_inode->i_ino, flag);
+ }
+ presto_d2d(dentry)->dd_flags |= flag;
+ EXIT;
+}
+
+/* given a path: complete the closes on the fset */
+int lento_complete_closes(char *path)
+{


+ struct nameidata nd;
+ struct dentry *dentry;

+ int error;
+ struct presto_file_set *fset;

+ ENTRY;
+
+
+ error = presto_walk(path, &nd);
+ if (error) {


+ EXIT;
+ return error;
+ }
+

+ dentry = nd.dentry;
+

+ error = -ENXIO;
+ if ( !presto_ispresto(dentry->d_inode) ) {
+ EXIT;
+ goto out_complete;
+ }


+
+ fset = presto_fset(dentry);
+ error = -EINVAL;
+ if ( !fset ) {
+ printk("No fileset!\n");
+ EXIT;

+ goto out_complete;
+ }
+
+ /* transactions and locking are internal to this function */
+ error = presto_complete_lml(fset);
+
+ EXIT;
+ out_complete:
+ path_release(&nd);

+ return error;
+}
+

+/* set the fset recno and offset to a given value */
+int lento_reset_fset(char *path, __u64 offset, __u32 recno)
+{


+ struct nameidata nd;
+ struct dentry *dentry;

+ int error;
+ struct presto_file_set *fset;

+ ENTRY;
+
+
+ error = presto_walk(path, &nd);


+ if (error)
+ return error;
+

+ dentry = nd.dentry;
+

+ error = -ENXIO;
+ if ( !presto_ispresto(dentry->d_inode) ) {
+ EXIT;
+ goto out_complete;
+ }


+
+ fset = presto_fset(dentry);
+ error = -EINVAL;
+ if ( !fset ) {
+ printk("No fileset!\n");
+ EXIT;

+ goto out_complete;
+ }
+
+ write_lock(&fset->fset_kml.fd_lock);
+ fset->fset_kml.fd_recno = recno;
+ fset->fset_kml.fd_offset = offset;


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

echo 'End of part 094'
echo 'File patch-2.4.15 is continued in part 095'
echo "095" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:09 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part093

#!/bin/sh -x
# this is part 093 of a 115 - part archive


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

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

+ sizeof(le32_to_cpu(pathlen)) +
+ sizeof(struct journal_suffix);
+
+ if ( size > sizeof(record) ) {
+ printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
+ }
+
+ rec->is_kml = 1;
+ rec->size = size + size_round(le32_to_cpu(pathlen));
+
+ logrecord = journal_log_prefix_with_groups(record, opcode, rec,
+ ngroups, groups);
+ logrecord = logit(logrecord, new_file_ver, sizeof(*new_file_ver));
+ logrecord = logit(logrecord, &ino, sizeof(ino));
+ logrecord = logit(logrecord, &generation, sizeof(generation));
+ logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
+ logrecord = journal_log_suffix(logrecord, record, fset, NULL, rec);
+
+ error = presto_log(fset, rec, record, size,
+ path, size_round(le32_to_cpu(pathlen)),
+ NULL, 0, NULL, 0);


+
+ EXIT;
+ return error;
+}
+
+

+/* write closes for the local close records in the LML */
+int presto_complete_lml(struct presto_file_set *fset)
+{
+ __u32 groups[NGROUPS_MAX];
+ loff_t lml_offset;
+ loff_t read_offset;
+ char *buffer;
+ void *handle;
+ struct rec_info rec;
+ struct close_rec {
+ struct presto_version new_file_ver;
+ __u64 ino;
+ __u32 generation;
+ __u32 pathlen;
+ __u64 remote_ino;
+ __u32 remote_generation;
+ __u32 remote_version;
+ __u64 lml_offset;
+ } close_rec;
+ struct file *file = fset->fset_lml.fd_file;
+ struct journal_prefix prefix;


+ int rc = 0;

+ ENTRY;
+
+ lml_offset = 0;
+ again:
+ if (lml_offset >= file->f_dentry->d_inode->i_size) {


+ EXIT;
+ return rc;
+ }
+

+ read_offset = lml_offset;
+ rc = presto_fread(file, (char *)&prefix,
+ sizeof(prefix), &read_offset);
+ if ( rc != sizeof(prefix) ) {
+ EXIT;
+ printk("presto_complete_lml: ioerror - 1, tell Peter\n");
+ return -EIO;
+ }
+
+ if ( prefix.opcode == PRESTO_OP_NOOP ) {
+ lml_offset += prefix.len;
+ goto again;
+ }
+
+ rc = presto_fread(file, (char *)groups,
+ prefix.ngroups * sizeof(__u32), &read_offset);
+ if ( rc != prefix.ngroups * sizeof(__u32) ) {
+ EXIT;
+ printk("presto_complete_lml: ioerror - 2, tell Peter\n");


+ return -EIO;
+ }
+

+ rc = presto_fread(file, (char *)&close_rec,
+ sizeof(close_rec), &read_offset);
+ if ( rc != sizeof(close_rec) ) {
+ EXIT;
+ printk("presto_complete_lml: ioerror - 3, tell Peter\n");


+ return -EIO;
+ }
+

+ /* is this a backfetch or a close record? */
+ if ( le64_to_cpu(close_rec.remote_ino) != 0 ) {
+ lml_offset += prefix.len;
+ goto again;
+ }
+
+ BUFF_ALLOC(buffer, NULL);
+ rc = presto_fread(file, (char *)buffer,
+ le32_to_cpu(close_rec.pathlen), &read_offset);
+ if ( rc != le32_to_cpu(close_rec.pathlen) ) {
+ EXIT;
+ printk("presto_complete_lml: ioerror - 4, tell Peter\n");
+ return -EIO;
+ }


+
+ handle = presto_trans_start(fset, file->f_dentry->d_inode,
+ PRESTO_OP_RELEASE);

+ if ( !handle ) {
+ EXIT;
+ return -ENOMEM;
+ }
+
+ rc = presto_clear_lml_close(fset, lml_offset);

+ if ( rc ) {

+ printk("error during clearing: %d\n", rc);
+ presto_trans_commit(fset, handle);


+ EXIT;
+ return rc;
+ }
+

+ rc = presto_rewrite_close(&rec, fset, buffer, close_rec.pathlen,
+ prefix.ngroups, groups,
+ close_rec.ino, close_rec.generation,
+ &close_rec.new_file_ver);

+ if ( rc ) {

+ printk("error during rewrite close: %d\n", rc);
+ presto_trans_commit(fset, handle);


+ EXIT;
+ return rc;
+ }
+

+ presto_trans_commit(fset, handle);

+ if ( rc ) {

+ printk("error during truncation: %d\n", rc);
+ EXIT;

+ return rc;
+ }
+

+ lml_offset += prefix.len;
+ CDEBUG(D_JOURNAL, "next LML record at: %ld\n", (long)lml_offset);
+ goto again;
+
+ EXIT;
+ return -EINVAL;
+}
+
+
+#ifdef CONFIG_FS_EXT_ATTR
+/* Journal an ea operation. A NULL buffer implies the attribute is
+ * getting deleted. In this case we simply change the opcode, but nothing
+ * else is affected.
+ */
+int presto_journal_set_ext_attr (struct rec_info *rec,
+ struct presto_file_set *fset,
+ struct dentry *dentry,
+ struct presto_version *ver, const char *name,
+ const char *buffer, int buffer_len,
+ int flags)
+{
+ int opcode = (buffer == NULL) ?
+ PRESTO_OP_DELEXTATTR :
+ PRESTO_OP_SETEXTATTR ;
+ char *temp;
+ char *path;
+ __u32 pathlen;
+ int size;
+ char *logrecord;
+ char record[292];
+ struct dentry *root;
+ int error;
+ __u32 namelen=cpu_to_le32(strnlen(name,PRESTO_EXT_ATTR_NAME_MAX));
+ __u32 buflen=(buffer != NULL)? cpu_to_le32(buffer_len): cpu_to_le32(0);
+ __u32 mode;
+
+
+ ENTRY;
+ if ( presto_no_journal(fset) ) {
+ EXIT;


+ return 0;
+ }
+

+ if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0) ) {
+ EXIT;
+ return 0;
+ }
+
+ root = fset->fset_mtpt;
+
+ BUFF_ALLOC(temp, NULL);
+ path = presto_path(dentry, root, temp, PAGE_SIZE);
+ pathlen = cpu_to_le32(MYPATHLEN(temp, path));
+
+ flags=cpu_to_le32(flags);
+ /* Ugly, but needed. posix ACLs change the mode without using
+ * setattr, we need to record these changes. The EA code per se
+ * is not really affected.
+ */
+ mode=cpu_to_le32(dentry->d_inode->i_mode);
+
+ size = sizeof(__u32) * current->ngroups +
+ sizeof(struct journal_prefix) +
+ 2 * sizeof(struct presto_version) +
+ sizeof(flags) + sizeof(mode) + sizeof(namelen) +
+ sizeof(buflen) + sizeof(pathlen) +
+ sizeof(struct journal_suffix);
+
+ if ( size > sizeof(record) ) {
+ printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
+ }
+
+ rec->is_kml = 1;
+ /* Make space for a path, a attr name and value*/
+ /* We use the buflen instead of buffer_len to make sure that we
+ * journal the right length. This may be a little paranoid, but
+ * with 64 bits round the corner, I would rather be safe than sorry!
+ * Also this handles deletes with non-zero buffer_lengths correctly.
+ * SHP
+ */
+ rec->size = size + size_round(le32_to_cpu(pathlen)) +
+ size_round(le32_to_cpu(namelen)) +
+ size_round(le32_to_cpu(buflen));
+
+ logrecord = journal_log_prefix(record, opcode, rec);
+ logrecord = logit(logrecord, ver, sizeof(*ver));
+ logrecord = log_version(logrecord, dentry);
+ logrecord = logit(logrecord, &flags, sizeof(flags));
+ logrecord = logit(logrecord, &mode, sizeof(flags));
+ logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
+ logrecord = logit(logrecord, &namelen, sizeof(namelen));
+ logrecord = logit(logrecord, &buflen, sizeof(buflen));
+ logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
+
+ error = presto_log(fset, rec, record, size,
+ path, size_round(le32_to_cpu(pathlen)),
+ name, size_round(le32_to_cpu(namelen)),
+ buffer, size_round(le32_to_cpu(buflen)));
+
+ BUFF_FREE(temp);


+ EXIT;
+ return error;
+}

+#endif
+
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/journal_ext2.c linux/fs/intermezzo/journal_ext2.c
--- v2.4.14/linux/fs/intermezzo/journal_ext2.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/journal_ext2.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,70 @@
+


+/*
+ * Intermezzo. (C) 1998 Peter J. Braam

+ */
+


+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>

+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/stat.h>
+#include <linux/errno.h>


+#include <linux/locks.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/string.h>

+#include <linux/ext2_fs.h>

+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+#include <linux/intermezzo_kml.h>
+

+#if defined(CONFIG_EXT2_FS)
+
+/* EXT2 has no journalling, so these functions do nothing */
+static loff_t presto_e2_freespace(struct presto_cache *cache,
+ struct super_block *sb)
+{
+ unsigned long freebl = le32_to_cpu(sb->u.ext2_sb.s_es->s_free_blocks_count);
+ unsigned long avail = freebl - le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count);
+ return (avail << EXT2_BLOCK_SIZE_BITS(sb));
+}
+
+/* start the filesystem journal operations */
+static void *presto_e2_trans_start(struct presto_file_set *fset, struct inode *inode, int op)
+{
+ __u32 avail_kmlblocks;
+
+ if ( presto_no_journal(fset) ||
+ strcmp(fset->fset_cache->cache_type, "ext2"))
+ return NULL;
+
+ avail_kmlblocks = inode->i_sb->u.ext2_sb.s_es->s_free_blocks_count;
+
+ if ( avail_kmlblocks < 3 ) {
+ return ERR_PTR(-ENOSPC);
+ }
+
+ if ( (op != PRESTO_OP_UNLINK && op != PRESTO_OP_RMDIR)
+ && avail_kmlblocks < 6 ) {
+ return ERR_PTR(-ENOSPC);
+ }
+ return (void *) 1;
+}
+
+static void presto_e2_trans_commit(struct presto_file_set *fset, void *handle)
+{
+ do {} while (0);
+}
+
+struct journal_ops presto_ext2_journal_ops = {
+ tr_avail: presto_e2_freespace,
+ tr_start: presto_e2_trans_start,
+ tr_commit: presto_e2_trans_commit,
+ tr_journal_data: NULL
+};
+
+#endif /* CONFIG_EXT2_FS */
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/journal_ext3.c linux/fs/intermezzo/journal_ext3.c
--- v2.4.14/linux/fs/intermezzo/journal_ext3.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/journal_ext3.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,205 @@
+


+/*
+ * Intermezzo. (C) 1998 Peter J. Braam

+ * Intermezzo. (C) 2000 Red Hat, Inc.
+ * Intermezzo. (C) 2000 Los Alamos National Laboratory
+ * Intermezzo. (C) 2000 TurboLinux, Inc.
+ * Intermezzo. (C) 2001 Mountain View Data, Inc.
+ */
+
+#include <linux/types.h>
+#include <linux/param.h>


+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>

+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/stat.h>
+#include <linux/errno.h>


+#include <linux/locks.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>

+#if defined(CONFIG_EXT3_FS) || defined (CONFIG_EXT3_FS_MODULE)


+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/ext3_jbd.h>

+#endif


+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+#include <linux/intermezzo_kml.h>
+

+#if defined(CONFIG_EXT3_FS) || defined (CONFIG_EXT3_FS_MODULE)
+

+#define MAX_PATH_BLOCKS(inode) (PATH_MAX >> EXT3_BLOCK_SIZE_BITS((inode)->i_sb))
+#define MAX_NAME_BLOCKS(inode) (NAME_MAX >> EXT3_BLOCK_SIZE_BITS((inode)->i_sb))
+
+/* space requirements:
+ presto_do_truncate:
+ used to truncate the KML forward to next fset->chunksize boundary
+ - zero partial block
+ - update inode
+ presto_write_record:
+ write header (< one block)
+ write one path (< MAX_PATHLEN)
+ possibly write another path (< MAX_PATHLEN)
+ write suffix (< one block)
+ presto_update_last_rcvd
+ write one block
+*/
+
+static loff_t presto_e3_freespace(struct presto_cache *cache,
+ struct super_block *sb)
+{
+ loff_t freebl = le32_to_cpu(sb->u.ext3_sb.s_es->s_free_blocks_count);
+ loff_t avail = freebl -
+ le32_to_cpu(sb->u.ext3_sb.s_es->s_r_blocks_count);
+ return (avail << EXT3_BLOCK_SIZE_BITS(sb));
+}
+
+/* start the filesystem journal operations */
+static void *presto_e3_trans_start(struct presto_file_set *fset,
+ struct inode *inode,
+ int op)
+{
+ int jblocks;
+ int trunc_blks, one_path_blks, extra_path_blks,
+ extra_name_blks, lml_blks;
+ __u32 avail_kmlblocks;
+ handle_t *handle;
+
+ if ( presto_no_journal(fset) ||
+ strcmp(fset->fset_cache->cache_type, "ext3"))
+ {
+ CDEBUG(D_JOURNAL, "got cache_type \"%s\"\n",
+ fset->fset_cache->cache_type);


+ return NULL;
+ }
+

+ avail_kmlblocks = inode->i_sb->u.ext3_sb.s_es->s_free_blocks_count;
+
+ if ( avail_kmlblocks < 3 ) {
+ return ERR_PTR(-ENOSPC);
+ }
+
+ if ( (op != PRESTO_OP_UNLINK && op != PRESTO_OP_RMDIR)
+ && avail_kmlblocks < 6 ) {
+ return ERR_PTR(-ENOSPC);
+ }
+
+ /* Need journal space for:
+ at least three writes to KML (two one block writes, one a path)
+ possibly a second name (unlink, rmdir)
+ possibly a second path (symlink, rename)
+ a one block write to the last rcvd file
+ */
+
+ trunc_blks = EXT3_DATA_TRANS_BLOCKS + 1;
+ one_path_blks = 4*EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode) + 3;
+ lml_blks = 4*EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode) + 2;
+ extra_path_blks = EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode);
+ extra_name_blks = EXT3_DATA_TRANS_BLOCKS + MAX_NAME_BLOCKS(inode);
+
+ /* additional blocks appear for "two pathname" operations
+ and operations involving the LML records
+ */
+ switch (op) {
+ case PRESTO_OP_TRUNC:
+ jblocks = one_path_blks + extra_name_blks + trunc_blks
+ + EXT3_DELETE_TRANS_BLOCKS;
+ break;
+ case PRESTO_OP_RELEASE:
+ /*
+ jblocks = one_path_blks + lml_blks + 2*trunc_blks;
+ */
+ jblocks = one_path_blks;
+ break;
+ case PRESTO_OP_SETATTR:
+ jblocks = one_path_blks + trunc_blks + 1 ;
+ break;
+ case PRESTO_OP_CREATE:
+ jblocks = one_path_blks + trunc_blks
+ + EXT3_DATA_TRANS_BLOCKS + 3 + 2;
+ break;
+ case PRESTO_OP_LINK:
+ jblocks = one_path_blks + trunc_blks
+ + EXT3_DATA_TRANS_BLOCKS + 2;
+ break;
+ case PRESTO_OP_UNLINK:
+ jblocks = one_path_blks + extra_name_blks + trunc_blks
+ + EXT3_DELETE_TRANS_BLOCKS + 2;
+ break;
+ case PRESTO_OP_SYMLINK:
+ jblocks = one_path_blks + extra_path_blks + trunc_blks
+ + EXT3_DATA_TRANS_BLOCKS + 5;
+ break;
+ case PRESTO_OP_MKDIR:
+ jblocks = one_path_blks + trunc_blks
+ + EXT3_DATA_TRANS_BLOCKS + 4 + 2;
+ break;
+ case PRESTO_OP_RMDIR:
+ jblocks = one_path_blks + extra_name_blks + trunc_blks
+ + EXT3_DELETE_TRANS_BLOCKS + 1;
+ break;
+ case PRESTO_OP_MKNOD:
+ jblocks = one_path_blks + trunc_blks +
+ EXT3_DATA_TRANS_BLOCKS + 3 + 2;
+ break;
+ case PRESTO_OP_RENAME:
+ jblocks = one_path_blks + extra_path_blks + trunc_blks +
+ 2 * EXT3_DATA_TRANS_BLOCKS + 2 + 3;
+ break;
+ case PRESTO_OP_WRITE:
+ jblocks = one_path_blks;
+ /* add this when we can wrap our transaction with
+ that of ext3_file_write (ordered writes)
+ + EXT3_DATA_TRANS_BLOCKS;
+ */
+ break;
+ default:
+ CDEBUG(D_JOURNAL, "invalid operation %d for journal\n", op);


+ return NULL;
+ }
+

+ CDEBUG(D_JOURNAL, "creating journal handle (%d blocks)\n", jblocks);
+ /* journal_start/stop does not do its own locking while updating
+ * the handle/transaction information. Hence we create our own
+ * critical section to protect these calls. -SHP
+ */
+ lock_kernel();
+ handle = journal_start(EXT3_JOURNAL(inode), jblocks);
+ unlock_kernel();
+ return handle;
+}
+
+void presto_e3_trans_commit(struct presto_file_set *fset, void *handle)
+{
+ if ( presto_no_journal(fset) || !handle)
+ return;
+
+ /* See comments before journal_start above. -SHP */
+ lock_kernel();
+ journal_stop(handle);
+ unlock_kernel();
+}
+
+void presto_e3_journal_file_data(struct inode *inode)
+{
+#ifdef EXT3_JOURNAL_DATA_FL


+ inode->u.ext3_i.i_flags |= EXT3_JOURNAL_DATA_FL;

+#else
+#warning You must have a facility to enable journaled writes for recovery!
+#endif
+}
+
+struct journal_ops presto_ext3_journal_ops = {
+ tr_avail: presto_e3_freespace,
+ tr_start: presto_e3_trans_start,
+ tr_commit: presto_e3_trans_commit,
+ tr_journal_data: presto_e3_journal_file_data
+};
+
+#endif /* CONFIG_EXT3_FS */
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/journal_obdfs.c linux/fs/intermezzo/journal_obdfs.c
--- v2.4.14/linux/fs/intermezzo/journal_obdfs.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/journal_obdfs.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,180 @@
+


+/*
+ * Intermezzo. (C) 1998 Peter J. Braam

+ * Intermezzo. (C) 2000 Red Hat, Inc.
+ * Intermezzo. (C) 2000 Los Alamos National Laboratory
+ * Intermezzo. (C) 2000 TurboLinux, Inc.
+ * Intermezzo. (C) 2001 Mountain View Data, Inc.
+ */
+
+#include <linux/types.h>
+#include <linux/param.h>


+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>

+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/stat.h>
+#include <linux/errno.h>


+#include <linux/locks.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/string.h>

+#ifdef CONFIG_OBDFS_FS
+#include /usr/src/obd/include/linux/obdfs.h
+#endif


+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+#include <linux/intermezzo_kml.h>
+

+#ifdef CONFIG_OBDFS_FS
+
+
+static unsigned long presto_obdfs_freespace(struct presto_file_set *fset,
+ struct super_block *sb)
+{
+ return 0x0fffff;
+}
+
+/* start the filesystem journal operations */
+static void *presto_obdfs_trans_start(struct presto_file_set *fset,
+ struct inode *inode,
+ int op)
+{
+
+ return (void *) 1;
+}
+
+#if 0
+ int jblocks;
+ int trunc_blks, one_path_blks, extra_path_blks,
+ extra_name_blks, lml_blks;
+ __u32 avail_kmlblocks;
+
+ if ( presto_no_journal(fset) ||
+ strcmp(fset->fset_cache->cache_type, "ext3"))
+ {
+ CDEBUG(D_JOURNAL, "got cache_type \"%s\"\n",
+ fset->fset_cache->cache_type);


+ return NULL;
+ }
+

+ avail_kmlblocks = inode->i_sb->u.ext3_sb.s_es->s_free_blocks_count;
+
+ if ( avail_kmlblocks < 3 ) {
+ return ERR_PTR(-ENOSPC);
+ }
+
+ if ( (op != PRESTO_OP_UNLINK && op != PRESTO_OP_RMDIR)
+ && avail_kmlblocks < 6 ) {
+ return ERR_PTR(-ENOSPC);
+ }
+
+ /* Need journal space for:
+ at least three writes to KML (two one block writes, one a path)
+ possibly a second name (unlink, rmdir)
+ possibly a second path (symlink, rename)
+ a one block write to the last rcvd file
+ */
+
+ trunc_blks = EXT3_DATA_TRANS_BLOCKS + 1;
+ one_path_blks = 4*EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode) + 3;
+ lml_blks = 4*EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode) + 2;
+ extra_path_blks = EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode);
+ extra_name_blks = EXT3_DATA_TRANS_BLOCKS + MAX_NAME_BLOCKS(inode);
+
+ /* additional blocks appear for "two pathname" operations
+ and operations involving the LML records
+ */
+ switch (op) {
+ case PRESTO_OP_TRUNC:
+ jblocks = one_path_blks + extra_name_blks + trunc_blks
+ + EXT3_DELETE_TRANS_BLOCKS;
+ break;
+ case PRESTO_OP_RELEASE:
+ /*
+ jblocks = one_path_blks + lml_blks + 2*trunc_blks;
+ */
+ jblocks = one_path_blks;
+ break;
+ case PRESTO_OP_SETATTR:
+ jblocks = one_path_blks + trunc_blks + 1 ;
+ break;
+ case PRESTO_OP_CREATE:
+ jblocks = one_path_blks + trunc_blks
+ + EXT3_DATA_TRANS_BLOCKS + 3;
+ break;
+ case PRESTO_OP_LINK:
+ jblocks = one_path_blks + trunc_blks
+ + EXT3_DATA_TRANS_BLOCKS;
+ break;
+ case PRESTO_OP_UNLINK:
+ jblocks = one_path_blks + extra_name_blks + trunc_blks
+ + EXT3_DELETE_TRANS_BLOCKS;
+ break;
+ case PRESTO_OP_SYMLINK:
+ jblocks = one_path_blks + extra_path_blks + trunc_blks
+ + EXT3_DATA_TRANS_BLOCKS + 5;
+ break;
+ case PRESTO_OP_MKDIR:
+ jblocks = one_path_blks + trunc_blks
+ + EXT3_DATA_TRANS_BLOCKS + 4;
+ break;
+ case PRESTO_OP_RMDIR:
+ jblocks = one_path_blks + extra_name_blks + trunc_blks
+ + EXT3_DELETE_TRANS_BLOCKS;
+ break;
+ case PRESTO_OP_MKNOD:
+ jblocks = one_path_blks + trunc_blks +
+ EXT3_DATA_TRANS_BLOCKS + 3;
+ break;
+ case PRESTO_OP_RENAME:
+ jblocks = one_path_blks + extra_path_blks + trunc_blks +
+ 2 * EXT3_DATA_TRANS_BLOCKS + 2;
+ break;
+ case PRESTO_OP_WRITE:
+ jblocks = one_path_blks;
+ /* add this when we can wrap our transaction with
+ that of ext3_file_write (ordered writes)
+ + EXT3_DATA_TRANS_BLOCKS;
+ */
+ break;
+ default:
+ CDEBUG(D_JOURNAL, "invalid operation %d for journal\n", op);


+ return NULL;
+ }
+

+ CDEBUG(D_JOURNAL, "creating journal handle (%d blocks)\n", jblocks);
+ return journal_start(EXT3_JOURNAL(inode), jblocks);
+}
+#endif
+
+void presto_obdfs_trans_commit(struct presto_file_set *fset, void *handle)
+{
+#if 0
+ if ( presto_no_journal(fset) || !handle)
+ return;
+
+ journal_stop(handle);
+#endif
+}
+
+void presto_obdfs_journal_file_data(struct inode *inode)
+{
+#ifdef EXT3_JOURNAL_DATA_FL


+ inode->u.ext3_i.i_flags |= EXT3_JOURNAL_DATA_FL;

+#else
+#warning You must have a facility to enable journaled writes for recovery!
+#endif
+}
+
+struct journal_ops presto_obdfs_journal_ops = {
+ tr_avail: presto_obdfs_freespace,
+ tr_start: presto_obdfs_trans_start,
+ tr_commit: presto_obdfs_trans_commit,
+ tr_journal_data: presto_obdfs_journal_file_data
+};
+
+#endif
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/journal_reiserfs.c linux/fs/intermezzo/journal_reiserfs.c
--- v2.4.14/linux/fs/intermezzo/journal_reiserfs.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/journal_reiserfs.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,119 @@
+


+/*
+ * Intermezzo. (C) 1998 Peter J. Braam

+ * Intermezzo. (C) 2000 Red Hat, Inc.
+ * Intermezzo. (C) 2000 Los Alamos National Laboratory
+ * Intermezzo. (C) 2000 TurboLinux, Inc.
+ * Intermezzo. (C) 2001 Mountain View Data, Inc.
+ */
+
+#include <linux/types.h>
+#include <linux/param.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/smp_lock.h>


+#include <linux/locks.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/string.h>

+#if 0
+#if defined(CONFIG_REISERFS_FS) || defined(CONFIG_REISERFS_FS_MODULE)
+#include <linux/reiserfs_fs.h>
+#include <linux/reiserfs_fs_sb.h>
+#include <linux/reiserfs_fs_i.h>
+#endif


+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+#include <linux/intermezzo_kml.h>

+#if defined(CONFIG_REISERFS_FS) || defined(CONFIG_REISERFS_FS_MODULE)
+
+
+static loff_t presto_reiserfs_freespace(struct presto_cache *cache,
+ struct super_block *sb)
+{
+ struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK (sb);
+ loff_t avail;
+
+ avail = le32_to_cpu(rs->s_free_blocks) *
+ le16_to_cpu(rs->s_blocksize);
+ return avail;
+}
+
+/* start the filesystem journal operations */
+static void *presto_reiserfs_trans_start(struct presto_file_set *fset,
+ struct inode *inode,
+ int op)
+{
+ int jblocks;
+ __u32 avail_kmlblocks;
+ struct reiserfs_transaction_handle *th ;
+
+ PRESTO_ALLOC(th, struct reiserfs_transaction_handle *, sizeof(*th));
+ if (!th) {
+ printk("presto: No memory for trans handle\n");


+ return NULL;
+ }
+

+ avail_kmlblocks = presto_reiserfs_freespace(fset->fset_cache,
+ inode->i_sb);
+ if ( presto_no_journal(fset) ||
+ strcmp(fset->fset_cache->cache_type, "reiserfs"))
+ {
+ CDEBUG(D_JOURNAL, "got cache_type \"%s\"\n",
+ fset->fset_cache->cache_type);


+ return NULL;
+ }
+

+ if ( avail_kmlblocks < 3 ) {
+ return ERR_PTR(-ENOSPC);
+ }
+
+ if ( (op != PRESTO_OP_UNLINK && op != PRESTO_OP_RMDIR)
+ && avail_kmlblocks < 6 ) {
+ return ERR_PTR(-ENOSPC);
+ }
+
+ jblocks = 3 + JOURNAL_PER_BALANCE_CNT * 4;
+ CDEBUG(D_JOURNAL, "creating journal handle (%d blocks)\n", jblocks);
+
+ lock_kernel();
+ //journal_begin(th, inode->i_sb, jblocks);
+ unlock_kernel();
+ return th;
+}
+
+void presto_reiserfs_trans_commit(struct presto_file_set *fset, void *handle)
+{
+ int jblocks;
+ jblocks = 3 + JOURNAL_PER_BALANCE_CNT * 4;
+
+ lock_kernel();
+ //journal_end(handle, fset->fset_cache->cache_sb, jblocks);
+ unlock_kernel();
+ PRESTO_FREE(handle, sizeof(struct reiserfs_transaction_handle));
+}
+
+void presto_reiserfs_journal_file_data(struct inode *inode)
+{
+#ifdef EXT3_JOURNAL_DATA_FL


+ inode->u.ext3_i.i_flags |= EXT3_JOURNAL_DATA_FL;

+#else
+#warning You must have a facility to enable journaled writes for recovery!
+#endif
+}
+
+struct journal_ops presto_reiserfs_journal_ops = {
+ tr_avail: presto_reiserfs_freespace,
+ tr_start: presto_reiserfs_trans_start,
+ tr_commit: presto_reiserfs_trans_commit,
+ tr_journal_data: presto_reiserfs_journal_file_data
+};
+
+#endif
+#endif
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/journal_xfs.c linux/fs/intermezzo/journal_xfs.c
--- v2.4.14/linux/fs/intermezzo/journal_xfs.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/journal_xfs.c Tue Nov 13 09:20:56 2001
@@ -0,0 +1,137 @@
+
+/*
+ * * Intermezzo. (C) 1998 Peter J. Braam
+ * */
+


+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>

+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/stat.h>
+#include <linux/errno.h>


+#include <linux/locks.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/string.h>

+#ifdef CONFIG_FS_XFS
+#include <linux/xfs_fs.h>
+#endif


+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+#include <linux/intermezzo_kml.h>

+#include <linux/intermezzo_journal.h>
+
+#if 0
+
+/* XFS has journalling, but these functions do nothing yet... */
+
+static unsigned long presto_xfs_freespace(struct presto_file_set *fset,
+ struct super_block *sb)
+{
+
+#if 0
+ vfs_t *vfsp = LINVFS_GET_VFS(sb);
+ struct statvfs_t stat;
+ bhv_desc_t *bdp;
+ unsigned long avail;
+ int rc;
+
+ VFS_STATVFS(vfsp, &stat, NULL, rc);
+ avail = statp.f_bfree;
+
+ return sbp->sb_fdblocks;;
+#endif
+ return 0x0fffffff;
+}
+
+
+/* start the filesystem journal operations */
+static void *
+presto_xfs_trans_start(struct presto_file_set *fset,
+ struct inode *inode, int op)
+{
+ int xfs_op;
+ /* do a free blocks check as in journal_ext3? does anything protect
+ * the space in that case or can it disappear out from under us
+ * anyway? */
+
+/* copied from xfs_trans.h, skipping header maze for now */
+#define XFS_TRANS_SETATTR_NOT_SIZE 1
+#define XFS_TRANS_SETATTR_SIZE 2
+#define XFS_TRANS_INACTIVE 3
+#define XFS_TRANS_CREATE 4
+#define XFS_TRANS_CREATE_TRUNC 5
+#define XFS_TRANS_TRUNCATE_FILE 6
+#define XFS_TRANS_REMOVE 7
+#define XFS_TRANS_LINK 8
+#define XFS_TRANS_RENAME 9
+#define XFS_TRANS_MKDIR 10
+#define XFS_TRANS_RMDIR 11
+#define XFS_TRANS_SYMLINK 12
+
+ /* map the op onto the values for XFS so it can do reservation. if
+ * we don't have enough info to differentiate between e.g. setattr
+ * with or without size, what do we do? will it adjust? */
+ switch (op) {
+ case PRESTO_OP_SETATTR:
+ /* or XFS_TRANS_SETATTR_NOT_SIZE? */
+ xfs_op = XFS_TRANS_SETATTR_SIZE;
+ break;
+ case PRESTO_OP_CREATE:
+ /* or CREATE_TRUNC? */
+ xfs_op = XFS_TRANS_CREATE;
+ break;
+ case PRESTO_OP_LINK:
+ xfs_op = XFS_TRANS_LINK;
+ break;
+ case PRESTO_OP_UNLINK:
+ xfs_op = XFS_TRANS_REMOVE;
+ break;
+ case PRESTO_OP_SYMLINK:
+ xfs_op = XFS_TRANS_SYMLINK;
+ break;
+ case PRESTO_OP_MKDIR:
+ xfs_op = XFS_TRANS_MKDIR;
+ break;
+ case PRESTO_OP_RMDIR:
+ xfs_op = XFS_TRANS_RMDIR;
+ break;
+ case PRESTO_OP_MKNOD:
+ /* XXX can't find an analog for mknod? */
+ xfs_op = XFS_TRANS_CREATE;
+ break;
+ case PRESTO_OP_RENAME:
+ xfs_op = XFS_TRANS_RENAME;
+ break;
+ default:
+ CDEBUG(D_JOURNAL, "invalid operation %d for journal\n", op);


+ return NULL;
+ }
+

+ return xfs_trans_start(inode, xfs_op);
+}
+
+static void presto_xfs_trans_commit(struct presto_file_set *fset, void *handle)
+{
+ /* assert (handle == current->j_handle) */
+ xfs_trans_stop(handle);
+}
+
+void presto_xfs_journal_file_data(struct inode *inode)


+{
+ return;
+}
+

+struct journal_ops presto_xfs_journal_ops = {
+ tr_avail: presto_xfs_freespace,
+ tr_start: presto_xfs_trans_start,
+ tr_commit: presto_xfs_trans_commit,
+ tr_journal_data: presto_xfs_journal_file_data
+};
+
+#endif /* CONFIG_XFS_FS */
+
+
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/kml.c linux/fs/intermezzo/kml.c
--- v2.4.14/linux/fs/intermezzo/kml.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/kml.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,199 @@


+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+#include <linux/intermezzo_kml.h>
+

+static struct presto_file_set * kml_getfset (char *path)
+{
+ return presto_path2fileset(path);
+}
+
+/* Send the KML buffer and related volume info into kernel */
+int begin_kml_reint (struct file *file, unsigned long arg)
+{
+ struct {
+ char *volname;
+ int namelen;
+ char *recbuf;
+ int reclen; /* int newpos; */
+ } input;
+ struct kml_fsdata *kml_fsdata = NULL;
+ struct presto_file_set *fset = NULL;
+ char *path;


+ int error;
+
+ ENTRY;

+ /* allocate buffer & copy it to kernel space */
+ error = copy_from_user(&input, (char *)arg, sizeof(input));
+ if ( error ) {
+ EXIT;


+ return error;
+ }
+

+ if (input.reclen > kml_fsdata->kml_maxsize)
+ return -ENOMEM; /* we'll find solution to this in the future */
+
+ PRESTO_ALLOC(path, char *, input.namelen + 1);
+ if ( !path ) {
+ EXIT;
+ return -ENOMEM;
+ }
+ error = copy_from_user(path, input.volname, input.namelen);


+ if ( error ) {

+ PRESTO_FREE(path, input.namelen + 1);


+ EXIT;
+ return error;
+ }

+ path[input.namelen] = '\0';
+ fset = kml_getfset (path);
+ PRESTO_FREE(path, input.namelen + 1);
+
+ kml_fsdata = FSET_GET_KMLDATA(fset);
+ /* read the buf from user memory here */
+ error = copy_from_user(kml_fsdata->kml_buf, input.recbuf, input.reclen);
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+ kml_fsdata->kml_len = input.reclen;
+
+ decode_kmlrec (&kml_fsdata->kml_reint_cache,
+ kml_fsdata->kml_buf, kml_fsdata->kml_len);
+
+ kml_fsdata->kml_reint_current = kml_fsdata->kml_reint_cache.next;
+ kml_fsdata->kml_reintpos = 0;
+ kml_fsdata->kml_count = 0;


+ return 0;
+}
+

+/* DO_KML_REINT */
+int do_kml_reint (struct file *file, unsigned long arg)
+{
+ struct {
+ char *volname;
+ int namelen;
+ char *path;
+ int pathlen;
+ int recno;
+ int offset;
+ int len;
+ int generation;
+ __u64 ino;
+ } input;
+ int error;
+ char *path;
+ struct kml_rec *close_rec;
+ struct kml_fsdata *kml_fsdata;


+ struct presto_file_set *fset;
+

+ ENTRY;
+ error = copy_from_user(&input, (char *)arg, sizeof(input));
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+ PRESTO_ALLOC(path, char *, input.namelen + 1);
+ if ( !path ) {
+ EXIT;
+ return -ENOMEM;
+ }
+ error = copy_from_user(path, input.volname, input.namelen);


+ if ( error ) {

+ PRESTO_FREE(path, input.namelen + 1);


+ EXIT;
+ return error;
+ }

+ path[input.namelen] = '\0';
+ fset = kml_getfset (path);
+ PRESTO_FREE(path, input.namelen + 1);
+
+ kml_fsdata = FSET_GET_KMLDATA(fset);
+
+ error = kml_reintbuf(kml_fsdata,
+ fset->fset_mtpt->d_name.name,
+ &close_rec);
+
+ if (error == KML_CLOSE_BACKFETCH && close_rec != NULL) {
+ struct kml_close *close = &close_rec->rec_kml.close;
+ input.ino = close->ino;
+ input.generation = close->generation;
+ if (strlen (close->path) + 1 < input.pathlen) {
+ strcpy (input.path, close->path);
+ input.pathlen = strlen (close->path) + 1;
+ input.recno = close_rec->rec_tail.recno;
+ input.offset = close_rec->rec_kml_offset;
+ input.len = close_rec->rec_size;
+ input.generation = close->generation;
+ input.ino = close->ino;
+ }
+ else {
+ CDEBUG(D_KML, "KML_DO_REINT::no space to save:%d < %d",
+ strlen (close->path) + 1, input.pathlen);
+ error = -ENOMEM;
+ }
+ copy_to_user((char *)arg, &input, sizeof (input));
+ }


+ return error;
+}
+

+/* END_KML_REINT */
+int end_kml_reint (struct file *file, unsigned long arg)
+{
+ /* Free KML buffer and related volume info */
+ struct {
+ char *volname;
+ int namelen;
+#if 0
+ int count;
+ int newpos;
+#endif
+ } input;
+ struct presto_file_set *fset = NULL;
+ struct kml_fsdata *kml_fsdata = NULL;
+ int error;
+ char *path;
+
+ ENTRY;
+ error = copy_from_user(&input, (char *)arg, sizeof(input));
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ PRESTO_ALLOC(path, char *, input.namelen + 1);
+ if ( !path ) {
+ EXIT;
+ return -ENOMEM;
+ }
+ error = copy_from_user(path, input.volname, input.namelen);


+ if ( error ) {

+ PRESTO_FREE(path, input.namelen + 1);


+ EXIT;
+ return error;
+ }

+ path[input.namelen] = '\0';
+ fset = kml_getfset (path);
+ PRESTO_FREE(path, input.namelen + 1);
+
+ kml_fsdata = FSET_GET_KMLDATA(fset);
+ delete_kmlrec (&kml_fsdata->kml_reint_cache);
+
+ /* kml reint support */
+ kml_fsdata->kml_reint_current = NULL;
+ kml_fsdata->kml_len = 0;
+ kml_fsdata->kml_reintpos = 0;
+ kml_fsdata->kml_count = 0;
+#if 0
+ input.newpos = kml_upc->newpos;
+ input.count = kml_upc->count;
+ copy_to_user((char *)arg, &input, sizeof (input));
+#endif
+ return error;
+}
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/kml_decode.c linux/fs/intermezzo/kml_decode.c
--- v2.4.14/linux/fs/intermezzo/kml_decode.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/kml_decode.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,1017 @@
+/*
+ * KML Decoding


+ *
+ * Copryright (C) 1996 Arthur Ma <arth...@mountainviewdata.com>
+ *

+ * Copyright (C) 2001 Mountainview Data, Inc.
+ */


+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/errno.h>

+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>

+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_kml.h>
+
+static int size_round (int val);
+static int unpack_create (struct kml_create *rec, char *buf,
+ int pos, int *rec_offs);
+static int unpack_open (struct kml_open *rec, char *buf,
+ int pos, int *rec_offs);
+static int unpack_symlink (struct kml_symlink *rec, char *buf,
+ int pos, int *rec_offs);
+static int unpack_mknod (struct kml_mknod *rec, char *buf,
+ int pos, int *rec_offs);
+static int unpack_link (struct kml_link *rec, char *buf,
+ int pos, int *rec_offs);
+static int unpack_rename (struct kml_rename *rec, char *buf,
+ int pos, int *rec_offs);
+static int unpack_unlink (struct kml_unlink *rec, char *buf,
+ int pos, int *rec_offs);
+static int unpack_rmdir (struct kml_rmdir *rec, char *buf,
+ int pos, int *rec_offs);
+static int unpack_setattr (struct kml_setattr *rec, char *buf,
+ int pos, int *rec_offs);
+static int unpack_close (struct kml_close *rec, char *buf,
+ int pos, int *rec_offs);


+static int unpack_mkdir (struct kml_mkdir *rec, char *buf,
+ int pos, int *rec_offs);
+

+#if 0
+static int unpack_endmark (struct kml_endmark *rec, char *buf,

+ int pos, int *rec_offs);
+static void print_kml_endmark (struct kml_endmark *rec);
+#endif
+
+static int kml_unpack (char *kml_buf, int rec_size, int kml_offset,
+ struct kml_rec **newrec);
+static char *kml_version (struct presto_version *ver);
+static void print_kml_prefix (struct big_journal_prefix *head);
+static void print_kml_create (struct kml_create *rec);
+static void print_kml_mkdir (struct kml_mkdir *rec);
+static void print_kml_unlink (struct kml_unlink *rec);
+static void print_kml_rmdir (struct kml_rmdir *rec);
+static void print_kml_close (struct kml_close *rec);
+static void print_kml_symlink (struct kml_symlink *rec);
+static void print_kml_rename (struct kml_rename *rec);
+static void print_kml_setattr (struct kml_setattr *rec);
+static void print_kml_link (struct kml_link *rec);
+static void print_kml_mknod (struct kml_mknod *rec);
+static void print_kml_open (struct kml_open *rec);
+static void print_kml_suffix (struct journal_suffix *tail);
+static char *readrec (char *recbuf, int reclen, int pos, int *size);
+
+#define KML_PREFIX_WORDS 8
+static int kml_unpack (char *kml_buf, int rec_size, int kml_offset,

+ struct kml_rec **newrec)
+{

+ struct kml_rec *rec;
+ char *p;
+ int pos, rec_offs;


+ int error;
+
+ ENTRY;

+ if (rec_size < sizeof (struct journal_prefix) +
+ sizeof (struct journal_suffix))
+ return -EBADF;
+
+ PRESTO_ALLOC(rec, struct kml_rec *, sizeof (struct kml_rec));
+ if (rec == NULL) {


+ EXIT;
+ return -ENOMEM;
+ }

+ rec->rec_kml_offset = kml_offset;
+ rec->rec_size = rec_size;
+ p = kml_buf;
+ p = dlogit (&rec->rec_head, p, KML_PREFIX_WORDS * sizeof (int));
+ p = dlogit (&rec->rec_head.groups, p,
+ sizeof (int) * rec->rec_head.ngroups);
+
+ pos = sizeof (struct journal_prefix) +
+ sizeof (int) * rec->rec_head.ngroups;


+ switch (rec->rec_head.opcode)
+ {
+ case KML_CREATE:

+ error = unpack_create (&rec->rec_kml.create,
+ kml_buf, pos, &rec_offs);


+ break;
+ case KML_MKDIR:

+ error = unpack_mkdir (&rec->rec_kml.mkdir,
+ kml_buf, pos, &rec_offs);


+ break;
+ case KML_UNLINK:

+ error = unpack_unlink (&rec->rec_kml.unlink,
+ kml_buf, pos, &rec_offs);


+ break;
+ case KML_RMDIR:

+ error = unpack_rmdir (&rec->rec_kml.rmdir,
+ kml_buf, pos, &rec_offs);


+ break;
+ case KML_CLOSE:

+ error = unpack_close (&rec->rec_kml.close,
+ kml_buf, pos, &rec_offs);


+ break;
+ case KML_SYMLINK:

+ error = unpack_symlink (&rec->rec_kml.symlink,
+ kml_buf, pos, &rec_offs);


+ break;
+ case KML_RENAME:

+ error = unpack_rename (&rec->rec_kml.rename,
+ kml_buf, pos, &rec_offs);


+ break;
+ case KML_SETATTR:

+ error = unpack_setattr (&rec->rec_kml.setattr,
+ kml_buf, pos, &rec_offs);


+ break;
+ case KML_LINK:

+ error = unpack_link (&rec->rec_kml.link,
+ kml_buf, pos, &rec_offs);


+ break;
+ case KML_OPEN:

+ error = unpack_open (&rec->rec_kml.open,
+ kml_buf, pos, &rec_offs);


+ break;
+ case KML_MKNOD:

+ error = unpack_mknod (&rec->rec_kml.mknod,
+ kml_buf, pos, &rec_offs);


+ break;
+#if 0
+ case KML_ENDMARK:

+ error = unpack_endmark (&rec->rec_kml.endmark,
+ kml_buf, pos, &rec_offs);
+ break;
+#endif
+ default:
+ CDEBUG (D_KML, "wrong opcode::%u\n",
+ rec->rec_head.opcode);


+ EXIT;
+ return -EINVAL;
+ }

+ if (error) {
+ PRESTO_FREE (rec, sizeof (struct kml_rec));
+ return -EINVAL;
+ }
+ p = kml_buf + rec_offs;
+ p = dlogit (&rec->rec_tail, p, sizeof (struct journal_suffix));
+ memset (&rec->kml_optimize, 0, sizeof (struct kml_optimize));
+ *newrec = rec;


+ EXIT;
+ return 0;
+}
+

+static int size_round (int val)
+{
+ return (val + 3) & (~0x3);
+}
+
+static int unpack_create (struct kml_create *rec, char *buf,

+ *rec_offs = pos + unpack_size + size_round(pathlen);
+ EXIT;
+ return 0;
+}
+

+static int unpack_open (struct kml_open *rec, char *buf,

+ int pos, int *rec_offs)
+{

+ *rec_offs = pos;


+ return 0;
+}
+

+static int unpack_symlink (struct kml_symlink *rec, char *buf,

+ int pos, int *rec_offs)
+{
+ char *p, *q;
+ int unpack_size = 88;

+ int pathlen, targetlen;


+
+ ENTRY;
+ p = buf + pos;
+ p = dlogit (&rec->old_parentv, p, sizeof (struct presto_version));
+ p = dlogit (&rec->new_parentv, p, sizeof (struct presto_version));
+ p = dlogit (&rec->new_objectv, p, sizeof (struct presto_version));

+ p = dlogit (&rec->uid, p, sizeof (int));
+ p = dlogit (&rec->gid, p, sizeof (int));
+ p = dlogit (&pathlen, p, sizeof (int));

+ p = dlogit (&targetlen, p, sizeof (int));


+
+ PRESTO_ALLOC(q, char *, pathlen + 1);
+ if (q == NULL) {
+ EXIT;
+ return -ENOMEM;
+ }
+
+ memcpy (q, p, pathlen);
+ q[pathlen] = '\0';

+ rec->sourcepath = q;
+
+ PRESTO_ALLOC(q, char *, targetlen + 1);


+ if (q == NULL) {

+ PRESTO_FREE (rec->sourcepath, pathlen + 1);


+ EXIT;
+ return -ENOMEM;
+ }
+

+ memcpy (q, p, targetlen);
+ q[targetlen] = '\0';
+ rec->targetpath = q;


+
+ *rec_offs = pos + unpack_size + size_round(pathlen) +

+ size_round(targetlen);


+ EXIT;
+ return 0;
+}
+

+static int unpack_mknod (struct kml_mknod *rec, char *buf,

+ int pos, int *rec_offs)
+{
+ char *p, *q;

+ int unpack_size = 96;


+ int pathlen;
+
+ ENTRY;
+ p = buf + pos;
+ p = dlogit (&rec->old_parentv, p, sizeof (struct presto_version));
+ p = dlogit (&rec->new_parentv, p, sizeof (struct presto_version));
+ p = dlogit (&rec->new_objectv, p, sizeof (struct presto_version));
+ p = dlogit (&rec->mode, p, sizeof (int));
+ p = dlogit (&rec->uid, p, sizeof (int));
+ p = dlogit (&rec->gid, p, sizeof (int));

+ p = dlogit (&rec->major, p, sizeof (int));
+ p = dlogit (&rec->minor, p, sizeof (int));


+ p = dlogit (&pathlen, p, sizeof (int));
+
+ PRESTO_ALLOC(q, char *, pathlen + 1);
+ if (q == NULL) {
+ EXIT;
+ return -ENOMEM;
+ }
+
+ memcpy (q, p, pathlen);
+ q[pathlen] = '\0';
+ rec->path = q;
+

+ *rec_offs = pos + unpack_size + size_round(pathlen);
+ EXIT;
+ return 0;
+}
+

+static int unpack_link (struct kml_link *rec, char *buf,

+ int pos, int *rec_offs)
+{
+ char *p, *q;

+ int unpack_size = 80;
+ int pathlen, targetlen;


+
+ ENTRY;
+ p = buf + pos;
+ p = dlogit (&rec->old_parentv, p, sizeof (struct presto_version));
+ p = dlogit (&rec->new_parentv, p, sizeof (struct presto_version));
+ p = dlogit (&rec->new_objectv, p, sizeof (struct presto_version));

+ p = dlogit (&pathlen, p, sizeof (int));

+ p = dlogit (&targetlen, p, sizeof (int));


+
+ PRESTO_ALLOC(q, char *, pathlen + 1);
+ if (q == NULL) {
+ EXIT;
+ return -ENOMEM;
+ }
+
+ memcpy (q, p, pathlen);
+ q[pathlen] = '\0';

+ rec->sourcepath = q;
+ p += size_round (pathlen);
+
+ PRESTO_ALLOC(q, char *, targetlen + 1);


+ if (q == NULL) {

+ PRESTO_FREE (rec->sourcepath, pathlen + 1);


+ EXIT;
+ return -ENOMEM;
+ }

+ memcpy (q, p, targetlen);
+ q[targetlen] = '\0';
+ rec->targetpath = q;


+
+ *rec_offs = pos + unpack_size + size_round(pathlen) +

+ size_round(targetlen);


+ EXIT;
+ return 0;
+}
+

+static int unpack_rename (struct kml_rename *rec, char *buf,

+ int pos, int *rec_offs)
+{
+ char *p, *q;

+ int unpack_size = 104;
+ int pathlen, targetlen;


+
+ ENTRY;
+ p = buf + pos;

+ p = dlogit (&rec->old_objectv, p, sizeof (struct presto_version));


+ p = dlogit (&rec->new_objectv, p, sizeof (struct presto_version));

+ p = dlogit (&rec->new_tgtv, p, sizeof (struct presto_version));
+ p = dlogit (&rec->old_tgtv, p, sizeof (struct presto_version));


+ p = dlogit (&pathlen, p, sizeof (int));

+ p = dlogit (&targetlen, p, sizeof (int));


+
+ PRESTO_ALLOC(q, char *, pathlen + 1);
+ if (q == NULL) {
+ EXIT;
+ return -ENOMEM;
+ }
+
+ memcpy (q, p, pathlen);
+ q[pathlen] = '\0';

+ rec->sourcepath = q;
+ p += size_round (pathlen);
+
+ PRESTO_ALLOC(q, char *, targetlen + 1);


+ if (q == NULL) {

+ PRESTO_FREE (rec->sourcepath, pathlen + 1);


+ EXIT;
+ return -ENOMEM;
+ }
+

+ memcpy (q, p, targetlen);
+ q[targetlen] = '\0';
+ rec->targetpath = q;


+
+ *rec_offs = pos + unpack_size + size_round(pathlen) +

+ size_round(targetlen);


+ EXIT;
+ return 0;
+}
+

+static int unpack_unlink (struct kml_unlink *rec, char *buf,

+ int pos, int *rec_offs)
+{
+ char *p, *q;

+ int unpack_size = 80;
+ int pathlen, targetlen;


+
+ ENTRY;
+ p = buf + pos;
+ p = dlogit (&rec->old_parentv, p, sizeof (struct presto_version));
+ p = dlogit (&rec->new_parentv, p, sizeof (struct presto_version));

+ p = dlogit (&rec->old_tgtv, p, sizeof (struct presto_version));


+ p = dlogit (&pathlen, p, sizeof (int));

+ p = dlogit (&targetlen, p, sizeof (int));


+
+ PRESTO_ALLOC(q, char *, pathlen + 1);
+ if (q == NULL) {
+ EXIT;
+ return -ENOMEM;
+ }
+
+ memcpy (q, p, pathlen);
+ q[pathlen] = '\0';
+ rec->path = q;

+ p += size_round (pathlen);
+
+ PRESTO_ALLOC(q, char *, targetlen + 1);


+ if (q == NULL) {

+ PRESTO_FREE (rec->path, pathlen + 1);


+ EXIT;
+ return -ENOMEM;
+ }
+

+ memcpy (q, p, targetlen);
+ q[targetlen] = '\0';
+ rec->name = q;
+
+ /* fix the presto_journal_unlink problem */


+ *rec_offs = pos + unpack_size + size_round(pathlen) +

+ size_round(targetlen);


+ EXIT;
+ return 0;
+}
+

+static int unpack_rmdir (struct kml_rmdir *rec, char *buf,

+ int pos, int *rec_offs)
+{
+ char *p, *q;

+ int unpack_size = 80;
+ int pathlen, targetlen;


+
+ ENTRY;
+ p = buf + pos;
+ p = dlogit (&rec->old_parentv, p, sizeof (struct presto_version));
+ p = dlogit (&rec->new_parentv, p, sizeof (struct presto_version));

+ p = dlogit (&rec->old_tgtv, p, sizeof (struct presto_version));


+ p = dlogit (&pathlen, p, sizeof (int));

+ p = dlogit (&targetlen, p, sizeof (int));


+
+ PRESTO_ALLOC(q, char *, pathlen + 1);
+ if (q == NULL) {
+ EXIT;
+ return -ENOMEM;
+ }
+
+ memcpy (q, p, pathlen);
+ q[pathlen] = '\0';
+ rec->path = q;

+ p += size_round (pathlen);
+
+ PRESTO_ALLOC(q, char *, targetlen + 1);


+ if (q == NULL) {

+ PRESTO_FREE (rec->path, pathlen + 1);


+ EXIT;
+ return -ENOMEM;
+ }

+ memcpy (q, p, targetlen);
+ q[targetlen] = '\0';
+ rec->name = q;


+
+ *rec_offs = pos + unpack_size + size_round(pathlen) +

+ size_round(targetlen);


+ EXIT;
+ return 0;
+}
+

+static int unpack_setattr (struct kml_setattr *rec, char *buf,

+ int pos, int *rec_offs)
+{
+ char *p, *q;

+ int unpack_size = 72;
+ struct kml_attr {
+ __u64 size, mtime, ctime;
+ } objattr;
+ int valid, mode, uid, gid, flags;


+ int pathlen;
+
+ ENTRY;
+ p = buf + pos;

+ p = dlogit (&rec->old_objectv, p, sizeof (struct presto_version));
+ p = dlogit (&valid, p, sizeof (int));
+ p = dlogit (&mode, p, sizeof (int));
+ p = dlogit (&uid, p, sizeof (int));
+ p = dlogit (&gid, p, sizeof (int));
+ p = dlogit (&objattr, p, sizeof (struct kml_attr));
+ p = dlogit (&flags, p, sizeof (int));


+ p = dlogit (&pathlen, p, sizeof (int));
+

+ rec->iattr.ia_valid = valid;
+ rec->iattr.ia_mode = mode;
+ rec->iattr.ia_uid = uid;
+ rec->iattr.ia_gid = gid;
+ rec->iattr.ia_size = objattr.size;
+ rec->iattr.ia_mtime = objattr.mtime;
+ rec->iattr.ia_ctime = objattr.ctime;
+ rec->iattr.ia_atime = 0;
+ rec->iattr.ia_attr_flags = flags;


+
+ PRESTO_ALLOC(q, char *, pathlen + 1);
+ if (q == NULL) {
+ EXIT;
+ return -ENOMEM;
+ }
+ memcpy (q, p, pathlen);
+ q[pathlen] = '\0';
+ rec->path = q;
+ p += pathlen;
+
+ *rec_offs = pos + unpack_size + size_round(pathlen);
+ EXIT;
+ return 0;
+}
+

+static int unpack_close (struct kml_close *rec, char *buf,

+ int pos, int *rec_offs)
+{
+ char *p, *q;

+ int unpack_size = 52;


+ int pathlen;
+
+ ENTRY;
+ p = buf + pos;

+ p = dlogit (&rec->open_mode, p, sizeof (int));
+ p = dlogit (&rec->open_uid, p, sizeof (int));
+ p = dlogit (&rec->open_gid, p, sizeof (int));


+ p = dlogit (&rec->new_objectv, p, sizeof (struct presto_version));

+ p = dlogit (&rec->ino, p, sizeof (__u64));
+ p = dlogit (&rec->generation, p, sizeof (int));


+ p = dlogit (&pathlen, p, sizeof (int));
+
+ PRESTO_ALLOC(q, char *, pathlen + 1);
+ if (q == NULL) {
+ EXIT;
+ return -ENOMEM;
+ }
+
+ memcpy (q, p, pathlen);
+ q[pathlen] = '\0';
+ rec->path = q;
+ p += pathlen;
+
+ *rec_offs = pos + unpack_size + size_round(pathlen);

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

echo 'End of part 093'
echo 'File patch-2.4.15 is continued in part 094'
echo "094" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:15 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part099

#!/bin/sh -x
# this is part 099 of a 115 - part archive


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

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

+ wait_for_iobuf:
+ while (commit_transaction->t_iobuf_list != NULL) {
+ struct buffer_head *bh;
+ jh = commit_transaction->t_iobuf_list->b_tprev;
+ bh = jh2bh(jh);
+ if (buffer_locked(bh)) {
+ unlock_journal(journal);
+ wait_on_buffer(bh);
+ lock_journal(journal);
+ goto wait_for_iobuf;
+ }
+
+ clear_bit(BH_JWrite, &jh2bh(jh)->b_state);
+
+ JBUFFER_TRACE(jh, "ph4: unfile after journal write");
+ journal_unfile_buffer(jh);
+
+ /*
+ * akpm: don't put back a buffer_head with stale pointers
+ * dangling around.
+ */
+ J_ASSERT_JH(jh, jh->b_transaction != NULL);
+ jh->b_transaction = NULL;
+
+ /*
+ * ->t_iobuf_list should contain only dummy buffer_heads
+ * which were created by journal_write_metadata_buffer().
+ */
+ bh = jh2bh(jh);
+ BUFFER_TRACE(bh, "dumping temporary bh");
+ journal_unlock_journal_head(jh);
+ __brelse(bh);
+ J_ASSERT_BH(bh, atomic_read(&bh->b_count) == 0);
+ put_unused_buffer_head(bh);
+
+ /* We also have to unlock and free the corresponding
+ shadowed buffer */
+ jh = commit_transaction->t_shadow_list->b_tprev;
+ bh = jh2bh(jh);
+ clear_bit(BH_JWrite, &bh->b_state);
+ J_ASSERT_BH(bh, buffer_jdirty(bh));
+
+ /* The metadata is now released for reuse, but we need
+ to remember it against this transaction so that when
+ we finally commit, we can do any checkpointing
+ required. */
+ JBUFFER_TRACE(jh, "file as BJ_Forget");
+ journal_file_buffer(jh, commit_transaction, BJ_Forget);
+ /* Wake up any transactions which were waiting for this
+ IO to complete */
+ wake_up(&bh->b_wait);
+ JBUFFER_TRACE(jh, "brelse shadowed buffer");
+ __brelse(bh);
+ }
+
+ J_ASSERT (commit_transaction->t_shadow_list == NULL);
+
+ jbd_debug(3, "JBD: commit phase 5\n");
+
+ /* Here we wait for the revoke record and descriptor record buffers */
+ wait_for_ctlbuf:
+ while (commit_transaction->t_log_list != NULL) {


+ struct buffer_head *bh;
+

+ jh = commit_transaction->t_log_list->b_tprev;
+ bh = jh2bh(jh);
+ if (buffer_locked(bh)) {
+ unlock_journal(journal);
+ wait_on_buffer(bh);
+ lock_journal(journal);
+ goto wait_for_ctlbuf;
+ }
+
+ BUFFER_TRACE(bh, "ph5: control buffer writeout done: unfile");
+ clear_bit(BH_JWrite, &bh->b_state);
+ journal_unfile_buffer(jh);
+ jh->b_transaction = NULL;
+ journal_unlock_journal_head(jh);
+ __brelse(bh); /* One for getblk */
+ /* AKPM: bforget here */
+ }
+
+ jbd_debug(3, "JBD: commit phase 6\n");
+
+ /* Done it all: now write the commit record. We should have
+ * cleaned up our previous buffers by now, so if we are in abort
+ * mode we can now just skip the rest of the journal write
+ * entirely. */
+
+ if (is_journal_aborted(journal))
+ goto skip_commit;
+
+ descriptor = journal_get_descriptor_buffer(journal);
+
+ /* AKPM: buglet - add `i' to tmp! */
+ for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
+ journal_header_t *tmp =
+ (journal_header_t*)jh2bh(descriptor)->b_data;
+ tmp->h_magic = htonl(JFS_MAGIC_NUMBER);
+ tmp->h_blocktype = htonl(JFS_COMMIT_BLOCK);
+ tmp->h_sequence = htonl(commit_transaction->t_tid);
+ }
+
+ unlock_journal(journal);
+ JBUFFER_TRACE(descriptor, "write commit block");
+ {
+ struct buffer_head *bh = jh2bh(descriptor);
+ ll_rw_block(WRITE, 1, &bh);
+ wait_on_buffer(bh);
+ __brelse(bh); /* One for getblk() */
+ journal_unlock_journal_head(descriptor);
+ }
+ lock_journal(journal);
+
+ /* End of a transaction! Finally, we can do checkpoint
+ processing: any buffers committed as a result of this
+ transaction can be removed from any checkpoint list it was on
+ before. */
+
+skip_commit:
+
+ jbd_debug(3, "JBD: commit phase 7\n");
+
+ J_ASSERT(commit_transaction->t_sync_datalist == NULL);
+ J_ASSERT(commit_transaction->t_async_datalist == NULL);
+ J_ASSERT(commit_transaction->t_buffers == NULL);
+ J_ASSERT(commit_transaction->t_checkpoint_list == NULL);
+ J_ASSERT(commit_transaction->t_iobuf_list == NULL);
+ J_ASSERT(commit_transaction->t_shadow_list == NULL);
+ J_ASSERT(commit_transaction->t_log_list == NULL);
+
+ while (commit_transaction->t_forget) {
+ transaction_t *cp_transaction;


+ struct buffer_head *bh;
+

+ jh = commit_transaction->t_forget;
+ J_ASSERT_JH(jh, jh->b_transaction == commit_transaction ||
+ jh->b_transaction == journal->j_running_transaction);
+
+ /*
+ * If there is undo-protected committed data against
+ * this buffer, then we can remove it now. If it is a
+ * buffer needing such protection, the old frozen_data
+ * field now points to a committed version of the
+ * buffer, so rotate that field to the new committed
+ * data.
+ *
+ * Otherwise, we can just throw away the frozen data now.
+ */
+ if (jh->b_committed_data) {
+ kfree(jh->b_committed_data);
+ jh->b_committed_data = NULL;
+ if (jh->b_frozen_data) {
+ jh->b_committed_data = jh->b_frozen_data;
+ jh->b_frozen_data = NULL;
+ }
+ } else if (jh->b_frozen_data) {
+ kfree(jh->b_frozen_data);
+ jh->b_frozen_data = NULL;
+ }
+
+ spin_lock(&journal_datalist_lock);
+ cp_transaction = jh->b_cp_transaction;
+ if (cp_transaction) {
+ JBUFFER_TRACE(jh, "remove from old cp transaction");
+ J_ASSERT_JH(jh, commit_transaction != cp_transaction);
+ __journal_remove_checkpoint(jh);
+ }
+
+ /* Only re-checkpoint the buffer_head if it is marked
+ * dirty. If the buffer was added to the BJ_Forget list
+ * by journal_forget, it may no longer be dirty and
+ * there's no point in keeping a checkpoint record for
+ * it. */
+ bh = jh2bh(jh);
+ if (buffer_jdirty(bh)) {
+ JBUFFER_TRACE(jh, "add to new checkpointing trans");
+ __journal_insert_checkpoint(jh, commit_transaction);
+ JBUFFER_TRACE(jh, "refile for checkpoint writeback");
+ __journal_refile_buffer(jh);
+ } else {
+ J_ASSERT_BH(bh, !buffer_dirty(bh));
+ J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
+ __journal_unfile_buffer(jh);
+ jh->b_transaction = 0;
+ __journal_remove_journal_head(bh);
+ __brelse(bh);
+ }
+ spin_unlock(&journal_datalist_lock);
+ }
+
+ /* Done with this transaction! */
+
+ jbd_debug(3, "JBD: commit phase 8\n");
+
+ J_ASSERT (commit_transaction->t_state == T_COMMIT);
+ commit_transaction->t_state = T_FINISHED;
+
+ J_ASSERT (commit_transaction == journal->j_committing_transaction);
+ journal->j_commit_sequence = commit_transaction->t_tid;
+ journal->j_committing_transaction = NULL;
+
+ spin_lock(&journal_datalist_lock);
+ if (commit_transaction->t_checkpoint_list == NULL) {
+ __journal_drop_transaction(journal, commit_transaction);
+ } else {
+ if (journal->j_checkpoint_transactions == NULL) {
+ journal->j_checkpoint_transactions = commit_transaction;
+ commit_transaction->t_cpnext = commit_transaction;
+ commit_transaction->t_cpprev = commit_transaction;
+ } else {
+ commit_transaction->t_cpnext =
+ journal->j_checkpoint_transactions;
+ commit_transaction->t_cpprev =
+ commit_transaction->t_cpnext->t_cpprev;
+ commit_transaction->t_cpnext->t_cpprev =
+ commit_transaction;
+ commit_transaction->t_cpprev->t_cpnext =
+ commit_transaction;
+ }
+ }
+ spin_unlock(&journal_datalist_lock);
+
+ jbd_debug(1, "JBD: commit %d complete, head %d\n",
+ journal->j_commit_sequence, journal->j_tail_sequence);
+
+ unlock_journal(journal);
+ wake_up(&journal->j_wait_done_commit);
+}
diff -u --recursive --new-file v2.4.14/linux/fs/jbd/journal.c linux/fs/jbd/journal.c
--- v2.4.14/linux/fs/jbd/journal.c Wed Dec 31 16:00:00 1969
+++ linux/fs/jbd/journal.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,1813 @@
+/*
+ * linux/fs/journal.c
+ *
+ * Written by Stephen C. Tweedie <s...@redhat.com>, 1998
+ *
+ * Copyright 1998 Red Hat corp --- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * Generic filesystem journal-writing code; part of the ext2fs
+ * journaling system.
+ *
+ * This file manages journals: areas of disk reserved for logging
+ * transactional updates. This includes the kernel journaling thread
+ * which is responsible for scheduling updates to the log.
+ *
+ * We do not actually manage the physical storage of the journal in this
+ * file: that is left to a per-journal policy function, which allows us
+ * to store the journal within a filesystem-specified area for ext2
+ * journaling (ext2 can use a reserved inode for storing the log).
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/jbd.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/locks.h>
+#include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <linux/proc_fs.h>
+
+EXPORT_SYMBOL(journal_start);
+EXPORT_SYMBOL(journal_try_start);
+EXPORT_SYMBOL(journal_restart);
+EXPORT_SYMBOL(journal_extend);
+EXPORT_SYMBOL(journal_stop);
+EXPORT_SYMBOL(journal_lock_updates);
+EXPORT_SYMBOL(journal_unlock_updates);
+EXPORT_SYMBOL(journal_get_write_access);
+EXPORT_SYMBOL(journal_get_create_access);
+EXPORT_SYMBOL(journal_get_undo_access);
+EXPORT_SYMBOL(journal_dirty_data);
+EXPORT_SYMBOL(journal_dirty_metadata);
+#if 0
+EXPORT_SYMBOL(journal_release_buffer);
+#endif
+EXPORT_SYMBOL(journal_forget);
+#if 0
+EXPORT_SYMBOL(journal_sync_buffer);
+#endif
+EXPORT_SYMBOL(journal_flush);
+EXPORT_SYMBOL(journal_revoke);
+
+EXPORT_SYMBOL(journal_init_dev);
+EXPORT_SYMBOL(journal_init_inode);
+EXPORT_SYMBOL(journal_update_format);
+EXPORT_SYMBOL(journal_check_used_features);
+EXPORT_SYMBOL(journal_check_available_features);
+EXPORT_SYMBOL(journal_set_features);
+EXPORT_SYMBOL(journal_create);
+EXPORT_SYMBOL(journal_load);
+EXPORT_SYMBOL(journal_destroy);
+EXPORT_SYMBOL(journal_recover);
+EXPORT_SYMBOL(journal_update_superblock);
+EXPORT_SYMBOL(__journal_abort);
+EXPORT_SYMBOL(journal_abort);
+EXPORT_SYMBOL(journal_errno);
+EXPORT_SYMBOL(journal_ack_err);
+EXPORT_SYMBOL(journal_clear_err);
+EXPORT_SYMBOL(log_wait_commit);
+EXPORT_SYMBOL(log_start_commit);
+EXPORT_SYMBOL(journal_wipe);
+EXPORT_SYMBOL(journal_blocks_per_page);
+EXPORT_SYMBOL(journal_flushpage);
+EXPORT_SYMBOL(journal_try_to_free_buffers);
+EXPORT_SYMBOL(journal_bmap);
+EXPORT_SYMBOL(journal_force_commit);
+
+static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
+
+/*
+ * journal_datalist_lock is used to protect data buffers:
+ *
+ * bh->b_transaction
+ * bh->b_tprev
+ * bh->b_tnext
+ *
+ * journal_free_buffer() is called from journal_try_to_free_buffer(), and is
+ * async wrt everything else.
+ *
+ * It is also used for checkpoint data, also to protect against
+ * journal_try_to_free_buffer():
+ *
+ * bh->b_cp_transaction
+ * bh->b_cpnext
+ * bh->b_cpprev
+ * transaction->t_checkpoint_list
+ * transaction->t_cpnext
+ * transaction->t_cpprev
+ * journal->j_checkpoint_transactions
+ *
+ * It is global at this time rather than per-journal because it's
+ * impossible for __journal_free_buffer to go from a buffer_head
+ * back to a journal_t unracily (well, not true. Fix later)
+ *
+ *
+ * The `datalist' and `checkpoint list' functions are quite
+ * separate and we could use two spinlocks here.
+ *
+ * lru_list_lock nests inside journal_datalist_lock.
+ */
+spinlock_t journal_datalist_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * jh_splice_lock needs explantion.
+ *
+ * In a number of places we want to do things like:
+ *
+ * if (buffer_jbd(bh) && bh2jh(bh)->foo)
+ *
+ * This is racy on SMP, because another CPU could remove the journal_head
+ * in the middle of this expression. We need locking.
+ *
+ * But we can greatly optimise the locking cost by testing BH_JBD
+ * outside the lock. So, effectively:
+ *
+ * ret = 0;
+ * if (buffer_jbd(bh)) {
+ * spin_lock(&jh_splice_lock);
+ * if (buffer_jbd(bh)) { (* Still there? *)
+ * ret = bh2jh(bh)->foo;
+ * }
+ * spin_unlock(&jh_splice_lock);
+ * }
+ * return ret;
+ *
+ * Now, that protects us from races where another CPU can remove the
+ * journal_head. But it doesn't defend us from the situation where another
+ * CPU can *add* a journal_head. This is a correctness issue. But it's not
+ * a problem because a) the calling code was *already* racy and b) it often
+ * can't happen at the call site and c) the places where we add journal_heads
+ * tend to be under external locking.
+ */
+spinlock_t jh_splice_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * List of all journals in the system. Protected by the BKL.
+ */
+static LIST_HEAD(all_journals);
+
+/*
+ * Helper function used to manage commit timeouts
+ */
+
+static void commit_timeout(unsigned long __data)
+{
+ struct task_struct * p = (struct task_struct *) __data;
+
+ wake_up_process(p);
+}
+
+/* Static check for data structure consistency. There's no code
+ * invoked --- we'll just get a linker failure if things aren't right.
+ */
+void __journal_internal_check(void)
+{
+ extern void journal_bad_superblock_size(void);
+ if (sizeof(struct journal_superblock_s) != 1024)
+ journal_bad_superblock_size();
+}
+
+/*
+ * kjournald: The main thread function used to manage a logging device
+ * journal.
+ *
+ * This kernel thread is responsible for two things:
+ *
+ * 1) COMMIT: Every so often we need to commit the current state of the
+ * filesystem to disk. The journal thread is responsible for writing
+ * all of the metadata buffers to disk.
+ *
+ * 2) CHECKPOINT: We cannot reuse a used section of the log file until all
+ * of the data in that part of the log has been rewritten elsewhere on
+ * the disk. Flushing these old buffers to reclaim space in the log is
+ * known as checkpointing, and this thread is responsible for that job.
+ */
+
+journal_t *current_journal; // AKPM: debug
+
+int kjournald(void *arg)
+{
+ journal_t *journal = (journal_t *) arg;
+ transaction_t *transaction;
+ struct timer_list timer;
+
+ current_journal = journal;
+
+ lock_kernel();
+ daemonize();
+ spin_lock_irq(&current->sigmask_lock);
+ sigfillset(&current->blocked);
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ sprintf(current->comm, "kjournald");
+
+ /* Set up an interval timer which can be used to trigger a
+ commit wakeup after the commit interval expires */
+ init_timer(&timer);
+ timer.data = (unsigned long) current;
+ timer.function = commit_timeout;
+ journal->j_commit_timer = &timer;
+
+ /* Record that the journal thread is running */
+ journal->j_task = current;
+ wake_up(&journal->j_wait_done_commit);
+
+ printk(KERN_INFO "kjournald starting. Commit interval %ld seconds\n",
+ journal->j_commit_interval / HZ);
+ list_add(&journal->j_all_journals, &all_journals);
+
+ /* And now, wait forever for commit wakeup events. */
+ while (1) {
+ if (journal->j_flags & JFS_UNMOUNT)
+ break;
+
+ jbd_debug(1, "commit_sequence=%d, commit_request=%d\n",
+ journal->j_commit_sequence, journal->j_commit_request);
+
+ if (journal->j_commit_sequence != journal->j_commit_request) {
+ jbd_debug(1, "OK, requests differ\n");
+ if (journal->j_commit_timer_active) {
+ journal->j_commit_timer_active = 0;
+ del_timer(journal->j_commit_timer);
+ }
+
+ journal_commit_transaction(journal);
+ continue;
+ }
+
+ wake_up(&journal->j_wait_done_commit);
+ interruptible_sleep_on(&journal->j_wait_commit);
+
+ jbd_debug(1, "kjournald wakes\n");
+
+ /* Were we woken up by a commit wakeup event? */
+ if ((transaction = journal->j_running_transaction) != NULL &&
+ time_after_eq(jiffies, transaction->t_expires)) {
+ journal->j_commit_request = transaction->t_tid;
+ jbd_debug(1, "woke because of timeout\n");
+ }
+ }
+
+ if (journal->j_commit_timer_active) {
+ journal->j_commit_timer_active = 0;
+ del_timer_sync(journal->j_commit_timer);
+ }
+
+ list_del(&journal->j_all_journals);
+
+ journal->j_task = NULL;
+ wake_up(&journal->j_wait_done_commit);
+ jbd_debug(1, "Journal thread exiting.\n");


+ return 0;
+}
+

+static void journal_start_thread(journal_t *journal)
+{
+ kernel_thread(kjournald, (void *) journal,
+ CLONE_VM | CLONE_FS | CLONE_FILES);
+ while (!journal->j_task)
+ sleep_on(&journal->j_wait_done_commit);
+}
+
+static void journal_kill_thread(journal_t *journal)
+{
+ journal->j_flags |= JFS_UNMOUNT;
+
+ while (journal->j_task) {
+ wake_up(&journal->j_wait_commit);
+ sleep_on(&journal->j_wait_done_commit);
+ }


+}
+
+#if 0
+

+This is no longer needed - we do it in commit quite efficiently.
+Note that if this function is resurrected, the loop needs to
+be reorganised into the next_jh/last_jh algorithm.
+
+/*
+ * journal_clean_data_list: cleanup after data IO.
+ *
+ * Once the IO system has finished writing the buffers on the transaction's
+ * data list, we can remove those buffers from the list. This function
+ * scans the list for such buffers and removes them cleanly.
+ *
+ * We assume that the journal is already locked.
+ * We are called with journal_datalist_lock held.
+ *
+ * AKPM: This function looks inefficient. Approximately O(n^2)
+ * for potentially thousands of buffers. It no longer shows on profiles
+ * because these buffers are mainly dropped in journal_commit_transaction().
+ */
+
+void __journal_clean_data_list(transaction_t *transaction)
+{
+ struct journal_head *jh, *next;
+
+ assert_spin_locked(&journal_datalist_lock);
+
+restart:
+ jh = transaction->t_sync_datalist;
+ if (!jh)
+ goto out;
+ do {
+ next = jh->b_tnext;
+ if (!buffer_locked(jh2bh(jh)) && !buffer_dirty(jh2bh(jh))) {
+ struct buffer_head *bh = jh2bh(jh);
+ BUFFER_TRACE(bh, "data writeout complete: unfile");
+ __journal_unfile_buffer(jh);
+ jh->b_transaction = NULL;
+ __journal_remove_journal_head(bh);
+ refile_buffer(bh);
+ __brelse(bh);
+ goto restart;
+ }
+ jh = next;
+ } while (transaction->t_sync_datalist &&
+ jh != transaction->t_sync_datalist);
+out:
+ return;
+}
+#endif
+
+/*
+ * journal_write_metadata_buffer: write a metadata buffer to the journal.
+ *
+ * Writes a metadata buffer to a given disk block. The actual IO is not
+ * performed but a new buffer_head is constructed which labels the data
+ * to be written with the correct destination disk block.
+ *
+ * Any magic-number escaping which needs to be done will cause a
+ * copy-out here. If the buffer happens to start with the
+ * JFS_MAGIC_NUMBER, then we can't write it to the log directly: the
+ * magic number is only written to the log for descripter blocks. In
+ * this case, we copy the data and replace the first word with 0, and we
+ * return a result code which indicates that this buffer needs to be
+ * marked as an escaped buffer in the corresponding log descriptor
+ * block. The missing word can then be restored when the block is read
+ * during recovery.
+ *
+ * If the source buffer has already been modified by a new transaction
+ * since we took the last commit snapshot, we use the frozen copy of
+ * that data for IO. If we end up using the existing buffer_head's data
+ * for the write, then we *have* to lock the buffer to prevent anyone
+ * else from using and possibly modifying it while the IO is in
+ * progress.
+ *
+ * The function returns a pointer to the buffer_heads to be used for IO.
+ *
+ * We assume that the journal has already been locked in this function.
+ *
+ * Return value:
+ * <0: Error
+ * >=0: Finished OK
+ *
+ * On success:
+ * Bit 0 set == escape performed on the data
+ * Bit 1 set == buffer copy-out performed (kfree the data after IO)
+ */
+
+static inline unsigned long virt_to_offset(void *p)
+{return ((unsigned long) p) & ~PAGE_MASK;}
+
+int journal_write_metadata_buffer(transaction_t *transaction,
+ struct journal_head *jh_in,
+ struct journal_head **jh_out,
+ int blocknr)
+{
+ int need_copy_out = 0;
+ int done_copy_out = 0;
+ int do_escape = 0;
+ char *mapped_data;
+ struct buffer_head *new_bh;
+ struct journal_head * new_jh;
+ struct page *new_page;
+ unsigned int new_offset;
+
+ /*
+ * The buffer really shouldn't be locked: only the current committing
+ * transaction is allowed to write it, so nobody else is allowed
+ * to do any IO.
+ *
+ * akpm: except if we're journalling data, and write() output is
+ * also part of a shared mapping, and another thread has
+ * decided to launch a writepage() against this buffer.
+ */
+ J_ASSERT_JH(jh_in, buffer_jdirty(jh2bh(jh_in)));
+
+ /*
+ * If a new transaction has already done a buffer copy-out, then
+ * we use that version of the data for the commit.
+ */
+
+ if (jh_in->b_frozen_data) {
+ done_copy_out = 1;
+ new_page = virt_to_page(jh_in->b_frozen_data);
+ new_offset = virt_to_offset(jh_in->b_frozen_data);
+ } else {
+ new_page = jh2bh(jh_in)->b_page;
+ new_offset = virt_to_offset(jh2bh(jh_in)->b_data);
+ }
+
+ mapped_data = ((char *) kmap(new_page)) + new_offset;
+
+ /*
+ * Check for escaping
+ */
+ if (* ((unsigned int *) mapped_data) == htonl(JFS_MAGIC_NUMBER)) {
+ need_copy_out = 1;
+ do_escape = 1;
+ }
+
+ /*
+ * Do we need to do a data copy?
+ */
+
+ if (need_copy_out && !done_copy_out) {
+ char *tmp;
+ tmp = jbd_rep_kmalloc(jh2bh(jh_in)->b_size, GFP_NOFS);
+
+ jh_in->b_frozen_data = tmp;
+ memcpy (tmp, mapped_data, jh2bh(jh_in)->b_size);
+
+ /* If we get to this path, we'll always need the new
+ address kmapped so that we can clear the escaped
+ magic number below. */
+ kunmap(new_page);
+ new_page = virt_to_page(tmp);
+ new_offset = virt_to_offset(tmp);
+ mapped_data = ((char *) kmap(new_page)) + new_offset;
+
+ done_copy_out = 1;
+ }
+
+ /*
+ * Right, time to make up the new buffer_head.
+ */
+ do {
+ new_bh = get_unused_buffer_head(0);
+ if (!new_bh) {
+ printk (KERN_NOTICE __FUNCTION__
+ ": ENOMEM at get_unused_buffer_head, "
+ "trying again.\n");
+ current->policy |= SCHED_YIELD;
+ schedule();
+ }
+ } while (!new_bh);
+ /* keep subsequent assertions sane */
+ new_bh->b_prev_free = 0;
+ new_bh->b_next_free = 0;
+ new_bh->b_state = 0;
+ init_buffer(new_bh, NULL, NULL);
+ atomic_set(&new_bh->b_count, 1);
+ new_jh = journal_add_journal_head(new_bh);
+
+ set_bh_page(new_bh, new_page, new_offset);
+
+ new_jh->b_transaction = NULL;
+ new_bh->b_size = jh2bh(jh_in)->b_size;
+ new_bh->b_dev = transaction->t_journal->j_dev;
+ new_bh->b_blocknr = blocknr;
+ new_bh->b_state |= (1 << BH_Mapped) | (1 << BH_Dirty);
+
+ *jh_out = new_jh;
+
+ /*
+ * Did we need to do an escaping? Now we've done all the
+ * copying, we can finally do so.
+ */
+
+ if (do_escape)
+ * ((unsigned int *) mapped_data) = 0;
+ kunmap(new_page);
+
+ /*
+ * The to-be-written buffer needs to get moved to the io queue,
+ * and the original buffer whose contents we are shadowing or
+ * copying is moved to the transaction's shadow queue.
+ */
+ JBUFFER_TRACE(jh_in, "file as BJ_Shadow");
+ journal_file_buffer(jh_in, transaction, BJ_Shadow);
+ JBUFFER_TRACE(new_jh, "file as BJ_IO");
+ journal_file_buffer(new_jh, transaction, BJ_IO);
+
+ return do_escape | (done_copy_out << 1);
+}
+
+/*
+ * Allocation code for the journal file. Manage the space left in the
+ * journal, so that we can begin checkpointing when appropriate.
+ */
+
+/*
+ * log_space_left: Return the number of free blocks left in the journal.
+ *
+ * Called with the journal already locked.
+ */
+
+int log_space_left (journal_t *journal)
+{
+ int left = journal->j_free;
+
+ /* Be pessimistic here about the number of those free blocks
+ * which might be required for log descriptor control blocks. */
+
+#define MIN_LOG_RESERVED_BLOCKS 32 /* Allow for rounding errors */
+
+ left -= MIN_LOG_RESERVED_BLOCKS;
+
+ if (left <= 0)
+ return 0;
+ left -= (left >> 3);
+ return left;
+}
+
+/*
+ * This function must be non-allocating for PF_MEMALLOC tasks
+ */
+tid_t log_start_commit (journal_t *journal, transaction_t *transaction)
+{
+ tid_t target = journal->j_commit_request;
+
+ lock_kernel(); /* Protect journal->j_running_transaction */
+
+ /*
+ * A NULL transaction asks us to commit the currently running
+ * transaction, if there is one.
+ */
+ if (transaction)
+ target = transaction->t_tid;
+ else {
+ transaction = journal->j_running_transaction;
+ if (!transaction)
+ goto out;
+ target = transaction->t_tid;
+ }
+
+ /*
+ * Are we already doing a recent enough commit?
+ */
+ if (tid_geq(journal->j_commit_request, target))
+ goto out;
+
+ /*
+ * We want a new commit: OK, mark the request and wakup the
+ * commit thread. We do _not_ do the commit ourselves.
+ */
+
+ journal->j_commit_request = target;
+ jbd_debug(1, "JBD: requesting commit %d/%d\n",
+ journal->j_commit_request,
+ journal->j_commit_sequence);
+ wake_up(&journal->j_wait_commit);
+
+out:
+ unlock_kernel();
+ return target;
+}
+
+/*
+ * Wait for a specified commit to complete.
+ * The caller may not hold the journal lock.
+ */
+void log_wait_commit (journal_t *journal, tid_t tid)
+{
+ lock_kernel();
+#ifdef CONFIG_JBD_DEBUG
+ lock_journal(journal);
+ if (!tid_geq(journal->j_commit_request, tid)) {
+ printk(KERN_EMERG __FUNCTION__
+ ": error: j_commit_request=%d, tid=%d\n",
+ journal->j_commit_request, tid);
+ }
+ unlock_journal(journal);
+#endif
+ while (tid_gt(tid, journal->j_commit_sequence)) {
+ jbd_debug(1, "JBD: want %d, j_commit_sequence=%d\n",
+ tid, journal->j_commit_sequence);
+ wake_up(&journal->j_wait_commit);
+ sleep_on(&journal->j_wait_done_commit);
+ }
+ unlock_kernel();
+}
+
+/*
+ * Log buffer allocation routines:
+ */
+
+unsigned long journal_next_log_block(journal_t *journal)
+{
+ unsigned long blocknr;
+
+ J_ASSERT(journal->j_free > 1);
+
+ blocknr = journal->j_head;
+ journal->j_head++;
+ journal->j_free--;
+ if (journal->j_head == journal->j_last)
+ journal->j_head = journal->j_first;
+ return journal_bmap(journal, blocknr);
+}
+
+/*
+ * Conversion of logical to physical block numbers for the journal
+ *
+ * On external journals the journal blocks are identity-mapped, so
+ * this is a no-op. If needed, we can use j_blk_offset - everything is
+ * ready.
+ */
+unsigned long journal_bmap(journal_t *journal, unsigned long blocknr)
+{
+ unsigned long ret;
+
+ if (journal->j_inode) {
+ ret = bmap(journal->j_inode, blocknr);
+ J_ASSERT(ret != 0);
+ } else {
+ ret = blocknr; /* +journal->j_blk_offset */
+ }
+ return ret;
+}
+
+/*
+ * We play buffer_head aliasing tricks to write data/metadata blocks to
+ * the journal without copying their contents, but for journal
+ * descriptor blocks we do need to generate bona fide buffers.
+ */
+
+struct journal_head * journal_get_descriptor_buffer(journal_t *journal)
+{
+ struct buffer_head *bh;
+ unsigned long blocknr = journal_next_log_block(journal);
+
+ bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
+ bh->b_state |= (1 << BH_Dirty);
+ BUFFER_TRACE(bh, "return this buffer");
+ return journal_add_journal_head(bh);
+}
+
+/*
+ * Management for journal control blocks: functions to create and
+ * destroy journal_t structures, and to initialise and read existing
+ * journal blocks from disk. */
+
+/* First: create and setup a journal_t object in memory. We initialise
+ * very few fields yet: that has to wait until we have created the
+ * journal structures from from scratch, or loaded them from disk. */
+
+static journal_t * journal_init_common (void)
+{
+ journal_t *journal;
+ int err;
+
+ MOD_INC_USE_COUNT;
+
+ journal = jbd_kmalloc(sizeof(*journal), GFP_KERNEL);
+ if (!journal)
+ goto fail;
+ memset(journal, 0, sizeof(*journal));
+
+ init_waitqueue_head(&journal->j_wait_transaction_locked);
+ init_waitqueue_head(&journal->j_wait_logspace);
+ init_waitqueue_head(&journal->j_wait_done_commit);
+ init_waitqueue_head(&journal->j_wait_checkpoint);
+ init_waitqueue_head(&journal->j_wait_commit);
+ init_waitqueue_head(&journal->j_wait_updates);
+ init_MUTEX(&journal->j_barrier);
+ init_MUTEX(&journal->j_checkpoint_sem);
+ init_MUTEX(&journal->j_sem);
+
+ journal->j_commit_interval = (HZ * 5);
+
+ /* The journal is marked for error until we succeed with recovery! */
+ journal->j_flags = JFS_ABORT;
+
+ /* Set up a default-sized revoke table for the new mount. */
+ err = journal_init_revoke(journal, JOURNAL_REVOKE_DEFAULT_HASH);
+ if (err) {
+ kfree(journal);
+ goto fail;
+ }
+ return journal;
+fail:
+ MOD_DEC_USE_COUNT;


+ return NULL;
+}
+

+/* journal_init_dev and journal_init_inode:
+ *
+ * Create a journal structure assigned some fixed set of disk blocks to
+ * the journal. We don't actually touch those disk blocks yet, but we
+ * need to set up all of the mapping information to tell the journaling
+ * system where the journal blocks are.
+ *
+ * journal_init_dev creates a journal which maps a fixed contiguous
+ * range of blocks on an arbitrary block device.
+ *
+ * journal_init_inode creates a journal which maps an on-disk inode as
+ * the journal. The inode must exist already, must support bmap() and
+ * must have all data blocks preallocated.
+ */
+
+journal_t * journal_init_dev(kdev_t dev, kdev_t fs_dev,
+ int start, int len, int blocksize)
+{
+ journal_t *journal = journal_init_common();


+ struct buffer_head *bh;
+

+ if (!journal)
+ return NULL;
+
+ journal->j_dev = dev;
+ journal->j_fs_dev = fs_dev;
+ journal->j_blk_offset = start;
+ journal->j_maxlen = len;
+ journal->j_blocksize = blocksize;
+
+ bh = getblk(journal->j_dev, start, journal->j_blocksize);
+ J_ASSERT(bh != NULL);
+ journal->j_sb_buffer = bh;
+ journal->j_superblock = (journal_superblock_t *)bh->b_data;
+


+ return journal;
+}
+

+journal_t * journal_init_inode (struct inode *inode)
+{
+ struct buffer_head *bh;
+ journal_t *journal = journal_init_common();
+ int blocknr;
+
+ if (!journal)
+ return NULL;
+
+ journal->j_dev = inode->i_dev;
+ journal->j_fs_dev = inode->i_dev;
+ journal->j_inode = inode;
+ jbd_debug(1,
+ "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n",
+ journal, bdevname(inode->i_dev), inode->i_ino, inode->i_size,
+ inode->i_sb->s_blocksize_bits, inode->i_sb->s_blocksize);
+
+ journal->j_maxlen = inode->i_size >> inode->i_sb->s_blocksize_bits;
+ journal->j_blocksize = inode->i_sb->s_blocksize;
+
+ blocknr = journal_bmap(journal, 0);
+ bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
+ J_ASSERT(bh != NULL);
+ journal->j_sb_buffer = bh;
+ journal->j_superblock = (journal_superblock_t *)bh->b_data;
+
+ return journal;
+}
+
+/*
+ * Given a journal_t structure, initialise the various fields for
+ * startup of a new journaling session. We use this both when creating
+ * a journal, and after recovering an old journal to reset it for
+ * subsequent use.
+ */
+
+static int journal_reset (journal_t *journal)
+{
+ journal_superblock_t *sb = journal->j_superblock;
+ unsigned int first, last;
+
+ first = ntohl(sb->s_first);
+ last = ntohl(sb->s_maxlen);
+
+ journal->j_first = first;
+ journal->j_last = last;
+
+ journal->j_head = first;
+ journal->j_tail = first;
+ journal->j_free = last - first;
+
+ journal->j_tail_sequence = journal->j_transaction_sequence;
+ journal->j_commit_sequence = journal->j_transaction_sequence - 1;
+ journal->j_commit_request = journal->j_commit_sequence;
+
+ journal->j_max_transaction_buffers = journal->j_maxlen / 4;
+
+ /* Add the dynamic fields and write it to disk. */
+ journal_update_superblock(journal, 1);
+
+ lock_journal(journal);
+ journal_start_thread(journal);
+ unlock_journal(journal);
+


+ return 0;
+}
+
+/*

+ * Given a journal_t structure which tells us which disk blocks we can
+ * use, create a new journal superblock and initialise all of the
+ * journal fields from scratch. */
+
+int journal_create (journal_t *journal)
+{
+ int blocknr;
+ struct buffer_head *bh;
+ journal_superblock_t *sb;
+ int i;
+
+ if (journal->j_maxlen < JFS_MIN_JOURNAL_BLOCKS) {
+ printk (KERN_ERR "Journal length (%d blocks) too short.\n",
+ journal->j_maxlen);


+ return -EINVAL;
+ }
+

+ if (journal->j_inode == NULL) {
+ /*
+ * We don't know what block to start at!
+ */
+ printk(KERN_EMERG __FUNCTION__
+ ": creation of journal on external device!\n");
+ BUG();
+ }
+
+ /* Zero out the entire journal on disk. We cannot afford to
+ have any blocks on disk beginning with JFS_MAGIC_NUMBER. */
+ jbd_debug(1, "JBD: Zeroing out journal blocks...\n");
+ for (i = 0; i < journal->j_maxlen; i++) {
+ blocknr = journal_bmap(journal, i);
+ bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
+ wait_on_buffer(bh);
+ memset (bh->b_data, 0, journal->j_blocksize);
+ BUFFER_TRACE(bh, "marking dirty");
+ mark_buffer_dirty(bh);


+ BUFFER_TRACE(bh, "marking uptodate");
+ mark_buffer_uptodate(bh, 1);

+ __brelse(bh);
+ }
+ sync_dev(journal->j_dev);
+ jbd_debug(1, "JBD: journal cleared.\n");
+
+ /* OK, fill in the initial static fields in the new superblock */
+ sb = journal->j_superblock;
+
+ sb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
+ sb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
+
+ sb->s_blocksize = htonl(journal->j_blocksize);
+ sb->s_maxlen = htonl(journal->j_maxlen);
+ sb->s_first = htonl(1);
+
+ journal->j_transaction_sequence = 1;
+
+ journal->j_flags &= ~JFS_ABORT;
+ journal->j_format_version = 2;
+
+ return journal_reset(journal);
+}
+
+/*
+ * Update a journal's dynamic superblock fields and write it to disk,
+ * optionally waiting for the IO to complete.
+*/
+
+void journal_update_superblock(journal_t *journal, int wait)
+{
+ journal_superblock_t *sb = journal->j_superblock;
+ struct buffer_head *bh = journal->j_sb_buffer;
+
+ jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n",
+ journal->j_tail, journal->j_tail_sequence, journal->j_errno);
+
+ sb->s_sequence = htonl(journal->j_tail_sequence);
+ sb->s_start = htonl(journal->j_tail);
+ sb->s_errno = htonl(journal->j_errno);
+
+ BUFFER_TRACE(bh, "marking dirty");
+ mark_buffer_dirty(bh);
+ ll_rw_block(WRITE, 1, &bh);
+ if (wait)
+ wait_on_buffer(bh);
+
+ /* If we have just flushed the log (by marking s_start==0), then
+ * any future commit will have to be careful to update the
+ * superblock again to re-record the true start of the log. */
+
+ if (sb->s_start)
+ journal->j_flags &= ~JFS_FLUSHED;
+ else
+ journal->j_flags |= JFS_FLUSHED;
+}
+
+
+/*
+ * Read the superblock for a given journal, performing initial
+ * validation of the format.
+ */
+
+static int journal_get_superblock(journal_t *journal)
+{
+ struct buffer_head *bh;
+ journal_superblock_t *sb;
+
+ bh = journal->j_sb_buffer;
+
+ J_ASSERT(bh != NULL);
+ if (!buffer_uptodate(bh)) {
+ ll_rw_block(READ, 1, &bh);


+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh)) {

+ printk (KERN_ERR
+ "JBD: IO error reading journal superblock\n");


+ return -EIO;
+ }
+ }
+

+ sb = journal->j_superblock;
+
+ if (sb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
+ sb->s_blocksize != htonl(journal->j_blocksize)) {
+ printk(KERN_WARNING "JBD: no valid journal superblock found\n");


+ return -EINVAL;
+ }
+

+ switch(ntohl(sb->s_header.h_blocktype)) {
+ case JFS_SUPERBLOCK_V1:
+ journal->j_format_version = 1;
+ break;
+ case JFS_SUPERBLOCK_V2:
+ journal->j_format_version = 2;
+ break;
+ default:
+ printk(KERN_WARNING "JBD: unrecognised superblock format ID\n");


+ return -EINVAL;
+ }
+

+ if (ntohl(sb->s_maxlen) < journal->j_maxlen)
+ journal->j_maxlen = ntohl(sb->s_maxlen);
+ else if (ntohl(sb->s_maxlen) > journal->j_maxlen) {
+ printk (KERN_WARNING "JBD: journal file too short\n");


+ return -EINVAL;
+ }
+

+ return 0;
+}
+
+/*

+ * Load the on-disk journal superblock and read the key fields into the
+ * journal_t.
+ */
+
+static int load_superblock(journal_t *journal)
+{
+ int err;
+ journal_superblock_t *sb;
+
+ err = journal_get_superblock(journal);
+ if (err)
+ return err;
+
+ sb = journal->j_superblock;
+
+ journal->j_tail_sequence = ntohl(sb->s_sequence);
+ journal->j_tail = ntohl(sb->s_start);
+ journal->j_first = ntohl(sb->s_first);
+ journal->j_last = ntohl(sb->s_maxlen);
+ journal->j_errno = ntohl(sb->s_errno);
+


+ return 0;
+}
+
+

+/*
+ * Given a journal_t structure which tells us which disk blocks contain
+ * a journal, read the journal from disk to initialise the in-memory
+ * structures.
+ */
+
+int journal_load(journal_t *journal)


+{
+ int err;
+

+ err = load_superblock(journal);
+ if (err)
+ return err;
+
+ /* If this is a V2 superblock, then we have to check the
+ * features flags on it. */
+
+ if (journal->j_format_version >= 2) {
+ journal_superblock_t *sb = journal->j_superblock;
+
+ if ((sb->s_feature_ro_compat &
+ ~cpu_to_be32(JFS_KNOWN_ROCOMPAT_FEATURES)) ||
+ (sb->s_feature_incompat &
+ ~cpu_to_be32(JFS_KNOWN_INCOMPAT_FEATURES))) {
+ printk (KERN_WARNING
+ "JBD: Unrecognised features on journal\n");


+ return -EINVAL;
+ }
+ }
+

+ /* Let the recovery code check whether it needs to recover any
+ * data from the journal. */
+ if (journal_recover(journal))
+ goto recovery_error;
+
+ /* OK, we've finished with the dynamic journal bits:
+ * reinitialise the dynamic contents of the superblock in memory
+ * and reset them on disk. */
+ if (journal_reset(journal))
+ goto recovery_error;
+
+ journal->j_flags &= ~JFS_ABORT;
+ journal->j_flags |= JFS_LOADED;
+ return 0;
+
+recovery_error:
+ printk (KERN_WARNING "JBD: recovery failed\n");


+ return -EIO;
+}
+

+/*
+ * Release a journal_t structure once it is no longer in use by the
+ * journaled object.
+ */
+
+void journal_destroy (journal_t *journal)
+{
+ /* Wait for the commit thread to wake up and die. */
+ journal_kill_thread(journal);
+
+ /* Force a final log commit */
+ if (journal->j_running_transaction)
+ journal_commit_transaction(journal);
+
+ /* Force any old transactions to disk */
+ lock_journal(journal);
+ while (journal->j_checkpoint_transactions != NULL)
+ log_do_checkpoint(journal, 1);
+
+ J_ASSERT(journal->j_running_transaction == NULL);
+ J_ASSERT(journal->j_committing_transaction == NULL);
+ J_ASSERT(journal->j_checkpoint_transactions == NULL);
+
+ /* We can now mark the journal as empty. */
+ journal->j_tail = 0;
+ journal->j_tail_sequence = ++journal->j_transaction_sequence;
+ journal_update_superblock(journal, 1);
+
+ if (journal->j_inode)
+ iput(journal->j_inode);
+ if (journal->j_revoke)
+ journal_destroy_revoke(journal);
+
+ unlock_journal(journal);
+ brelse(journal->j_sb_buffer);
+ kfree(journal);
+ MOD_DEC_USE_COUNT;
+}
+
+
+/* Published API: Check whether the journal uses all of a given set of
+ * features. Return true (non-zero) if it does. */
+
+int journal_check_used_features (journal_t *journal, unsigned long compat,
+ unsigned long ro, unsigned long incompat)
+{
+ journal_superblock_t *sb;
+
+ if (!compat && !ro && !incompat)
+ return 1;
+ if (journal->j_format_version == 1)
+ return 0;
+
+ sb = journal->j_superblock;
+
+ if (((be32_to_cpu(sb->s_feature_compat) & compat) == compat) &&
+ ((be32_to_cpu(sb->s_feature_ro_compat) & ro) == ro) &&
+ ((be32_to_cpu(sb->s_feature_incompat) & incompat) == incompat))
+ return 1;
+


+ return 0;
+}
+

+/* Published API: Check whether the journaling code supports the use of
+ * all of a given set of features on this journal. Return true
+ * (non-zero) if it can. */
+
+int journal_check_available_features (journal_t *journal, unsigned long compat,
+ unsigned long ro, unsigned long incompat)
+{
+ journal_superblock_t *sb;
+
+ if (!compat && !ro && !incompat)
+ return 1;
+
+ sb = journal->j_superblock;
+
+ /* We can support any known requested features iff the
+ * superblock is in version 2. Otherwise we fail to support any
+ * extended sb features. */
+
+ if (journal->j_format_version != 2)
+ return 0;
+
+ if ((compat & JFS_KNOWN_COMPAT_FEATURES) == compat &&
+ (ro & JFS_KNOWN_ROCOMPAT_FEATURES) == ro &&
+ (incompat & JFS_KNOWN_INCOMPAT_FEATURES) == incompat)
+ return 1;
+


+ return 0;
+}
+

+/* Published API: Mark a given journal feature as present on the
+ * superblock. Returns true if the requested features could be set. */
+
+int journal_set_features (journal_t *journal, unsigned long compat,
+ unsigned long ro, unsigned long incompat)
+{
+ journal_superblock_t *sb;
+
+ if (journal_check_used_features(journal, compat, ro, incompat))
+ return 1;
+
+ if (!journal_check_available_features(journal, compat, ro, incompat))
+ return 0;
+
+ jbd_debug(1, "Setting new features 0x%lx/0x%lx/0x%lx\n",
+ compat, ro, incompat);
+
+ sb = journal->j_superblock;
+
+ sb->s_feature_compat |= cpu_to_be32(compat);
+ sb->s_feature_ro_compat |= cpu_to_be32(ro);
+ sb->s_feature_incompat |= cpu_to_be32(incompat);
+


+ return 1;
+}
+
+
+/*

+ * Published API:
+ * Given an initialised but unloaded journal struct, poke about in the
+ * on-disk structure to update it to the most recent supported version.
+ */
+
+int journal_update_format (journal_t *journal)
+{
+ journal_superblock_t *sb;
+ int err;
+
+ err = journal_get_superblock(journal);
+ if (err)
+ return err;
+
+ sb = journal->j_superblock;
+
+ switch (ntohl(sb->s_header.h_blocktype)) {
+ case JFS_SUPERBLOCK_V2:
+ return 0;
+ case JFS_SUPERBLOCK_V1:
+ return journal_convert_superblock_v1(journal, sb);


+ default:
+ break;
+ }

+ return -EINVAL;
+}
+

+static int journal_convert_superblock_v1(journal_t *journal,
+ journal_superblock_t *sb)
+{
+ int offset, blocksize;


+ struct buffer_head *bh;
+

+ printk(KERN_WARNING
+ "JBD: Converting superblock from version 1 to 2.\n");
+
+ /* Pre-initialise new fields to zero */
+ offset = ((char *) &(sb->s_feature_compat)) - ((char *) sb);
+ blocksize = ntohl(sb->s_blocksize);
+ memset(&sb->s_feature_compat, 0, blocksize-offset);
+
+ sb->s_nr_users = cpu_to_be32(1);
+ sb->s_header.h_blocktype = cpu_to_be32(JFS_SUPERBLOCK_V2);
+ journal->j_format_version = 2;
+
+ bh = journal->j_sb_buffer;
+ BUFFER_TRACE(bh, "marking dirty");
+ mark_buffer_dirty(bh);
+ ll_rw_block(WRITE, 1, &bh);
+ wait_on_buffer(bh);


+ return 0;
+}
+
+

+/*
+ * Flush all data for a given journal to disk and empty the journal.
+ * Filesystems can use this when remounting readonly to ensure that
+ * recovery does not need to happen on remount.
+ */
+
+int journal_flush (journal_t *journal)
+{


+ int err = 0;

+ transaction_t *transaction = NULL;
+ unsigned long old_tail;
+
+ lock_kernel();
+
+ /* Force everything buffered to the log... */
+ if (journal->j_running_transaction) {
+ transaction = journal->j_running_transaction;
+ log_start_commit(journal, transaction);
+ } else if (journal->j_committing_transaction)
+ transaction = journal->j_committing_transaction;
+
+ /* Wait for the log commit to complete... */
+ if (transaction)
+ log_wait_commit(journal, transaction->t_tid);
+
+ /* ...and flush everything in the log out to disk. */
+ lock_journal(journal);
+ while (!err && journal->j_checkpoint_transactions != NULL)
+ err = log_do_checkpoint(journal, journal->j_maxlen);
+ cleanup_journal_tail(journal);
+
+ /* Finally, mark the journal as really needing no recovery.
+ * This sets s_start==0 in the underlying superblock, which is
+ * the magic code for a fully-recovered superblock. Any future
+ * commits of data to the journal will restore the current
+ * s_start value. */
+ old_tail = journal->j_tail;
+ journal->j_tail = 0;
+ journal_update_superblock(journal, 1);
+ journal->j_tail = old_tail;
+
+ unlock_journal(journal);
+
+ J_ASSERT(!journal->j_running_transaction);
+ J_ASSERT(!journal->j_committing_transaction);
+ J_ASSERT(!journal->j_checkpoint_transactions);
+ J_ASSERT(journal->j_head == journal->j_tail);
+ J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence);
+
+ unlock_kernel();


+
+ return err;
+}
+

+/*
+ * Wipe out all of the contents of a journal, safely. This will produce
+ * a warning if the journal contains any valid recovery information.
+ * Must be called between journal_init_*() and journal_load().
+ *
+ * If (write) is non-zero, then we wipe out the journal on disk; otherwise
+ * we merely suppress recovery.
+ */
+
+int journal_wipe (journal_t *journal, int write)
+{
+ journal_superblock_t *sb;


+ int err = 0;
+

+ J_ASSERT (!(journal->j_flags & JFS_LOADED));
+
+ err = load_superblock(journal);
+ if (err)
+ return err;
+
+ sb = journal->j_superblock;
+
+ if (!journal->j_tail)
+ goto no_recovery;
+
+ printk (KERN_WARNING "JBD: %s recovery information on journal\n",
+ write ? "Clearing" : "Ignoring");
+
+ err = journal_skip_recovery(journal);
+ if (write)
+ journal_update_superblock(journal, 1);
+
+ no_recovery:


+ return err;
+}
+

+/*
+ * journal_dev_name: format a character string to describe on what
+ * device this journal is present.
+ */
+
+const char * journal_dev_name(journal_t *journal)
+{
+ kdev_t dev;
+
+ if (journal->j_inode)
+ dev = journal->j_inode->i_dev;
+ else
+ dev = journal->j_dev;
+
+ return bdevname(dev);
+}
+
+/*
+ * journal_abort: perform a complete, immediate shutdown of the ENTIRE
+ * journal (not of a single transaction). This operation cannot be
+ * undone without closing and reopening the journal.
+ *
+ * The journal_abort function is intended to support higher level error
+ * recovery mechanisms such as the ext2/ext3 remount-readonly error
+ * mode.
+ *
+ * Journal abort has very specific semantics. Any existing dirty,
+ * unjournaled buffers in the main filesystem will still be written to
+ * disk by bdflush, but the journaling mechanism will be suspended
+ * immediately and no further transaction commits will be honoured.
+ *
+ * Any dirty, journaled buffers will be written back to disk without
+ * hitting the journal. Atomicity cannot be guaranteed on an aborted
+ * filesystem, but we _do_ attempt to leave as much data as possible
+ * behind for fsck to use for cleanup.
+ *
+ * Any attempt to get a new transaction handle on a journal which is in
+ * ABORT state will just result in an -EROFS error return. A
+ * journal_stop on an existing handle will return -EIO if we have
+ * entered abort state during the update.
+ *
+ * Recursive transactions are not disturbed by journal abort until the
+ * final journal_stop, which will receive the -EIO error.
+ *
+ * Finally, the journal_abort call allows the caller to supply an errno
+ * which will be recored (if possible) in the journal superblock. This
+ * allows a client to record failure conditions in the middle of a
+ * transaction without having to complete the transaction to record the
+ * failure to disk. ext3_error, for example, now uses this
+ * functionality.
+ *
+ * Errors which originate from within the journaling layer will NOT
+ * supply an errno; a null errno implies that absolutely no further
+ * writes are done to the journal (unless there are any already in
+ * progress).
+ */
+
+/* Quick version for internal journal use (doesn't lock the journal) */
+void __journal_abort (journal_t *journal)
+{
+ transaction_t *transaction;
+
+ printk (KERN_ERR "Aborting journal on device %s.\n",
+ journal_dev_name(journal));
+
+ journal->j_flags |= JFS_ABORT;
+ transaction = journal->j_running_transaction;
+ if (transaction)
+ log_start_commit(journal, transaction);
+}
+
+/* Full version for external use */
+void journal_abort (journal_t *journal, int errno)
+{
+ lock_journal(journal);
+
+ if (journal->j_flags & JFS_ABORT)
+ goto out;
+
+ if (!journal->j_errno)
+ journal->j_errno = errno;
+
+ __journal_abort(journal);
+
+ if (errno)
+ journal_update_superblock(journal, 1);
+
+ out:
+ unlock_journal(journal);
+}
+
+int journal_errno (journal_t *journal)


+{
+ int err;
+

+ lock_journal(journal);
+ if (journal->j_flags & JFS_ABORT)
+ err = -EROFS;
+ else
+ err = journal->j_errno;
+ unlock_journal(journal);


+ return err;
+}
+

+int journal_clear_err (journal_t *journal)
+{


+ int err = 0;
+

+ lock_journal(journal);
+ if (journal->j_flags & JFS_ABORT)
+ err = -EROFS;
+ else
+ journal->j_errno = 0;
+ unlock_journal(journal);


+ return err;
+}
+

+void journal_ack_err (journal_t *journal)
+{
+ lock_journal(journal);
+ if (journal->j_errno)
+ journal->j_flags |= JFS_ACK_ERR;
+ unlock_journal(journal);
+}
+
+int journal_blocks_per_page(struct inode *inode)
+{
+ return 1 << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
+}
+
+/*
+ * shrink_journal_memory().
+ * Called when we're under memory pressure. Free up all the written-back
+ * checkpointed metadata buffers.
+ */
+void shrink_journal_memory(void)
+{
+ struct list_head *list;
+
+ lock_kernel();
+ list_for_each(list, &all_journals) {
+ journal_t *journal =
+ list_entry(list, journal_t, j_all_journals);
+ spin_lock(&journal_datalist_lock);
+ __journal_clean_checkpoint_list(journal);
+ spin_unlock(&journal_datalist_lock);
+ }
+ unlock_kernel();
+}
+
+/*
+ * Simple support for retying memory allocations. Introduced to help to
+ * debug different VM deadlock avoidance strategies.
+ */
+/*
+ * Simple support for retying memory allocations. Introduced to help to
+ * debug different VM deadlock avoidance strategies.
+ */
+void * __jbd_kmalloc (char *where, size_t size, int flags, int retry)
+{
+ void *p;
+ static unsigned long last_warning;
+
+ while (1) {
+ p = kmalloc(size, flags);
+ if (p)
+ return p;
+ if (!retry)
+ return NULL;
+ /* Log every retry for debugging. Also log them to the
+ * syslog, but do rate-limiting on the non-debugging
+ * messages. */
+ jbd_debug(1, "ENOMEM in %s, retrying.\n", where);
+
+ if (time_after(jiffies, last_warning + 5*HZ)) {
+ printk(KERN_NOTICE
+ "ENOMEM in %s, retrying.\n", where);
+ last_warning = jiffies;
+ }
+
+ current->policy |= SCHED_YIELD;
+ schedule();
+ }
+}
+
+/*
+ * Journal_head storage management
+ */
+static kmem_cache_t *journal_head_cache;
+#ifdef CONFIG_JBD_DEBUG
+static atomic_t nr_journal_heads = ATOMIC_INIT(0);
+#endif
+
+static int journal_init_journal_head_cache(void)


+{
+ int retval;
+

+ J_ASSERT(journal_head_cache == 0);
+ journal_head_cache = kmem_cache_create("journal_head",
+ sizeof(struct journal_head),
+ 0, /* offset */
+ 0, /* flags */
+ NULL, /* ctor */
+ NULL); /* dtor */
+ retval = 0;
+ if (journal_head_cache == 0) {
+ retval = -ENOMEM;
+ printk(KERN_EMERG "JBD: no memory for journal_head cache\n");
+ }


+ return retval;
+}
+

+static void journal_destroy_journal_head_cache(void)
+{
+ J_ASSERT(journal_head_cache != NULL);
+ kmem_cache_destroy(journal_head_cache);
+ journal_head_cache = 0;
+}
+
+/*
+ * journal_head splicing and dicing
+ */
+static struct journal_head *journal_alloc_journal_head(void)
+{
+ struct journal_head *ret;
+ static unsigned long last_warning;
+
+#ifdef CONFIG_JBD_DEBUG
+ atomic_inc(&nr_journal_heads);
+#endif
+ ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS);


+ if (ret == 0) {

+ jbd_debug(1, "out of memory for journal_head\n");
+ if (time_after(jiffies, last_warning + 5*HZ)) {
+ printk(KERN_NOTICE "ENOMEM in " __FUNCTION__
+ ", retrying.\n");
+ last_warning = jiffies;
+ }
+ while (ret == 0) {
+ current->policy |= SCHED_YIELD;
+ schedule();
+ ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS);
+ }
+ }


+ return ret;
+}
+

+static void journal_free_journal_head(struct journal_head *jh)
+{
+#ifdef CONFIG_JBD_DEBUG
+ atomic_dec(&nr_journal_heads);
+ memset(jh, 0x5b, sizeof(*jh));
+#endif
+ kmem_cache_free(journal_head_cache, jh);
+}
+
+/*
+ * A journal_head is attached to a buffer_head whenever JBD has an
+ * interest in the buffer.
+ *
+ * Whenever a buffer has an attached journal_head, its ->b_state:BH_JBD bit
+ * is set. This bit is tested in core kernel code where we need to take
+ * JBD-specific actions. Testing the zeroness of ->b_private is not reliable
+ * there.
+ *
+ * When a buffer has its BH_JBD bit set, its ->b_count is elevated by one.
+ *
+ * When a buffer has its BH_JBD bit set it is immune from being released by
+ * core kernel code, mainly via ->b_count.
+ *
+ * A journal_head may be detached from its buffer_head when the journal_head's
+ * b_transaction, b_cp_transaction and b_next_transaction pointers are NULL.
+ * Various places in JBD call journal_remove_journal_head() to indicate that the
+ * journal_head can be dropped if needed.
+ *
+ * Various places in the kernel want to attach a journal_head to a buffer_head
+ * _before_ attaching the journal_head to a transaction. To protect the
+ * journal_head in this situation, journal_add_journal_head elevates the
+ * journal_head's b_jcount refcount by one. The caller must call
+ * journal_unlock_journal_head() to undo this.
+ *
+ * So the typical usage would be:
+ *
+ * (Attach a journal_head if needed. Increments b_jcount)
+ * struct journal_head *jh = journal_add_journal_head(bh);
+ * ...
+ * jh->b_transaction = xxx;
+ * journal_unlock_journal_head(jh);
+ *
+ * Now, the journal_head's b_jcount is zero, but it is safe from being released
+ * because it has a non-zero b_transaction.
+ */
+
+/*
+ * Give a buffer_head a journal_head.
+ *
+ * Doesn't need the journal lock.
+ * May sleep.
+ * Cannot be called with journal_datalist_lock held.
+ */
+struct journal_head *journal_add_journal_head(struct buffer_head *bh)
+{
+ struct journal_head *jh;
+
+ spin_lock(&journal_datalist_lock);
+ if (buffer_jbd(bh)) {
+ jh = bh2jh(bh);
+ } else {
+ J_ASSERT_BH(bh,
+ (atomic_read(&bh->b_count) > 0) ||
+ (bh->b_page && bh->b_page->mapping));
+ spin_unlock(&journal_datalist_lock);
+ jh = journal_alloc_journal_head();
+ memset(jh, 0, sizeof(*jh));
+ spin_lock(&journal_datalist_lock);
+
+ if (buffer_jbd(bh)) {
+ /* Someone did it for us! */
+ J_ASSERT_BH(bh, bh->b_private != NULL);
+ journal_free_journal_head(jh);
+ jh = bh->b_private;
+ } else {
+ /*
+ * We actually don't need jh_splice_lock when
+ * adding a journal_head - only on removal.
+ */
+ spin_lock(&jh_splice_lock);
+ set_bit(BH_JBD, &bh->b_state);
+ bh->b_private = jh;
+ jh->b_bh = bh;
+ atomic_inc(&bh->b_count);
+ spin_unlock(&jh_splice_lock);
+ BUFFER_TRACE(bh, "added journal_head");
+ }
+ }
+ jh->b_jcount++;
+ spin_unlock(&journal_datalist_lock);
+ return bh->b_private;
+}
+
+/*
+ * journal_remove_journal_head(): if the buffer isn't attached to a transaction
+ * and has a zero b_jcount then remove and release its journal_head. If we did
+ * see that the buffer is not used by any transaction we also "logically"
+ * decrement ->b_count.
+ *
+ * We in fact take an additional increment on ->b_count as a convenience,
+ * because the caller usually wants to do additional things with the bh
+ * after calling here.
+ * The caller of journal_remove_journal_head() *must* run __brelse(bh) at some
+ * time. Once the caller has run __brelse(), the buffer is eligible for
+ * reaping by try_to_free_buffers().
+ *
+ * Requires journal_datalist_lock.
+ */
+void __journal_remove_journal_head(struct buffer_head *bh)
+{
+ struct journal_head *jh = bh2jh(bh);
+
+ assert_spin_locked(&journal_datalist_lock);
+ J_ASSERT_JH(jh, jh->b_jcount >= 0);
+ atomic_inc(&bh->b_count);
+ if (jh->b_jcount == 0) {
+ if (jh->b_transaction == NULL &&
+ jh->b_next_transaction == NULL &&
+ jh->b_cp_transaction == NULL) {
+ J_ASSERT_BH(bh, buffer_jbd(bh));
+ J_ASSERT_BH(bh, jh2bh(jh) == bh);
+ BUFFER_TRACE(bh, "remove journal_head");
+ spin_lock(&jh_splice_lock);
+ bh->b_private = NULL;
+ jh->b_bh = NULL; /* debug, really */
+ clear_bit(BH_JBD, &bh->b_state);
+ __brelse(bh);
+ spin_unlock(&jh_splice_lock);
+ journal_free_journal_head(jh);
+ } else {
+ BUFFER_TRACE(bh, "journal_head was locked");
+ }
+ }
+}
+
+void journal_unlock_journal_head(struct journal_head *jh)
+{
+ spin_lock(&journal_datalist_lock);
+ J_ASSERT_JH(jh, jh->b_jcount > 0);
+ --jh->b_jcount;
+ if (!jh->b_jcount && !jh->b_transaction) {
+ struct buffer_head *bh;
+ bh = jh2bh(jh);
+ __journal_remove_journal_head(bh);
+ __brelse(bh);
+ }
+
+ spin_unlock(&journal_datalist_lock);
+}
+
+void journal_remove_journal_head(struct buffer_head *bh)
+{
+ spin_lock(&journal_datalist_lock);
+ __journal_remove_journal_head(bh);
+ spin_unlock(&journal_datalist_lock);
+}
+
+/*
+ * /proc tunables
+ */
+#if defined(CONFIG_JBD_DEBUG)
+int journal_enable_debug;
+EXPORT_SYMBOL(journal_enable_debug);
+#endif
+
+#if defined(CONFIG_JBD_DEBUG) && defined(CONFIG_PROC_FS)
+
+static struct proc_dir_entry *proc_jbd_debug;
+
+int read_jbd_debug(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int ret;
+
+ ret = sprintf(page + off, "%d\n", journal_enable_debug);
+ *eof = 1;


+ return ret;
+}
+

+int write_jbd_debug(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char buf[32];
+
+ if (count > ARRAY_SIZE(buf) - 1)
+ count = ARRAY_SIZE(buf) - 1;
+ if (copy_from_user(buf, buffer, count))
+ return -EFAULT;
+ buf[ARRAY_SIZE(buf) - 1] = '\0';
+ journal_enable_debug = simple_strtoul(buf, NULL, 10);
+ return count;
+}
+
+#define JBD_PROC_NAME "sys/fs/jbd-debug"
+
+static void __init create_jbd_proc_entry(void)
+{
+ proc_jbd_debug = create_proc_entry(JBD_PROC_NAME, 0644, NULL);
+ if (proc_jbd_debug) {
+ /* Why is this so hard? */
+ proc_jbd_debug->read_proc = read_jbd_debug;
+ proc_jbd_debug->write_proc = write_jbd_debug;
+ }
+}
+
+static void __exit remove_jbd_proc_entry(void)
+{
+ if (proc_jbd_debug)
+ remove_proc_entry(JBD_PROC_NAME, NULL);
+}
+
+#else
+
+#define create_jbd_proc_entry() do {} while (0)
+#define remove_jbd_proc_entry() do {} while (0)
+
+#endif
+
+/*
+ * Module startup and shutdown
+ */
+
+static int __init journal_init_caches(void)
+{
+ int ret;
+
+ ret = journal_init_revoke_caches();


+ if (ret == 0)

+ ret = journal_init_journal_head_cache();


+ return ret;
+}
+

+static void journal_destroy_caches(void)
+{
+ journal_destroy_revoke_caches();
+ journal_destroy_journal_head_cache();
+}
+
+static int __init journal_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "Journalled Block Device driver loaded\n");
+ ret = journal_init_caches();


+ if (ret != 0)

+ journal_destroy_caches();
+ create_jbd_proc_entry();


+ return ret;
+}
+

+static void __exit journal_exit(void)
+{
+#ifdef CONFIG_JBD_DEBUG


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

echo 'End of part 099'
echo 'File patch-2.4.15 is continued in part 100'
echo "100" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:08 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part092

#!/bin/sh -x
# this is part 092 of a 115 - part archive


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

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

+ return -EINVAL;
+
+ fs_down(&inode->i_sem);
+ lock_kernel();
+
+ if (size_check != inode->i_size) {
+ unlock_kernel();
+ fs_up(&inode->i_sem);
+ EXIT;
+ return -EALREADY;
+ }
+
+ newattrs.ia_size = length;
+ newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
+ op = filter_c2cfiops(fset->fset_cache->cache_filter);
+
+ if (op != NULL && op->setattr != NULL)
+ error = op->setattr(dentry, &newattrs);
+ else {
+ inode_setattr(dentry->d_inode, &newattrs);
+ /* Some filesystems, e.g. ext2 and older versions of ext3
+ legitimately do not have a <fs>_setattr method. -SHP
+ */
+ /*
+ printk ("Warning:: int presto_do_truncate(xxx), op->setattr == NULL");
+ error = -EOPNOTSUPP;
+ */
+ error = 0;
+ }
+ unlock_kernel();
+ fs_up(&inode->i_sem);


+ EXIT;
+ return error;
+}
+
+

+void *presto_trans_start(struct presto_file_set *fset, struct inode *inode,
+ int op)
+{
+ ENTRY;
+ if ( !fset->fset_cache->cache_filter->o_trops )
+ return NULL;
+ EXIT;
+ return fset->fset_cache->cache_filter->o_trops->tr_start
+ (fset, inode, op);
+}
+
+void presto_trans_commit(struct presto_file_set *fset, void *handle)
+{
+ ENTRY;
+ if (!fset->fset_cache->cache_filter->o_trops )
+ return;
+ EXIT;
+ return fset->fset_cache->cache_filter->o_trops->tr_commit(fset, handle);
+
+}
+
+inline int presto_no_journal(struct presto_file_set *fset)
+{
+ int minor = fset->fset_cache->cache_psdev->uc_minor;
+ return upc_comms[minor].uc_no_journal;
+}
+
+#define size_round(x) (((x)+3) & ~0x3)
+
+#define BUFF_FREE(buf) PRESTO_FREE(buf, PAGE_SIZE)
+#define BUFF_ALLOC(newbuf, oldbuf) \
+ PRESTO_ALLOC(newbuf, char *, PAGE_SIZE); \
+ if ( !newbuf ) { \
+ if (oldbuf) \
+ BUFF_FREE(oldbuf); \


+ return -ENOMEM; \
+ }
+

+/*
+ * "buflen" should be PAGE_SIZE or more.
+ * Give relative path wrt to a fsetroot
+ */
+char * presto_path(struct dentry *dentry, struct dentry *root,
+ char *buffer, int buflen)
+{
+ char * end = buffer+buflen;
+ char * retval;
+
+ *--end = '\0';
+ buflen--;
+ if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) {
+ buflen -= 10;
+ end -= 10;
+ memcpy(end, " (deleted)", 10);
+ }
+
+ /* Get '/' right */
+ retval = end-1;
+ *retval = '/';
+
+ for (;;) {
+ struct dentry * parent;
+ int namelen;
+
+ if (dentry == root)
+ break;


+ parent = dentry->d_parent;

+ if (dentry == parent)
+ break;
+ namelen = dentry->d_name.len;
+ buflen -= namelen + 1;
+ if (buflen < 0)
+ break;
+ end -= namelen;
+ memcpy(end, dentry->d_name.name, namelen);
+ *--end = '/';
+ retval = end;
+ dentry = parent;


+ }
+ return retval;
+}
+

+static inline char *logit(char *buf, const void *value, int size)
+{
+ char *ptr = (char *)value;
+
+ memcpy(buf, ptr, size);
+ buf += size;


+ return buf;
+}
+
+

+static inline char *
+journal_log_prefix_with_groups_and_ids(char *buf, int opcode,
+ struct rec_info *rec,
+ __u32 ngroups, gid_t *groups,
+ __u32 fsuid, __u32 fsgid)
+{
+ struct big_journal_prefix p;
+ int i;
+
+ p.len = cpu_to_le32(rec->size);
+ p.version = PRESTO_KML_MAJOR_VERSION | PRESTO_KML_MINOR_VERSION;
+ p.pid = cpu_to_le32(current->pid);
+ p.uid = cpu_to_le32(current->uid);
+ p.fsuid = cpu_to_le32(fsuid);
+ p.fsgid = cpu_to_le32(fsgid);
+ p.ngroups = cpu_to_le32(ngroups);
+ p.opcode = cpu_to_le32(opcode);
+ for (i=0 ; i < ngroups ; i++)
+ p.groups[i] = cpu_to_le32((__u32) groups[i]);
+
+ buf = logit(buf, &p, sizeof(struct journal_prefix) +
+ sizeof(__u32) * ngroups);


+ return buf;
+}
+

+static inline char *
+journal_log_prefix(char *buf, int opcode, struct rec_info *rec)


+{
+ __u32 groups[NGROUPS_MAX];

+ int i;
+
+ /* convert 16 bit gid's to 32 bit gid's */


+ for (i=0; i<current->ngroups; i++)

+ groups[i] = (__u32) current->groups[i];
+
+ return journal_log_prefix_with_groups_and_ids(buf, opcode, rec,
+ (__u32)current->ngroups,
+ groups,
+ (__u32)current->fsuid,
+ (__u32)current->fsgid);
+}
+
+static inline char *
+journal_log_prefix_with_groups(char *buf, int opcode, struct rec_info *rec,
+ __u32 ngroups, gid_t *groups)
+{
+ return journal_log_prefix_with_groups_and_ids(buf, opcode, rec,
+ ngroups, groups,
+ (__u32)current->fsuid,
+ (__u32)current->fsgid);
+}
+
+static inline char *log_version(char *buf, struct dentry *dentry)
+{
+ struct presto_version version;
+
+ presto_getversion(&version, dentry->d_inode);
+
+ return logit(buf, &version, sizeof(version));
+}
+
+static inline char *journal_log_suffix(char *buf, char *log,
+ struct presto_file_set *fset,
+ struct dentry *dentry,
+ struct rec_info *rec)
+{
+ struct journal_suffix s;
+ struct journal_prefix *p = (struct journal_prefix *)log;
+
+#if 0
+ /* XXX needs to be done after reservation,
+ disable ths until version 1.2 */
+ if ( dentry ) {
+ s.prevrec = cpu_to_le32(rec->offset -
+ presto_d2d(dentry)->dd_kml_offset);
+ presto_d2d(dentry)->dd_kml_offset = rec->offset;
+ } else {
+ s.prevrec = -1;
+ }
+#endif
+ s.prevrec = 0;
+
+ /* record number needs to be filled in after reservation
+ s.recno = cpu_to_le32(rec->recno); */
+ s.time = cpu_to_le32(CURRENT_TIME);
+ s.len = cpu_to_le32(p->len);
+ return logit(buf, &s, sizeof(s));
+}
+
+int presto_close_journal_file(struct presto_file_set *fset)


+{
+ int rc = 0;

+ int rc2 = 0;
+ int rc3 = 0;
+
+ ENTRY;
+ if ( fset->fset_kml.fd_file) {
+ rc =filp_close(fset->fset_kml.fd_file, 0);
+ fset->fset_kml.fd_file = NULL;
+ } else {
+ printk("hehehehe no filp\n");


+ }
+ if ( rc ) {

+ printk("presto: close files: kml filp won't close %d\n", rc);
+ }
+
+ if ( fset->fset_last_rcvd) {
+ rc2 = filp_close(fset->fset_last_rcvd, 0);
+ fset->fset_last_rcvd = NULL;
+ } else {
+ printk("hehehehe no filp\n");
+ }
+
+ if ( rc2 ) {
+ if ( !rc )
+ rc = rc2;
+ printk("presto: close files: last_rcvd filp won't close %d\n", rc2);
+ }
+
+ if ( fset->fset_lml.fd_file) {
+ rc3 = filp_close(fset->fset_lml.fd_file, 0);
+ fset->fset_lml.fd_file = NULL;
+ } else {
+ printk("hehehehe no filp\n");
+ }
+ if ( rc3 ) {
+ if ( (!rc) && (!rc2) )
+ rc = rc3;
+ printk("presto: close files: lml filp won't close %d\n", rc3);
+ }


+ return rc;
+}
+

+int presto_fwrite(struct file *file, const char *str, int len, loff_t *off)
+{
+ int rc;
+ mm_segment_t old_fs;
+ ENTRY;
+
+ rc = -EINVAL;
+ if ( !off ) {


+ EXIT;
+ return rc;
+ }
+

+ if ( ! file ) {


+ EXIT;
+ return rc;
+ }
+

+ if ( ! file->f_op ) {


+ EXIT;
+ return rc;
+ }
+

+ if ( ! file->f_op->write ) {


+ EXIT;
+ return rc;
+ }
+

+ old_fs = get_fs();
+ set_fs(get_ds());
+ rc = file->f_op->write(file, str, len, off);
+ if (rc != len) {
+ printk("presto_fwrite: wrote %d bytes instead of "
+ "%d at %ld\n", rc, len, (long)*off);
+ rc = -EIO;
+ }
+ set_fs(old_fs);


+ EXIT;
+ return rc;
+}
+

+int presto_fread(struct file *file, char *str, int len, loff_t *off)
+{
+ int rc;
+ mm_segment_t old_fs;
+ ENTRY;
+
+ if ( len > 512 ) {
+ printk("presto_fread: read at %Ld for %d bytes, ino %ld\n",
+ *off, len, file->f_dentry->d_inode->i_ino);
+ }
+
+ rc = -EINVAL;
+ if ( !off ) {


+ EXIT;
+ return rc;
+ }
+

+ if ( ! file ) {


+ EXIT;
+ return rc;
+ }
+

+ if ( ! file->f_op ) {


+ EXIT;
+ return rc;
+ }
+

+ if ( ! file->f_op->read ) {


+ EXIT;
+ return rc;
+ }
+

+ old_fs = get_fs();
+ set_fs(get_ds());
+ rc = file->f_op->read(file, str, len, off);
+ if (rc != len) {
+ printk("presto_fread: read %d bytes instead of "
+ "%d at %ld\n", rc, len, (long)*off);
+ rc = -EIO;
+ }
+ set_fs(old_fs);


+ return rc;
+}
+
+

+static int presto_kml_dispatch(struct presto_file_set *fset)


+{
+ int rc = 0;

+ unsigned int kml_recno;
+ struct presto_log_fd *fd = &fset->fset_kml;
+ loff_t offset;


+ ENTRY;
+
+ write_lock(&fd->fd_lock);
+

+ /* Determine the largest valid offset, i.e. up until the first
+ * reservation held on the file. */
+ if ( !list_empty(&fd->fd_reservations) ) {
+ struct presto_reservation_data *rd;
+ rd = list_entry(fd->fd_reservations.next,
+ struct presto_reservation_data,
+ ri_list);
+ offset = rd->ri_offset;
+ kml_recno = rd->ri_recno;
+ } else {
+ offset = fd->fd_file->f_dentry->d_inode->i_size;
+ kml_recno = fset->fset_kml.fd_recno;
+ }
+
+ if ( kml_recno < fset->fset_lento_recno ) {
+ printk("presto_kml_dispatch: smoke is coming\n");
+ write_unlock(&fd->fd_lock);
+ return 0;
+ } else if ( kml_recno == fset->fset_lento_recno ) {
+ write_unlock(&fd->fd_lock);


+ EXIT;
+ return 0;
+ }

+ CDEBUG(D_PIOCTL, "fset: %s\n", fset->fset_name);
+ rc = lento_kml(fset->fset_cache->cache_psdev->uc_minor,
+ fset->fset_lento_off, fset->fset_lento_recno,
+ offset, kml_recno, strlen(fset->fset_name),
+ fset->fset_name);


+
+ if ( rc ) {

+ write_unlock(&fd->fd_lock);


+ EXIT;
+ return rc;
+ }
+

+ fset->fset_lento_off = offset;
+ fset->fset_lento_recno = kml_recno;
+ write_unlock(&fd->fd_lock);


+ EXIT;
+ return 0;
+}
+
+

+/* structure of an extended log record:
+
+ buf-prefix buf-body [string1 [string2 [string3]]] buf-suffix
+
+ note: moves offset forward
+*/
+static inline int presto_write_record(struct file *f, loff_t *off,


+ const char *buf, size_t size,
+ const char *string1, int len1,
+ const char *string2, int len2,
+ const char *string3, int len3)

+{
+ size_t prefix_size;
+ int rc;
+
+ prefix_size = size - sizeof(struct journal_suffix);
+ rc = presto_fwrite(f, buf, prefix_size, off);
+ if ( rc != prefix_size ) {
+ printk("Write error!\n");
+ EXIT;
+ return -EIO;
+ }
+
+ if ( string1 && len1 ) {
+ rc = presto_fwrite(f, string1, len1, off);
+ if ( rc != len1 ) {
+ printk("Write error!\n");
+ EXIT;
+ return -EIO;
+ }
+ }
+
+ if ( string2 && len2 ) {
+ rc = presto_fwrite(f, string2, len2, off);
+ if ( rc != len2 ) {
+ printk("Write error!\n");
+ EXIT;
+ return -EIO;
+ }
+ }
+
+ if ( string3 && len3 ) {
+ rc = presto_fwrite(f, string3, len3, off);
+ if ( rc != len3 ) {
+ printk("Write error!\n");
+ EXIT;


+ return -EIO;
+ }
+ }
+

+ rc = presto_fwrite(f, buf + prefix_size,
+ sizeof(struct journal_suffix), off);
+ if ( rc != sizeof(struct journal_suffix) ) {
+ printk("Write error!\n");
+ EXIT;
+ return -EIO;


+ }
+ return 0;
+}
+
+

+/*
+ * rec->size must be valid prior to calling this function.
+ */


+static int presto_log(struct presto_file_set *fset, struct rec_info *rec,
+ const char *buf, size_t size,
+ const char *string1, int len1,
+ const char *string2, int len2,
+ const char *string3, int len3)

+{
+ int rc;
+ struct presto_reservation_data rd;
+ loff_t offset;
+ struct presto_log_fd *fd;
+ struct journal_suffix *s;
+ int prefix_size;
+
+ ENTRY;
+
+ /* buf is NULL when no_journal is in effect */
+ if (!buf) {


+ EXIT;
+ return -EINVAL;
+ }
+

+ if (rec->is_kml) {
+ fd = &fset->fset_kml;
+ } else {
+ fd = &fset->fset_lml;
+ }
+
+ presto_reserve_record(fset, fd, rec, &rd);
+ offset = rec->offset;
+
+ /* now we know the record number */
+ prefix_size = size - sizeof(struct journal_suffix);
+ s = (struct journal_suffix *) (buf + prefix_size);
+ s->recno = cpu_to_le32(rec->recno);
+
+ rc = presto_write_record(fd->fd_file, &offset, buf, size,
+ string1, len1, string2, len2, string3, len3);
+ if (rc) {
+ printk("presto: error writing record to %s\n",
+ rec->is_kml ? "KML" : "LML");
+ return rc;
+ }
+ presto_release_record(fd, &rd);
+
+ rc = presto_kml_dispatch(fset);


+
+ EXIT;
+ return rc;
+}
+

+/* read from the record at tail */
+static int presto_last_record(struct presto_log_fd *fd, loff_t *size,
+ loff_t *tail_offset, __u32 *recno, loff_t tail)
+{
+ struct journal_suffix suffix;
+ int rc;
+ loff_t zeroes;
+
+ *recno = 0;
+ *tail_offset = 0;
+ *size = 0;
+
+ if (tail < sizeof(struct journal_prefix) + sizeof(suffix)) {


+ EXIT;
+ return 0;
+ }
+

+ zeroes = tail - sizeof(int);
+ while ( zeroes >= 0 ) {
+ int data;
+ rc = presto_fread(fd->fd_file, (char *)&data, sizeof(data),
+ &zeroes);
+ if ( rc != sizeof(data) ) {
+ rc = -EIO;
+ return rc;
+ }
+ if (data)
+ break;
+ zeroes -= 2 * sizeof(data);
+ }
+
+ /* zeroes at the begining of file. this is needed to prevent
+ presto_fread errors -SHP
+ */
+ if (zeroes <= 0) return 0;
+
+ zeroes -= sizeof(suffix);
+ rc = presto_fread(fd->fd_file, (char *)&suffix, sizeof(suffix), &zeroes);
+ if ( rc != sizeof(suffix) ) {


+ EXIT;
+ return rc;
+ }

+ if ( suffix.len > 500 ) {
+ printk("PRESTO: Warning long record tail at %ld, rec tail_offset at %ld (size %d)\n",
+ (long) zeroes, (long)*tail_offset, suffix.len);
+ }
+
+ *recno = suffix.recno;
+ *size = suffix.len;
+ *tail_offset = zeroes;


+ return 0;
+}
+

+static int presto_kml_last_recno(struct presto_file_set *fset)
+{
+ int rc;
+ loff_t size;
+ loff_t tail_offset;
+ int recno;
+ loff_t tail = fset->fset_kml.fd_file->f_dentry->d_inode->i_size;
+
+ if ((rc = presto_last_record(&fset->fset_kml, &size,
+ &tail_offset, &recno, tail)) ) {


+ EXIT;
+ return rc;
+ }
+

+ fset->fset_kml.fd_offset = tail_offset;


+ fset->fset_kml.fd_recno = recno;

+ CDEBUG(D_JOURNAL, "setting fset_kml->fd_recno to %d, offset %Ld\n",
+ recno, tail_offset);

+ EXIT;
+ return 0;
+}
+

+static struct file *presto_log_open(struct presto_file_set *fset, char *name, int flags)
+{


+ struct presto_cache *cache = fset->fset_cache;

+ struct file *f;
+ int error;
+ int mtpt_len, path_len;
+ char *path;
+ ENTRY;
+
+ mtpt_len = strlen(cache->cache_mtpt);
+ path_len = mtpt_len + strlen("/.intermezzo/") +
+ strlen(fset->fset_name) + strlen(name);
+
+ error = -ENOMEM;
+ PRESTO_ALLOC(path, char *, path_len + 1);
+ if ( !path ) {
+ EXIT;
+ return ERR_PTR(-ENOMEM);
+ }
+
+ sprintf(path, "%s/.intermezzo/%s/%s", cache->cache_mtpt,
+ fset->fset_name, name);
+ CDEBUG(D_INODE, "opening file %s\n", path);
+
+ f = filp_open(path, flags, 0);
+ error = PTR_ERR(f);
+ if (IS_ERR(f)) {
+ CDEBUG(D_INODE, "Error %d\n", error);
+ EXIT;
+ goto out_free;
+ }
+
+ error = -EINVAL;
+ if ( cache != presto_get_cache(f->f_dentry->d_inode) ) {
+ printk("PRESTO: %s cache does not match fset cache!\n", name);
+ fset->fset_kml.fd_file = NULL;
+ filp_close(f, NULL);
+ goto out_free;
+ }
+
+ if (cache->cache_filter && cache->cache_filter->o_trops &&
+ cache->cache_filter->o_trops->tr_journal_data) {
+ CDEBUG(D_INODE, "\n");
+ cache->cache_filter->o_trops->tr_journal_data
+ (f->f_dentry->d_inode);
+ } else {
+ printk("WARNING: InterMezzo no file data logging!\n");
+ }
+
+ out_free:
+ PRESTO_FREE(path, path_len + 1);
+
+ EXIT;
+ return f;
+}
+
+int presto_init_kml_file(struct presto_file_set *fset)
+{


+ int error = 0;

+ struct file *f;
+
+ ENTRY;
+ if (fset->fset_kml.fd_file) {
+ CDEBUG(D_INODE, "fset already has KML open\n");
+ EXIT;
+ return 0;
+ }
+
+ fset->fset_kml.fd_lock = RW_LOCK_UNLOCKED;
+ INIT_LIST_HEAD(&fset->fset_kml.fd_reservations);
+ f = presto_log_open(fset, "kml", O_RDWR | O_CREAT);
+ if ( IS_ERR(f) ) {
+ error = PTR_ERR(f);


+ return error;
+ }
+

+ fset->fset_kml.fd_file = f;
+ error = presto_kml_last_recno(fset);
+


+ if ( error ) {
+ EXIT;

+ fset->fset_kml.fd_file = NULL;
+ filp_close(f, NULL);
+ printk("presto: IO error in KML of fset %s\n",
+ fset->fset_name);
+ }
+ fset->fset_lento_off = fset->fset_kml.fd_offset;
+ fset->fset_lento_recno = fset->fset_kml.fd_recno;
+
+ EXIT;
+ return error;
+}
+
+
+int presto_init_last_rcvd_file(struct presto_file_set *fset)
+{


+ int error = 0;

+ struct file *f;
+
+ ENTRY;
+ if (fset->fset_last_rcvd) {
+ CDEBUG(D_INODE, "fset already has last_rcvd open\n");
+ EXIT;
+ return 0;
+ }
+
+ f = presto_log_open(fset, "last_rcvd", O_RDWR | O_CREAT);
+ if ( IS_ERR(f) ) {
+ error = PTR_ERR(f);


+ return error;
+ }
+

+ fset->fset_last_rcvd = f;
+
+ EXIT;
+ return error;
+}
+
+int presto_init_lml_file(struct presto_file_set *fset)
+{


+ int error = 0;

+ struct file *f;
+
+ ENTRY;
+ if (fset->fset_lml.fd_file) {
+ CDEBUG(D_INODE, "fset already has lml open\n");
+ EXIT;
+ return 0;
+ }
+
+ fset->fset_lml.fd_lock = RW_LOCK_UNLOCKED;
+ INIT_LIST_HEAD(&fset->fset_lml.fd_reservations);
+ f = presto_log_open(fset, "lml", O_RDWR | O_CREAT);
+ if ( IS_ERR(f) ) {
+ error = PTR_ERR(f);


+ return error;
+ }
+

+ fset->fset_lml.fd_file = f;
+ fset->fset_lml.fd_offset =
+ fset->fset_lml.fd_file->f_dentry->d_inode->i_size;
+


+ EXIT;
+ return error;
+}
+

+/* Write the last_rcvd values to the last)_rcvd file */
+int presto_write_last_rcvd(struct rec_info *recinfo,
+ struct presto_file_set *fset,


+ struct lento_vfs_context *info)
+{

+ int ret;
+ loff_t off = info->slot_offset;
+ struct {
+ __u32 remote_recno;
+ __u64 remote_offset;
+ __u32 local_recno;
+ __u64 local_offset;
+ } rcvd_rec;
+
+ rcvd_rec.remote_recno = cpu_to_le32(info->recno);
+ rcvd_rec.remote_offset = cpu_to_le64(info->kml_offset);
+ rcvd_rec.local_recno = cpu_to_le32(recinfo->recno);
+ rcvd_rec.local_offset = cpu_to_le64(recinfo->offset + recinfo->size);
+
+ ret = presto_fwrite(fset->fset_last_rcvd, (char *)(&rcvd_rec),
+ sizeof(rcvd_rec), &off);
+
+ if (ret == sizeof(rcvd_rec))
+ ret = 0;


+
+ return ret;
+}
+

+/* LML records here */
+/* this writes the LML records for close, in conjunction with the KML */
+int presto_write_lml_close(struct rec_info *rec,
+ struct presto_file_set *fset,
+ struct file *file,
+ __u64 remote_ino,
+ __u32 remote_generation,
+ __u32 remote_version,
+ struct presto_version *new_file_ver)
+{
+ int opcode = PRESTO_OP_CLOSE;
+ char *buffer;
+ struct dentry *dentry = file->f_dentry;
+ __u64 ino;
+ __u32 pathlen;
+ char *path;
+ __u32 generation;


+ int size;
+ char *logrecord;
+ char record[292];
+ struct dentry *root;

+ int error;
+
+ ENTRY;
+

+ if ( presto_no_journal(fset) ) {
+ EXIT;
+ return 0;


+ }
+ root = fset->fset_mtpt;
+

+ BUFF_ALLOC(buffer, NULL);
+ path = presto_path(dentry, root, buffer, PAGE_SIZE);
+ CDEBUG(D_INODE, "Path: %s\n", path);
+ pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
+ ino = cpu_to_le64(dentry->d_inode->i_ino);
+ generation = cpu_to_le32(dentry->d_inode->i_generation);


+ size = sizeof(__u32) * current->ngroups +

+ sizeof(struct journal_prefix) + sizeof(*new_file_ver) +
+ sizeof(ino) + sizeof(generation) + sizeof(pathlen) +
+ sizeof(remote_ino) + sizeof(remote_generation) +
+ sizeof(remote_version) + sizeof(rec->offset) +


+ sizeof(struct journal_suffix);
+
+ if ( size > sizeof(record) ) {
+ printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
+ }
+

+ rec->is_kml = 0;


+ rec->size = size + size_round(le32_to_cpu(pathlen));
+

+ logrecord = journal_log_prefix(record, opcode, rec);

+ logrecord = logit(logrecord, new_file_ver, sizeof(*new_file_ver));
+ logrecord = logit(logrecord, &ino, sizeof(ino));
+ logrecord = logit(logrecord, &generation, sizeof(generation));
+ logrecord = logit(logrecord, &pathlen, sizeof(pathlen));

+ logrecord = logit(logrecord, &remote_ino, sizeof(remote_ino));
+ logrecord = logit(logrecord, &remote_generation,
+ sizeof(remote_generation));
+ logrecord = logit(logrecord, &remote_version, sizeof(remote_version));
+ logrecord = logit(logrecord, &rec->offset, sizeof(rec->offset));


+ logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
+
+ error = presto_log(fset, rec, record, size,
+ path, size_round(le32_to_cpu(pathlen)),

+ NULL, 0, NULL, 0);
+

+ BUFF_FREE(buffer);
+
+ EXIT;
+ return error;
+}
+
+int presto_journal_write(struct rec_info *rec,
+ struct presto_file_set *fset,
+ struct file *file)
+{
+ struct presto_version file_version;
+ int rc;
+ ENTRY;
+
+ presto_getversion(&file_version, file->f_dentry->d_inode);
+ /* append this record */
+ rc = presto_write_lml_close
+ (rec,
+ fset,
+ file,
+ 0, /* remote_ino */
+ 0, /* remote_generation */
+ 0, /* remote_version */
+ &file_version);


+ EXIT;
+ return rc;
+}
+

+/*
+ * Check if the given record is at the end of the file. If it is, truncate
+ * the lml to the record's offset, removing it. Repeat on prior record,
+ * until we reach an active record or a reserved record (as defined by the
+ * reservations list).
+ */
+static int presto_truncate_lml_tail(struct presto_file_set *fset)
+{
+ loff_t lml_tail;
+ loff_t lml_last_rec;
+ loff_t lml_last_recsize;
+ loff_t local_offset;
+ int recno;
+ struct journal_prefix prefix;
+ struct inode *inode = fset->fset_lml.fd_file->f_dentry->d_inode;
+ void *handle;


+ int rc;
+
+ ENTRY;

+ /* If someone else is already truncating the LML, return. */
+ write_lock(&fset->fset_lml.fd_lock);
+ if (fset->fset_lml.fd_truncating == 1 ) {
+ write_unlock(&fset->fset_lml.fd_lock);

+ EXIT;
+ return 0;
+ }

+ /* someone is about to write to the end of the LML */
+ if ( !list_empty(&fset->fset_lml.fd_reservations) ) {
+ write_unlock(&fset->fset_lml.fd_lock);

+ EXIT;
+ return 0;
+ }

+ lml_tail = fset->fset_lml.fd_file->f_dentry->d_inode->i_size;
+ /* Nothing to truncate?*/
+ if (lml_tail == 0) {
+ write_unlock(&fset->fset_lml.fd_lock);

+ EXIT;
+ return 0;
+ }

+ fset->fset_lml.fd_truncating = 1;
+ write_unlock(&fset->fset_lml.fd_lock);
+
+ presto_last_record(&fset->fset_lml, &lml_last_recsize,
+ &lml_last_rec, &recno, lml_tail);
+ /* Do we have a record to check? If not we have zeroes at the
+ beginning of the file. -SHP
+ */
+ if (lml_last_recsize != 0) {
+ local_offset = lml_last_rec - lml_last_recsize;
+ rc = presto_fread(fset->fset_lml.fd_file, (char *)&prefix,
+ sizeof(prefix), &local_offset);
+ if (rc != sizeof(prefix)) {
+ EXIT;
+ goto tr_out;
+ }
+
+ if ( prefix.opcode != PRESTO_OP_NOOP ) {
+ EXIT;
+ rc = 0;
+ /* We may have zeroes at the end of the file, should
+ we clear them out? -SHP
+ */
+ goto tr_out;
+ }
+ } else
+ lml_last_rec=0;
+
+ handle = presto_trans_start(fset, inode, PRESTO_OP_TRUNC);


+ if ( !handle ) {
+ EXIT;

+ rc = -ENOMEM;
+ goto tr_out;
+ }
+
+ rc = presto_do_truncate(fset, fset->fset_lml.fd_file->f_dentry,
+ lml_last_rec - lml_last_recsize, lml_tail);
+ presto_trans_commit(fset, handle);

+ if ( rc == 0 ) {

+ rc = 1;
+ }
+ EXIT;
+
+ tr_out:
+ CDEBUG(D_JOURNAL, "rc = %d\n", rc);
+ write_lock(&fset->fset_lml.fd_lock);
+ fset->fset_lml.fd_truncating = 0;
+ write_unlock(&fset->fset_lml.fd_lock);


+ return rc;
+}
+

+int presto_truncate_lml(struct presto_file_set *fset)
+{
+
+ int rc;
+ ENTRY;
+
+ while ( (rc = presto_truncate_lml_tail(fset)) > 0);
+ if ( rc < 0 && rc != -EALREADY) {
+ printk("truncate_lml error %d\n", rc);
+ }


+ EXIT;
+ return rc;
+}
+
+
+

+int presto_clear_lml_close(struct presto_file_set *fset,
+ loff_t lml_offset)
+{
+ int rc;
+ struct journal_prefix record;
+ loff_t offset = lml_offset;
+
+ ENTRY;
+
+ if ( presto_no_journal(fset) ) {
+ EXIT;
+ return 0;
+ }
+
+ CDEBUG(D_JOURNAL, "reading prefix: off %ld, size %d\n",
+ (long)lml_offset, sizeof(record));
+ rc = presto_fread(fset->fset_lml.fd_file, (char *)&record,
+ sizeof(record), &offset);
+
+ if ( rc != sizeof(record) ) {
+ printk("presto: clear_lml io error %d\n", rc);
+ EXIT;


+ return -EIO;
+ }
+

+ /* overwrite the prefix */
+ CDEBUG(D_JOURNAL, "overwriting prefix: off %ld\n", (long)lml_offset);
+ record.opcode = PRESTO_OP_NOOP;
+ offset = lml_offset;
+ /* note: this does just a single transaction in the cache */
+ rc = presto_fwrite(fset->fset_lml.fd_file, (char *)(&record),
+ sizeof(record), &offset);
+ if ( rc != sizeof(record) ) {
+ EXIT;
+ return -EIO;
+ }
+
+ EXIT;
+ return 0;
+}
+
+
+
+/* now a journal function for every operation */
+
+int presto_journal_setattr(struct rec_info *rec,
+ struct presto_file_set *fset,
+ struct dentry *dentry,
+ struct presto_version *old_ver, struct iattr *iattr)
+{
+ int opcode = PRESTO_OP_SETATTR;
+ char *buffer;


+ char *path;
+ __u32 pathlen;
+ int size;
+ char *logrecord;
+ char record[292];
+ struct dentry *root;

+ __u32 uid, gid, mode, valid, flags;
+ __u64 fsize, mtime, ctime;


+ int error;
+
+ ENTRY;

+ if ( presto_no_journal(fset) ) {
+ EXIT;


+ return 0;
+ }
+

+ if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0) ) {
+ EXIT;


+ return 0;
+ }
+
+ root = fset->fset_mtpt;
+

+ BUFF_ALLOC(buffer, NULL);
+ path = presto_path(dentry, root, buffer, PAGE_SIZE);
+ pathlen = cpu_to_le32(MYPATHLEN(buffer, path));


+ size = sizeof(__u32) * current->ngroups +

+ sizeof(struct journal_prefix) + sizeof(*old_ver) +
+ sizeof(valid) + sizeof(mode) + sizeof(uid) + sizeof(gid) +
+ sizeof(fsize) + sizeof(mtime) + sizeof(ctime) + sizeof(flags) +
+ sizeof(pathlen) + sizeof(struct journal_suffix);


+
+ if ( size > sizeof(record) ) {
+ printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
+ }

+ /* Only journal one kind of mtime, and not atime at all. Also don't
+ * journal bogus data in iattr, to make the journal more compressible.
+ */
+ if (iattr->ia_valid & ATTR_MTIME_SET)
+ iattr->ia_valid = iattr->ia_valid | ATTR_MTIME;
+ valid = cpu_to_le32(iattr->ia_valid & ~(ATTR_ATIME | ATTR_MTIME_SET |
+ ATTR_ATIME_SET));
+ mode = iattr->ia_valid & ATTR_MODE ? cpu_to_le32(iattr->ia_mode): 0;
+ uid = iattr->ia_valid & ATTR_UID ? cpu_to_le32(iattr->ia_uid): 0;
+ gid = iattr->ia_valid & ATTR_GID ? cpu_to_le32(iattr->ia_gid): 0;
+ fsize = iattr->ia_valid & ATTR_SIZE ? cpu_to_le64(iattr->ia_size): 0;
+ mtime = iattr->ia_valid & ATTR_MTIME ? cpu_to_le64(iattr->ia_mtime): 0;
+ ctime = iattr->ia_valid & ATTR_CTIME ? cpu_to_le64(iattr->ia_ctime): 0;
+ flags = iattr->ia_valid & ATTR_ATTR_FLAG ?
+ cpu_to_le32(iattr->ia_attr_flags): 0;


+
+ rec->is_kml = 1;
+ rec->size = size + size_round(le32_to_cpu(pathlen));
+

+ logrecord = journal_log_prefix(record, opcode, rec);

+ logrecord = logit(logrecord, old_ver, sizeof(*old_ver));
+ logrecord = logit(logrecord, &valid, sizeof(valid));
+ logrecord = logit(logrecord, &mode, sizeof(mode));
+ logrecord = logit(logrecord, &uid, sizeof(uid));
+ logrecord = logit(logrecord, &gid, sizeof(gid));
+ logrecord = logit(logrecord, &fsize, sizeof(fsize));
+ logrecord = logit(logrecord, &mtime, sizeof(mtime));
+ logrecord = logit(logrecord, &ctime, sizeof(ctime));


+ logrecord = logit(logrecord, &flags, sizeof(flags));

+ logrecord = logit(logrecord, &pathlen, sizeof(pathlen));

+ logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
+
+ error = presto_log(fset, rec, record, size,
+ path, size_round(le32_to_cpu(pathlen)),

+ NULL, 0, NULL, 0);
+

+ BUFF_FREE(buffer);


+ EXIT;
+ return error;
+}
+

+int presto_journal_create(struct rec_info *rec, struct presto_file_set *fset,
+ struct dentry *dentry,
+ struct presto_version *tgt_dir_ver,
+ struct presto_version *new_file_ver, int mode)
+{
+ int opcode = PRESTO_OP_CREATE;
+ char *buffer;


+ char *path;
+ __u32 pathlen;
+ int size;
+ char *logrecord;
+ char record[292];
+ struct dentry *root;

+ __u32 uid, gid, lmode;


+ int error;
+
+ ENTRY;

+ if ( presto_no_journal(fset) ) {
+ EXIT;


+ return 0;
+ }
+
+ root = fset->fset_mtpt;
+

+ uid = cpu_to_le32(dentry->d_inode->i_uid);
+ gid = cpu_to_le32(dentry->d_inode->i_gid);
+ lmode = cpu_to_le32(mode);
+
+ BUFF_ALLOC(buffer, NULL);
+ path = presto_path(dentry, root, buffer, PAGE_SIZE);
+ pathlen = cpu_to_le32(MYPATHLEN(buffer, path));


+ size = sizeof(__u32) * current->ngroups +

+ sizeof(struct journal_prefix) + 3 * sizeof(*tgt_dir_ver) +
+ sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(pathlen) +


+ sizeof(struct journal_suffix);
+
+ if ( size > sizeof(record) ) {
+ printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
+ }
+
+ rec->is_kml = 1;

+ rec->size = size + size_round(le32_to_cpu(pathlen));
+

+ logrecord = journal_log_prefix(record, opcode, rec);

+ logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
+ logrecord = log_version(logrecord, dentry->d_parent);


+ logrecord = logit(logrecord, new_file_ver, sizeof(*new_file_ver));

+ logrecord = logit(logrecord, &lmode, sizeof(lmode));
+ logrecord = logit(logrecord, &uid, sizeof(uid));
+ logrecord = logit(logrecord, &gid, sizeof(gid));


+ logrecord = logit(logrecord, &pathlen, sizeof(pathlen));

+ logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
+
+ error = presto_log(fset, rec, record, size,
+ path, size_round(le32_to_cpu(pathlen)),

+ NULL, 0, NULL, 0);
+

+ BUFF_FREE(buffer);


+ EXIT;
+ return error;
+}
+

+int presto_journal_symlink(struct rec_info *rec, struct presto_file_set *fset, struct dentry *dentry,
+ const char *target,
+ struct presto_version *tgt_dir_ver,
+ struct presto_version *new_link_ver)
+{
+ int opcode = PRESTO_OP_SYMLINK;
+ char *buffer;


+ char *path;
+ __u32 pathlen;
+ int size;
+ char *logrecord;
+ char record[292];

+ __u32 targetlen = cpu_to_le32(strlen(target));
+ struct dentry *root;
+ __u32 uid, gid;


+ int error;
+
+ ENTRY;

+ if ( presto_no_journal(fset) ) {
+ EXIT;


+ return 0;
+ }
+
+ root = fset->fset_mtpt;
+

+ uid = cpu_to_le32(dentry->d_inode->i_uid);
+ gid = cpu_to_le32(dentry->d_inode->i_gid);
+
+ BUFF_ALLOC(buffer, NULL);
+ path = presto_path(dentry, root, buffer, PAGE_SIZE);
+ pathlen = cpu_to_le32(MYPATHLEN(buffer, path));


+ size = sizeof(__u32) * current->ngroups +

+ sizeof(struct journal_prefix) + 3 * sizeof(*tgt_dir_ver) +
+ sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
+ sizeof(targetlen) + sizeof(struct journal_suffix);


+
+ if ( size > sizeof(record) ) {
+ printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
+ }
+
+ rec->is_kml = 1;
+ rec->size = size + size_round(le32_to_cpu(pathlen)) +

+ size_round(le32_to_cpu(targetlen));


+
+ logrecord = journal_log_prefix(record, opcode, rec);

+ logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
+ logrecord = log_version(logrecord, dentry->d_parent);
+ logrecord = logit(logrecord, new_link_ver, sizeof(*new_link_ver));
+ logrecord = logit(logrecord, &uid, sizeof(uid));
+ logrecord = logit(logrecord, &gid, sizeof(gid));


+ logrecord = logit(logrecord, &pathlen, sizeof(pathlen));

+ logrecord = logit(logrecord, &targetlen, sizeof(targetlen));


+ logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
+
+ error = presto_log(fset, rec, record, size,
+ path, size_round(le32_to_cpu(pathlen)),

+ target, size_round(le32_to_cpu(targetlen)),
+ NULL, 0);
+
+ BUFF_FREE(buffer);


+ EXIT;
+ return error;
+}
+

+int presto_journal_mkdir(struct rec_info *rec, struct presto_file_set *fset, struct dentry *dentry,
+ struct presto_version *tgt_dir_ver,
+ struct presto_version *new_dir_ver, int mode)
+{
+ int opcode = PRESTO_OP_MKDIR;
+ char *buffer;


+ char *path;
+ __u32 pathlen;
+ int size;
+ char *logrecord;
+ char record[292];
+ struct dentry *root;

+ __u32 uid, gid, lmode;


+ int error;
+
+ ENTRY;

+ if ( presto_no_journal(fset) ) {
+ EXIT;


+ return 0;
+ }
+
+ root = fset->fset_mtpt;
+

+ uid = cpu_to_le32(dentry->d_inode->i_uid);
+ gid = cpu_to_le32(dentry->d_inode->i_gid);
+ lmode = cpu_to_le32(mode);
+
+ BUFF_ALLOC(buffer, NULL);
+ path = presto_path(dentry, root, buffer, PAGE_SIZE);
+ pathlen = cpu_to_le32(MYPATHLEN(buffer, path));


+ size = sizeof(__u32) * current->ngroups +

+ sizeof(struct journal_prefix) + 3 * sizeof(*tgt_dir_ver) +
+ sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(pathlen) +


+ sizeof(struct journal_suffix);
+
+ if ( size > sizeof(record) ) {
+ printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
+ }
+
+ rec->is_kml = 1;

+ rec->size = size + size_round(le32_to_cpu(pathlen));

+ logrecord = journal_log_prefix(record, opcode, rec);
+

+ logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
+ logrecord = log_version(logrecord, dentry->d_parent);
+ logrecord = logit(logrecord, new_dir_ver, sizeof(*new_dir_ver));
+ logrecord = logit(logrecord, &lmode, sizeof(lmode));
+ logrecord = logit(logrecord, &uid, sizeof(uid));
+ logrecord = logit(logrecord, &gid, sizeof(gid));


+ logrecord = logit(logrecord, &pathlen, sizeof(pathlen));

+ logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
+
+ error = presto_log(fset, rec, record, size,
+ path, size_round(le32_to_cpu(pathlen)),

+ NULL, 0, NULL, 0);
+

+ BUFF_FREE(buffer);


+ EXIT;
+ return error;
+}
+
+

+int
+presto_journal_rmdir(struct rec_info *rec, struct presto_file_set *fset,
+ struct dentry *dir, struct presto_version *tgt_dir_ver,
+ struct presto_version *old_dir_ver, int len,


+ const char *name)
+{

+ int opcode = PRESTO_OP_RMDIR;
+ char *buffer;
+ char *path;
+ __u32 pathlen, llen;


+ int size;
+ char *logrecord;
+ char record[292];
+ struct dentry *root;

+ int error;
+
+ ENTRY;

+ if ( presto_no_journal(fset) ) {
+ EXIT;


+ return 0;
+ }
+
+ root = fset->fset_mtpt;
+

+ llen = cpu_to_le32(len);
+ BUFF_ALLOC(buffer, NULL);
+ path = presto_path(dir, root, buffer, PAGE_SIZE);
+ pathlen = cpu_to_le32(MYPATHLEN(buffer, path));


+ size = sizeof(__u32) * current->ngroups +

+ sizeof(struct journal_prefix) + 3 * sizeof(*tgt_dir_ver) +
+ sizeof(pathlen) + sizeof(llen) + sizeof(struct journal_suffix);


+
+ if ( size > sizeof(record) ) {
+ printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
+ }
+

+ CDEBUG(D_JOURNAL, "path: %s (%d), name: %s (%d), size %d\n",
+ path, pathlen, name, len, size);


+
+ rec->is_kml = 1;
+ rec->size = size + size_round(le32_to_cpu(pathlen)) +

+ size_round(len);


+
+ logrecord = journal_log_prefix(record, opcode, rec);

+ logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
+ logrecord = log_version(logrecord, dir);
+ logrecord = logit(logrecord, old_dir_ver, sizeof(*old_dir_ver));


+ logrecord = logit(logrecord, &pathlen, sizeof(pathlen));

+ logrecord = logit(logrecord, &llen, sizeof(llen));
+ logrecord = journal_log_suffix(logrecord, record, fset, dir, rec);


+ error = presto_log(fset, rec, record, size,
+ path, size_round(le32_to_cpu(pathlen)),

+ name, size_round(len),
+ NULL, 0);
+
+ BUFF_FREE(buffer);


+ EXIT;
+ return error;
+}
+
+

+int
+presto_journal_mknod(struct rec_info *rec, struct presto_file_set *fset,
+ struct dentry *dentry, struct presto_version *tgt_dir_ver,
+ struct presto_version *new_node_ver, int mode,
+ int dmajor, int dminor )
+{
+ int opcode = PRESTO_OP_MKNOD;
+ char *buffer;


+ char *path;
+ __u32 pathlen;
+ int size;
+ char *logrecord;
+ char record[292];
+ struct dentry *root;

+ __u32 uid, gid, lmode, lmajor, lminor;


+ int error;
+
+ ENTRY;

+ if ( presto_no_journal(fset) ) {
+ EXIT;


+ return 0;
+ }
+
+ root = fset->fset_mtpt;
+

+ uid = cpu_to_le32(dentry->d_inode->i_uid);
+ gid = cpu_to_le32(dentry->d_inode->i_gid);
+ lmode = cpu_to_le32(mode);
+ lmajor = cpu_to_le32(dmajor);
+ lminor = cpu_to_le32(dminor);
+
+ BUFF_ALLOC(buffer, NULL);
+ path = presto_path(dentry, root, buffer, PAGE_SIZE);
+ pathlen = cpu_to_le32(MYPATHLEN(buffer, path));


+ size = sizeof(__u32) * current->ngroups +

+ sizeof(struct journal_prefix) + 3 * sizeof(*tgt_dir_ver) +
+ sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(lmajor) +
+ sizeof(lminor) + sizeof(pathlen) +


+ sizeof(struct journal_suffix);
+
+ if ( size > sizeof(record) ) {
+ printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
+ }
+
+ rec->is_kml = 1;

+ rec->size = size + size_round(le32_to_cpu(pathlen));
+

+ logrecord = journal_log_prefix(record, opcode, rec);

+ logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
+ logrecord = log_version(logrecord, dentry->d_parent);
+ logrecord = logit(logrecord, new_node_ver, sizeof(*new_node_ver));
+ logrecord = logit(logrecord, &lmode, sizeof(lmode));
+ logrecord = logit(logrecord, &uid, sizeof(uid));
+ logrecord = logit(logrecord, &gid, sizeof(gid));
+ logrecord = logit(logrecord, &lmajor, sizeof(lmajor));
+ logrecord = logit(logrecord, &lminor, sizeof(lminor));


+ logrecord = logit(logrecord, &pathlen, sizeof(pathlen));

+ logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
+
+ error = presto_log(fset, rec, record, size,
+ path, size_round(le32_to_cpu(pathlen)),

+ NULL, 0, NULL, 0);
+

+ BUFF_FREE(buffer);


+ EXIT;
+ return error;
+}
+

+int
+presto_journal_link(struct rec_info *rec, struct presto_file_set *fset,
+ struct dentry *src, struct dentry *tgt,
+ struct presto_version *tgt_dir_ver,
+ struct presto_version *new_link_ver)
+{
+ int opcode = PRESTO_OP_LINK;
+ char *buffer, *srcbuffer;
+ char *path, *srcpath;
+ __u32 pathlen, srcpathlen;


+ int size;
+ char *logrecord;
+ char record[292];
+ struct dentry *root;

+ int error;
+
+ ENTRY;

+ if ( presto_no_journal(fset) ) {
+ EXIT;


+ return 0;
+ }
+
+ root = fset->fset_mtpt;
+

+ BUFF_ALLOC(srcbuffer, NULL);
+ srcpath = presto_path(src, root, srcbuffer, PAGE_SIZE);
+ srcpathlen = cpu_to_le32(MYPATHLEN(srcbuffer, srcpath));
+
+ BUFF_ALLOC(buffer, srcbuffer);
+ path = presto_path(tgt, root, buffer, PAGE_SIZE);
+ pathlen = cpu_to_le32(MYPATHLEN(buffer, path));


+ size = sizeof(__u32) * current->ngroups +

+ sizeof(struct journal_prefix) + 3 * sizeof(*tgt_dir_ver) +
+ sizeof(srcpathlen) + sizeof(pathlen) +


+ sizeof(struct journal_suffix);
+
+ if ( size > sizeof(record) ) {
+ printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
+ }
+
+ rec->is_kml = 1;

+ rec->size = size + size_round(le32_to_cpu(pathlen)) +

+ size_round(le32_to_cpu(srcpathlen));


+
+ logrecord = journal_log_prefix(record, opcode, rec);

+ logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
+ logrecord = log_version(logrecord, tgt->d_parent);
+ logrecord = logit(logrecord, new_link_ver, sizeof(*new_link_ver));
+ logrecord = logit(logrecord, &srcpathlen, sizeof(srcpathlen));


+ logrecord = logit(logrecord, &pathlen, sizeof(pathlen));

+ logrecord = journal_log_suffix(logrecord, record, fset, tgt, rec);


+
+ error = presto_log(fset, rec, record, size,

+ srcpath, size_round(le32_to_cpu(srcpathlen)),
+ path, size_round(le32_to_cpu(pathlen)),
+ NULL, 0);
+
+ BUFF_FREE(srcbuffer);
+ BUFF_FREE(buffer);


+ EXIT;
+ return error;
+}
+
+

+int presto_journal_rename(struct rec_info *rec, struct presto_file_set *fset, struct dentry *src,
+ struct dentry *tgt,
+ struct presto_version *src_dir_ver,
+ struct presto_version *tgt_dir_ver)
+{
+ int opcode = PRESTO_OP_RENAME;
+ char *buffer, *srcbuffer;
+ char *path, *srcpath;
+ __u32 pathlen, srcpathlen;


+ int size;
+ char *logrecord;
+ char record[292];
+ struct dentry *root;

+ int error;
+
+ ENTRY;

+ if ( presto_no_journal(fset) ) {
+ EXIT;


+ return 0;
+ }
+
+ root = fset->fset_mtpt;
+

+ BUFF_ALLOC(srcbuffer, NULL);
+ srcpath = presto_path(src, root, srcbuffer, PAGE_SIZE);
+ srcpathlen = cpu_to_le32(MYPATHLEN(srcbuffer, srcpath));
+
+ BUFF_ALLOC(buffer, srcbuffer);
+ path = presto_path(tgt, root, buffer, PAGE_SIZE);
+ pathlen = cpu_to_le32(MYPATHLEN(buffer, path));


+ size = sizeof(__u32) * current->ngroups +

+ sizeof(struct journal_prefix) + 4 * sizeof(*src_dir_ver) +
+ sizeof(srcpathlen) + sizeof(pathlen) +


+ sizeof(struct journal_suffix);
+
+ if ( size > sizeof(record) ) {
+ printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
+ }
+
+ rec->is_kml = 1;

+ rec->size = size + size_round(le32_to_cpu(pathlen)) +

+ size_round(le32_to_cpu(srcpathlen));


+
+ logrecord = journal_log_prefix(record, opcode, rec);

+ logrecord = logit(logrecord, src_dir_ver, sizeof(*src_dir_ver));
+ logrecord = log_version(logrecord, src->d_parent);
+ logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
+ logrecord = log_version(logrecord, tgt->d_parent);
+ logrecord = logit(logrecord, &srcpathlen, sizeof(srcpathlen));


+ logrecord = logit(logrecord, &pathlen, sizeof(pathlen));

+ logrecord = journal_log_suffix(logrecord, record, fset, tgt, rec);


+
+ error = presto_log(fset, rec, record, size,

+ srcpath, size_round(le32_to_cpu(srcpathlen)),
+ path, size_round(le32_to_cpu(pathlen)),
+ NULL, 0);
+
+ BUFF_FREE(buffer);
+ BUFF_FREE(srcbuffer);


+ EXIT;
+ return error;
+}
+
+

+int presto_journal_unlink(struct rec_info *rec, struct presto_file_set *fset, struct dentry *dir,
+ struct presto_version *tgt_dir_ver,
+ struct presto_version *old_file_ver, int len,


+ const char *name)
+{

+ int opcode = PRESTO_OP_UNLINK;
+ char *buffer;
+ char *path;
+ __u32 pathlen, llen;


+ int size;
+ char *logrecord;
+ char record[292];
+ struct dentry *root;

+ int error;
+
+ ENTRY;

+ if ( presto_no_journal(fset) ) {
+ EXIT;


+ return 0;
+ }
+
+ root = fset->fset_mtpt;
+

+ llen = cpu_to_le32(len);
+ BUFF_ALLOC(buffer, NULL);
+ path = presto_path(dir, root, buffer, PAGE_SIZE);
+ pathlen = cpu_to_le32(MYPATHLEN(buffer, path));


+ size = sizeof(__u32) * current->ngroups +

+ sizeof(struct journal_prefix) + 3 * sizeof(*tgt_dir_ver) +
+ sizeof(pathlen) + sizeof(llen) + sizeof(struct journal_suffix);


+
+ if ( size > sizeof(record) ) {
+ printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
+ }
+
+ rec->is_kml = 1;

+ rec->size = size + size_round(le32_to_cpu(pathlen)) + size_round(len);


+
+ logrecord = journal_log_prefix(record, opcode, rec);

+ logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
+ logrecord = log_version(logrecord, dir);
+ logrecord = logit(logrecord, old_file_ver, sizeof(*old_file_ver));


+ logrecord = logit(logrecord, &pathlen, sizeof(pathlen));

+ logrecord = logit(logrecord, &llen, sizeof(llen));
+ logrecord = journal_log_suffix(logrecord, record, fset, dir, rec);


+
+ error = presto_log(fset, rec, record, size,
+ path, size_round(le32_to_cpu(pathlen)),

+ name, size_round(len),
+ NULL, 0);
+
+ BUFF_FREE(buffer);


+ EXIT;
+ return error;
+}
+

+int
+presto_journal_close(struct rec_info *rec, struct presto_file_set *fset,
+ struct file *file, struct dentry *dentry,
+ struct presto_version *new_file_ver)
+{
+ int opcode = PRESTO_OP_CLOSE;
+ struct presto_file_data *fd;
+ char *buffer;
+ char *path;
+ __u64 ino;
+ __u32 pathlen;
+ __u32 generation;


+ int size;
+ char *logrecord;
+ char record[292];
+ struct dentry *root;
+ int error;

+ __u32 open_fsuid;
+ __u32 open_fsgid;
+ __u32 open_ngroups;
+ __u32 open_groups[NGROUPS_MAX];
+ __u32 open_mode;
+ __u32 open_uid;
+ __u32 open_gid;


+ int i;
+
+ ENTRY;
+

+ if ( presto_no_journal(fset) ) {
+ EXIT;


+ return 0;
+ }
+

+ if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0) ) {
+ EXIT;


+ return 0;
+ }
+
+ root = fset->fset_mtpt;
+

+ fd = (struct presto_file_data *)file->private_data;
+ if (fd) {
+ open_ngroups = fd->fd_ngroups;
+ for (i = 0; i < fd->fd_ngroups; i++)
+ open_groups[i] = (__u32) fd->fd_groups[i];
+ open_mode = fd->fd_mode;
+ open_uid = fd->fd_uid;
+ open_gid = fd->fd_gid;
+ open_fsuid = fd->fd_fsuid;
+ open_fsgid = fd->fd_fsgid;
+ } else {
+ open_ngroups = current->ngroups;


+ for (i=0; i<current->ngroups; i++)

+ open_groups[i] = (__u32) current->groups[i];
+ open_mode = dentry->d_inode->i_mode;
+ open_uid = dentry->d_inode->i_uid;
+ open_gid = dentry->d_inode->i_gid;
+ open_fsuid = current->fsuid;
+ open_fsgid = current->fsgid;
+ }
+ BUFF_ALLOC(buffer, NULL);
+ path = presto_path(dentry, root, buffer, PAGE_SIZE);
+ pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
+ ino = cpu_to_le64(dentry->d_inode->i_ino);
+ generation = cpu_to_le32(dentry->d_inode->i_generation);
+ size = sizeof(__u32) * open_ngroups +
+ sizeof(open_mode) + sizeof(open_uid) + sizeof(open_gid) +
+ sizeof(struct journal_prefix) + sizeof(*new_file_ver) +
+ sizeof(ino) + sizeof(generation) + sizeof(pathlen) +


+ sizeof(struct journal_suffix);
+
+ if ( size > sizeof(record) ) {
+ printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
+ }
+
+ rec->is_kml = 1;

+ rec->size = size + size_round(le32_to_cpu(pathlen));
+

+ logrecord = journal_log_prefix_with_groups_and_ids(
+ record, opcode, rec, open_ngroups, open_groups,
+ open_fsuid, open_fsgid);
+ logrecord = logit(logrecord, &open_mode, sizeof(open_mode));
+ logrecord = logit(logrecord, &open_uid, sizeof(open_uid));
+ logrecord = logit(logrecord, &open_gid, sizeof(open_gid));


+ logrecord = logit(logrecord, new_file_ver, sizeof(*new_file_ver));
+ logrecord = logit(logrecord, &ino, sizeof(ino));
+ logrecord = logit(logrecord, &generation, sizeof(generation));
+ logrecord = logit(logrecord, &pathlen, sizeof(pathlen));

+ logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
+
+ error = presto_log(fset, rec, record, size,
+ path, size_round(le32_to_cpu(pathlen)),

+ NULL, 0, NULL, 0);

+ BUFF_FREE(buffer);
+
+ EXIT;
+ return error;
+}
+
+int presto_rewrite_close(struct rec_info *rec, struct presto_file_set *fset,
+ char *path, __u32 pathlen,
+ int ngroups, __u32 *groups,
+ __u64 ino, __u32 generation,
+ struct presto_version *new_file_ver)
+{
+ int opcode = PRESTO_OP_CLOSE;


+ int size;
+ char *logrecord;
+ char record[292];
+ struct dentry *root;

+ int error;
+
+ ENTRY;
+

+ if ( presto_no_journal(fset) ) {
+ EXIT;


+ return 0;
+ }
+
+ root = fset->fset_mtpt;
+

+ size = sizeof(__u32) * ngroups +
+ sizeof(struct journal_prefix) + sizeof(*new_file_ver) +
+ sizeof(ino) + sizeof(generation) +

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

echo 'End of part 092'
echo 'File patch-2.4.15 is continued in part 093'
echo "093" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:13 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part097

#!/bin/sh -x
# this is part 097 of a 115 - part archive


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

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

+ *
+ * Carnegie Mellon University encourages users of this code to contribute
+ * improvements to the Coda project. Contact Peter Braam <co...@cs.cmu.edu>.
+ *
+ * Much cleaned up for InterMezzo
+ * Copyright (C) 1998 Peter J. Braam <br...@cs.cmu.edu>,
+ * Copyright (C) 1999 Carnegie Mellon University


+ *
+ */
+

+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/signal.h>
+#include <linux/signal.h>


+
+#include <linux/types.h>
+#include <linux/kernel.h>

+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/fs.h>


+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/locks.h>

+#include <linux/string.h>
+#include <asm/uaccess.h>
+#include <linux/vmalloc.h>
+#include <asm/segment.h>


+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+

+/*
+ At present: four upcalls
+ - opendir: fetch a directory (synchronous & asynchronous)
+ - open: fetch file (synchronous)
+ - journal: send a journal page (asynchronous)
+ - permit: get a permit (synchronous)
+
+ Errors returned here are positive.


+
+ */
+
+

+#define INSIZE(tag) sizeof(struct lento_ ## tag ## _in)
+#define OUTSIZE(tag) sizeof(struct lento_ ## tag ## _out)
+#define SIZE(tag) ( (INSIZE(tag)>OUTSIZE(tag)) ? INSIZE(tag) : OUTSIZE(tag) )
+
+#define UPARG(op)\
+do {\
+ PRESTO_ALLOC(inp, union up_args *, insize);\
+ if ( !inp ) { return -ENOMEM; }\
+ outp = (union down_args *) (inp);\
+ inp->uh.opcode = (op);\
+ inp->uh.pid = current->pid;\
+ inp->uh.uid = current->fsuid;\
+ outsize = insize;\
+} while (0)
+
+#define BUFF_ALLOC(buffer) \
+ PRESTO_ALLOC(buffer, char *, PAGE_SIZE); \


+ if ( !buffer ) { \

+ printk("PRESTO: out of memory!\n"); \


+ return -ENOMEM; \
+ }
+

+/* the upcalls */
+int lento_kml(int minor, unsigned int offset, unsigned int first_recno,
+ unsigned int length, unsigned int last_recno, int namelen,
+ char *fsetname)
+{
+ union up_args *inp;
+ union down_args *outp;
+ int insize, outsize, error;
+ ENTRY;
+
+ if (!presto_lento_up(minor)) {


+ EXIT;
+ return 0;
+ }
+

+ insize = SIZE(kml) + namelen + 1;
+ UPARG(LENTO_KML);
+ inp->lento_kml.namelen = namelen;
+ memcpy(inp->lento_kml.fsetname, fsetname, namelen);
+ inp->lento_kml.fsetname[namelen] = '\0';
+ inp->lento_kml.offset = offset;
+ inp->lento_kml.first_recno = first_recno;
+ inp->lento_kml.length = length;
+ inp->lento_kml.last_recno = last_recno;
+
+ CDEBUG(D_UPCALL, "KML: fileset %s, offset %d, length %d, "
+ "first %d, last %d; minor %d\n",
+ inp->lento_kml.fsetname,
+ inp->lento_kml.offset,
+ inp->lento_kml.length,
+ inp->lento_kml.first_recno,
+ inp->lento_kml.last_recno, minor);
+
+ error = lento_upcall(minor, insize, &outsize, inp,
+ ASYNCHRONOUS, NULL);


+
+ EXIT;
+ return error;
+}
+

+int lento_release_permit( int minor, int mycookie )
+{
+ union up_args *inp;
+ union down_args *outp;
+ int insize, outsize, error;
+ ENTRY;
+
+ if (!presto_lento_up(minor)) {


+ EXIT;
+ return 0;
+ }
+

+ insize= SIZE(response_cookie);
+ UPARG(LENTO_COOKIE);
+ inp->lento_response_cookie.cookie= mycookie;
+
+ CDEBUG(D_UPCALL, "cookie %d\n", mycookie);
+
+ error = lento_upcall(minor, insize, &outsize, inp,
+ ASYNCHRONOUS, NULL);


+
+ EXIT;
+ return error;
+}
+

+int lento_opendir(int minor, int pathlen, char *path, int async)
+{
+ union up_args *inp;
+ union down_args *outp;
+ int insize, outsize, error;
+ ENTRY;
+
+ insize = SIZE(opendir) + pathlen + 1;
+ UPARG(LENTO_OPENDIR);
+ inp->lento_opendir.async = async;
+ inp->lento_opendir.pathlen = pathlen;
+ memcpy(inp->lento_opendir.path, path, pathlen);
+ inp->lento_opendir.path[pathlen] = '\0';
+
+ CDEBUG(D_UPCALL, "path %s\n", inp->lento_opendir.path);
+
+ if (async) {
+ error = lento_upcall(minor, insize, &outsize, inp,
+ ASYNCHRONOUS, NULL);


+ return 0;
+ }
+

+ error = lento_upcall(minor, insize, &outsize, inp,
+ SYNCHRONOUS, NULL);
+ if (error && error != EISFSETROOT) {
+ printk("lento_opendir: error %d\n", error);
+ }


+
+ EXIT;
+ return error;
+}
+

+int lento_open(int minor, int pathlen, char *path)
+{
+ union up_args *inp;
+ union down_args *outp;
+ int insize, outsize, error;
+
+ ENTRY;
+ insize = SIZE(open) + pathlen + 1;
+ UPARG(LENTO_OPEN);
+ inp->lento_open.pathlen = pathlen;
+ memcpy(inp->lento_open.path, path, pathlen);
+ inp->lento_open.path[pathlen] = '\0';
+
+ CDEBUG(D_UPCALL, "path %s\n", inp->lento_open.path);
+
+ error = lento_upcall(minor, insize, &outsize, inp,
+ SYNCHRONOUS, NULL);
+ if (error) {
+ printk("lento_open: error %d\n", error);
+ }


+
+ EXIT;
+ return error;
+}
+
+

+int lento_permit(int minor, int pathlen, int fsetnamelen, char *path, char *fsetname)
+{
+ union up_args *inp;
+ union down_args *outp;
+ int insize, outsize, error;
+ ENTRY;
+
+ insize = SIZE(permit) + pathlen + 1 + fsetnamelen + 1;
+ UPARG(LENTO_PERMIT);
+ inp->lento_permit.pathlen = pathlen;
+ inp->lento_permit.fsetnamelen = fsetnamelen;
+
+ memcpy(inp->lento_permit.path, path, pathlen);
+ inp->lento_permit.path[pathlen] = '\0';
+
+ memcpy(&(inp->lento_permit.path[pathlen+1]), fsetname, fsetnamelen);
+ inp->lento_permit.path[fsetnamelen + 1 + pathlen] = '\0';
+
+ CDEBUG(D_UPCALL, "Permit minor %d path %s\n", minor,
+ inp->lento_permit.path);
+
+ error = lento_upcall(minor, insize, &outsize, inp,
+ SYNCHRONOUS, NULL);
+ if (error) {
+ if( error == -EROFS ) {
+ int err;
+ printk("lento_permit: ERROR - requested permit for "
+ "read-only fileset.\n"
+ " Setting \"%s\" read-only!\n",
+ path);
+ err= presto_mark_cache(path, 0xFFFFFFFF,
+ CACHE_CLIENT_RO, NULL);
+ if( err ) {
+ printk("ERROR : mark_cache %d\n", err);
+ }
+ }
+ else {
+ printk("lento_permit: error %d\n", error);
+ }


+ }
+
+ EXIT;
+

+ return error;
+}
+

diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/vfs.c linux/fs/intermezzo/vfs.c
--- v2.4.14/linux/fs/intermezzo/vfs.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/vfs.c Tue Nov 13 09:20:56 2001
@@ -0,0 +1,2304 @@
+/*
+ * vfs.c
+ *
+ * This file implements kernel downcalls from lento.
+ *
+ * Author: Rob Simmonds <simm...@stelias.com>
+ * Andreas Dilger <adi...@stelias.com>
+ * Copyright (C) 2000 Stelias Computing Inc
+ * Copyright (C) 2000 Red Hat Inc.
+ *
+ * Extended attribute support


+ * Copyright (C) 2001 Shirish H. Phatak, Tacit Networks, Inc.

+ *
+ * This code is based on code from namei.c in the linux file system;
+ * see copyright notice below.
+ */
+
+/** namei.c copyright **/
+
+/*
+ * linux/fs/namei.c
+ *


+ * Copyright (C) 1991, 1992 Linus Torvalds

+ */
+
+/*
+ * Some corrections by tytso.
+ */
+
+/* [Feb 1997 T. Schoebel-Theuer] Complete rewrite of the pathname
+ * lookup logic.
+ */
+
+/** end of namei.c copyright **/
+
+#include <linux/mm.h>
+#include <linux/proc_fs.h>
+#include <linux/smp_lock.h>
+#include <linux/quotaops.h>
+
+#include <asm/uaccess.h>
+#include <asm/unaligned.h>
+#include <asm/semaphore.h>
+#include <asm/pgtable.h>
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/blk.h>


+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+#include <linux/intermezzo_kml.h>
+

+#ifdef CONFIG_FS_EXT_ATTR
+#include <linux/ext_attr.h>
+
+#ifdef CONFIG_FS_POSIX_ACL
+#include <linux/posix_acl.h>
+#endif
+#endif
+
+extern struct inode_operations presto_sym_iops;
+
+/*
+ * It's inline, so penalty for filesystems that don't use sticky bit is
+ * minimal.
+ */
+static inline int check_sticky(struct inode *dir, struct inode *inode)
+{
+ if (!(dir->i_mode & S_ISVTX))
+ return 0;
+ if (inode->i_uid == current->fsuid)
+ return 0;
+ if (dir->i_uid == current->fsuid)
+ return 0;
+ return !capable(CAP_FOWNER);
+}
+
+/* from linux/fs/namei.c */
+static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
+{
+ int error;
+ if (!victim->d_inode || victim->d_parent->d_inode != dir)
+ return -ENOENT;
+ error = permission(dir,MAY_WRITE | MAY_EXEC);


+ if (error)
+ return error;

+ if (IS_APPEND(dir))
+ return -EPERM;
+ if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||
+ IS_IMMUTABLE(victim->d_inode))
+ return -EPERM;
+ if (isdir) {
+ if (!S_ISDIR(victim->d_inode->i_mode))
+ return -ENOTDIR;
+ if (IS_ROOT(victim))
+ return -EBUSY;
+ } else if (S_ISDIR(victim->d_inode->i_mode))
+ return -EISDIR;


+ return 0;
+}
+

+/* from linux/fs/namei.c */
+static inline int may_create(struct inode *dir, struct dentry *child) {
+ if (child->d_inode)
+ return -EEXIST;
+ if (IS_DEADDIR(dir))
+ return -ENOENT;
+ return permission(dir,MAY_WRITE | MAY_EXEC);
+}
+
+#ifdef PRESTO_DEBUG
+/* The loop_discard_io() function is available via a kernel patch to the
+ * loop block device. It "works" by accepting writes, but throwing them
+ * away, rather than trying to write them to disk. The old method worked
+ * by setting the underlying device read-only, but that has the problem
+ * that dirty buffers are kept in memory, and ext3 didn't like that at all.
+ */
+#ifdef CONFIG_LOOP_DISCARD
+#define BLKDEV_FAIL(dev,fail) loop_discard_io(dev,fail)
+#else
+#define BLKDEV_FAIL(dev,fail) set_device_ro(dev, 1)
+#endif
+
+/* If a breakpoint has been set via /proc/sys/intermezzo/intermezzoX/errorval,
+ * that is the same as "value", the underlying device will "fail" now.
+ */
+inline void presto_debug_fail_blkdev(struct presto_file_set *fset,
+ unsigned long value)
+{
+ int minor = presto_f2m(fset);
+ int errorval = upc_comms[minor].uc_errorval;
+ kdev_t dev = fset->fset_mtpt->d_inode->i_dev;
+
+ if (errorval && errorval == (long)value && !is_read_only(dev)) {
+ CDEBUG(D_SUPER, "setting device %s read only\n", kdevname(dev));
+ BLKDEV_FAIL(dev, 1);
+ upc_comms[minor].uc_errorval = -dev;
+ }
+}
+#else
+#define presto_debug_fail_blkdev(dev,value) do {} while (0)
+#endif
+
+
+static inline int presto_do_kml(struct lento_vfs_context *info, struct inode* inode)
+{
+ if ( ! (info->flags & LENTO_FL_KML) )
+ return 0;
+ if ( inode->i_gid == presto_excluded_gid )
+ return 0;


+ return 1;
+}
+

+static inline int presto_do_expect(struct lento_vfs_context *info, struct inode *inode)
+{
+ if ( ! (info->flags & LENTO_FL_EXPECT) )
+ return 0;
+ if ( inode->i_gid == presto_excluded_gid )
+ return 0;


+ return 1;
+}
+
+

+/* XXX fixme: this should not fail, all these dentries are in memory
+ when _we_ call this */
+int presto_settime(struct presto_file_set *fset,
+ struct dentry *dentry,
+ struct lento_vfs_context *ctx,
+ int valid)
+{
+ int error;

+ struct inode *inode = dentry->d_inode;

+ struct inode_operations *iops;
+ struct iattr iattr;
+
+ ENTRY;
+ if (ctx->flags & LENTO_FL_IGNORE_TIME ) {

+ EXIT;
+ return 0;
+ }

+ iattr.ia_ctime = ctx->updated_time;
+ iattr.ia_mtime = ctx->updated_time;
+ iattr.ia_valid = valid;
+
+ error = -EROFS;
+ if (IS_RDONLY(inode)) {


+ EXIT;
+ return -EROFS;
+ }
+

+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
+ EXIT;
+ return -EPERM;
+ }
+
+ error = -EPERM;
+ iops = filter_c2cdiops(fset->fset_cache->cache_filter);
+ if (!iops) {

+ EXIT;
+ return error;
+ }
+

+ if (iops->setattr != NULL)
+ error = iops->setattr(dentry, &iattr);
+ else {
+ error = 0;
+ inode_setattr(dentry->d_inode, &iattr);


+ }
+ EXIT;
+ return error;
+}
+
+

+int presto_do_setattr(struct presto_file_set *fset, struct dentry *dentry,
+ struct iattr *iattr, struct lento_vfs_context *info)
+{
+ struct rec_info rec;


+ struct inode *inode = dentry->d_inode;

+ struct inode_operations *iops;
+ int error;
+ struct presto_version old_ver, new_ver;
+ void *handle;
+ off_t old_size=inode->i_size;
+
+ ENTRY;
+ error = -EROFS;
+ if (IS_RDONLY(inode)) {


+ EXIT;
+ return -EROFS;
+ }
+

+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
+ EXIT;


+ return -EPERM;
+ }
+

+ presto_getversion(&old_ver, dentry->d_inode);
+ error = -EPERM;
+ iops = filter_c2cdiops(fset->fset_cache->cache_filter);
+ if (!iops &&
+ !iops->setattr) {


+ EXIT;
+ return error;
+ }
+

+ error = presto_reserve_space(fset->fset_cache, 2*PRESTO_REQHIGH);
+ if (error) {


+ EXIT;
+ return error;
+ }
+

+ if (iattr->ia_valid & ATTR_SIZE) {
+ handle = presto_trans_start(fset, dentry->d_inode, PRESTO_OP_TRUNC);
+ } else {
+ handle = presto_trans_start(fset, dentry->d_inode, PRESTO_OP_SETATTR);
+ }
+
+ if ( IS_ERR(handle) ) {
+ printk("presto_do_setattr: no space for transaction\n");
+ presto_release_space(fset->fset_cache, 2*PRESTO_REQHIGH);

+ return -ENOSPC;
+ }
+

+ if (dentry->d_inode && iops->setattr) {
+ error = iops->setattr(dentry, iattr);
+ } else {
+ error = inode_change_ok(dentry->d_inode, iattr);
+ if (!error)
+ inode_setattr(inode, iattr);
+ }
+
+ if (!error && (iattr->ia_valid & ATTR_SIZE))
+ vmtruncate(inode, iattr->ia_size);
+
+ if (error) {


+ EXIT;
+ goto exit;
+ }
+

+ presto_debug_fail_blkdev(fset, PRESTO_OP_SETATTR | 0x10);
+
+ if ( presto_do_kml(info, dentry->d_inode) ) {
+ if ((iattr->ia_valid & ATTR_SIZE) && (old_size != inode->i_size)) {
+ struct file file;
+ /* Journal a close whenever we see a potential truncate
+ * At the receiving end, lento should explicitly remove
+ * ATTR_SIZE from the list of valid attributes */
+ presto_getversion(&new_ver, inode);
+ file.private_data = NULL;
+ file.f_dentry = dentry;
+ error=presto_journal_close(&rec, fset, &file, dentry, &new_ver);
+ }
+
+ if (!error)
+ error = presto_journal_setattr(&rec, fset, dentry, &old_ver, iattr);
+ }
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_SETATTR | 0x20);
+ if ( presto_do_expect(info, dentry->d_inode) )
+ error = presto_write_last_rcvd(&rec, fset, info);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_SETATTR | 0x30);
+
+ EXIT;
+exit:
+ presto_release_space(fset->fset_cache, 2*PRESTO_REQHIGH);
+ presto_trans_commit(fset, handle);


+ return error;
+}
+

+int lento_setattr(const char *name, struct iattr *iattr,


+ struct lento_vfs_context *info)
+{

+ struct nameidata nd;
+ struct dentry *dentry;

+ struct presto_file_set *fset;
+ int error;
+#ifdef CONFIG_FS_POSIX_ACL
+ int (*set_posix_acl)(struct inode *, int type, posix_acl_t *)=NULL;
+#endif
+
+ ENTRY;
+ CDEBUG(D_PIOCTL,"name %s, valid %#x, mode %#o, uid %d, gid %d, size %Ld\n",
+ name, iattr->ia_valid, iattr->ia_mode, iattr->ia_uid,
+ iattr->ia_gid, iattr->ia_size);
+ CDEBUG(D_PIOCTL, "atime %#lx, mtime %#lx, ctime %#lx, attr_flags %#x\n",
+ iattr->ia_atime, iattr->ia_mtime, iattr->ia_ctime,
+ iattr->ia_attr_flags);
+ CDEBUG(D_PIOCTL, "offset %d, recno %d, flags %#x\n",
+ info->slot_offset, info->recno, info->flags);
+
+ lock_kernel();


+ error = presto_walk(name, &nd);

+ if (error) {


+ EXIT;
+ goto exit;

+ }
+ dentry = nd.dentry;
+

+ fset = presto_fset(dentry);
+ error = -EINVAL;


+ if ( !fset ) {

+ printk("No fileset!\n");
+ EXIT;
+ goto exit_lock;
+ }
+
+ /* NOTE: this prevents us from changing the filetype on setattr,
+ * as we normally only want to change permission bits.
+ * If this is not correct, then we need to fix the perl code
+ * to always send the file type OR'ed with the permission.
+ */
+ if (iattr->ia_valid & ATTR_MODE) {
+ int set_mode = iattr->ia_mode;
+ iattr->ia_mode = (iattr->ia_mode & S_IALLUGO) |
+ (dentry->d_inode->i_mode & ~S_IALLUGO);
+ CDEBUG(D_PIOCTL, "chmod: orig %#o, set %#o, result %#o\n",
+ dentry->d_inode->i_mode, set_mode, iattr->ia_mode);
+#ifdef CONFIG_FS_POSIX_ACL
+ /* ACl code interacts badly with setattr
+ * since it tries to modify the ACL using
+ * set_ext_attr which recurses back into presto.
+ * This only happens if ATTR_MODE is set.
+ * Here we are doing a "forced" mode set
+ * (initiated by lento), so we disable the
+ * set_posix_acl operation which
+ * prevents such recursion. -SHP
+ *
+ * This will probably still be required when native
+ * acl journalling is in place.
+ */
+ set_posix_acl=dentry->d_inode->i_op->set_posix_acl;
+ dentry->d_inode->i_op->set_posix_acl=NULL;
+#endif
+ }
+
+ error = presto_do_setattr(fset, dentry, iattr, info);
+
+#ifdef CONFIG_FS_POSIX_ACL
+ /* restore the inode_operations if we changed them*/
+ if (iattr->ia_valid & ATTR_MODE)
+ dentry->d_inode->i_op->set_posix_acl=set_posix_acl;
+#endif
+
+
+ EXIT;
+exit_lock:
+ path_release(&nd);
+exit:
+ unlock_kernel();


+ return error;
+}
+

+int presto_do_create(struct presto_file_set *fset, struct dentry *dir,
+ struct dentry *dentry, int mode,


+ struct lento_vfs_context *info)
+{

+ struct rec_info rec;
+ int error;
+ struct presto_version tgt_dir_ver, new_file_ver;
+ struct inode_operations *iops;
+ void *handle;
+
+ ENTRY;
+ mode &= S_IALLUGO;
+ mode |= S_IFREG;
+
+ down(&dir->d_inode->i_zombie);
+ error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);

+ if (error) {
+ EXIT;

+ up(&dir->d_inode->i_zombie);


+ return error;
+ }
+

+ error = may_create(dir->d_inode, dentry);


+ if (error) {
+ EXIT;

+ goto exit_pre_lock;
+ }
+
+ error = -EPERM;
+ iops = filter_c2cdiops(fset->fset_cache->cache_filter);
+ if (!iops->create) {
+ EXIT;
+ goto exit_pre_lock;
+ }
+
+ presto_getversion(&tgt_dir_ver, dir->d_inode);
+ handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_CREATE);


+ if ( IS_ERR(handle) ) {

+ EXIT;
+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
+ printk("presto_do_create: no space for transaction\n");
+ error=-ENOSPC;
+ goto exit_pre_lock;
+ }
+ DQUOT_INIT(dir->d_inode);
+ lock_kernel();
+ error = iops->create(dir->d_inode, dentry, mode);


+ if (error) {
+ EXIT;

+ goto exit_lock;
+ }
+
+ if (dentry->d_inode &&
+ dentry->d_inode->i_gid != presto_excluded_gid) {


+ struct presto_cache *cache = fset->fset_cache;

+ /* was this already done? */


+ presto_set_ops(dentry->d_inode, cache->cache_filter);
+

+ filter_setup_dentry_ops(cache->cache_filter,
+ dentry->d_op,

+ &presto_dentry_ops);


+ dentry->d_op = filter_c2udops(cache->cache_filter);
+

+ /* if Lento creates this file, we won't have data */
+ if ( ISLENTO(presto_c2m(cache)) ) {
+ presto_set(dentry, PRESTO_ATTR);
+ } else {
+ presto_set(dentry, PRESTO_ATTR | PRESTO_DATA);
+ }
+ }
+
+ error = presto_settime(fset, dir, info, ATTR_CTIME | ATTR_MTIME);


+ if (error) {
+ EXIT;

+ goto exit_lock;
+ }
+ error = presto_settime(fset, dentry, info, ATTR_CTIME | ATTR_MTIME);


+ if (error) {
+ EXIT;

+ goto exit_lock;
+ }
+
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_CREATE | 0x10);
+ presto_getversion(&new_file_ver, dentry->d_inode);
+ if ( presto_do_kml(info, dentry->d_inode) )
+ error = presto_journal_create(&rec, fset, dentry, &tgt_dir_ver,
+ &new_file_ver,
+ dentry->d_inode->i_mode);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_CREATE | 0x20);
+ if ( presto_do_expect(info, dentry->d_inode) )
+ error = presto_write_last_rcvd(&rec, fset, info);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_CREATE | 0x30);
+ EXIT;
+
+ exit_lock:
+ unlock_kernel();
+ presto_trans_commit(fset, handle);
+ exit_pre_lock:
+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
+ up(&dir->d_inode->i_zombie);


+ return error;
+}
+

+/* from namei.c */
+static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
+{


+ struct dentry *dentry;
+

+ down(&nd->dentry->d_inode->i_sem);
+ dentry = ERR_PTR(-EEXIST);
+ if (nd->last_type != LAST_NORM)
+ goto fail;
+ dentry = lookup_hash(&nd->last, nd->dentry);
+ if (IS_ERR(dentry))
+ goto fail;
+ if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
+ goto enoent;
+ return dentry;
+enoent:
+ dput(dentry);
+ dentry = ERR_PTR(-ENOENT);
+fail:
+ return dentry;
+}
+
+int lento_create(const char *name, int mode, struct lento_vfs_context *info)
+{
+ int error;
+ struct nameidata nd;
+ char * pathname;
+ struct dentry *dentry;


+ struct presto_file_set *fset;
+
+ ENTRY;

+ pathname = getname(name);


+ error = PTR_ERR(pathname);
+ if (IS_ERR(pathname)) {
+ EXIT;
+ goto exit;
+ }
+

+ /* this looks up the parent */
+// if (path_init(pathname, LOOKUP_FOLLOW | LOOKUP_POSITIVE, &nd))


+ if (path_init(pathname, LOOKUP_PARENT, &nd))

+ error = path_walk(pathname, &nd);


+ if (error) {
+ EXIT;

+ goto exit;
+ }
+ dentry = lookup_create(&nd, 0);
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry)) {
+ EXIT;
+ goto exit_lock;


+ }
+
+ fset = presto_fset(dentry);

+ error = -EINVAL;


+ if ( !fset ) {

+ printk("No fileset!\n");
+ EXIT;
+ goto exit_lock;
+ }
+ error = presto_do_create(fset, dentry->d_parent, dentry, (mode&S_IALLUGO)|S_IFREG,
+ info);
+
+ EXIT;
+
+ exit_lock:
+ path_release (&nd);
+ dput(dentry);
+ up(&dentry->d_parent->d_inode->i_sem);
+ putname(pathname);
+exit:


+ return error;
+}
+

+int presto_do_link(struct presto_file_set *fset, struct dentry *old_dentry,
+ struct dentry *dir, struct dentry *new_dentry,


+ struct lento_vfs_context *info)
+{

+ struct rec_info rec;
+ struct inode *inode;
+ int error;
+ struct inode_operations *iops;
+ struct presto_version tgt_dir_ver;
+ struct presto_version new_link_ver;
+ void *handle;
+
+ down(&dir->d_inode->i_zombie);
+ error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);

+ if (error) {
+ EXIT;

+ up(&dir->d_inode->i_zombie);
+ return error;
+ }
+ error = -ENOENT;
+ inode = old_dentry->d_inode;
+ if (!inode)
+ goto exit_lock;
+
+ error = may_create(dir->d_inode, new_dentry);
+ if (error)
+ goto exit_lock;
+
+ error = -EXDEV;
+ if (dir->d_inode->i_dev != inode->i_dev)
+ goto exit_lock;
+
+ /*
+ * A link to an append-only or immutable file cannot be created.
+ */
+ error = -EPERM;
+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
+ EXIT;
+ goto exit_lock;
+ }
+
+ iops = filter_c2cdiops(fset->fset_cache->cache_filter);
+ if (!iops->link) {
+ EXIT;
+ goto exit_lock;
+ }
+
+
+ presto_getversion(&tgt_dir_ver, dir->d_inode);
+ handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_LINK);


+ if ( IS_ERR(handle) ) {

+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
+ printk("presto_do_link: no space for transaction\n");


+ return -ENOSPC;
+ }
+

+ DQUOT_INIT(dir->d_inode);
+ lock_kernel();
+ error = iops->link(old_dentry, dir->d_inode, new_dentry);
+ unlock_kernel();


+ if (error) {
+ EXIT;

+ goto exit_lock;
+ }
+
+ error = presto_settime(fset, dir, info, ATTR_CTIME | ATTR_MTIME);


+ if (error) {
+ EXIT;

+ goto exit_lock;
+ }
+ error = presto_settime(fset, new_dentry, info, ATTR_CTIME);


+ if (error) {
+ EXIT;

+ goto exit_lock;
+ }
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_LINK | 0x10);
+ presto_getversion(&new_link_ver, new_dentry->d_inode);
+ if ( presto_do_kml(info, old_dentry->d_inode) )
+ error = presto_journal_link(&rec, fset, old_dentry, new_dentry,
+ &tgt_dir_ver, &new_link_ver);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_LINK | 0x20);
+ if ( presto_do_expect(info, old_dentry->d_inode) )
+ error = presto_write_last_rcvd(&rec, fset, info);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_LINK | 0x30);
+ EXIT;
+ presto_trans_commit(fset, handle);
+exit_lock:
+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
+ up(&dir->d_inode->i_zombie);


+ return error;
+}
+
+

+int lento_link(const char * oldname, const char * newname,

+ struct lento_vfs_context *info)
+{

+ int error;
+ char * from;
+ char * to;


+ struct presto_file_set *fset;
+

+ from = getname(oldname);
+ if(IS_ERR(from))
+ return PTR_ERR(from);
+ to = getname(newname);
+ error = PTR_ERR(to);
+ if (!IS_ERR(to)) {
+ struct dentry *new_dentry;
+ struct nameidata nd, old_nd;
+
+ error = 0;
+ if (path_init(from, LOOKUP_POSITIVE, &old_nd))
+ error = path_walk(from, &old_nd);


+ if (error)
+ goto exit;

+ if (path_init(to, LOOKUP_PARENT, &nd))
+ error = path_walk(to, &nd);
+ if (error)
+ goto out;
+ error = -EXDEV;
+ if (old_nd.mnt != nd.mnt)
+ goto out;
+ new_dentry = lookup_create(&nd, 0);
+ error = PTR_ERR(new_dentry);
+
+ if (!IS_ERR(new_dentry)) {
+ fset = presto_fset(new_dentry);
+ error = -EINVAL;


+ if ( !fset ) {

+ printk("No fileset!\n");
+ EXIT;
+ goto out2;
+ }
+ error = presto_do_link(fset, old_nd.dentry,
+ nd.dentry,
+ new_dentry, info);
+ dput(new_dentry);
+ }
+ out2:
+ up(&nd.dentry->d_inode->i_sem);
+ path_release(&nd);
+ out:
+ path_release(&old_nd);
+ exit:
+ putname(to);
+ }
+ putname(from);
+


+ return error;
+}
+
+

+int presto_do_unlink(struct presto_file_set *fset, struct dentry *dir,
+ struct dentry *dentry, struct lento_vfs_context *info)
+{
+ struct rec_info rec;
+ int error;
+ struct inode_operations *iops;
+ struct presto_version tgt_dir_ver, old_file_ver;
+ void *handle;
+ int do_kml = 0, do_expect =0;
+ int linkno = 0;
+ ENTRY;
+ down(&dir->d_inode->i_zombie);
+ error = may_delete(dir->d_inode, dentry, 0);


+ if (error) {
+ EXIT;

+ up(&dir->d_inode->i_zombie);


+ return error;
+ }
+

+ error = -EPERM;
+ iops = filter_c2cdiops(fset->fset_cache->cache_filter);
+ if (!iops->unlink) {
+ EXIT;
+ up(&dir->d_inode->i_zombie);


+ return error;
+ }
+

+ error = presto_reserve_space(fset->fset_cache, PRESTO_REQLOW);

+ if (error) {
+ EXIT;

+ up(&dir->d_inode->i_zombie);


+ return error;
+ }
+

+ presto_getversion(&tgt_dir_ver, dir->d_inode);
+ presto_getversion(&old_file_ver, dentry->d_inode);
+ handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_UNLINK);


+ if ( IS_ERR(handle) ) {

+ presto_release_space(fset->fset_cache, PRESTO_REQLOW);
+ printk("ERROR: presto_do_unlink: no space for transaction. Tell Peter.\n");
+ up(&dir->d_inode->i_zombie);
+ return -ENOSPC;
+ }
+ DQUOT_INIT(dir->d_inode);
+ if (d_mountpoint(dentry))
+ error = -EBUSY;
+ else {
+ lock_kernel();
+ linkno = dentry->d_inode->i_nlink;
+ if (linkno > 1) {
+ dget(dentry);
+ }
+ do_kml = presto_do_kml(info, dir->d_inode);
+ do_expect = presto_do_expect(info, dir->d_inode);
+ error = iops->unlink(dir->d_inode, dentry);
+ unlock_kernel();
+ if (!error)
+ d_delete(dentry);
+ }
+
+ if (linkno > 1) {
+ error = presto_settime(fset, dentry, info, ATTR_CTIME);
+ dput(dentry);

+ if (error) {
+ EXIT;

+ goto exit;
+ }
+ }
+
+ error = presto_settime(fset, dir, info, ATTR_CTIME | ATTR_MTIME);


+ if (error) {
+ EXIT;

+ goto exit;
+ }
+

+ up(&dir->d_inode->i_zombie);


+ if (error) {
+ EXIT;

+ goto exit;
+ }
+

+ presto_debug_fail_blkdev(fset, PRESTO_OP_UNLINK | 0x10);
+ if ( do_kml ) {
+ error = presto_journal_unlink(&rec, fset, dir, &tgt_dir_ver,
+ &old_file_ver,
+ dentry->d_name.len,
+ dentry->d_name.name);
+ }
+ presto_debug_fail_blkdev(fset, PRESTO_OP_UNLINK | 0x20);
+ if ( do_expect ) {
+ error = presto_write_last_rcvd(&rec, fset, info);
+ }
+ presto_debug_fail_blkdev(fset, PRESTO_OP_UNLINK | 0x30);
+ EXIT;
+exit:
+ presto_release_space(fset->fset_cache, PRESTO_REQLOW);
+ presto_trans_commit(fset, handle);


+ return error;
+}
+
+

+int lento_unlink(const char *pathname, struct lento_vfs_context *info)
+{
+ int error = 0;
+ char * name;
+ struct dentry *dentry;
+ struct nameidata nd;
+ struct presto_file_set *fset;
+
+ ENTRY;
+
+ name = getname(pathname);
+ if(IS_ERR(name))
+ return PTR_ERR(name);
+
+ if (path_init(name, LOOKUP_PARENT, &nd))
+ error = path_walk(name, &nd);
+ if (error)
+ goto exit;
+ error = -EISDIR;
+ if (nd.last_type != LAST_NORM)
+ goto exit1;
+ down(&nd.dentry->d_inode->i_sem);
+ dentry = lookup_hash(&nd.last, nd.dentry);
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ fset = presto_fset(dentry);
+ error = -EINVAL;


+ if ( !fset ) {

+ printk("No fileset!\n");
+ EXIT;
+ goto exit2;
+ }
+ /* Why not before? Because we want correct error value */
+ if (nd.last.name[nd.last.len])
+ goto slashes;
+ error = presto_do_unlink(fset, nd.dentry, dentry, info);
+ exit2:
+ EXIT;
+ dput(dentry);
+ }
+ up(&nd.dentry->d_inode->i_sem);
+exit1:
+ path_release(&nd);
+exit:
+ putname(name);


+
+ return error;
+

+slashes:
+ error = !dentry->d_inode ? -ENOENT :
+ S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR;
+ goto exit2;
+}
+
+int presto_do_symlink(struct presto_file_set *fset, struct dentry *dir,
+ struct dentry *dentry, const char *oldname,


+ struct lento_vfs_context *info)
+{

+ struct rec_info rec;
+ int error;
+ struct presto_version tgt_dir_ver, new_link_ver;
+ struct inode_operations *iops;
+ void *handle;
+
+ ENTRY;
+ down(&dir->d_inode->i_zombie);
+ /* record + max path len + space to free */
+ error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH + 4096);

+ if (error) {
+ EXIT;

+ up(&dir->d_inode->i_zombie);


+ return error;
+ }
+

+ error = may_create(dir->d_inode, dentry);


+ if (error) {
+ EXIT;

+ goto exit_lock;
+ }
+
+ error = -EPERM;
+ iops = filter_c2cdiops(fset->fset_cache->cache_filter);
+ if (!iops->symlink) {
+ EXIT;
+ goto exit_lock;
+ }
+
+ presto_getversion(&tgt_dir_ver, dir->d_inode);
+ handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_SYMLINK);


+ if ( IS_ERR(handle) ) {

+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
+ printk("ERROR: presto_do_symlink: no space for transaction. Tell Peter.\n");
+ EXIT;
+ return -ENOSPC;
+ }
+ DQUOT_INIT(dir->d_inode);
+ lock_kernel();
+ error = iops->symlink(dir->d_inode, dentry, oldname);


+ if (error) {
+ EXIT;

+ goto exit;
+ }
+

+ if (dentry->d_inode &&
+ dentry->d_inode->i_gid != presto_excluded_gid) {


+ struct presto_cache *cache = fset->fset_cache;
+

+ presto_set_ops(dentry->d_inode, cache->cache_filter);
+

+ filter_setup_dentry_ops(cache->cache_filter, dentry->d_op,
+ &presto_dentry_ops);


+ dentry->d_op = filter_c2udops(cache->cache_filter);

+ /* XXX ? Cache state ? if Lento creates a symlink */
+ if ( ISLENTO(presto_c2m(cache)) ) {
+ presto_set(dentry, PRESTO_ATTR);
+ } else {
+ presto_set(dentry, PRESTO_ATTR | PRESTO_DATA);
+ }
+ }
+
+ error = presto_settime(fset, dir, info, ATTR_CTIME | ATTR_MTIME);


+ if (error) {
+ EXIT;

+ goto exit;
+ }
+ error = presto_settime(fset, dentry, info, ATTR_CTIME | ATTR_MTIME);


+ if (error) {
+ EXIT;

+ goto exit;
+ }
+

+ presto_debug_fail_blkdev(fset, PRESTO_OP_SYMLINK | 0x10);
+ presto_getversion(&new_link_ver, dentry->d_inode);
+ if ( presto_do_kml(info, dentry->d_inode) )
+ error = presto_journal_symlink(&rec, fset, dentry, oldname,
+ &tgt_dir_ver, &new_link_ver);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_SYMLINK | 0x20);
+ if ( presto_do_expect(info, dentry->d_inode) )
+ error = presto_write_last_rcvd(&rec, fset, info);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_SYMLINK | 0x30);
+ EXIT;
+exit:
+ unlock_kernel();
+ presto_trans_commit(fset, handle);
+ exit_lock:
+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
+ up(&dir->d_inode->i_zombie);


+ return error;
+}
+

+int lento_symlink(const char *oldname, const char *newname,


+ struct lento_vfs_context *info)
+{

+ int error;
+ char *from;
+ char *to;
+ struct dentry *dentry;
+ struct presto_file_set *fset;
+ struct nameidata nd;


+
+ ENTRY;
+ lock_kernel();

+ from = getname(oldname);
+ error = PTR_ERR(from);
+ if (IS_ERR(from)) {


+ EXIT;
+ goto exit;
+ }
+

+ to = getname(newname);
+ error = PTR_ERR(to);
+ if (IS_ERR(to)) {
+ EXIT;
+ goto exit_from;
+ }
+
+ if (path_init(to, LOOKUP_PARENT, &nd))
+ error = path_walk(to, &nd);


+ if (error) {
+ EXIT;

+ goto exit_to;
+ }
+
+ dentry = lookup_create(&nd, 0);
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry)) {
+ path_release(&nd);
+ EXIT;
+ goto exit_to;


+ }
+
+ fset = presto_fset(dentry);

+ error = -EINVAL;


+ if ( !fset ) {
+ printk("No fileset!\n");

+ path_release(&nd);
+ EXIT;
+ goto exit_lock;
+ }
+ error = presto_do_symlink(fset, nd.dentry,
+ dentry, oldname, info);
+ path_release(&nd);
+ EXIT;
+ exit_lock:
+ up(&nd.dentry->d_inode->i_sem);
+ dput(dentry);
+ exit_to:
+ putname(to);
+ exit_from:
+ putname(from);
+ exit:
+ unlock_kernel();


+ return error;
+}
+

+int presto_do_mkdir(struct presto_file_set *fset, struct dentry *dir,
+ struct dentry *dentry, int mode,


+ struct lento_vfs_context *info)
+{

+ struct rec_info rec;
+ int error;
+ struct presto_version tgt_dir_ver, new_dir_ver;
+ void *handle;
+
+ ENTRY;
+ down(&dir->d_inode->i_zombie);
+ /* one journal record + directory block + room for removals*/
+ error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH + 4096);

+ if (error) {
+ EXIT;

+ up(&dir->d_inode->i_zombie);


+ return error;
+ }
+

+ error = may_create(dir->d_inode, dentry);


+ if (error) {
+ EXIT;

+ goto exit_lock;
+ }
+
+ error = -EPERM;
+ if (!filter_c2cdiops(fset->fset_cache->cache_filter)->mkdir) {
+ EXIT;
+ goto exit_lock;
+ }
+
+ error = -ENOSPC;
+ presto_getversion(&tgt_dir_ver, dir->d_inode);
+ handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_MKDIR);


+ if ( IS_ERR(handle) ) {

+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
+ printk("presto_do_mkdir: no space for transaction\n");
+ goto exit_lock;
+ }
+
+ DQUOT_INIT(dir->d_inode);
+ mode &= (S_IRWXUGO|S_ISVTX);
+ lock_kernel();
+ error = filter_c2cdiops(fset->fset_cache->cache_filter)->mkdir(dir->d_inode, dentry, mode);


+ if (error) {
+ EXIT;

+ goto exit;
+ }
+
+ if ( dentry->d_inode && !error &&
+ dentry->d_inode->i_gid != presto_excluded_gid) {


+ struct presto_cache *cache = fset->fset_cache;
+

+ presto_set_ops(dentry->d_inode, cache->cache_filter);
+

+ filter_setup_dentry_ops(cache->cache_filter,
+ dentry->d_op,

+ &presto_dentry_ops);


+ dentry->d_op = filter_c2udops(cache->cache_filter);

+ /* if Lento does this, we won't have data */
+ if ( ISLENTO(presto_c2m(cache)) ) {
+ presto_set(dentry, PRESTO_ATTR);
+ } else {
+ presto_set(dentry, PRESTO_ATTR | PRESTO_DATA);
+ }
+ }
+
+ error = presto_settime(fset, dir, info, ATTR_CTIME | ATTR_MTIME);


+ if (error) {
+ EXIT;

+ goto exit;
+ }
+ error = presto_settime(fset, dentry, info, ATTR_CTIME | ATTR_MTIME);


+ if (error) {
+ EXIT;

+ goto exit;
+ }
+

+ presto_debug_fail_blkdev(fset, PRESTO_OP_MKDIR | 0x10);
+ presto_getversion(&new_dir_ver, dentry->d_inode);
+ if ( presto_do_kml(info, dentry->d_inode) )
+ error = presto_journal_mkdir(&rec, fset, dentry, &tgt_dir_ver,
+ &new_dir_ver,
+ dentry->d_inode->i_mode);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_MKDIR | 0x20);
+ if ( presto_do_expect(info, dentry->d_inode) )
+ error = presto_write_last_rcvd(&rec, fset, info);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_MKDIR | 0x30);
+ EXIT;
+exit:
+ unlock_kernel();
+ presto_trans_commit(fset, handle);
+ exit_lock:
+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
+ up(&dir->d_inode->i_zombie);


+ return error;
+}
+
+/*

+ * Look out: this function may change a normal dentry
+ * into a directory dentry (different size)..
+ */
+int lento_mkdir(const char *name, int mode, struct lento_vfs_context *info)
+{
+ int error;
+ char *pathname;
+ struct dentry *dentry;
+ struct presto_file_set *fset;
+ struct nameidata nd;
+
+ ENTRY;
+ CDEBUG(D_PIOCTL, "name: %s, mode %o, offset %d, recno %d, flags %x\n",
+ name, mode, info->slot_offset, info->recno, info->flags);
+ pathname = getname(name);


+ error = PTR_ERR(pathname);
+ if (IS_ERR(pathname)) {

+ EXIT;
+ return error;
+ }
+

+ if (path_init(pathname, LOOKUP_PARENT, &nd))

+ error = path_walk(pathname, &nd);
+ if (error)
+ goto out_name;
+
+ dentry = lookup_create(&nd, 1);
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ fset = presto_fset(dentry);
+ error = -EINVAL;


+ if ( !fset ) {

+ printk("No fileset!\n");
+ EXIT;
+ goto out_dput;
+ }
+
+ error = presto_do_mkdir(fset, nd.dentry, dentry,
+ mode & S_IALLUGO, info);
+out_dput:
+ dput(dentry);
+ }
+ up(&nd.dentry->d_inode->i_sem);
+ path_release(&nd);
+out_name:
+ EXIT;
+ putname(pathname);
+ CDEBUG(D_PIOCTL, "error: %d\n", error);


+ return error;
+}
+

+static void d_unhash(struct dentry *dentry)
+{
+ dget(dentry);
+ switch (atomic_read(&dentry->d_count)) {
+ default:
+ shrink_dcache_parent(dentry);
+ if (atomic_read(&dentry->d_count) != 2)


+ break;
+ case 2:

+ d_drop(dentry);
+ }
+}
+
+int presto_do_rmdir(struct presto_file_set *fset, struct dentry *dir,
+ struct dentry *dentry, struct lento_vfs_context *info)
+{
+ struct rec_info rec;
+ int error;
+ struct presto_version tgt_dir_ver, old_dir_ver;
+ struct inode_operations *iops;
+ void *handle;
+ int do_kml, do_expect;
+ int size;
+
+ ENTRY;
+ error = may_delete(dir->d_inode, dentry, 1);
+ if (error)
+ return error;
+
+ error = -EPERM;
+ iops = filter_c2cdiops(fset->fset_cache->cache_filter);
+ if (!iops->rmdir) {


+ EXIT;
+ return error;
+ }
+

+ size = PRESTO_REQHIGH - dentry->d_inode->i_size;
+ error = presto_reserve_space(fset->fset_cache, size);
+ if (error) {

+ EXIT;
+ return error;
+ }
+

+ presto_getversion(&tgt_dir_ver, dir->d_inode);
+ presto_getversion(&old_dir_ver, dentry->d_inode);
+ handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_RMDIR);


+ if ( IS_ERR(handle) ) {

+ presto_release_space(fset->fset_cache, size);
+ printk("ERROR: presto_do_rmdir: no space for transaction. Tell Peter.\n");


+ return -ENOSPC;
+ }
+

+ DQUOT_INIT(dir->d_inode);
+
+ do_kml = presto_do_kml(info, dir->d_inode);
+ do_expect = presto_do_expect(info, dir->d_inode);
+
+ double_down(&dir->d_inode->i_zombie, &dentry->d_inode->i_zombie);
+ d_unhash(dentry);
+ if (IS_DEADDIR(dir->d_inode))
+ error = -ENOENT;
+ else if (d_mountpoint(dentry))
+ error = -EBUSY;
+ else {
+ lock_kernel();
+ error = iops->rmdir(dir->d_inode, dentry);
+ unlock_kernel();
+ if (!error) {
+ dentry->d_inode->i_flags |= S_DEAD;
+ error = presto_settime(fset, dir, info,
+ ATTR_CTIME | ATTR_MTIME);
+ }
+ }
+ double_up(&dir->d_inode->i_zombie, &dentry->d_inode->i_zombie);
+ if (!error)
+ d_delete(dentry);
+ dput(dentry);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_RMDIR | 0x10);
+ if ( !error && do_kml )
+ error = presto_journal_rmdir(&rec, fset, dir, &tgt_dir_ver,
+ &old_dir_ver,
+ dentry->d_name.len,
+ dentry->d_name.name);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_RMDIR | 0x20);
+ if ( !error && do_expect )
+ error = presto_write_last_rcvd(&rec, fset, info);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_RMDIR | 0x30);
+ EXIT;
+
+ presto_trans_commit(fset, handle);
+ presto_release_space(fset->fset_cache, size);

+ return error;
+}
+

+int lento_rmdir(const char *pathname, struct lento_vfs_context *info)
+{
+ int error = 0;
+ char * name;
+ struct dentry *dentry;
+ struct presto_file_set *fset;
+ struct nameidata nd;
+
+ ENTRY;
+ name = getname(pathname);
+ if(IS_ERR(name))
+ return PTR_ERR(name);
+
+ if (path_init(name, LOOKUP_PARENT, &nd))
+ error = path_walk(name, &nd);
+ if (error)
+ goto exit;
+
+ switch(nd.last_type) {
+ case LAST_DOTDOT:
+ error = -ENOTEMPTY;
+ goto exit1;
+ case LAST_ROOT: case LAST_DOT:
+ error = -EBUSY;
+ goto exit1;
+ }
+ down(&nd.dentry->d_inode->i_sem);
+ dentry = lookup_hash(&nd.last, nd.dentry);
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ fset = presto_fset(dentry);
+ error = -EINVAL;


+ if ( !fset ) {

+ printk("No fileset!\n");
+ EXIT;
+ goto exit_put;
+ }
+ error = presto_do_rmdir(fset, nd.dentry, dentry, info);
+ exit_put:
+ dput(dentry);
+ }
+ up(&nd.dentry->d_inode->i_sem);
+exit1:
+ EXIT;
+ path_release(&nd);
+exit:
+ EXIT;
+ putname(name);


+ return error;
+}
+

+int presto_do_mknod(struct presto_file_set *fset, struct dentry *dir,
+ struct dentry *dentry, int mode, dev_t dev,


+ struct lento_vfs_context *info)
+{

+ struct rec_info rec;
+ int error = -EPERM;
+ struct presto_version tgt_dir_ver, new_node_ver;
+ struct inode_operations *iops;
+ void *handle;
+
+ ENTRY;
+
+ down(&dir->d_inode->i_zombie);
+ /* one KML entry */
+ error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);

+ if (error) {
+ EXIT;

+ up(&dir->d_inode->i_zombie);


+ return error;
+ }
+

+ if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) {
+ EXIT;
+ goto exit_lock;
+ }
+
+ error = may_create(dir->d_inode, dentry);


+ if (error) {
+ EXIT;

+ goto exit_lock;
+ }
+
+ error = -EPERM;
+ iops = filter_c2cdiops(fset->fset_cache->cache_filter);
+ if (!iops->mknod) {
+ EXIT;
+ goto exit_lock;
+ }
+
+ DQUOT_INIT(dir->d_inode);
+ lock_kernel();
+
+ error = -ENOSPC;
+ presto_getversion(&tgt_dir_ver, dir->d_inode);
+ handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_MKNOD);


+ if ( IS_ERR(handle) ) {

+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
+ printk("presto_do_mknod: no space for transaction\n");
+ goto exit_lock2;
+ }
+
+ error = iops->mknod(dir->d_inode, dentry, mode, dev);
+ if ( dentry->d_inode &&
+ dentry->d_inode->i_gid != presto_excluded_gid) {


+ struct presto_cache *cache = fset->fset_cache;
+

+ presto_set_ops(dentry->d_inode, cache->cache_filter);
+

+ filter_setup_dentry_ops(cache->cache_filter, dentry->d_op,
+ &presto_dentry_ops);


+ dentry->d_op = filter_c2udops(cache->cache_filter);
+

+ /* if Lento does this, we won't have data */
+ if ( ISLENTO(presto_c2m(cache)) ) {
+ presto_set(dentry, PRESTO_ATTR);
+ } else {
+ presto_set(dentry, PRESTO_ATTR | PRESTO_DATA);
+ }
+ }
+
+ error = presto_settime(fset, dir, info, ATTR_MTIME);


+ if (error) {
+ EXIT;
+ }

+ error = presto_settime(fset, dentry, info, ATTR_CTIME | ATTR_MTIME);


+ if (error) {
+ EXIT;
+ }

+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_MKNOD | 0x10);
+ presto_getversion(&new_node_ver, dentry->d_inode);
+ if ( presto_do_kml(info, dentry->d_inode) )
+ error = presto_journal_mknod(&rec, fset, dentry, &tgt_dir_ver,
+ &new_node_ver,
+ dentry->d_inode->i_mode,
+ MAJOR(dev), MINOR(dev) );
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_MKNOD | 0x20);
+ if ( presto_do_expect(info, dentry->d_inode) )
+ error = presto_write_last_rcvd(&rec, fset, info);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_MKNOD | 0x30);
+ EXIT;
+ presto_trans_commit(fset, handle);
+ exit_lock2:
+ unlock_kernel();
+ exit_lock:
+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
+ up(&dir->d_inode->i_zombie);


+ return error;
+}
+

+int lento_mknod(const char *filename, int mode, dev_t dev,


+ struct lento_vfs_context *info)
+{

+ int error = 0;
+ char * tmp;
+ struct dentry * dentry;
+ struct nameidata nd;
+ struct presto_file_set *fset;
+
+ ENTRY;
+
+ if (S_ISDIR(mode))
+ return -EPERM;
+ tmp = getname(filename);
+ if (IS_ERR(tmp))
+ return PTR_ERR(tmp);
+
+ if (path_init(tmp, LOOKUP_PARENT, &nd))
+ error = path_walk(tmp, &nd);
+ if (error)
+ goto out;
+ dentry = lookup_create(&nd, 0);
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ fset = presto_fset(dentry);
+ error = -EINVAL;


+ if ( !fset ) {

+ printk("No fileset!\n");
+ EXIT;
+ goto exit_put;
+ }
+ switch (mode & S_IFMT) {
+ case 0: case S_IFREG:
+ error = -EOPNOTSUPP;
+ break;
+ case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
+ error = presto_do_mknod(fset, nd.dentry, dentry,
+ mode, dev, info);
+ break;
+ case S_IFDIR:
+ error = -EPERM;
+ break;
+ default:


+ error = -EINVAL;
+ }

+ exit_put:
+ dput(dentry);
+ }
+ up(&nd.dentry->d_inode->i_sem);
+ path_release(&nd);
+out:
+ putname(tmp);
+


+ return error;
+}
+

+static int do_rename(struct presto_file_set *fset,
+ struct dentry *old_parent, struct dentry *old_dentry,
+ struct dentry *new_parent, struct dentry *new_dentry,


+ struct lento_vfs_context *info)
+{

+ struct rec_info rec;
+ int error;
+ struct inode_operations *iops;
+ struct presto_version src_dir_ver, tgt_dir_ver;
+ void *handle;
+ int new_inode_unlink = 0;
+ struct inode *old_dir = old_parent->d_inode;
+ struct inode *new_dir = new_parent->d_inode;
+
+ ENTRY;
+ presto_getversion(&src_dir_ver, old_dir);
+ presto_getversion(&tgt_dir_ver, new_dir);
+
+ error = -EPERM;
+ iops = filter_c2cdiops(fset->fset_cache->cache_filter);
+ if (!iops || !iops->rename) {


+ EXIT;
+ return error;
+ }
+

+ error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);
+ if (error) {


+ EXIT;
+ return error;
+ }

+ handle = presto_trans_start(fset, old_dir, PRESTO_OP_RENAME);


+ if ( IS_ERR(handle) ) {

+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
+ printk("presto_do_rename: no space for transaction\n");
+ return -ENOSPC;
+ }
+ if (new_dentry->d_inode && new_dentry->d_inode->i_nlink > 1) {
+ dget(new_dentry);
+ new_inode_unlink = 1;
+ }
+
+ error = iops->rename(old_dir, old_dentry, new_dir, new_dentry);
+
+ if (error) {


+ EXIT;
+ goto exit;
+ }
+

+ if (new_inode_unlink) {
+ error = presto_settime(fset, old_dentry, info, ATTR_CTIME);
+ dput(old_dentry);

+ if (error) {
+ EXIT;

+ goto exit;
+ }
+ }
+ error = presto_settime(fset, old_parent, info, ATTR_CTIME | ATTR_MTIME);


+ if (error) {
+ EXIT;

+ goto exit;
+ }
+ error = presto_settime(fset, new_parent, info, ATTR_CTIME | ATTR_MTIME);


+ if (error) {
+ EXIT;

+ goto exit;
+ }
+

+ /* XXX make a distinction between cross file set
+ * and intra file set renames here
+ */
+ presto_debug_fail_blkdev(fset, PRESTO_OP_RENAME | 0x10);


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

echo 'End of part 097'
echo 'File patch-2.4.15 is continued in part 098'
echo "098" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:14 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part098

#!/bin/sh -x
# this is part 098 of a 115 - part archive


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

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

+ if ( presto_do_kml(info, old_dir) )
+ error = presto_journal_rename(&rec, fset, old_dentry, new_dentry,
+ &src_dir_ver, &tgt_dir_ver);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_RENAME | 0x20);
+
+ if ( presto_do_expect(info, new_dir) )

+ error = presto_write_last_rcvd(&rec, fset, info);
+

+ presto_debug_fail_blkdev(fset, PRESTO_OP_RENAME | 0x30);
+ EXIT;
+exit:
+ presto_trans_commit(fset, handle);
+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH);

+ return error;
+}
+
+static

+int presto_rename_dir(struct presto_file_set *fset, struct dentry *old_parent,
+ struct dentry *old_dentry, struct dentry *new_parent,
+ struct dentry *new_dentry, struct lento_vfs_context *info)
+{
+ int error;
+ struct inode *target;


+ struct inode *old_dir = old_parent->d_inode;
+ struct inode *new_dir = new_parent->d_inode;
+

+ if (old_dentry->d_inode == new_dentry->d_inode)
+ return 0;
+
+ error = may_delete(old_dir, old_dentry, 1);


+ if (error)
+ return error;
+

+ if (new_dir->i_dev != old_dir->i_dev)
+ return -EXDEV;
+
+ if (!new_dentry->d_inode)
+ error = may_create(new_dir, new_dentry);
+ else
+ error = may_delete(new_dir, new_dentry, 1);


+ if (error)
+ return error;
+

+ if (!old_dir->i_op || !old_dir->i_op->rename)
+ return -EPERM;
+
+ /*
+ * If we are going to change the parent - check write permissions,
+ * we'll need to flip '..'.
+ */
+ if (new_dir != old_dir) {
+ error = permission(old_dentry->d_inode, MAY_WRITE);
+ }
+ if (error)
+ return error;
+
+ DQUOT_INIT(old_dir);
+ DQUOT_INIT(new_dir);
+ down(&old_dir->i_sb->s_vfs_rename_sem);
+ error = -EINVAL;
+ if (is_subdir(new_dentry, old_dentry))
+ goto out_unlock;
+ target = new_dentry->d_inode;
+ if (target) { /* Hastur! Hastur! Hastur! */


+ triple_down(&old_dir->i_zombie,
+ &new_dir->i_zombie,

+ &target->i_zombie);
+ d_unhash(new_dentry);


+ } else
+ double_down(&old_dir->i_zombie,
+ &new_dir->i_zombie);

+ if (IS_DEADDIR(old_dir)||IS_DEADDIR(new_dir))
+ error = -ENOENT;
+ else if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))


+ error = -EBUSY;
+ else

+ error = do_rename(fset, old_parent, old_dentry,
+ new_parent, new_dentry, info);
+ if (target) {
+ if (!error)
+ target->i_flags |= S_DEAD;


+ triple_up(&old_dir->i_zombie,
+ &new_dir->i_zombie,

+ &target->i_zombie);
+ if (d_unhashed(new_dentry))
+ d_rehash(new_dentry);
+ dput(new_dentry);


+ } else
+ double_up(&old_dir->i_zombie,
+ &new_dir->i_zombie);

+
+ if (!error)
+ d_move(old_dentry,new_dentry);
+out_unlock:
+ up(&old_dir->i_sb->s_vfs_rename_sem);


+ return error;
+}
+
+static

+int presto_rename_other(struct presto_file_set *fset, struct dentry *old_parent,
+ struct dentry *old_dentry, struct dentry *new_parent,
+ struct dentry *new_dentry, struct lento_vfs_context *info)
+{


+ struct inode *old_dir = old_parent->d_inode;
+ struct inode *new_dir = new_parent->d_inode;

+ int error;
+
+ if (old_dentry->d_inode == new_dentry->d_inode)
+ return 0;
+
+ error = may_delete(old_dir, old_dentry, 0);
+ if (error)
+ return error;
+
+ if (new_dir->i_dev != old_dir->i_dev)
+ return -EXDEV;
+
+ if (!new_dentry->d_inode)
+ error = may_create(new_dir, new_dentry);
+ else
+ error = may_delete(new_dir, new_dentry, 0);
+ if (error)
+ return error;
+
+ if (!old_dir->i_op || !old_dir->i_op->rename)
+ return -EPERM;
+
+ DQUOT_INIT(old_dir);
+ DQUOT_INIT(new_dir);


+ double_down(&old_dir->i_zombie, &new_dir->i_zombie);

+ if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))


+ error = -EBUSY;
+ else

+ error = do_rename(fset, old_parent, old_dentry,
+ new_parent, new_dentry, info);
+ double_up(&old_dir->i_zombie, &new_dir->i_zombie);
+ if (error)
+ return error;
+ /* The following d_move() should become unconditional */
+ if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME)) {
+ d_move(old_dentry, new_dentry);
+ }


+ return 0;
+}
+

+int presto_do_rename(struct presto_file_set *fset,

+ struct dentry *old_parent, struct dentry *old_dentry,
+ struct dentry *new_parent, struct dentry *new_dentry,
+ struct lento_vfs_context *info)
+{

+ if (S_ISDIR(old_dentry->d_inode->i_mode))

+ return presto_rename_dir(fset, old_parent,old_dentry,new_parent,
+ new_dentry, info);
+ else
+ return presto_rename_other(fset, old_parent, old_dentry,
+ new_parent,new_dentry, info);
+}
+
+
+int lento_do_rename(const char *oldname, const char *newname,


+ struct lento_vfs_context *info)
+{

+ int error = 0;
+ struct dentry * old_dir, * new_dir;
+ struct dentry * old_dentry, *new_dentry;
+ struct nameidata oldnd, newnd;


+ struct presto_file_set *fset;
+
+ ENTRY;
+

+ if (path_init(oldname, LOOKUP_PARENT, &oldnd))
+ error = path_walk(oldname, &oldnd);
+
+ if (error)
+ goto exit;
+
+ if (path_init(newname, LOOKUP_PARENT, &newnd))
+ error = path_walk(newname, &newnd);
+ if (error)
+ goto exit1;


+
+ error = -EXDEV;

+ if (oldnd.mnt != newnd.mnt)
+ goto exit2;
+
+ old_dir = oldnd.dentry;
+ error = -EBUSY;
+ if (oldnd.last_type != LAST_NORM)
+ goto exit2;
+
+ new_dir = newnd.dentry;
+ if (newnd.last_type != LAST_NORM)
+ goto exit2;
+
+ double_lock(new_dir, old_dir);
+
+ old_dentry = lookup_hash(&oldnd.last, old_dir);
+ error = PTR_ERR(old_dentry);
+ if (IS_ERR(old_dentry))
+ goto exit3;
+ /* source must exist */
+ error = -ENOENT;
+ if (!old_dentry->d_inode)
+ goto exit4;
+ fset = presto_fset(old_dentry);


+ error = -EINVAL;
+ if ( !fset ) {
+ printk("No fileset!\n");
+ EXIT;

+ goto exit4;
+ }
+ /* unless the source is a directory trailing slashes give -ENOTDIR */
+ if (!S_ISDIR(old_dentry->d_inode->i_mode)) {
+ error = -ENOTDIR;
+ if (oldnd.last.name[oldnd.last.len])
+ goto exit4;
+ if (newnd.last.name[newnd.last.len])
+ goto exit4;
+ }
+ new_dentry = lookup_hash(&newnd.last, new_dir);
+ error = PTR_ERR(new_dentry);
+ if (IS_ERR(new_dentry))
+ goto exit4;
+
+ lock_kernel();
+ error = presto_do_rename(fset, old_dir, old_dentry,
+ new_dir, new_dentry, info);
+ unlock_kernel();
+
+ dput(new_dentry);
+exit4:
+ dput(old_dentry);
+exit3:
+ double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem);
+exit2:
+ path_release(&newnd);
+exit1:
+ path_release(&oldnd);


+exit:
+ return error;
+}
+

+int lento_rename(const char * oldname, const char * newname,


+ struct lento_vfs_context *info)
+{
+ int error;
+ char * from;
+ char * to;
+

+ from = getname(oldname);
+ if(IS_ERR(from))
+ return PTR_ERR(from);
+ to = getname(newname);
+ error = PTR_ERR(to);
+ if (!IS_ERR(to)) {

+ error = lento_do_rename(from,to, info);


+ putname(to);
+ }
+ putname(from);

+ return error;
+}
+
+struct dentry *presto_iopen(struct dentry *dentry,


+ ino_t ino, unsigned int generation)
+{

+ struct presto_file_set *fset;
+ char name[48];
+ int error;
+
+ ENTRY;
+ /* see if we already have the dentry we want */
+ if (dentry->d_inode && dentry->d_inode->i_ino == ino &&
+ dentry->d_inode->i_generation == generation) {
+ EXIT;


+ return dentry;
+ }
+

+ /* Make sure we have a cache beneath us. We should always find at
+ * least one dentry inside the cache (if it exists), otherwise not
+ * even the cache root exists, or we passed in a bad name.
+ */


+ fset = presto_fset(dentry);
+ error = -EINVAL;
+ if (!fset) {

+ printk("No fileset for %*s!\n",
+ dentry->d_name.len, dentry->d_name.name);
+ EXIT;
+ dput(dentry);
+ return ERR_PTR(error);
+ }
+ dput(dentry);
+
+ sprintf(name, "%s%#lx%c%#x",
+ PRESTO_ILOOKUP_MAGIC, ino, PRESTO_ILOOKUP_SEP, generation);
+ CDEBUG(D_PIOCTL, "opening %ld by number (as %s)\n", ino, name);
+ return lookup_one_len(name, fset->fset_mtpt, strlen(name));
+}
+
+static struct file *presto_filp_dopen(struct dentry *dentry, int flags)
+{
+ struct file *f;
+ struct inode *inode;
+ int flag, error;
+
+ ENTRY;
+ error = -ENFILE;
+ f = get_empty_filp();
+ if (!f) {
+ CDEBUG(D_PIOCTL, "error getting file pointer\n");
+ EXIT;
+ goto out;
+ }
+ f->f_flags = flag = flags;
+ f->f_mode = (flag+1) & O_ACCMODE;


+ inode = dentry->d_inode;

+ if (f->f_mode & FMODE_WRITE) {
+ error = get_write_access(inode);
+ if (error) {
+ CDEBUG(D_PIOCTL, "error getting write access\n");
+ EXIT;
+ goto cleanup_file;
+ }
+ }
+
+ f->f_dentry = dentry;
+ f->f_pos = 0;
+ f->f_reada = 0;
+ f->f_op = NULL;
+ if (inode->i_op)
+ /* XXX should we set to presto ops, or leave at cache ops? */
+ f->f_op = inode->i_fop;
+ if (f->f_op && f->f_op->open) {
+ error = f->f_op->open(inode, f);
+ if (error) {
+ CDEBUG(D_PIOCTL, "error calling cache 'open'\n");
+ EXIT;
+ goto cleanup_all;
+ }
+ }
+ f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
+
+ return f;
+
+cleanup_all:
+ if (f->f_mode & FMODE_WRITE)
+ put_write_access(inode);
+cleanup_file:
+ put_filp(f);
+out:


+ return ERR_PTR(error);
+}
+
+

+/* Open an inode by number. We pass in the cache root name (or a subdirectory
+ * from the cache that is guaranteed to exist) to be able to access the cache.
+ */
+int lento_iopen(const char *name, ino_t ino, unsigned int generation,
+ int flags)
+{
+ char * tmp;


+ struct dentry *dentry;
+ struct nameidata nd;

+ int fd;
+ int error;
+
+ ENTRY;
+ CDEBUG(D_PIOCTL,
+ "open %s:inode %#lx (%ld), generation %x (%d), flags %d \n",
+ name, ino, ino, generation, generation, flags);
+ /* We don't allow creation of files by number only, as it would
+ * lead to a dangling files not in any directory. We could also
+ * just turn off the flag and ignore it.
+ */
+ if (flags & O_CREAT) {
+ printk(KERN_WARNING __FUNCTION__
+ ": create file by inode number (%ld) not allowed\n",ino);
+ EXIT;
+ return -EACCES;
+ }
+
+ tmp = getname(name);
+ if (IS_ERR(tmp)) {
+ EXIT;


+ return PTR_ERR(tmp);
+ }
+

+ lock_kernel();
+again: /* look the named file or a parent directory so we can get the cache */
+ error = presto_walk(tmp, &nd);
+ if ( error && error != -ENOENT ) {
+ EXIT;
+ return error;
+ }
+ if (error == -ENOENT)
+ dentry = NULL;
+ else

+ dentry = nd.dentry;
+

+ /* we didn't find the named file, so see if a parent exists */
+ if (!dentry) {
+ char *slash;
+
+ slash = strrchr(tmp, '/');
+ if (slash && slash != tmp) {
+ *slash = '\0';
+ path_release(&nd);
+ goto again;
+ }
+ /* we should never get here... */
+ CDEBUG(D_PIOCTL, "no more path components to try!\n");
+ fd = -ENOENT;
+ goto exit;
+ }
+ CDEBUG(D_PIOCTL, "returned dentry %p\n", dentry);
+
+ dentry = presto_iopen(dentry, ino, generation);
+ fd = PTR_ERR(dentry);


+ if (IS_ERR(dentry)) {
+ EXIT;

+ goto exit;
+ }
+

+ /* XXX start of code that might be replaced by something like:
+ * if (flags & (O_WRONLY | O_RDWR)) {
+ * error = get_write_access(dentry->d_inode);
+ * if (error) {
+ * EXIT;
+ * goto cleanup_dput;
+ * }
+ * }
+ * fd = open_dentry(dentry, flags);
+ *
+ * including the presto_filp_dopen() function (check dget counts!)
+ */
+ fd = get_unused_fd();
+ if (fd < 0) {
+ EXIT;
+ goto cleanup_dput;
+ }
+
+ {
+ int error;
+ struct file * f = presto_filp_dopen(dentry, flags);


+ error = PTR_ERR(f);
+ if (IS_ERR(f)) {

+ put_unused_fd(fd);
+ fd = error;
+ EXIT;
+ goto cleanup_dput;
+ }
+ fd_install(fd, f);
+ }
+ /* end of code that might be replaced by open_dentry */
+
+ EXIT;
+exit:
+ unlock_kernel();
+ path_release(&nd);
+ putname(tmp);
+ return fd;
+
+cleanup_dput:
+ putname(&nd);


+ goto exit;
+}
+

+int lento_close(unsigned int fd, struct lento_vfs_context *info)


+{
+ struct rec_info rec;
+ int error;

+ struct file * filp;
+ struct dentry *dentry;
+ int do_kml, do_expect;


+
+ ENTRY;
+ lock_kernel();
+

+ error = -EBADF;
+ filp = fcheck(fd);
+ if (filp) {
+
+ struct files_struct * files = current->files;
+ dentry = filp->f_dentry;
+ dget(dentry);
+ do_kml = presto_do_kml(info, dentry->d_inode);
+ do_expect = presto_do_expect(info, dentry->d_inode);
+ files->fd[fd] = NULL;
+ put_unused_fd(fd);
+ FD_CLR(fd, files->close_on_exec);
+ error = filp_close(filp, files);
+ } else {


+ EXIT;
+ return error;
+ }
+

+ if (error) {
+ EXIT;
+ goto exit;
+ }
+

+ if ( do_kml ) {
+ struct presto_file_set *fset;
+ struct presto_version new_file_ver;


+
+ fset = presto_fset(dentry);
+ error = -EINVAL;
+ if (!fset) {

+ printk("No fileset for %*s!\n",
+ dentry->d_name.len, dentry->d_name.name);


+ EXIT;
+ goto exit;
+ }

+ presto_getversion(&new_file_ver, dentry->d_inode);
+ error = presto_journal_close(&rec, fset, filp, dentry,
+ &new_file_ver);


+ if ( error ) {

+ printk("presto: close error %d!\n", error);


+ EXIT;
+ goto exit;
+ }

+ if ( do_expect )
+

+ error = presto_write_last_rcvd(&rec, fset, info);
+ }
+

+ EXIT;
+exit:
+ dput(dentry);


+ unlock_kernel();
+ return error;
+}
+

+#ifdef CONFIG_FS_EXT_ATTR
+
+#ifdef CONFIG_FS_POSIX_ACL
+/* Posix ACL code changes i_mode without using a notify_change (or
+ * a mark_inode_dirty!). We need to duplicate this at the reintegrator
+ * which is done by this function. This function also takes care of
+ * resetting the cached posix acls in this inode. If we don't reset these
+ * VFS continues using the old acl information, which by now may be out of
+ * date.
+ */
+int presto_setmode(struct presto_file_set *fset, struct dentry *dentry,
+ mode_t mode)
+{


+ struct inode *inode = dentry->d_inode;
+

+ ENTRY;
+ /* The extended attributes for this inode were modified.
+ * At this point we can not be sure if any of the ACL
+ * information for this inode was updated. So we will
+ * force VFS to reread the acls. Note that we do this
+ * only when called from the SETEXTATTR ioctl, which is why we
+ * do this while setting the mode of the file. Also note
+ * that mark_inode_dirty is not be needed for i_*acl only
+ * to force i_mode info to disk, and should be removed once
+ * we use notify_change to update the mode.
+ * XXX: is mode setting really needed? Just setting acl's should
+ * be enough! VFS should change the i_mode as needed? SHP
+ */
+ if (inode->i_acl &&
+ inode->i_acl != POSIX_ACL_NOT_CACHED)
+ posix_acl_release(inode->i_acl);
+ if (inode->i_default_acl &&
+ inode->i_default_acl != POSIX_ACL_NOT_CACHED)
+ posix_acl_release(inode->i_default_acl);
+ inode->i_acl = POSIX_ACL_NOT_CACHED;
+ inode->i_default_acl = POSIX_ACL_NOT_CACHED;


+ inode->i_mode = mode;

+ /* inode should already be dirty...but just in case */
+ mark_inode_dirty(inode);
+ return 0;
+
+#if 0
+ /* XXX: The following code is the preferred way to set mode,
+ * however, I need to carefully go through possible recursion
+ * paths back into presto. See comments in presto_do_setattr.
+ */
+ {
+ int error=0;
+ struct super_operations *sops;


+ struct iattr iattr;
+

+ iattr.ia_mode = mode;
+ iattr.ia_valid = ATTR_MODE|ATTR_FORCE;


+
+ error = -EPERM;

+ sops = filter_c2csops(fset->fset_cache->cache_filter);
+ if (!sops &&
+ !sops->notify_change) {


+ EXIT;
+ return error;
+ }
+

+ error = sops->notify_change(dentry, &iattr);


+
+ EXIT;
+ return error;
+ }

+#endif
+}
+#endif
+
+/* setextattr Interface to cache filesystem */
+int presto_do_set_ext_attr(struct presto_file_set *fset,
+ struct dentry *dentry,

+ const char *name, void *buffer,

+ size_t buffer_len, int flags, mode_t *mode,


+ struct lento_vfs_context *info)
+{
+ struct rec_info rec;

+ struct inode *inode = dentry->d_inode;
+ struct inode_operations *iops;
+ int error;

+ struct presto_version ver;
+ void *handle;
+ char temp[PRESTO_EXT_ATTR_NAME_MAX+1];


+
+ ENTRY;
+ error = -EROFS;
+ if (IS_RDONLY(inode)) {
+ EXIT;
+ return -EROFS;
+ }
+
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
+ EXIT;
+ return -EPERM;
+ }
+

+ presto_getversion(&ver, inode);
+ error = -EPERM;
+ /* We need to invoke different filters based on whether
+ * this dentry is a regular file, directory or symlink.
+ */
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFLNK: /* symlink */
+ iops = filter_c2csiops(fset->fset_cache->cache_filter);
+ break;
+ case S_IFDIR: /* directory */


+ iops = filter_c2cdiops(fset->fset_cache->cache_filter);

+ break;
+ case S_IFREG:
+ default: /* everything else including regular files */
+ iops = filter_c2cfiops(fset->fset_cache->cache_filter);
+ }
+
+ if (!iops && !iops->set_ext_attr) {


+ EXIT;
+ return error;
+ }
+
+ error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);
+ if (error) {
+ EXIT;
+ return error;
+ }
+

+
+ handle = presto_trans_start(fset,dentry->d_inode,PRESTO_OP_SETEXTATTR);


+ if ( IS_ERR(handle) ) {

+ printk("presto_do_set_ext_attr: no space for transaction\n");
+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH);

+ return -ENOSPC;
+ }
+

+ /* We first "truncate" name to the maximum allowable in presto */
+ /* This simulates the strncpy_from_use code in fs/ext_attr.c */
+ strncpy(temp,name,sizeof(temp));
+
+ /* Pass down to cache*/
+ error = iops->set_ext_attr(inode,temp,buffer,buffer_len,flags);


+ if (error) {
+ EXIT;
+ goto exit;
+ }
+

+#ifdef CONFIG_FS_POSIX_ACL
+ /* Reset mode if specified*/
+ /* XXX: when we do native acl support, move this code out! */
+ if (mode != NULL) {
+ error = presto_setmode(fset, dentry, *mode);


+ if (error) {
+ EXIT;
+ goto exit;
+ }
+ }

+#endif
+
+ /* Reset ctime. Only inode change time (ctime) is affected */


+ error = presto_settime(fset, dentry, info, ATTR_CTIME);

+ if (error) {
+ EXIT;
+ goto exit;
+ }
+

+ if (flags & EXT_ATTR_FLAG_USER) {
+ printk(" USER flag passed to presto_do_set_ext_attr!\n");
+ *(int *)0 = 1;
+ }
+
+ /* We are here, so set_ext_attr succeeded. We no longer need to keep
+ * track of EXT_ATTR_FLAG_{EXISTS,CREATE}, instead, we will force
+ * the attribute value during log replay. -SHP
+ */
+ flags &= ~(EXT_ATTR_FLAG_EXISTS | EXT_ATTR_FLAG_CREATE);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_SETEXTATTR | 0x10);


+ if ( presto_do_kml(info, dentry->d_inode) )

+ error = presto_journal_set_ext_attr
+ (&rec, fset, dentry, &ver, name, buffer,
+ buffer_len, flags);
+
+ presto_debug_fail_blkdev(fset, PRESTO_OP_SETEXTATTR | 0x20);


+ if ( presto_do_expect(info, dentry->d_inode) )
+ error = presto_write_last_rcvd(&rec, fset, info);
+

+ presto_debug_fail_blkdev(fset, PRESTO_OP_SETEXTATTR | 0x30);
+ EXIT;
+exit:
+ presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
+ presto_trans_commit(fset, handle);


+
+ return error;
+}

+#endif
diff -u --recursive --new-file v2.4.14/linux/fs/isofs/compress.c linux/fs/isofs/compress.c
--- v2.4.14/linux/fs/isofs/compress.c Mon Nov 5 15:55:33 2001
+++ linux/fs/isofs/compress.c Tue Nov 6 08:34:40 2001
@@ -44,9 +44,6 @@
X
X #include "zisofs.h"
X
-#define min(a,b) ((a)<(b)?(a):(b))
-#define max(a,b) ((a)>(b)?(a):(b))
-
X /* This should probably be global. */
X static char zisofs_sink_page[PAGE_CACHE_SIZE];
X
diff -u --recursive --new-file v2.4.14/linux/fs/jbd/Makefile linux/fs/jbd/Makefile
--- v2.4.14/linux/fs/jbd/Makefile Wed Dec 31 16:00:00 1969
+++ linux/fs/jbd/Makefile Fri Nov 9 14:25:04 2001
@@ -0,0 +1,15 @@
+#
+# fs/jbd/Makefile
+#
+# Makefile for the linux journaling routines.
+#
+
+export-objs := journal.o
+O_TARGET := jbd.o
+
+obj-y := transaction.o commit.o recovery.o checkpoint.o revoke.o journal.o


+
+obj-m := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make

+
diff -u --recursive --new-file v2.4.14/linux/fs/jbd/checkpoint.c linux/fs/jbd/checkpoint.c
--- v2.4.14/linux/fs/jbd/checkpoint.c Wed Dec 31 16:00:00 1969
+++ linux/fs/jbd/checkpoint.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,608 @@
+/*
+ * linux/fs/checkpoint.c
+ *
+ * Written by Stephen C. Tweedie <s...@redhat.com>, 1999
+ *
+ * Copyright 1999 Red Hat Software --- All Rights Reserved
+ *


+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *

+ * Checkpoint routines for the generic filesystem journaling code.
+ * Part of the ext2fs journaling system.
+ *
+ * Checkpointing is the process of ensuring that a section of the log is
+ * committed fully to disk, so that that portion of the log can be
+ * reused.
+ */
+
+#include <linux/sched.h>
+#include <linux/fs.h>


+#include <linux/jbd.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/locks.h>
+

+extern spinlock_t journal_datalist_lock;
+
+/*
+ * Unlink a buffer from a transaction.
+ *
+ * Called with journal_datalist_lock held.
+ */
+
+static inline void __buffer_unlink(struct journal_head *jh)


+{
+ transaction_t *transaction;
+

+ transaction = jh->b_cp_transaction;
+ jh->b_cp_transaction = NULL;
+
+ jh->b_cpnext->b_cpprev = jh->b_cpprev;
+ jh->b_cpprev->b_cpnext = jh->b_cpnext;
+ if (transaction->t_checkpoint_list == jh)
+ transaction->t_checkpoint_list = jh->b_cpnext;
+ if (transaction->t_checkpoint_list == jh)
+ transaction->t_checkpoint_list = NULL;
+}
+
+/*
+ * Try to release a checkpointed buffer from its transaction.
+ * Returns 1 if we released it.
+ * Requires journal_datalist_lock
+ */
+static int __try_to_free_cp_buf(struct journal_head *jh)
+{


+ int ret = 0;

+ struct buffer_head *bh = jh2bh(jh);
+

+ if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) {
+ JBUFFER_TRACE(jh, "remove from checkpoint list");
+ __journal_remove_checkpoint(jh);
+ __journal_remove_journal_head(bh);
+ BUFFER_TRACE(bh, "release");
+ /* BUF_LOCKED -> BUF_CLEAN (fwiw) */
+ refile_buffer(bh);
+ __brelse(bh);


+ ret = 1;
+ }

+ return ret;
+}
+
+/*
+ * log_wait_for_space: wait until there is space in the journal.
+ *
+ * Called with the journal already locked, but it will be unlocked if we have
+ * to wait for a checkpoint to free up some space in the log.
+ */
+
+void log_wait_for_space(journal_t *journal, int nblocks)
+{
+ while (log_space_left(journal) < nblocks) {


+ if (journal->j_flags & JFS_ABORT)

+ return;
+ unlock_journal(journal);
+ down(&journal->j_checkpoint_sem);
+ lock_journal(journal);
+
+ /* Test again, another process may have checkpointed
+ * while we were waiting for the checkpoint lock */
+ if (log_space_left(journal) < nblocks) {
+ log_do_checkpoint(journal, nblocks);
+ }
+ up(&journal->j_checkpoint_sem);
+ }
+}
+
+/*
+ * Clean up a transaction's checkpoint list.
+ *
+ * We wait for any pending IO to complete and make sure any clean
+ * buffers are removed from the transaction.
+ *
+ * Return 1 if we performed any actions which might have destroyed the
+ * checkpoint. (journal_remove_checkpoint() deletes the transaction when
+ * the last checkpoint buffer is cleansed)
+ *
+ * Called with the journal locked.
+ * Called with journal_datalist_lock held.
+ */
+static int __cleanup_transaction(journal_t *journal, transaction_t *transaction)
+{
+ struct journal_head *jh, *next_jh, *last_jh;
+ struct buffer_head *bh;
+ int ret = 0;
+
+ assert_spin_locked(&journal_datalist_lock);
+ jh = transaction->t_checkpoint_list;
+ if (!jh)
+ return 0;
+
+ last_jh = jh->b_cpprev;
+ next_jh = jh;
+ do {
+ jh = next_jh;


+ bh = jh2bh(jh);
+ if (buffer_locked(bh)) {

+ atomic_inc(&bh->b_count);
+ spin_unlock(&journal_datalist_lock);
+ unlock_journal(journal);
+ wait_on_buffer(bh);
+ /* the journal_head may have gone by now */
+ BUFFER_TRACE(bh, "brelse");
+ __brelse(bh);
+ goto out_return_1;
+ }
+
+ if (jh->b_transaction != NULL) {
+ transaction_t *transaction = jh->b_transaction;
+ tid_t tid = transaction->t_tid;
+
+ spin_unlock(&journal_datalist_lock);
+ log_start_commit(journal, transaction);
+ unlock_journal(journal);
+ log_wait_commit(journal, tid);
+ goto out_return_1;
+ }
+
+ /*
+ * We used to test for (jh->b_list != BUF_CLEAN) here.
+ * But unmap_underlying_metadata() can place buffer onto
+ * BUF_CLEAN. Since refile_buffer() no longer takes buffers
+ * off checkpoint lists, we cope with it here
+ */
+ /*
+ * AKPM: I think the buffer_jdirty test is redundant - it
+ * shouldn't have NULL b_transaction?
+ */
+ next_jh = jh->b_cpnext;
+ if (!buffer_dirty(bh) && !buffer_jdirty(bh)) {
+ BUFFER_TRACE(bh, "remove from checkpoint");
+ __journal_remove_checkpoint(jh);


+ __journal_remove_journal_head(bh);
+ refile_buffer(bh);
+ __brelse(bh);

+ ret = 1;
+ }
+
+ jh = next_jh;
+ } while (jh != last_jh);
+
+ return ret;
+out_return_1:
+ lock_journal(journal);
+ spin_lock(&journal_datalist_lock);


+ return 1;
+}
+

+#define NR_BATCH 64
+
+static void __flush_batch(struct buffer_head **bhs, int *batch_count)
+{
+ int i;
+
+ spin_unlock(&journal_datalist_lock);
+ ll_rw_block(WRITE, *batch_count, bhs);
+ run_task_queue(&tq_disk);
+ spin_lock(&journal_datalist_lock);
+ for (i = 0; i < *batch_count; i++) {
+ struct buffer_head *bh = bhs[i];
+ clear_bit(BH_JWrite, &bh->b_state);
+ BUFFER_TRACE(bh, "brelse");
+ __brelse(bh);
+ }
+ *batch_count = 0;
+}
+
+/*
+ * Try to flush one buffer from the checkpoint list to disk.
+ *
+ * Return 1 if something happened which requires us to abort the current
+ * scan of the checkpoint list.
+ *
+ * Called with journal_datalist_lock held.
+ */
+static int __flush_buffer(journal_t *journal, struct journal_head *jh,
+ struct buffer_head **bhs, int *batch_count,
+ int *drop_count)
+{
+ struct buffer_head *bh = jh2bh(jh);
+ int ret = 0;
+
+ if (buffer_dirty(bh) && !buffer_locked(bh) && jh->b_jlist == BJ_None) {
+ J_ASSERT_JH(jh, jh->b_transaction == NULL);
+
+ /*
+ * Important: we are about to write the buffer, and
+ * possibly block, while still holding the journal lock.
+ * We cannot afford to let the transaction logic start
+ * messing around with this buffer before we write it to
+ * disk, as that would break recoverability.
+ */
+ BUFFER_TRACE(bh, "queue");
+ atomic_inc(&bh->b_count);
+ J_ASSERT_BH(bh, !test_bit(BH_JWrite, &bh->b_state));
+ set_bit(BH_JWrite, &bh->b_state);
+ bhs[*batch_count] = bh;
+ (*batch_count)++;
+ if (*batch_count == NR_BATCH) {
+ __flush_batch(bhs, batch_count);


+ ret = 1;
+ }

+ } else {
+ int last_buffer = 0;
+ if (jh->b_cpnext == jh) {
+ /* We may be about to drop the transaction. Tell the
+ * caller that the lists have changed.
+ */
+ last_buffer = 1;
+ }
+ if (__try_to_free_cp_buf(jh)) {
+ (*drop_count)++;
+ ret = last_buffer;
+ }


+ }
+ return ret;
+}

+
+
+/*
+ * Perform an actual checkpoint. We don't write out only enough to
+ * satisfy the current blocked requests: rather we submit a reasonably
+ * sized chunk of the outstanding data to disk at once for
+ * efficiency. log_wait_for_space() will retry if we didn't free enough.
+ *
+ * However, we _do_ take into account the amount requested so that once
+ * the IO has been queued, we can return as soon as enough of it has
+ * completed to disk.
+ *
+ * The journal should be locked before calling this function.
+ */
+
+/* @@@ `nblocks' is unused. Should it be used? */
+int log_do_checkpoint (journal_t *journal, int nblocks)
+{
+ transaction_t *transaction, *last_transaction, *next_transaction;
+ int result;
+ int target;
+ int batch_count = 0;
+ struct buffer_head *bhs[NR_BATCH];
+
+ jbd_debug(1, "Start checkpoint\n");
+
+ /*
+ * First thing: if there are any transactions in the log which
+ * don't need checkpointing, just eliminate them from the
+ * journal straight away.
+ */
+ result = cleanup_journal_tail(journal);
+ jbd_debug(1, "cleanup_journal_tail returned %d\n", result);
+ if (result <= 0)
+ return result;
+
+ /*
+ * OK, we need to start writing disk blocks. Try to free up a
+ * quarter of the log in a single checkpoint if we can.
+ */
+ /*
+ * AKPM: check this code. I had a feeling a while back that it
+ * degenerates into a busy loop at unmount time.
+ */
+ target = (journal->j_last - journal->j_first) / 4;
+
+ spin_lock(&journal_datalist_lock);
+repeat:
+ transaction = journal->j_checkpoint_transactions;
+ if (transaction == NULL)
+ goto done;
+ last_transaction = transaction->t_cpprev;
+ next_transaction = transaction;
+
+ do {
+ struct journal_head *jh, *last_jh, *next_jh;
+ int drop_count = 0;
+ int cleanup_ret, retry = 0;
+
+ transaction = next_transaction;
+ next_transaction = transaction->t_cpnext;
+ jh = transaction->t_checkpoint_list;
+ last_jh = jh->b_cpprev;
+ next_jh = jh;
+ do {
+ jh = next_jh;
+ next_jh = jh->b_cpnext;
+ retry = __flush_buffer(journal, jh, bhs, &batch_count,
+ &drop_count);
+ } while (jh != last_jh && !retry);
+ if (batch_count) {
+ __flush_batch(bhs, &batch_count);
+ goto repeat;
+ }
+ if (retry)
+ goto repeat;
+ /*
+ * We have walked the whole transaction list without
+ * finding anything to write to disk. We had better be
+ * able to make some progress or we are in trouble.
+ */
+ cleanup_ret = __cleanup_transaction(journal, transaction);
+ J_ASSERT(drop_count != 0 || cleanup_ret != 0);
+ goto repeat; /* __cleanup may have dropped lock */
+ } while (transaction != last_transaction);
+
+done:
+ spin_unlock(&journal_datalist_lock);
+ result = cleanup_journal_tail(journal);
+ if (result < 0)
+ return result;
+

+ return 0;
+}
+
+/*

+ * Check the list of checkpoint transactions for the journal to see if
+ * we have already got rid of any since the last update of the log tail
+ * in the journal superblock. If so, we can instantly roll the
+ * superblock forward to remove those transactions from the log.
+ *
+ * Return <0 on error, 0 on success, 1 if there was nothing to clean up.
+ *
+ * Called with the journal lock held.
+ *
+ * This is the only part of the journaling code which really needs to be
+ * aware of transaction aborts. Checkpointing involves writing to the
+ * main filesystem area rather than to the journal, so it can proceed
+ * even in abort state, but we must not update the journal superblock if
+ * we have an abort error outstanding.
+ */
+
+int cleanup_journal_tail(journal_t *journal)
+{
+ transaction_t * transaction;
+ tid_t first_tid;
+ unsigned long blocknr, freed;
+
+ /* OK, work out the oldest transaction remaining in the log, and
+ * the log block it starts at.
+ *
+ * If the log is now empty, we need to work out which is the
+ * next transaction ID we will write, and where it will
+ * start. */
+
+ /* j_checkpoint_transactions needs locking */
+ spin_lock(&journal_datalist_lock);
+ transaction = journal->j_checkpoint_transactions;
+ if (transaction) {
+ first_tid = transaction->t_tid;
+ blocknr = transaction->t_log_start;
+ } else if ((transaction = journal->j_committing_transaction) != NULL) {
+ first_tid = transaction->t_tid;
+ blocknr = transaction->t_log_start;
+ } else if ((transaction = journal->j_running_transaction) != NULL) {
+ first_tid = transaction->t_tid;


+ blocknr = journal->j_head;

+ } else {
+ first_tid = journal->j_transaction_sequence;


+ blocknr = journal->j_head;
+ }

+ spin_unlock(&journal_datalist_lock);
+ J_ASSERT (blocknr != 0);
+
+ /* If the oldest pinned transaction is at the tail of the log
+ already then there's not much we can do right now. */
+ if (journal->j_tail_sequence == first_tid)
+ return 1;
+
+ /* OK, update the superblock to recover the freed space.
+ * Physical blocks come first: have we wrapped beyond the end of
+ * the log? */
+ freed = blocknr - journal->j_tail;
+ if (blocknr < journal->j_tail)
+ freed = freed + journal->j_last - journal->j_first;
+
+ jbd_debug(1,
+ "Cleaning journal tail from %d to %d (offset %lu), "
+ "freeing %lu\n",
+ journal->j_tail_sequence, first_tid, blocknr, freed);
+
+ journal->j_free += freed;
+ journal->j_tail_sequence = first_tid;
+ journal->j_tail = blocknr;
+ if (!(journal->j_flags & JFS_ABORT))
+ journal_update_superblock(journal, 1);


+ return 0;
+}
+
+

+/* Checkpoint list management */
+
+/*
+ * journal_clean_checkpoint_list
+ *
+ * Find all the written-back checkpoint buffers in the journal and release them.
+ *
+ * Called with the journal locked.
+ * Called with journal_datalist_lock held.
+ * Returns number of bufers reaped (for debug)
+ */
+
+int __journal_clean_checkpoint_list(journal_t *journal)
+{
+ transaction_t *transaction, *last_transaction, *next_transaction;
+ int ret = 0;
+
+ transaction = journal->j_checkpoint_transactions;
+ if (transaction == 0)
+ goto out;
+
+ last_transaction = transaction->t_cpprev;
+ next_transaction = transaction;
+ do {


+ struct journal_head *jh;
+

+ transaction = next_transaction;
+ next_transaction = transaction->t_cpnext;
+ jh = transaction->t_checkpoint_list;
+ if (jh) {
+ struct journal_head *last_jh = jh->b_cpprev;
+ struct journal_head *next_jh = jh;
+ do {


+ struct buffer_head *bh;
+

+ jh = next_jh;
+ next_jh = jh->b_cpnext;
+ bh = jh2bh(jh);
+ ret += __try_to_free_cp_buf(jh);
+ } while (jh != last_jh);
+ }
+ } while (transaction != last_transaction);
+out:
+ return ret;
+}
+
+/*
+ * journal_remove_checkpoint: called after a buffer has been committed
+ * to disk (either by being write-back flushed to disk, or being
+ * committed to the log).
+ *
+ * We cannot safely clean a transaction out of the log until all of the
+ * buffer updates committed in that transaction have safely been stored
+ * elsewhere on disk. To achieve this, all of the buffers in a
+ * transaction need to be maintained on the transaction's checkpoint
+ * list until they have been rewritten, at which point this function is
+ * called to remove the buffer from the existing transaction's
+ * checkpoint list.
+ *
+ * This function is called with the journal locked.
+ * This function is called with journal_datalist_lock held.
+ */
+
+void __journal_remove_checkpoint(struct journal_head *jh)
+{
+ transaction_t *transaction;
+ journal_t *journal;
+
+ JBUFFER_TRACE(jh, "entry");
+
+ if ((transaction = jh->b_cp_transaction) == NULL) {
+ JBUFFER_TRACE(jh, "not on transaction");


+ goto out;
+ }
+

+ journal = transaction->t_journal;
+
+ __buffer_unlink(jh);
+
+ if (transaction->t_checkpoint_list != NULL)
+ goto out;
+ JBUFFER_TRACE(jh, "transaction has no more buffers");
+
+ /* There is one special case to worry about: if we have just
+ pulled the buffer off a committing transaction's forget list,
+ then even if the checkpoint list is empty, the transaction
+ obviously cannot be dropped! */
+
+ if (transaction == journal->j_committing_transaction) {
+ JBUFFER_TRACE(jh, "belongs to committing transaction");


+ goto out;
+ }
+

+ /* OK, that was the last buffer for the transaction: we can now
+ safely remove this transaction from the log */
+
+ __journal_drop_transaction(journal, transaction);
+
+ /* Just in case anybody was waiting for more transactions to be
+ checkpointed... */
+ wake_up(&journal->j_wait_logspace);
+out:
+ JBUFFER_TRACE(jh, "exit");
+}
+
+void journal_remove_checkpoint(struct journal_head *jh)
+{
+ spin_lock(&journal_datalist_lock);
+ __journal_remove_checkpoint(jh);
+ spin_unlock(&journal_datalist_lock);
+}
+
+/*
+ * journal_insert_checkpoint: put a committed buffer onto a checkpoint
+ * list so that we know when it is safe to clean the transaction out of
+ * the log.
+ *
+ * Called with the journal locked.
+ * Called with journal_datalist_lock held.
+ */
+void __journal_insert_checkpoint(struct journal_head *jh,
+ transaction_t *transaction)
+{
+ JBUFFER_TRACE(jh, "entry");
+ J_ASSERT_JH(jh, buffer_dirty(jh2bh(jh)) || buffer_jdirty(jh2bh(jh)));
+ J_ASSERT_JH(jh, jh->b_cp_transaction == NULL);
+
+ assert_spin_locked(&journal_datalist_lock);
+ jh->b_cp_transaction = transaction;
+
+ if (!transaction->t_checkpoint_list) {
+ jh->b_cpnext = jh->b_cpprev = jh;
+ } else {
+ jh->b_cpnext = transaction->t_checkpoint_list;
+ jh->b_cpprev = transaction->t_checkpoint_list->b_cpprev;
+ jh->b_cpprev->b_cpnext = jh;
+ jh->b_cpnext->b_cpprev = jh;
+ }
+ transaction->t_checkpoint_list = jh;
+}
+
+void journal_insert_checkpoint(struct journal_head *jh,
+ transaction_t *transaction)
+{
+ spin_lock(&journal_datalist_lock);
+ __journal_insert_checkpoint(jh, transaction);
+ spin_unlock(&journal_datalist_lock);
+}
+
+/*
+ * We've finished with this transaction structure: adios...
+ *
+ * The transaction must have no links except for the checkpoint by this
+ * point.
+ *
+ * Called with the journal locked.
+ * Called with journal_datalist_lock held.
+ */
+
+void __journal_drop_transaction(journal_t *journal, transaction_t *transaction)
+{
+ assert_spin_locked(&journal_datalist_lock);
+ if (transaction->t_cpnext) {
+ transaction->t_cpnext->t_cpprev = transaction->t_cpprev;
+ transaction->t_cpprev->t_cpnext = transaction->t_cpnext;
+ if (journal->j_checkpoint_transactions == transaction)
+ journal->j_checkpoint_transactions =
+ transaction->t_cpnext;
+ if (journal->j_checkpoint_transactions == transaction)
+ journal->j_checkpoint_transactions = NULL;
+ }
+
+ J_ASSERT (transaction->t_ilist == NULL);
+ J_ASSERT (transaction->t_buffers == NULL);
+ J_ASSERT (transaction->t_sync_datalist == NULL);
+ J_ASSERT (transaction->t_async_datalist == NULL);
+ J_ASSERT (transaction->t_forget == NULL);
+ J_ASSERT (transaction->t_iobuf_list == NULL);
+ J_ASSERT (transaction->t_shadow_list == NULL);
+ J_ASSERT (transaction->t_log_list == NULL);
+ J_ASSERT (transaction->t_checkpoint_list == NULL);
+ J_ASSERT (transaction->t_updates == 0);
+
+ J_ASSERT (transaction->t_journal->j_committing_transaction !=
+ transaction);
+
+ jbd_debug (1, "Dropping transaction %d, all done\n",
+ transaction->t_tid);
+ kfree (transaction);
+}
+
diff -u --recursive --new-file v2.4.14/linux/fs/jbd/commit.c linux/fs/jbd/commit.c
--- v2.4.14/linux/fs/jbd/commit.c Wed Dec 31 16:00:00 1969
+++ linux/fs/jbd/commit.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,701 @@
+/*
+ * linux/fs/commit.c


+ *
+ * Written by Stephen C. Tweedie <s...@redhat.com>, 1998

+ *


+ * Copyright 1998 Red Hat corp --- All Rights Reserved

+ *


+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *

+ * Journal commit routines for the generic filesystem journaling code;
+ * part of the ext2fs journaling system.
+ */
+
+#include <linux/sched.h>
+#include <linux/fs.h>


+#include <linux/jbd.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/locks.h>
+#include <linux/smp_lock.h>
+

+extern spinlock_t journal_datalist_lock;
+
+/*
+ * Default IO end handler for temporary BJ_IO buffer_heads.
+ */
+static void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
+{
+ BUFFER_TRACE(bh, "");
+ mark_buffer_uptodate(bh, uptodate);
+ unlock_buffer(bh);
+}
+
+/*
+ * journal_commit_transaction
+ *
+ * The primary function for committing a transaction to the log. This
+ * function is called by the journal thread to begin a complete commit.
+ */
+void journal_commit_transaction(journal_t *journal)
+{
+ transaction_t *commit_transaction;
+ struct journal_head *jh, *new_jh, *descriptor;
+ struct journal_head *next_jh, *last_jh;
+ struct buffer_head *wbuf[64];
+ int bufs;
+ int flags;
+ int blocknr;
+ char *tagp = NULL;
+ journal_header_t *header;
+ journal_block_tag_t *tag = NULL;
+ int space_left = 0;
+ int first_tag = 0;
+ int tag_flag;
+ int i;
+
+ /*
+ * First job: lock down the current transaction and wait for
+ * all outstanding updates to complete.
+ */
+
+ lock_journal(journal); /* Protect journal->j_running_transaction */
+
+#ifdef COMMIT_STATS
+ spin_lock(&journal_datalist_lock);
+ summarise_journal_usage(journal);
+ spin_unlock(&journal_datalist_lock);
+#endif
+
+ lock_kernel();
+
+ J_ASSERT (journal->j_running_transaction != NULL);
+ J_ASSERT (journal->j_committing_transaction == NULL);
+
+ commit_transaction = journal->j_running_transaction;
+ J_ASSERT (commit_transaction->t_state == T_RUNNING);
+
+ jbd_debug (1, "JBD: starting commit of transaction %d\n",
+ commit_transaction->t_tid);
+
+ commit_transaction->t_state = T_LOCKED;
+ while (commit_transaction->t_updates != 0) {
+ unlock_journal(journal);
+ sleep_on(&journal->j_wait_updates);
+ lock_journal(journal);
+ }
+
+ J_ASSERT (commit_transaction->t_outstanding_credits <=
+ journal->j_max_transaction_buffers);
+
+ /* Do we need to erase the effects of a prior journal_flush? */
+ if (journal->j_flags & JFS_FLUSHED) {
+ jbd_debug(3, "super block updated\n");
+ journal_update_superblock(journal, 1);
+ } else {
+ jbd_debug(3, "superblock not updated\n");
+ }
+
+ /*
+ * First thing we are allowed to do is to discard any remaining
+ * BJ_Reserved buffers. Note, it is _not_ permissible to assume
+ * that there are no such buffers: if a large filesystem
+ * operation like a truncate needs to split itself over multiple
+ * transactions, then it may try to do a journal_restart() while
+ * there are still BJ_Reserved buffers outstanding. These must
+ * be released cleanly from the current transaction.
+ *
+ * In this case, the filesystem must still reserve write access
+ * again before modifying the buffer in the new transaction, but
+ * we do not require it to remember exactly which old buffers it
+ * has reserved. This is consistent with the existing behaviour
+ * that multiple journal_get_write_access() calls to the same
+ * buffer are perfectly permissable.
+ */
+
+ while (commit_transaction->t_reserved_list) {
+ jh = commit_transaction->t_reserved_list;
+ JBUFFER_TRACE(jh, "reserved, unused: refile");
+ journal_refile_buffer(jh);
+ }
+
+ /*
+ * Now try to drop any written-back buffers from the journal's
+ * checkpoint lists. We do this *before* commit because it potentially
+ * frees some memory
+ */


+ spin_lock(&journal_datalist_lock);
+ __journal_clean_checkpoint_list(journal);
+ spin_unlock(&journal_datalist_lock);
+

+ /* First part of the commit: force the revoke list out to disk.
+ * The revoke code generates its own metadata blocks on disk for this.
+ *
+ * It is important that we do this while the transaction is
+ * still locked. Generating the revoke records should not
+ * generate any IO stalls, so this should be quick; and doing
+ * the work while we have the transaction locked means that we
+ * only ever have to maintain the revoke list for one
+ * transaction at a time.
+ */
+
+ jbd_debug (3, "JBD: commit phase 1\n");
+
+ journal_write_revoke_records(journal, commit_transaction);
+
+ /*
+ * Now that we have built the revoke records, we can start
+ * reusing the revoke list for a new running transaction. We
+ * can now safely start committing the old transaction: time to
+ * get a new running transaction for incoming filesystem updates
+ */
+
+ commit_transaction->t_state = T_FLUSH;
+
+ wake_up(&journal->j_wait_transaction_locked);
+
+ journal->j_committing_transaction = commit_transaction;
+ journal->j_running_transaction = NULL;
+
+ commit_transaction->t_log_start = journal->j_head;
+
+ unlock_kernel();
+
+ jbd_debug (3, "JBD: commit phase 2\n");
+
+ /*
+ * Now start flushing things to disk, in the order they appear
+ * on the transaction lists. Data blocks go first.
+ */
+
+ /*
+ * Whenever we unlock the journal and sleep, things can get added
+ * onto ->t_datalist, so we have to keep looping back to write_out_data
+ * until we *know* that the list is empty.
+ */
+write_out_data:
+
+ /*
+ * Cleanup any flushed data buffers from the data list. Even in
+ * abort mode, we want to flush this out as soon as possible.
+ *
+ * We take journal_datalist_lock to protect the lists from
+ * journal_try_to_free_buffers().
+ */
+ spin_lock(&journal_datalist_lock);
+
+write_out_data_locked:
+ bufs = 0;
+ next_jh = commit_transaction->t_sync_datalist;
+ if (next_jh == NULL)
+ goto sync_datalist_empty;
+ last_jh = next_jh->b_tprev;
+
+ do {


+ struct buffer_head *bh;
+

+ jh = next_jh;
+ next_jh = jh->b_tnext;
+ bh = jh2bh(jh);
+ if (!buffer_locked(bh)) {
+ if (buffer_dirty(bh)) {
+ BUFFER_TRACE(bh, "start journal writeout");
+ atomic_inc(&bh->b_count);
+ wbuf[bufs++] = bh;
+ } else {
+ BUFFER_TRACE(bh, "writeout complete: unfile");


+ __journal_unfile_buffer(jh);
+ jh->b_transaction = NULL;
+ __journal_remove_journal_head(bh);
+ refile_buffer(bh);
+ __brelse(bh);
+ }

+ }
+ if (bufs == ARRAY_SIZE(wbuf)) {
+ /*
+ * Major speedup: start here on the next scan
+ */
+ J_ASSERT(commit_transaction->t_sync_datalist != 0);
+ commit_transaction->t_sync_datalist = jh;
+ break;
+ }
+ } while (jh != last_jh);
+
+ if (bufs || current->need_resched) {
+ jbd_debug(2, "submit %d writes\n", bufs);
+ spin_unlock(&journal_datalist_lock);
+ unlock_journal(journal);
+ if (bufs)
+ ll_rw_block(WRITE, bufs, wbuf);
+ if (current->need_resched)
+ schedule();
+ journal_brelse_array(wbuf, bufs);
+ lock_journal(journal);
+ spin_lock(&journal_datalist_lock);
+ if (bufs)
+ goto write_out_data_locked;
+ }
+
+ /*
+ * Wait for all previously submitted IO on the data list to complete.
+ */
+ jh = commit_transaction->t_sync_datalist;
+ if (jh == NULL)
+ goto sync_datalist_empty;
+
+ do {
+ struct buffer_head *bh;
+ jh = jh->b_tprev; /* Wait on the last written */
+ bh = jh2bh(jh);
+ if (buffer_locked(bh)) {
+ spin_unlock(&journal_datalist_lock);
+ unlock_journal(journal);
+ wait_on_buffer(bh);
+ /* the journal_head may have been removed now */
+ lock_journal(journal);
+ goto write_out_data;
+ } else if (buffer_dirty(bh)) {
+ goto write_out_data_locked;
+ }
+ } while (jh != commit_transaction->t_sync_datalist);
+ goto write_out_data_locked;
+
+sync_datalist_empty:
+ /*
+ * Wait for all the async writepage data. As they become unlocked
+ * in end_buffer_io_async(), the only place where they can be
+ * reaped is in try_to_free_buffers(), and we're locked against
+ * that.
+ */
+ while ((jh = commit_transaction->t_async_datalist)) {


+ struct buffer_head *bh = jh2bh(jh);

+ if (buffer_locked(bh)) {
+ spin_unlock(&journal_datalist_lock);


+ unlock_journal(journal);
+ wait_on_buffer(bh);
+ lock_journal(journal);

+ spin_lock(&journal_datalist_lock);
+ continue; /* List may have changed */
+ }
+ if (jh->b_next_transaction) {
+ /*
+ * For writepage() buffers in journalled data mode: a
+ * later transaction may want the buffer for "metadata"
+ */
+ __journal_refile_buffer(jh);
+ } else {
+ BUFFER_TRACE(bh, "finished async writeout: unfile");


+ __journal_unfile_buffer(jh);
+ jh->b_transaction = NULL;
+ __journal_remove_journal_head(bh);

+ BUFFER_TRACE(bh, "finished async writeout: refile");
+ /* It can sometimes be on BUF_LOCKED due to migration
+ * from syncdata to asyncdata */
+ if (bh->b_list != BUF_CLEAN)


+ refile_buffer(bh);
+ __brelse(bh);
+ }

+ }
+ spin_unlock(&journal_datalist_lock);
+
+ /*
+ * If we found any dirty or locked buffers, then we should have
+ * looped back up to the write_out_data label. If there weren't
+ * any then journal_clean_data_list should have wiped the list
+ * clean by now, so check that it is in fact empty.
+ */
+ J_ASSERT (commit_transaction->t_sync_datalist == NULL);
+ J_ASSERT (commit_transaction->t_async_datalist == NULL);
+
+ jbd_debug (3, "JBD: commit phase 3\n");
+
+ /*
+ * Way to go: we have now written out all of the data for a
+ * transaction! Now comes the tricky part: we need to write out
+ * metadata. Loop over the transaction's entire buffer list:
+ */
+ commit_transaction->t_state = T_COMMIT;
+
+ descriptor = 0;
+ bufs = 0;
+ while (commit_transaction->t_buffers) {
+
+ /* Find the next buffer to be journaled... */
+
+ jh = commit_transaction->t_buffers;
+
+ /* If we're in abort mode, we just un-journal the buffer and
+ release it for background writing. */
+
+ if (is_journal_aborted(journal)) {
+ JBUFFER_TRACE(jh, "journal is aborting: refile");
+ journal_refile_buffer(jh);
+ /* If that was the last one, we need to clean up
+ * any descriptor buffers which may have been
+ * already allocated, even if we are now
+ * aborting. */
+ if (!commit_transaction->t_buffers)
+ goto start_journal_io;
+ continue;
+ }
+
+ /* Make sure we have a descriptor block in which to
+ record the metadata buffer. */
+
+ if (!descriptor) {


+ struct buffer_head *bh;
+

+ J_ASSERT (bufs == 0);
+
+ jbd_debug(4, "JBD: get descriptor\n");


+
+ descriptor = journal_get_descriptor_buffer(journal);

+ bh = jh2bh(descriptor);
+ jbd_debug(4, "JBD: got buffer %ld (%p)\n",
+ bh->b_blocknr, bh->b_data);
+ header = (journal_header_t *)&bh->b_data[0];
+ header->h_magic = htonl(JFS_MAGIC_NUMBER);
+ header->h_blocktype = htonl(JFS_DESCRIPTOR_BLOCK);
+ header->h_sequence = htonl(commit_transaction->t_tid);
+
+ tagp = &bh->b_data[sizeof(journal_header_t)];
+ space_left = bh->b_size - sizeof(journal_header_t);
+ first_tag = 1;
+ set_bit(BH_JWrite, &bh->b_state);
+ wbuf[bufs++] = bh;
+
+ /* Record it so that we can wait for IO
+ completion later */
+ BUFFER_TRACE(bh, "ph3: file as descriptor");
+ journal_file_buffer(descriptor, commit_transaction,
+ BJ_LogCtl);
+ }
+
+ /* Where is the buffer to be written? */
+
+ blocknr = journal_next_log_block(journal);
+
+ /* Bump b_count to prevent truncate from stumbling over
+ the shadowed buffer! @@@ This can go if we ever get
+ rid of the BJ_IO/BJ_Shadow pairing of buffers. */
+ atomic_inc(&jh2bh(jh)->b_count);
+
+ /* Make a temporary IO buffer with which to write it out
+ (this will requeue both the metadata buffer and the
+ temporary IO buffer). new_bh goes on BJ_IO*/
+
+ set_bit(BH_JWrite, &jh2bh(jh)->b_state);
+ /*
+ * akpm: journal_write_metadata_buffer() sets
+ * new_bh->b_transaction to commit_transaction.
+ * We need to clean this up before we release new_bh
+ * (which is of type BJ_IO)
+ */
+ JBUFFER_TRACE(jh, "ph3: write metadata");
+ flags = journal_write_metadata_buffer(commit_transaction,
+ jh, &new_jh, blocknr);
+ set_bit(BH_JWrite, &jh2bh(new_jh)->b_state);
+ wbuf[bufs++] = jh2bh(new_jh);
+
+ /* Record the new block's tag in the current descriptor
+ buffer */
+
+ tag_flag = 0;
+ if (flags & 1)
+ tag_flag |= JFS_FLAG_ESCAPE;
+ if (!first_tag)
+ tag_flag |= JFS_FLAG_SAME_UUID;
+
+ tag = (journal_block_tag_t *) tagp;
+ tag->t_blocknr = htonl(jh2bh(jh)->b_blocknr);
+ tag->t_flags = htonl(tag_flag);
+ tagp += sizeof(journal_block_tag_t);
+ space_left -= sizeof(journal_block_tag_t);
+
+ if (first_tag) {
+ memcpy (tagp, journal->j_uuid, 16);
+ tagp += 16;
+ space_left -= 16;
+ first_tag = 0;
+ }
+
+ /* If there's no more to do, or if the descriptor is full,
+ let the IO rip! */
+
+ if (bufs == ARRAY_SIZE(wbuf) ||
+ commit_transaction->t_buffers == NULL ||
+ space_left < sizeof(journal_block_tag_t) + 16) {
+
+ jbd_debug(4, "JBD: Submit %d IOs\n", bufs);
+
+ /* Write an end-of-descriptor marker before
+ submitting the IOs. "tag" still points to
+ the last tag we set up. */
+
+ tag->t_flags |= htonl(JFS_FLAG_LAST_TAG);
+
+start_journal_io:
+ unlock_journal(journal);
+ for (i=0; i<bufs; i++) {
+ struct buffer_head *bh = wbuf[i];
+ set_bit(BH_Lock, &bh->b_state);
+ clear_bit(BH_Dirty, &bh->b_state);
+ bh->b_end_io = journal_end_buffer_io_sync;
+ submit_bh(WRITE, bh);
+ }
+ if (current->need_resched)
+ schedule();
+ lock_journal(journal);
+
+ /* Force a new descriptor to be generated next
+ time round the loop. */
+ descriptor = NULL;
+ bufs = 0;
+ }
+ }
+
+ /* Lo and behold: we have just managed to send a transaction to
+ the log. Before we can commit it, wait for the IO so far to
+ complete. Control buffers being written are on the
+ transaction's t_log_list queue, and metadata buffers are on
+ the t_iobuf_list queue.
+
+ Wait for the transactions in reverse order. That way we are
+ less likely to be woken up until all IOs have completed, and
+ so we incur less scheduling load.
+ */
+
+ jbd_debug(3, "JBD: commit phase 4\n");
+
+ /* akpm: these are BJ_IO, and journal_datalist_lock is not needed */


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

echo 'End of part 098'
echo 'File patch-2.4.15 is continued in part 099'
echo "099" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:21 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part105

#!/bin/sh -x
# this is part 105 of a 115 - part archive


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

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

-
X sb->s_root = d_alloc_root(iget(sb, UFS_ROOTINO));
X
X
@@ -832,20 +813,20 @@
X struct ufs_sb_private_info * uspi;
X struct ufs_super_block_first * usb1;
X struct ufs_super_block_third * usb3;
- unsigned flags, swab;
+ unsigned flags;
X
X UFSD(("ENTER\n"))
- swab = sb->u.ufs_sb.s_swab;
X flags = sb->u.ufs_sb.s_flags;
X uspi = sb->u.ufs_sb.s_uspi;
X usb1 = ubh_get_usb_first(USPI_UBH);
X usb3 = ubh_get_usb_third(USPI_UBH);
X
X if (!(sb->s_flags & MS_RDONLY)) {
- usb1->fs_time = SWAB32(CURRENT_TIME);
+ usb1->fs_time = cpu_to_fs32(sb, CURRENT_TIME);
X if ((flags & UFS_ST_MASK) == UFS_ST_SUN
X || (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
- ufs_set_fs_state(usb1, usb3, UFS_FSOK - SWAB32(usb1->fs_time));
+ ufs_set_fs_state(sb, usb1, usb3,
+ UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
X ubh_mark_buffer_dirty (USPI_UBH);
X }
X sb->s_dirt = 0;
@@ -855,12 +836,10 @@
X void ufs_put_super (struct super_block * sb)
X {
X struct ufs_sb_private_info * uspi;
- unsigned swab;
X
X UFSD(("ENTER\n"))
X
X uspi = sb->u.ufs_sb.s_uspi;
- swab = sb->u.ufs_sb.s_swab;
X
X if (!(sb->s_flags & MS_RDONLY))
X ufs_put_cylinder_structures (sb);
@@ -877,11 +856,10 @@
X struct ufs_super_block_first * usb1;
X struct ufs_super_block_third * usb3;
X unsigned new_mount_opt, ufstype;
- unsigned flags, swab;
+ unsigned flags;
X
X uspi = sb->u.ufs_sb.s_uspi;
X flags = sb->u.ufs_sb.s_flags;
- swab = sb->u.ufs_sb.s_swab;
X usb1 = ubh_get_usb_first(USPI_UBH);
X usb3 = ubh_get_usb_third(USPI_UBH);
X
@@ -912,10 +890,11 @@
X */
X if (*mount_flags & MS_RDONLY) {
X ufs_put_cylinder_structures(sb);
- usb1->fs_time = SWAB32(CURRENT_TIME);
+ usb1->fs_time = cpu_to_fs32(sb, CURRENT_TIME);
X if ((flags & UFS_ST_MASK) == UFS_ST_SUN
X || (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
- ufs_set_fs_state(usb1, usb3, UFS_FSOK - SWAB32(usb1->fs_time));
+ ufs_set_fs_state(sb, usb1, usb3,
+ UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
X ubh_mark_buffer_dirty (USPI_UBH);
X sb->s_dirt = 0;
X sb->s_flags |= MS_RDONLY;
@@ -950,21 +929,19 @@
X {
X struct ufs_sb_private_info * uspi;
X struct ufs_super_block_first * usb1;
- unsigned swab;
X
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;
X usb1 = ubh_get_usb_first (USPI_UBH);
X
X buf->f_type = UFS_MAGIC;
X buf->f_bsize = sb->s_blocksize;
X buf->f_blocks = uspi->s_dsize;
- buf->f_bfree = ufs_blkstofrags(SWAB32(usb1->fs_cstotal.cs_nbfree)) +
- SWAB32(usb1->fs_cstotal.cs_nffree);
+ buf->f_bfree = ufs_blkstofrags(fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree)) +
+ fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree);
X buf->f_bavail = (buf->f_bfree > ((buf->f_blocks / 100) * uspi->s_minfree))
X ? (buf->f_bfree - ((buf->f_blocks / 100) * uspi->s_minfree)) : 0;
X buf->f_files = uspi->s_ncg * uspi->s_ipg;
- buf->f_ffree = SWAB32(usb1->fs_cstotal.cs_nifree);
+ buf->f_ffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree);
X buf->f_namelen = UFS_MAXNAMLEN;
X return 0;
X }
diff -u --recursive --new-file v2.4.14/linux/fs/ufs/swab.h linux/fs/ufs/swab.h
--- v2.4.14/linux/fs/ufs/swab.h Mon Dec 11 13:26:44 2000
+++ linux/fs/ufs/swab.h Mon Nov 19 14:55:46 2001
@@ -3,6 +3,7 @@
X *
X * Copyright (C) 1997, 1998 Francois-Rene Rideau <fa...@tunes.org>
X * Copyright (C) 1998 Jakub Jelinek <j...@ultra.linux.cz>
+ * Copyright (C) 2001 Christoph Hellwig <h...@caldera.de>
X */
X
X #ifndef _UFS_SWAB_H
@@ -14,124 +15,119 @@
X * in case there are ufs implementations that have strange bytesexes,
X * you'll need to modify code here as well as in ufs_super.c and ufs_fs.h
X * to support them.
- *
- * WE ALSO ASSUME A REMOTELY SANE ARCHITECTURE BYTESEX.
- * We are not ready to confront insane bytesexual perversions where
- * conversion to/from little/big-endian is not an involution.
- * That is, we require that XeYZ_to_cpu(x) == cpu_to_XeYZ(x)
- *
- * NOTE that swab macros depend on a variable (or macro) swab being in
- * scope and properly initialized (usually from sb->u.ufs_sb.s_swab).
- * Its meaning depends on whether the architecture is sane-endian or not.
- * For sane architectures, it's a flag taking values UFS_NATIVE_ENDIAN (0)
- * or UFS_SWABBED_ENDIAN (1), indicating whether to swab or not.
- * For pervert architectures, it's either UFS_LITTLE_ENDIAN or
- * UFS_BIG_ENDIAN whose meaning you'll have to guess.
- *
- * It is important to keep these conventions in synch with ufs_fs.h
- * and super.c. Failure to do so (initializing swab to 0 both for
- * NATIVE_ENDIAN and LITTLE_ENDIAN) led to nasty crashes on big endian
- * machines reading little endian UFSes. Search for "swab =" in super.c.
- *
- * I also suspect the whole UFS code to trust the on-disk structures
- * much too much, which might lead to losing badly when mounting
- * inconsistent partitions as UFS filesystems. fsck required (but of
- * course, no fsck.ufs has yet to be ported from BSD to Linux as of 199808).
X */
X
-#include <linux/ufs_fs.h>
-#include <asm/byteorder.h>
+enum {
+ BYTESEX_LE,
+ BYTESEX_BE
+};
X
-/*
- * These are only valid inside ufs routines,
- * after swab has been initialized to sb->u.ufs_sb.s_swab
- */
-#define SWAB16(x) ufs_swab16(swab,x)
-#define SWAB32(x) ufs_swab32(swab,x)
-#define SWAB64(x) ufs_swab64(swab,x)
-
-/*
- * We often use swabing, when we want to increment/decrement some value,
- * so these macros might become handy and increase readability. (Daniel)
- */
-#define INC_SWAB16(x) ((x)=ufs_swab16_add(swab,x,1))
-#define INC_SWAB32(x) ((x)=ufs_swab32_add(swab,x,1))
-#define INC_SWAB64(x) ((x)=ufs_swab64_add(swab,x,1))
-#define DEC_SWAB16(x) ((x)=ufs_swab16_add(swab,x,-1))
-#define DEC_SWAB32(x) ((x)=ufs_swab32_add(swab,x,-1))
-#define DEC_SWAB64(x) ((x)=ufs_swab64_add(swab,x,-1))
-#define ADD_SWAB16(x,y) ((x)=ufs_swab16_add(swab,x,y))
-#define ADD_SWAB32(x,y) ((x)=ufs_swab32_add(swab,x,y))
-#define ADD_SWAB64(x,y) ((x)=ufs_swab64_add(swab,x,y))
-#define SUB_SWAB16(x,y) ((x)=ufs_swab16_add(swab,x,-(y)))
-#define SUB_SWAB32(x,y) ((x)=ufs_swab32_add(swab,x,-(y)))
-#define SUB_SWAB64(x,y) ((x)=ufs_swab64_add(swab,x,-(y)))
-
-#if defined(__LITTLE_ENDIAN) || defined(__BIG_ENDIAN) /* sane bytesex */
-extern __inline__ __const__ __u16 ufs_swab16(unsigned swab, __u16 x) {
- if (swab)
- return swab16(x);
+static __inline u64
+fs64_to_cpu(struct super_block *sbp, u64 n)
+{
+ if (sbp->u.ufs_sb.s_bytesex == BYTESEX_LE)
+ return le64_to_cpu(n);
X else
- return x;
+ return be64_to_cpu(n);
X }
-extern __inline__ __const__ __u32 ufs_swab32(unsigned swab, __u32 x) {
- if (swab)
- return swab32(x);
+
+static __inline u64
+cpu_to_fs64(struct super_block *sbp, u64 n)
+{
+ if (sbp->u.ufs_sb.s_bytesex == BYTESEX_LE)
+ return cpu_to_le64(n);
X else
- return x;
+ return cpu_to_be64(n);
X }
-extern __inline__ __const__ __u64 ufs_swab64(unsigned swab, __u64 x) {
- if (swab)
- return swab64(x);
+
+static __inline u32
+fs64_add(struct super_block *sbp, u32 *n, int d)
+{
+ if (sbp->u.ufs_sb.s_bytesex == BYTESEX_LE)
+ return *n = cpu_to_le64(le64_to_cpu(*n)+d);
X else
- return x;
+ return *n = cpu_to_be64(be64_to_cpu(*n)+d);
X }
-extern __inline__ __const__ __u16 ufs_swab16_add(unsigned swab, __u16 x, __u16 y) {
- if (swab)
- return swab16(swab16(x)+y);
+
+static __inline u32
+fs64_sub(struct super_block *sbp, u32 *n, int d)
+{
+ if (sbp->u.ufs_sb.s_bytesex == BYTESEX_LE)
+ return *n = cpu_to_le64(le64_to_cpu(*n)-d);
X else
- return x + y;
+ return *n = cpu_to_be64(be64_to_cpu(*n)-d);
X }
-extern __inline__ __const__ __u32 ufs_swab32_add(unsigned swab, __u32 x, __u32 y) {
- if (swab)
- return swab32(swab32(x)+y);
+
+static __inline u32
+fs32_to_cpu(struct super_block *sbp, u32 n)
+{
+ if (sbp->u.ufs_sb.s_bytesex == BYTESEX_LE)
+ return le32_to_cpu(n);
X else
- return x + y;
+ return be32_to_cpu(n);
X }
-extern __inline__ __const__ __u64 ufs_swab64_add(unsigned swab, __u64 x, __u64 y) {
- if (swab)
- return swab64(swab64(x)+y);
+
+static __inline u32
+cpu_to_fs32(struct super_block *sbp, u32 n)
+{
+ if (sbp->u.ufs_sb.s_bytesex == BYTESEX_LE)
+ return cpu_to_le32(n);
X else
- return x + y;
+ return cpu_to_be32(n);
X }
-#else /* bytesexual perversion -- BEWARE! Read note at top of file! */
-extern __inline__ __const__ __u16 ufs_swab16(unsigned swab, __u16 x) {
- if (swab == UFS_LITTLE_ENDIAN)
- return le16_to_cpu(x);
+
+static __inline u32
+fs32_add(struct super_block *sbp, u32 *n, int d)
+{
+ if (sbp->u.ufs_sb.s_bytesex == BYTESEX_LE)
+ return *n = cpu_to_le32(le32_to_cpu(*n)+d);
X else
- return be16_to_cpu(x);
+ return *n = cpu_to_be32(be32_to_cpu(*n)+d);
X }
-extern __inline__ __const__ __u32 ufs_swab32(unsigned swab, __u32 x) {
- if (swab == UFS_LITTLE_ENDIAN)
- return le32_to_cpu(x);
+
+static __inline u32
+fs32_sub(struct super_block *sbp, u32 *n, int d)
+{
+ if (sbp->u.ufs_sb.s_bytesex == BYTESEX_LE)
+ return *n = cpu_to_le32(le32_to_cpu(*n)-d);
X else
- return be32_to_cpu(x);
+ return *n = cpu_to_be32(be32_to_cpu(*n)-d);
X }
-extern __inline__ __const__ __u64 ufs_swab64(unsigned swab, __u64 x) {
- if (swab == UFS_LITTLE_ENDIAN)
- return le64_to_cpu(x);
+
+static __inline u16
+fs16_to_cpu(struct super_block *sbp, u16 n)
+{
+ if (sbp->u.ufs_sb.s_bytesex == BYTESEX_LE)
+ return le16_to_cpu(n);
X else
- return be64_to_cpu(x);
+ return be16_to_cpu(n);
X }
-extern __inline__ __const__ __u16 ufs_swab16_add(unsigned swab, __u16 x, __u16 y) {
- return ufs_swab16(swab, ufs_swab16(swab, x) + y);
+
+static __inline u16
+cpu_to_fs16(struct super_block *sbp, u16 n)
+{
+ if (sbp->u.ufs_sb.s_bytesex == BYTESEX_LE)
+ return cpu_to_le16(n);
+ else
+ return cpu_to_be16(n);
X }
-extern __inline__ __const__ __u32 ufs_swab32_add(unsigned swab, __u32 x, __u32 y) {
- return ufs_swab32(swab, ufs_swab32(swab, x) + y);
+
+static __inline u16
+fs16_add(struct super_block *sbp, u16 *n, int d)
+{
+ if (sbp->u.ufs_sb.s_bytesex == BYTESEX_LE)
+ return *n = cpu_to_le16(le16_to_cpu(*n)+d);
+ else
+ return *n = cpu_to_be16(be16_to_cpu(*n)+d);
X }
-extern __inline__ __const__ __u64 ufs_swab64_add(unsigned swab, __u64 x, __u64 y) {
- return ufs_swab64(swab, ufs_swab64(swab, x) + y);
+
+static __inline u16
+fs16_sub(struct super_block *sbp, u16 *n, int d)
+{
+ if (sbp->u.ufs_sb.s_bytesex == BYTESEX_LE)
+ return *n = cpu_to_le16(le16_to_cpu(*n)-d);
+ else
+ return *n = cpu_to_be16(be16_to_cpu(*n)-d);
X }
-#endif /* byte sexuality */
X
X #endif /* _UFS_SWAB_H */
diff -u --recursive --new-file v2.4.14/linux/fs/ufs/truncate.c linux/fs/ufs/truncate.c
--- v2.4.14/linux/fs/ufs/truncate.c Sun Sep 23 11:41:01 2001
+++ linux/fs/ufs/truncate.c Mon Nov 19 14:55:46 2001
@@ -75,12 +75,10 @@
X unsigned frag_to_free, free_count;
X unsigned i, j, tmp;
X int retry;
- unsigned swab;
X
X UFSD(("ENTER\n"))
X
X sb = inode->i_sb;
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;
X
X frag_to_free = 0;
@@ -110,14 +108,14 @@
X * Free first free fragments
X */
X p = inode->u.ufs_i.i_u1.i_data + ufs_fragstoblks (frag1);
- tmp = SWAB32(*p);
+ tmp = fs32_to_cpu(sb, *p);
X if (!tmp )
X ufs_panic (sb, "ufs_trunc_direct", "internal error");
X frag1 = ufs_fragnum (frag1);
X frag2 = ufs_fragnum (frag2);
X for (j = frag1; j < frag2; j++) {
X bh = get_hash_table (sb->s_dev, tmp + j, uspi->s_fsize);
- if ((bh && DATA_BUFFER_USED(bh)) || tmp != SWAB32(*p)) {
+ if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) {
X retry = 1;
X brelse (bh);
X goto next1;
@@ -135,19 +133,19 @@
X */
X for (i = block1 ; i < block2; i++) {
X p = inode->u.ufs_i.i_u1.i_data + i;
- tmp = SWAB32(*p);
+ tmp = fs32_to_cpu(sb, *p);
X if (!tmp)
X continue;
X for (j = 0; j < uspi->s_fpb; j++) {
X bh = get_hash_table (sb->s_dev, tmp + j, uspi->s_fsize);
- if ((bh && DATA_BUFFER_USED(bh)) || tmp != SWAB32(*p)) {
+ if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) {
X retry = 1;
X brelse (bh);
X goto next2;
X }
X bforget (bh);
X }
- *p = SWAB32(0);
+ *p = 0;
X inode->i_blocks -= uspi->s_nspb;
X mark_inode_dirty(inode);
X if (free_count == 0) {
@@ -173,20 +171,20 @@
X * Free last free fragments
X */
X p = inode->u.ufs_i.i_u1.i_data + ufs_fragstoblks (frag3);
- tmp = SWAB32(*p);
+ tmp = fs32_to_cpu(sb, *p);
X if (!tmp )
X ufs_panic(sb, "ufs_truncate_direct", "internal error");
X frag4 = ufs_fragnum (frag4);
X for (j = 0; j < frag4; j++) {
X bh = get_hash_table (sb->s_dev, tmp + j, uspi->s_fsize);
- if ((bh && DATA_BUFFER_USED(bh)) || tmp != SWAB32(*p)) {
+ if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) {
X retry = 1;
X brelse (bh);
X goto next1;
X }
X bforget (bh);
X }
- *p = SWAB32(0);
+ *p = 0;
X inode->i_blocks -= frag4 << uspi->s_nspfshift;
X mark_inode_dirty(inode);
X ufs_free_fragments (inode, tmp, frag4);
@@ -207,47 +205,45 @@
X unsigned indirect_block, i, j, tmp;
X unsigned frag_to_free, free_count;
X int retry;
- unsigned swab;
X
X UFSD(("ENTER\n"))
X
X sb = inode->i_sb;
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;
X
X frag_to_free = 0;
X free_count = 0;
X retry = 0;
X
- tmp = SWAB32(*p);
+ tmp = fs32_to_cpu(sb, *p);
X if (!tmp)
X return 0;
X ind_ubh = ubh_bread (sb->s_dev, tmp, uspi->s_bsize);
- if (tmp != SWAB32(*p)) {
+ if (tmp != fs32_to_cpu(sb, *p)) {
X ubh_brelse (ind_ubh);
X return 1;
X }
X if (!ind_ubh) {
- *p = SWAB32(0);
+ *p = 0;


X return 0;
X }
X

X indirect_block = (DIRECT_BLOCK > offset) ? (DIRECT_BLOCK - offset) : 0;
X for (i = indirect_block; i < uspi->s_apb; i++) {
X ind = ubh_get_addr32 (ind_ubh, i);
- tmp = SWAB32(*ind);
+ tmp = fs32_to_cpu(sb, *ind);
X if (!tmp)
X continue;
X for (j = 0; j < uspi->s_fpb; j++) {
X bh = get_hash_table (sb->s_dev, tmp + j, uspi->s_fsize);
- if ((bh && DATA_BUFFER_USED(bh)) || tmp != SWAB32(*ind)) {
+ if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *ind)) {
X retry = 1;
X brelse (bh);
X goto next;
X }
X bforget (bh);
X }
- *ind = SWAB32(0);
+ *ind = 0;
X ubh_mark_buffer_dirty(ind_ubh);
X if (free_count == 0) {
X frag_to_free = tmp;
@@ -268,15 +264,15 @@
X ufs_free_blocks (inode, frag_to_free, free_count);
X }
X for (i = 0; i < uspi->s_apb; i++)
- if (SWAB32(*ubh_get_addr32(ind_ubh,i)))
+ if (*ubh_get_addr32(ind_ubh,i))
X break;
X if (i >= uspi->s_apb) {
X if (ubh_max_bcount(ind_ubh) != 1) {
X retry = 1;
X }
X else {
- tmp = SWAB32(*p);
- *p = SWAB32(0);
+ tmp = fs32_to_cpu(sb, *p);
+ *p = 0;
X inode->i_blocks -= uspi->s_nspb;
X mark_inode_dirty(inode);
X ufs_free_blocks (inode, tmp, uspi->s_fpb);
@@ -303,34 +299,32 @@
X unsigned i, tmp, dindirect_block;
X u32 * dind;
X int retry = 0;
- unsigned swab;
X
X UFSD(("ENTER\n"))
X
X sb = inode->i_sb;
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;
X
X dindirect_block = (DIRECT_BLOCK > offset)
X ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0;
X retry = 0;
X
- tmp = SWAB32(*p);
+ tmp = fs32_to_cpu(sb, *p);
X if (!tmp)
X return 0;
X dind_bh = ubh_bread (inode->i_dev, tmp, uspi->s_bsize);
- if (tmp != SWAB32(*p)) {
+ if (tmp != fs32_to_cpu(sb, *p)) {
X ubh_brelse (dind_bh);
X return 1;
X }
X if (!dind_bh) {
- *p = SWAB32(0);
+ *p = 0;


X return 0;
X }
X

X for (i = dindirect_block ; i < uspi->s_apb ; i++) {
X dind = ubh_get_addr32 (dind_bh, i);
- tmp = SWAB32(*dind);
+ tmp = fs32_to_cpu(sb, *dind);
X if (!tmp)
X continue;
X retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind);
@@ -338,14 +332,14 @@
X }
X
X for (i = 0; i < uspi->s_apb; i++)
- if (SWAB32(*ubh_get_addr32 (dind_bh, i)))
+ if (*ubh_get_addr32 (dind_bh, i))
X break;
X if (i >= uspi->s_apb) {
X if (ubh_max_bcount(dind_bh) != 1)
X retry = 1;
X else {
- tmp = SWAB32(*p);
- *p = SWAB32(0);
+ tmp = fs32_to_cpu(sb, *p);
+ *p = 0;
X inode->i_blocks -= uspi->s_nspb;
X mark_inode_dirty(inode);
X ufs_free_blocks (inode, tmp, uspi->s_fpb);
@@ -372,27 +366,25 @@
X unsigned tindirect_block, tmp, i;
X u32 * tind, * p;
X int retry;
- unsigned swab;
X
X UFSD(("ENTER\n"))
X
X sb = inode->i_sb;
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;
X retry = 0;
X
X tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb))
X ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0;
X p = inode->u.ufs_i.i_u1.i_data + UFS_TIND_BLOCK;
- if (!(tmp = SWAB32(*p)))
+ if (!(tmp = fs32_to_cpu(sb, *p)))
X return 0;
X tind_bh = ubh_bread (sb->s_dev, tmp, uspi->s_bsize);
- if (tmp != SWAB32(*p)) {
+ if (tmp != fs32_to_cpu(sb, *p)) {
X ubh_brelse (tind_bh);
X return 1;
X }
X if (!tind_bh) {
- *p = SWAB32(0);
+ *p = 0;


X return 0;
X }
X

@@ -403,14 +395,14 @@
X ubh_mark_buffer_dirty(tind_bh);
X }
X for (i = 0; i < uspi->s_apb; i++)
- if (SWAB32(*ubh_get_addr32 (tind_bh, i)))
+ if (*ubh_get_addr32 (tind_bh, i))
X break;
X if (i >= uspi->s_apb) {
X if (ubh_max_bcount(tind_bh) != 1)
X retry = 1;
X else {
- tmp = SWAB32(*p);
- *p = SWAB32(0);
+ tmp = fs32_to_cpu(sb, *p);
+ *p = 0;
X inode->i_blocks -= uspi->s_nspb;
X mark_inode_dirty(inode);
X ufs_free_blocks (inode, tmp, uspi->s_fpb);
diff -u --recursive --new-file v2.4.14/linux/fs/ufs/util.h linux/fs/ufs/util.h
--- v2.4.14/linux/fs/ufs/util.h Sun Sep 23 11:41:01 2001
+++ linux/fs/ufs/util.h Mon Nov 19 15:25:45 2001
@@ -26,180 +26,203 @@
X /*
X * macros used for accesing structures
X */
-#define ufs_get_fs_state(usb1,usb3) _ufs_get_fs_state_(usb1,usb3,flags,swab)
-static inline __s32 _ufs_get_fs_state_(struct ufs_super_block_first * usb1,
- struct ufs_super_block_third * usb3, unsigned flags, unsigned swab)
-{
- switch (flags & UFS_ST_MASK) {
- case UFS_ST_SUN:
- return SWAB32((usb3)->fs_u2.fs_sun.fs_state);
- case UFS_ST_SUNx86:
- return SWAB32((usb1)->fs_u1.fs_sunx86.fs_state);
- case UFS_ST_44BSD:
- default:
- return SWAB32((usb3)->fs_u2.fs_44.fs_state);
+static inline s32
+ufs_get_fs_state(struct super_block *sb, struct ufs_super_block_first *usb1,
+ struct ufs_super_block_third *usb3)
+{
+ switch (sb->u.ufs_sb.s_flags & UFS_ST_MASK) {
+ case UFS_ST_SUN:
+ return fs32_to_cpu(sb, usb3->fs_u2.fs_sun.fs_state);
+ case UFS_ST_SUNx86:
+ return fs32_to_cpu(sb, usb1->fs_u1.fs_sunx86.fs_state);
+ case UFS_ST_44BSD:
+ default:
+ return fs32_to_cpu(sb, usb3->fs_u2.fs_44.fs_state);
X }
X }
X
-#define ufs_set_fs_state(usb1,usb3,value) _ufs_set_fs_state_(usb1,usb3,value,flags,swab)
-static inline void _ufs_set_fs_state_(struct ufs_super_block_first * usb1,
- struct ufs_super_block_third * usb3, __s32 value, unsigned flags, unsigned swab)
-{
- switch (flags & UFS_ST_MASK) {
- case UFS_ST_SUN:
- (usb3)->fs_u2.fs_sun.fs_state = SWAB32(value);
- break;
- case UFS_ST_SUNx86:
- (usb1)->fs_u1.fs_sunx86.fs_state = SWAB32(value);
- break;
- case UFS_ST_44BSD:
- (usb3)->fs_u2.fs_44.fs_state = SWAB32(value);
- break;
+static inline void
+ufs_set_fs_state(struct super_block *sb, struct ufs_super_block_first *usb1,
+ struct ufs_super_block_third *usb3, s32 value)
+{
+ switch (sb->u.ufs_sb.s_flags & UFS_ST_MASK) {
+ case UFS_ST_SUN:
+ usb3->fs_u2.fs_sun.fs_state = cpu_to_fs32(sb, value);
+ break;
+ case UFS_ST_SUNx86:
+ usb1->fs_u1.fs_sunx86.fs_state = cpu_to_fs32(sb, value);
+ break;
+ case UFS_ST_44BSD:
+ usb3->fs_u2.fs_44.fs_state = cpu_to_fs32(sb, value);


+ break;
X }
X }
X

-#define ufs_get_fs_npsect(usb1,usb3) _ufs_get_fs_npsect_(usb1,usb3,flags,swab)
-static inline __u32 _ufs_get_fs_npsect_(struct ufs_super_block_first * usb1,
- struct ufs_super_block_third * usb3, unsigned flags, unsigned swab)
+static inline u32
+ufs_get_fs_npsect(struct super_block *sb, struct ufs_super_block_first *usb1,
+ struct ufs_super_block_third *usb3)
X {
- if ((flags & UFS_ST_MASK) == UFS_ST_SUNx86)
- return SWAB32((usb3)->fs_u2.fs_sunx86.fs_npsect);
+ if ((sb->u.ufs_sb.s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
+ return fs32_to_cpu(sb, usb3->fs_u2.fs_sunx86.fs_npsect);
X else
- return SWAB32((usb1)->fs_u1.fs_sun.fs_npsect);
+ return fs32_to_cpu(sb, usb1->fs_u1.fs_sun.fs_npsect);
X }
X
-#define ufs_get_fs_qbmask(usb3) _ufs_get_fs_qbmask_(usb3,flags,swab)
-static inline __u64 _ufs_get_fs_qbmask_(struct ufs_super_block_third * usb3,
- unsigned flags, unsigned swab)
-{
- __u64 tmp;
- switch (flags & UFS_ST_MASK) {
- case UFS_ST_SUN:
- ((u32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qbmask[0];
- ((u32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qbmask[1];
- break;
- case UFS_ST_SUNx86:
- ((u32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qbmask[0];
- ((u32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qbmask[1];
- break;
- case UFS_ST_44BSD:
- ((u32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qbmask[0];
- ((u32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qbmask[1];
- break;
- }
- return SWAB64(tmp);
-}
+static inline u64
+ufs_get_fs_qbmask(struct super_block *sb, struct ufs_super_block_third *usb3)
+{
+ u64 tmp;
X
-#define ufs_get_fs_qfmask(usb3) _ufs_get_fs_qfmask_(usb3,flags,swab)
-static inline __u64 _ufs_get_fs_qfmask_(struct ufs_super_block_third * usb3,
- unsigned flags, unsigned swab)
-{
- __u64 tmp;
- switch (flags & UFS_ST_MASK) {
- case UFS_ST_SUN:
- ((u32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qfmask[0];
- ((u32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qfmask[1];
- break;
- case UFS_ST_SUNx86:
- ((u32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qfmask[0];
- ((u32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qfmask[1];
- break;
- case UFS_ST_44BSD:
- ((u32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qfmask[0];
- ((u32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qfmask[1];
- break;
+ switch (sb->u.ufs_sb.s_flags & UFS_ST_MASK) {
+ case UFS_ST_SUN:
+ ((u32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qbmask[0];
+ ((u32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qbmask[1];
+ break;
+ case UFS_ST_SUNx86:
+ ((u32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qbmask[0];
+ ((u32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qbmask[1];
+ break;
+ case UFS_ST_44BSD:
+ ((u32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qbmask[0];
+ ((u32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qbmask[1];
+ break;
X }
- return SWAB64(tmp);
-}
X
-#define ufs_get_de_namlen(de) \
- (((flags & UFS_DE_MASK) == UFS_DE_OLD) \
- ? SWAB16(de->d_u.d_namlen) \
- : de->d_u.d_44.d_namlen)
-
-#define ufs_set_de_namlen(de,value) \
- (((flags & UFS_DE_MASK) == UFS_DE_OLD) \
- ? (de->d_u.d_namlen = SWAB16(value)) \
- : (de->d_u.d_44.d_namlen = value))
-
-#define ufs_set_de_type(de,mode) _ufs_set_de_type_(de,mode,flags,swab)
-static inline void _ufs_set_de_type_(struct ufs_dir_entry * de, int mode,
- unsigned flags, unsigned swab)
-{
- if ((flags & UFS_DE_MASK) == UFS_DE_44BSD) {
- switch (mode & S_IFMT) {
- case S_IFSOCK: de->d_u.d_44.d_type = DT_SOCK; break;
- case S_IFLNK: de->d_u.d_44.d_type = DT_LNK; break;
- case S_IFREG: de->d_u.d_44.d_type = DT_REG; break;
- case S_IFBLK: de->d_u.d_44.d_type = DT_BLK; break;
- case S_IFDIR: de->d_u.d_44.d_type = DT_DIR; break;
- case S_IFCHR: de->d_u.d_44.d_type = DT_CHR; break;
- case S_IFIFO: de->d_u.d_44.d_type = DT_FIFO; break;
- default: de->d_u.d_44.d_type = DT_UNKNOWN;
- }
- }
+ return fs64_to_cpu(sb, tmp);
X }
X
-#define ufs_get_inode_uid(inode) _ufs_get_inode_uid_(inode,flags,swab)
-static inline __u32 _ufs_get_inode_uid_(struct ufs_inode * inode,
- unsigned flags, unsigned swab)
-{
- switch (flags & UFS_UID_MASK) {
- case UFS_UID_EFT:
- return SWAB32(inode->ui_u3.ui_sun.ui_uid);
- case UFS_UID_44BSD:
- return SWAB32(inode->ui_u3.ui_44.ui_uid);
- default:
- return SWAB16(inode->ui_u1.oldids.ui_suid);
+static inline u64
+ufs_get_fs_qfmask(struct super_block *sb, struct ufs_super_block_third *usb3)
+{
+ u64 tmp;
+
+ switch (sb->u.ufs_sb.s_flags & UFS_ST_MASK) {
+ case UFS_ST_SUN:
+ ((u32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qfmask[0];
+ ((u32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qfmask[1];
+ break;
+ case UFS_ST_SUNx86:
+ ((u32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qfmask[0];
+ ((u32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qfmask[1];
+ break;
+ case UFS_ST_44BSD:
+ ((u32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qfmask[0];
+ ((u32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qfmask[1];
+ break;
X }
+
+ return fs64_to_cpu(sb, tmp);
X }
X
-#define ufs_set_inode_uid(inode,value) _ufs_set_inode_uid_(inode,value,flags,swab)
-static inline void _ufs_set_inode_uid_(struct ufs_inode * inode, __u32 value,
- unsigned flags, unsigned swab)
-{
- inode->ui_u1.oldids.ui_suid = SWAB16(value);
- switch (flags & UFS_UID_MASK) {
- case UFS_UID_EFT:
- inode->ui_u3.ui_sun.ui_uid = SWAB32(value);
- break;
- case UFS_UID_44BSD:
- inode->ui_u3.ui_44.ui_uid = SWAB32(value);
- break;
- }
+static inline u16
+ufs_get_de_namlen(struct super_block *sb, struct ufs_dir_entry *de)
+{
+ if ((sb->u.ufs_sb.s_flags & UFS_DE_MASK) == UFS_DE_OLD)
+ return fs16_to_cpu(sb, de->d_u.d_namlen);
+ else
+ return de->d_u.d_44.d_namlen; /* XXX this seems wrong */
X }
X
-#define ufs_get_inode_gid(inode) _ufs_get_inode_gid_(inode,flags,swab)
-static inline __u32 _ufs_get_inode_gid_(struct ufs_inode * inode,
- unsigned flags, unsigned swab)
-{
- switch (flags & UFS_UID_MASK) {
- case UFS_UID_EFT:
- return SWAB32(inode->ui_u3.ui_sun.ui_gid);
- case UFS_UID_44BSD:
- return SWAB32(inode->ui_u3.ui_44.ui_gid);
- default:
- return SWAB16(inode->ui_u1.oldids.ui_sgid);
- }
+static inline void
+ufs_set_de_namlen(struct super_block *sb, struct ufs_dir_entry *de, u16 value)
+{
+ if ((sb->u.ufs_sb.s_flags & UFS_DE_MASK) == UFS_DE_OLD)
+ de->d_u.d_namlen = cpu_to_fs16(sb, value);
+ else
+ de->d_u.d_44.d_namlen = value; /* XXX this seems wrong */
X }
X
-#define ufs_set_inode_gid(inode,value) _ufs_set_inode_gid_(inode,value,flags,swab)
-static inline void _ufs_set_inode_gid_(struct ufs_inode * inode, __u32 value,
- unsigned flags, unsigned swab)
-{
- inode->ui_u1.oldids.ui_sgid = SWAB16(value);
- switch (flags & UFS_UID_MASK) {
- case UFS_UID_EFT:
- inode->ui_u3.ui_sun.ui_gid = SWAB32(value);
- break;
- case UFS_UID_44BSD:
- inode->ui_u3.ui_44.ui_gid = SWAB32(value);
- break;
+static inline void
+ufs_set_de_type(struct super_block *sb, struct ufs_dir_entry *de, int mode)
+{
+ if ((sb->u.ufs_sb.s_flags & UFS_DE_MASK) != UFS_DE_44BSD)
+ return;
+
+ /*
+ * TODO turn this into a table lookup
+ */


+ switch (mode & S_IFMT) {

+ case S_IFSOCK:
+ de->d_u.d_44.d_type = DT_SOCK;
+ break;
+ case S_IFLNK:
+ de->d_u.d_44.d_type = DT_LNK;


+ break;
+ case S_IFREG:

+ de->d_u.d_44.d_type = DT_REG;
+ break;
+ case S_IFBLK:
+ de->d_u.d_44.d_type = DT_BLK;


+ break;
+ case S_IFDIR:

+ de->d_u.d_44.d_type = DT_DIR;


+ break;
+ case S_IFCHR:

+ de->d_u.d_44.d_type = DT_CHR;
+ break;
+ case S_IFIFO:
+ de->d_u.d_44.d_type = DT_FIFO;
+ break;
+ default:
+ de->d_u.d_44.d_type = DT_UNKNOWN;
+ }
+}
+
+static inline u32
+ufs_get_inode_uid(struct super_block *sb, struct ufs_inode *inode)
+{
+ switch (sb->u.ufs_sb.s_flags & UFS_UID_MASK) {
+ case UFS_UID_EFT:
+ return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_uid);
+ case UFS_UID_44BSD:
+ return fs32_to_cpu(sb, inode->ui_u3.ui_44.ui_uid);
+ default:
+ return fs16_to_cpu(sb, inode->ui_u1.oldids.ui_suid);
+ }
+}
+
+static inline void
+ufs_set_inode_uid(struct super_block *sb, struct ufs_inode *inode, u32 value)
+{
+ switch (sb->u.ufs_sb.s_flags & UFS_UID_MASK) {
+ case UFS_UID_EFT:
+ inode->ui_u3.ui_sun.ui_uid = cpu_to_fs32(sb, value);
+ break;
+ case UFS_UID_44BSD:
+ inode->ui_u3.ui_44.ui_uid = cpu_to_fs32(sb, value);
+ break;
+ }
+ inode->ui_u1.oldids.ui_suid = cpu_to_fs16(sb, value);
+}
+
+static inline u32
+ufs_get_inode_gid(struct super_block *sb, struct ufs_inode *inode)
+{
+ switch (sb->u.ufs_sb.s_flags & UFS_UID_MASK) {
+ case UFS_UID_EFT:
+ return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_gid);
+ case UFS_UID_44BSD:
+ return fs32_to_cpu(sb, inode->ui_u3.ui_44.ui_gid);
+ default:
+ return fs16_to_cpu(sb, inode->ui_u1.oldids.ui_sgid);
+ }
+}
+
+static inline void
+ufs_set_inode_gid(struct super_block *sb, struct ufs_inode *inode, u32 value)
+{
+ switch (sb->u.ufs_sb.s_flags & UFS_UID_MASK) {
+ case UFS_UID_EFT:
+ inode->ui_u3.ui_sun.ui_gid = cpu_to_fs32(sb, value);
+ break;
+ case UFS_UID_44BSD:
+ inode->ui_u3.ui_44.ui_gid = cpu_to_fs32(sb, value);
+ break;
X }
+ inode->ui_u1.oldids.ui_sgid = cpu_to_fs16(sb, value);
X }
X
X
-
X /*
X * These functions manipulate ufs buffers
X */
@@ -284,8 +307,8 @@
X * percentage to hold in reserve.
X */
X #define ufs_freespace(usb, percentreserved) \
- (ufs_blkstofrags(SWAB32((usb)->fs_cstotal.cs_nbfree)) + \
- SWAB32((usb)->fs_cstotal.cs_nffree) - (uspi->s_dsize * (percentreserved) / 100))
+ (ufs_blkstofrags(fs32_to_cpu(sb, (usb)->fs_cstotal.cs_nbfree)) + \
+ fs32_to_cpu(sb, (usb)->fs_cstotal.cs_nffree) - (uspi->s_dsize * (percentreserved) / 100))
X
X /*
X * Macros to access cylinder group array structures
@@ -456,9 +479,7 @@
X {
X struct ufs_sb_private_info * uspi;
X unsigned fragsize, pos;
- unsigned swab;
X
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;
X
X fragsize = 0;
@@ -467,12 +488,12 @@
X fragsize++;
X }
X else if (fragsize > 0) {
- ADD_SWAB32(fraglist[fragsize], cnt);
+ fs32_add(sb, &fraglist[fragsize], cnt);
X fragsize = 0;
X }
X }
X if (fragsize > 0 && fragsize < uspi->s_fpb)
- ADD_SWAB32(fraglist[fragsize], cnt);
+ fs32_add(sb, &fraglist[fragsize], cnt);
X }
X
X #define ubh_scanc(ubh,begin,size,table,mask) _ubh_scanc_(uspi,ubh,begin,size,table,mask)
diff -u --recursive --new-file v2.4.14/linux/include/asm-alpha/core_apecs.h linux/include/asm-alpha/core_apecs.h
--- v2.4.14/linux/include/asm-alpha/core_apecs.h Tue Oct 9 17:06:53 2001
+++ linux/include/asm-alpha/core_apecs.h Fri Nov 9 13:45:35 2001
@@ -374,13 +374,13 @@
X #define vuip volatile unsigned int *
X #define vulp volatile unsigned long *
X
-__EXTERN_INLINE unsigned int apecs_inb(unsigned long addr)
+__EXTERN_INLINE u8 apecs_inb(unsigned long addr)
X {
X long result = *(vip) ((addr << 5) + APECS_IO + 0x00);
X return __kernel_extbl(result, addr & 3);
X }
X
-__EXTERN_INLINE void apecs_outb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void apecs_outb(u8 b, unsigned long addr)
X {
X unsigned long w;
X
@@ -389,13 +389,13 @@
X mb();
X }
X
-__EXTERN_INLINE unsigned int apecs_inw(unsigned long addr)
+__EXTERN_INLINE u16 apecs_inw(unsigned long addr)
X {
X long result = *(vip) ((addr << 5) + APECS_IO + 0x08);
X return __kernel_extwl(result, addr & 3);
X }
X
-__EXTERN_INLINE void apecs_outw(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void apecs_outw(u16 b, unsigned long addr)
X {
X unsigned long w;
X
@@ -404,12 +404,12 @@
X mb();
X }
X
-__EXTERN_INLINE unsigned int apecs_inl(unsigned long addr)
+__EXTERN_INLINE u32 apecs_inl(unsigned long addr)
X {
X return *(vuip) ((addr << 5) + APECS_IO + 0x18);
X }
X
-__EXTERN_INLINE void apecs_outl(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void apecs_outl(u32 b, unsigned long addr)
X {
X *(vuip) ((addr << 5) + APECS_IO + 0x18) = b;
X mb();
@@ -421,7 +421,7 @@
X * dense memory space, everything else through sparse space.
X */
X
-__EXTERN_INLINE unsigned long apecs_readb(unsigned long addr)
+__EXTERN_INLINE u8 apecs_readb(unsigned long addr)
X {
X unsigned long result, msb;
X
@@ -435,7 +435,7 @@
X return __kernel_extbl(result, addr & 3);
X }
X
-__EXTERN_INLINE unsigned long apecs_readw(unsigned long addr)
+__EXTERN_INLINE u16 apecs_readw(unsigned long addr)
X {
X unsigned long result, msb;
X
@@ -449,17 +449,17 @@
X return __kernel_extwl(result, addr & 3);
X }
X
-__EXTERN_INLINE unsigned long apecs_readl(unsigned long addr)
+__EXTERN_INLINE u32 apecs_readl(unsigned long addr)
X {
- return *(vuip)addr;
+ return (*(vuip)addr) & 0xffffffff;
X }
X
-__EXTERN_INLINE unsigned long apecs_readq(unsigned long addr)
+__EXTERN_INLINE u64 apecs_readq(unsigned long addr)
X {
X return *(vulp)addr;
X }
X
-__EXTERN_INLINE void apecs_writeb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void apecs_writeb(u8 b, unsigned long addr)
X {
X unsigned long msb;
X
@@ -472,7 +472,7 @@
X *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x00) = b * 0x01010101;
X }
X
-__EXTERN_INLINE void apecs_writew(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void apecs_writew(u16 b, unsigned long addr)
X {
X unsigned long msb;
X
@@ -485,12 +485,12 @@
X *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x08) = b * 0x00010001;
X }
X
-__EXTERN_INLINE void apecs_writel(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void apecs_writel(u32 b, unsigned long addr)
X {
X *(vuip)addr = b;
X }
X
-__EXTERN_INLINE void apecs_writeq(unsigned long b, unsigned long addr)
+__EXTERN_INLINE void apecs_writeq(u64 b, unsigned long addr)
X {
X *(vulp)addr = b;
X }
diff -u --recursive --new-file v2.4.14/linux/include/asm-alpha/core_cia.h linux/include/asm-alpha/core_cia.h
--- v2.4.14/linux/include/asm-alpha/core_cia.h Tue Oct 23 22:48:53 2001
+++ linux/include/asm-alpha/core_cia.h Fri Nov 9 13:45:35 2001
@@ -307,46 +307,46 @@
X #define vuip volatile unsigned int *
X #define vulp volatile unsigned long *
X
-__EXTERN_INLINE unsigned int cia_inb(unsigned long addr)
+__EXTERN_INLINE u8 cia_inb(unsigned long addr)
X {
X long result;
X result = *(vip) ((addr << 5) + CIA_IO + 0x00);
X return __kernel_extbl(result, addr & 3);
X }
X
-__EXTERN_INLINE void cia_outb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void cia_outb(u8 b, unsigned long addr)
X {
X unsigned long w = __kernel_insbl(b, addr & 3);
X *(vuip) ((addr << 5) + CIA_IO + 0x00) = w;
X mb();
X }
X
-__EXTERN_INLINE unsigned int cia_inw(unsigned long addr)
+__EXTERN_INLINE u16 cia_inw(unsigned long addr)
X {
X long result;
X result = *(vip) ((addr << 5) + CIA_IO + 0x08);
X return __kernel_extwl(result, addr & 3);
X }
X
-__EXTERN_INLINE void cia_outw(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void cia_outw(u16 b, unsigned long addr)
X {
X unsigned long w = __kernel_inswl(b, addr & 3);
X *(vuip) ((addr << 5) + CIA_IO + 0x08) = w;
X mb();
X }
X
-__EXTERN_INLINE unsigned int cia_inl(unsigned long addr)
+__EXTERN_INLINE u32 cia_inl(unsigned long addr)
X {
X return *(vuip) ((addr << 5) + CIA_IO + 0x18);
X }
X
-__EXTERN_INLINE void cia_outl(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void cia_outl(u32 b, unsigned long addr)
X {
X *(vuip) ((addr << 5) + CIA_IO + 0x18) = b;
X mb();
X }
X
-__EXTERN_INLINE unsigned int cia_bwx_inb(unsigned long addr)
+__EXTERN_INLINE u8 cia_bwx_inb(unsigned long addr)
X {
X /* ??? I wish I could get rid of this. But there's no ioremap
X equivalent for I/O space. PCI I/O can be forced into the
@@ -356,29 +356,29 @@
X return __kernel_ldbu(*(vucp)(addr+CIA_BW_IO));
X }
X
-__EXTERN_INLINE void cia_bwx_outb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void cia_bwx_outb(u8 b, unsigned long addr)
X {
X __kernel_stb(b, *(vucp)(addr+CIA_BW_IO));
X mb();
X }
X
-__EXTERN_INLINE unsigned int cia_bwx_inw(unsigned long addr)
+__EXTERN_INLINE u16 cia_bwx_inw(unsigned long addr)
X {
X return __kernel_ldwu(*(vusp)(addr+CIA_BW_IO));
X }
X
-__EXTERN_INLINE void cia_bwx_outw(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void cia_bwx_outw(u16 b, unsigned long addr)
X {
X __kernel_stw(b, *(vusp)(addr+CIA_BW_IO));
X mb();
X }
X
-__EXTERN_INLINE unsigned int cia_bwx_inl(unsigned long addr)
+__EXTERN_INLINE u32 cia_bwx_inl(unsigned long addr)
X {
X return *(vuip)(addr+CIA_BW_IO);
X }
X
-__EXTERN_INLINE void cia_bwx_outl(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void cia_bwx_outl(u32 b, unsigned long addr)
X {
X *(vuip)(addr+CIA_BW_IO) = b;
X mb();
@@ -417,7 +417,7 @@


X *
X */
X

-__EXTERN_INLINE unsigned long cia_readb(unsigned long addr)
+__EXTERN_INLINE u8 cia_readb(unsigned long addr)
X {
X unsigned long result;
X
@@ -426,7 +426,7 @@
X return __kernel_extbl(result, addr & 3);
X }
X
-__EXTERN_INLINE unsigned long cia_readw(unsigned long addr)
+__EXTERN_INLINE u16 cia_readw(unsigned long addr)
X {
X unsigned long result;
X
@@ -435,7 +435,7 @@
X return __kernel_extwl(result, addr & 3);
X }
X
-__EXTERN_INLINE void cia_writeb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void cia_writeb(u8 b, unsigned long addr)
X {
X unsigned long w;
X
@@ -444,7 +444,7 @@
X *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x00) = w;
X }
X
-__EXTERN_INLINE void cia_writew(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void cia_writew(u16 b, unsigned long addr)
X {
X unsigned long w;
X
@@ -453,22 +453,22 @@
X *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x08) = w;
X }
X
-__EXTERN_INLINE unsigned long cia_readl(unsigned long addr)
+__EXTERN_INLINE u32 cia_readl(unsigned long addr)
X {
X return *(vuip)addr;
X }
X
-__EXTERN_INLINE unsigned long cia_readq(unsigned long addr)
+__EXTERN_INLINE u64 cia_readq(unsigned long addr)
X {
X return *(vulp)addr;
X }
X
-__EXTERN_INLINE void cia_writel(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void cia_writel(u32 b, unsigned long addr)
X {
X *(vuip)addr = b;
X }
X
-__EXTERN_INLINE void cia_writeq(unsigned long b, unsigned long addr)
+__EXTERN_INLINE void cia_writeq(u64 b, unsigned long addr)
X {
X *(vulp)addr = b;
X }
@@ -485,42 +485,42 @@
X return;
X }
X
-__EXTERN_INLINE unsigned long cia_bwx_readb(unsigned long addr)
+__EXTERN_INLINE u8 cia_bwx_readb(unsigned long addr)
X {
X return __kernel_ldbu(*(vucp)addr);
X }
X
-__EXTERN_INLINE unsigned long cia_bwx_readw(unsigned long addr)
+__EXTERN_INLINE u16 cia_bwx_readw(unsigned long addr)
X {
X return __kernel_ldwu(*(vusp)addr);
X }
X
-__EXTERN_INLINE unsigned long cia_bwx_readl(unsigned long addr)
+__EXTERN_INLINE u32 cia_bwx_readl(unsigned long addr)
X {
X return *(vuip)addr;
X }
X
-__EXTERN_INLINE unsigned long cia_bwx_readq(unsigned long addr)
+__EXTERN_INLINE u64 cia_bwx_readq(unsigned long addr)
X {
X return *(vulp)addr;
X }
X
-__EXTERN_INLINE void cia_bwx_writeb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void cia_bwx_writeb(u8 b, unsigned long addr)
X {
X __kernel_stb(b, *(vucp)addr);
X }
X
-__EXTERN_INLINE void cia_bwx_writew(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void cia_bwx_writew(u16 b, unsigned long addr)
X {
X __kernel_stw(b, *(vusp)addr);
X }
X
-__EXTERN_INLINE void cia_bwx_writel(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void cia_bwx_writel(u32 b, unsigned long addr)
X {
X *(vuip)addr = b;
X }
X
-__EXTERN_INLINE void cia_bwx_writeq(unsigned long b, unsigned long addr)
+__EXTERN_INLINE void cia_bwx_writeq(u64 b, unsigned long addr)
X {
X *(vulp)addr = b;
X }
diff -u --recursive --new-file v2.4.14/linux/include/asm-alpha/core_irongate.h linux/include/asm-alpha/core_irongate.h
--- v2.4.14/linux/include/asm-alpha/core_irongate.h Sun Sep 23 11:41:01 2001
+++ linux/include/asm-alpha/core_irongate.h Fri Nov 9 13:45:35 2001
@@ -190,34 +190,34 @@
X #define vuip volatile unsigned int *
X #define vulp volatile unsigned long *
X
-__EXTERN_INLINE unsigned int irongate_inb(unsigned long addr)
+__EXTERN_INLINE u8 irongate_inb(unsigned long addr)
X {
X return __kernel_ldbu(*(vucp)(addr + IRONGATE_IO));
X }
X
-__EXTERN_INLINE void irongate_outb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void irongate_outb(u8 b, unsigned long addr)
X {
X __kernel_stb(b, *(vucp)(addr + IRONGATE_IO));
X mb();
X }
X
-__EXTERN_INLINE unsigned int irongate_inw(unsigned long addr)
+__EXTERN_INLINE u16 irongate_inw(unsigned long addr)
X {
X return __kernel_ldwu(*(vusp)(addr + IRONGATE_IO));
X }
X
-__EXTERN_INLINE void irongate_outw(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void irongate_outw(u16 b, unsigned long addr)
X {
X __kernel_stw(b, *(vusp)(addr + IRONGATE_IO));
X mb();
X }
X
-__EXTERN_INLINE unsigned int irongate_inl(unsigned long addr)
+__EXTERN_INLINE u32 irongate_inl(unsigned long addr)
X {
X return *(vuip)(addr + IRONGATE_IO);
X }
X
-__EXTERN_INLINE void irongate_outl(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void irongate_outl(u32 b, unsigned long addr)
X {
X *(vuip)(addr + IRONGATE_IO) = b;
X mb();
@@ -227,42 +227,42 @@
X * Memory functions. All accesses are done through linear space.
X */
X
-__EXTERN_INLINE unsigned long irongate_readb(unsigned long addr)
+__EXTERN_INLINE u8 irongate_readb(unsigned long addr)
X {
X return __kernel_ldbu(*(vucp)addr);
X }
X
-__EXTERN_INLINE unsigned long irongate_readw(unsigned long addr)
+__EXTERN_INLINE u16 irongate_readw(unsigned long addr)
X {
X return __kernel_ldwu(*(vusp)addr);
X }
X
-__EXTERN_INLINE unsigned long irongate_readl(unsigned long addr)
+__EXTERN_INLINE u32 irongate_readl(unsigned long addr)
X {
- return *(vuip)addr;
+ return (*(vuip)addr) & 0xffffffff;
X }
X
-__EXTERN_INLINE unsigned long irongate_readq(unsigned long addr)
+__EXTERN_INLINE u64 irongate_readq(unsigned long addr)
X {
X return *(vulp)addr;
X }
X
-__EXTERN_INLINE void irongate_writeb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void irongate_writeb(u8 b, unsigned long addr)
X {
X __kernel_stb(b, *(vucp)addr);
X }
X
-__EXTERN_INLINE void irongate_writew(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void irongate_writew(u16 b, unsigned long addr)
X {
X __kernel_stw(b, *(vusp)addr);
X }
X
-__EXTERN_INLINE void irongate_writel(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void irongate_writel(u32 b, unsigned long addr)
X {
X *(vuip)addr = b;
X }
X
-__EXTERN_INLINE void irongate_writeq(unsigned long b, unsigned long addr)
+__EXTERN_INLINE void irongate_writeq(u64 b, unsigned long addr)
X {
X *(vulp)addr = b;
X }
diff -u --recursive --new-file v2.4.14/linux/include/asm-alpha/core_lca.h linux/include/asm-alpha/core_lca.h
--- v2.4.14/linux/include/asm-alpha/core_lca.h Sun Sep 23 11:41:01 2001
+++ linux/include/asm-alpha/core_lca.h Fri Nov 9 13:45:35 2001
@@ -219,13 +219,13 @@
X #define vuip volatile unsigned int *
X #define vulp volatile unsigned long *
X
-__EXTERN_INLINE unsigned int lca_inb(unsigned long addr)
+__EXTERN_INLINE u8 lca_inb(unsigned long addr)
X {
X long result = *(vip) ((addr << 5) + LCA_IO + 0x00);
X return __kernel_extbl(result, addr & 3);
X }
X
-__EXTERN_INLINE void lca_outb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void lca_outb(u8 b, unsigned long addr)
X {
X unsigned long w;
X
@@ -234,13 +234,13 @@
X mb();
X }
X
-__EXTERN_INLINE unsigned int lca_inw(unsigned long addr)
+__EXTERN_INLINE u16 lca_inw(unsigned long addr)
X {
X long result = *(vip) ((addr << 5) + LCA_IO + 0x08);
X return __kernel_extwl(result, addr & 3);
X }
X
-__EXTERN_INLINE void lca_outw(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void lca_outw(u16 b, unsigned long addr)
X {
X unsigned long w;
X
@@ -249,12 +249,12 @@
X mb();
X }
X
-__EXTERN_INLINE unsigned int lca_inl(unsigned long addr)
+__EXTERN_INLINE u32 lca_inl(unsigned long addr)
X {
X return *(vuip) ((addr << 5) + LCA_IO + 0x18);
X }
X
-__EXTERN_INLINE void lca_outl(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void lca_outl(u32 b, unsigned long addr)
X {
X *(vuip) ((addr << 5) + LCA_IO + 0x18) = b;
X mb();
@@ -266,7 +266,7 @@
X * dense memory space, everything else through sparse space.
X */
X
-__EXTERN_INLINE unsigned long lca_readb(unsigned long addr)
+__EXTERN_INLINE u8 lca_readb(unsigned long addr)
X {
X unsigned long result, msb;
X
@@ -280,7 +280,7 @@
X return __kernel_extbl(result, addr & 3);
X }
X
-__EXTERN_INLINE unsigned long lca_readw(unsigned long addr)
+__EXTERN_INLINE u16 lca_readw(unsigned long addr)
X {
X unsigned long result, msb;
X
@@ -294,17 +294,17 @@
X return __kernel_extwl(result, addr & 3);
X }
X
-__EXTERN_INLINE unsigned long lca_readl(unsigned long addr)
+__EXTERN_INLINE u32 lca_readl(unsigned long addr)
X {
- return *(vuip)addr;
+ return (*(vuip)addr) & 0xffffffff;
X }
X
-__EXTERN_INLINE unsigned long lca_readq(unsigned long addr)
+__EXTERN_INLINE u64 lca_readq(unsigned long addr)
X {
X return *(vulp)addr;
X }
X
-__EXTERN_INLINE void lca_writeb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void lca_writeb(u8 b, unsigned long addr)
X {
X unsigned long msb;
X unsigned long w;
@@ -319,7 +319,7 @@
X *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x00) = w;
X }
X
-__EXTERN_INLINE void lca_writew(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void lca_writew(u16 b, unsigned long addr)
X {
X unsigned long msb;
X unsigned long w;
@@ -334,12 +334,12 @@
X *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x08) = w;
X }
X
-__EXTERN_INLINE void lca_writel(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void lca_writel(u32 b, unsigned long addr)
X {
X *(vuip)addr = b;
X }
X
-__EXTERN_INLINE void lca_writeq(unsigned long b, unsigned long addr)
+__EXTERN_INLINE void lca_writeq(u64 b, unsigned long addr)
X {
X *(vulp)addr = b;
X }
diff -u --recursive --new-file v2.4.14/linux/include/asm-alpha/core_mcpcia.h linux/include/asm-alpha/core_mcpcia.h
--- v2.4.14/linux/include/asm-alpha/core_mcpcia.h Tue Oct 23 22:48:53 2001
+++ linux/include/asm-alpha/core_mcpcia.h Fri Nov 9 13:45:35 2001
@@ -217,7 +217,7 @@
X #define vuip volatile unsigned int *
X #define vulp volatile unsigned long *
X
-__EXTERN_INLINE unsigned int mcpcia_inb(unsigned long in_addr)
+__EXTERN_INLINE u8 mcpcia_inb(unsigned long in_addr)
X {
X unsigned long addr, hose, result;
X
@@ -234,7 +234,7 @@
X return __kernel_extbl(result, addr & 3);
X }
X
-__EXTERN_INLINE void mcpcia_outb(unsigned char b, unsigned long in_addr)
+__EXTERN_INLINE void mcpcia_outb(u8 b, unsigned long in_addr)
X {
X unsigned long addr, hose, w;
X
@@ -247,7 +247,7 @@
X mb();
X }
X
-__EXTERN_INLINE unsigned int mcpcia_inw(unsigned long in_addr)
+__EXTERN_INLINE u16 mcpcia_inw(unsigned long in_addr)
X {
X unsigned long addr, hose, result;
X
@@ -259,7 +259,7 @@
X return __kernel_extwl(result, addr & 3);
X }
X
-__EXTERN_INLINE void mcpcia_outw(unsigned short b, unsigned long in_addr)
+__EXTERN_INLINE void mcpcia_outw(u16 b, unsigned long in_addr)
X {
X unsigned long addr, hose, w;
X
@@ -272,7 +272,7 @@
X mb();
X }
X
-__EXTERN_INLINE unsigned int mcpcia_inl(unsigned long in_addr)
+__EXTERN_INLINE u32 mcpcia_inl(unsigned long in_addr)
X {
X unsigned long addr, hose;
X
@@ -283,7 +283,7 @@
X return *(vuip) ((addr << 5) + hose + 0x18);
X }
X
-__EXTERN_INLINE void mcpcia_outl(unsigned int b, unsigned long in_addr)
+__EXTERN_INLINE void mcpcia_outl(u32 b, unsigned long in_addr)
X {
X unsigned long addr, hose;
X
@@ -345,7 +345,7 @@
X return addr >= MCPCIA_SPARSE(0);
X }
X
-__EXTERN_INLINE unsigned long mcpcia_readb(unsigned long in_addr)
+__EXTERN_INLINE u8 mcpcia_readb(unsigned long in_addr)
X {
X unsigned long addr = in_addr & 0xffffffffUL;
X unsigned long hose = in_addr & ~0xffffffffUL;
@@ -364,7 +364,7 @@
X return __kernel_extbl(result, addr & 3);
X }
X
-__EXTERN_INLINE unsigned long mcpcia_readw(unsigned long in_addr)
+__EXTERN_INLINE u16 mcpcia_readw(unsigned long in_addr)
X {
X unsigned long addr = in_addr & 0xffffffffUL;
X unsigned long hose = in_addr & ~0xffffffffUL;
@@ -383,7 +383,7 @@
X return __kernel_extwl(result, addr & 3);
X }
X
-__EXTERN_INLINE void mcpcia_writeb(unsigned char b, unsigned long in_addr)
+__EXTERN_INLINE void mcpcia_writeb(u8 b, unsigned long in_addr)
X {
X unsigned long addr = in_addr & 0xffffffffUL;
X unsigned long hose = in_addr & ~0xffffffffUL;
@@ -401,7 +401,7 @@
X *(vuip) ((addr << 5) + hose + 0x00) = w;
X }
X
-__EXTERN_INLINE void mcpcia_writew(unsigned short b, unsigned long in_addr)
+__EXTERN_INLINE void mcpcia_writew(u16 b, unsigned long in_addr)
X {
X unsigned long addr = in_addr & 0xffffffffUL;
X unsigned long hose = in_addr & ~0xffffffffUL;
@@ -419,22 +419,22 @@
X *(vuip) ((addr << 5) + hose + 0x08) = w;
X }
X
-__EXTERN_INLINE unsigned long mcpcia_readl(unsigned long addr)
+__EXTERN_INLINE u32 mcpcia_readl(unsigned long addr)
X {
- return *(vuip)addr;
+ return (*(vuip)addr) & 0xffffffff;
X }
X
-__EXTERN_INLINE unsigned long mcpcia_readq(unsigned long addr)
+__EXTERN_INLINE u64 mcpcia_readq(unsigned long addr)
X {
X return *(vulp)addr;
X }
X
-__EXTERN_INLINE void mcpcia_writel(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void mcpcia_writel(u32 b, unsigned long addr)
X {
X *(vuip)addr = b;
X }
X
-__EXTERN_INLINE void mcpcia_writeq(unsigned long b, unsigned long addr)
+__EXTERN_INLINE void mcpcia_writeq(u64 b, unsigned long addr)
X {
X *(vulp)addr = b;
X }
diff -u --recursive --new-file v2.4.14/linux/include/asm-alpha/core_polaris.h linux/include/asm-alpha/core_polaris.h
--- v2.4.14/linux/include/asm-alpha/core_polaris.h Sun Sep 23 11:41:01 2001
+++ linux/include/asm-alpha/core_polaris.h Fri Nov 9 13:45:35 2001
@@ -68,7 +68,7 @@
X #define vuip volatile unsigned int *
X #define vulp volatile unsigned long *
X
-__EXTERN_INLINE unsigned int polaris_inb(unsigned long addr)
+__EXTERN_INLINE u8 polaris_inb(unsigned long addr)
X {
X /* ??? I wish I could get rid of this. But there's no ioremap
X equivalent for I/O space. PCI I/O can be forced into the
@@ -78,29 +78,29 @@
X return __kernel_ldbu(*(vucp)(addr + POLARIS_DENSE_IO_BASE));
X }
X
-__EXTERN_INLINE void polaris_outb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void polaris_outb(u8 b, unsigned long addr)
X {
X __kernel_stb(b, *(vucp)(addr + POLARIS_DENSE_IO_BASE));
X mb();
X }
X
-__EXTERN_INLINE unsigned int polaris_inw(unsigned long addr)
+__EXTERN_INLINE u16 polaris_inw(unsigned long addr)
X {
X return __kernel_ldwu(*(vusp)(addr + POLARIS_DENSE_IO_BASE));
X }
X
-__EXTERN_INLINE void polaris_outw(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void polaris_outw(u16 b, unsigned long addr)
X {
X __kernel_stw(b, *(vusp)(addr + POLARIS_DENSE_IO_BASE));
X mb();
X }
X
-__EXTERN_INLINE unsigned int polaris_inl(unsigned long addr)
+__EXTERN_INLINE u32 polaris_inl(unsigned long addr)
X {
X return *(vuip)(addr + POLARIS_DENSE_IO_BASE);
X }
X
-__EXTERN_INLINE void polaris_outl(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void polaris_outl(u32 b, unsigned long addr)
X {
X *(vuip)(addr + POLARIS_DENSE_IO_BASE) = b;
X mb();
@@ -113,42 +113,42 @@
X * We will only support DENSE access via BWX insns.
X */
X
-__EXTERN_INLINE unsigned long polaris_readb(unsigned long addr)
+__EXTERN_INLINE u8 polaris_readb(unsigned long addr)
X {
X return __kernel_ldbu(*(vucp)addr);
X }
X
-__EXTERN_INLINE unsigned long polaris_readw(unsigned long addr)
+__EXTERN_INLINE u16 polaris_readw(unsigned long addr)
X {
X return __kernel_ldwu(*(vusp)addr);
X }
X
-__EXTERN_INLINE unsigned long polaris_readl(unsigned long addr)
+__EXTERN_INLINE u32 polaris_readl(unsigned long addr)
X {
- return *(vuip)addr;
+ return (*(vuip)addr) & 0xffffffff;
X }
X
-__EXTERN_INLINE unsigned long polaris_readq(unsigned long addr)
+__EXTERN_INLINE u64 polaris_readq(unsigned long addr)
X {
X return *(vulp)addr;
X }
X
-__EXTERN_INLINE void polaris_writeb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void polaris_writeb(u8 b, unsigned long addr)
X {
X __kernel_stb(b, *(vucp)addr);
X }
X
-__EXTERN_INLINE void polaris_writew(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void polaris_writew(u16 b, unsigned long addr)
X {
X __kernel_stw(b, *(vusp)addr);
X }
X
-__EXTERN_INLINE void polaris_writel(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void polaris_writel(u32 b, unsigned long addr)
X {
X *(vuip)addr = b;
X }
X
-__EXTERN_INLINE void polaris_writeq(unsigned long b, unsigned long addr)
+__EXTERN_INLINE void polaris_writeq(u64 b, unsigned long addr)
X {
X *(vulp)addr = b;
X }
diff -u --recursive --new-file v2.4.14/linux/include/asm-alpha/core_t2.h linux/include/asm-alpha/core_t2.h
--- v2.4.14/linux/include/asm-alpha/core_t2.h Sun Sep 23 11:41:01 2001
+++ linux/include/asm-alpha/core_t2.h Fri Nov 9 13:45:35 2001
@@ -329,13 +329,13 @@
X #define vip volatile int *
X #define vuip volatile unsigned int *
X
-__EXTERN_INLINE unsigned int t2_inb(unsigned long addr)
+__EXTERN_INLINE u8 t2_inb(unsigned long addr)
X {
X long result = *(vip) ((addr << 5) + T2_IO + 0x00);
X return __kernel_extbl(result, addr & 3);
X }
X
-__EXTERN_INLINE void t2_outb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void t2_outb(u8 b, unsigned long addr)
X {
X unsigned long w;
X
@@ -344,13 +344,13 @@
X mb();
X }
X
-__EXTERN_INLINE unsigned int t2_inw(unsigned long addr)
+__EXTERN_INLINE u16 t2_inw(unsigned long addr)
X {
X long result = *(vip) ((addr << 5) + T2_IO + 0x08);
X return __kernel_extwl(result, addr & 3);
X }
X
-__EXTERN_INLINE void t2_outw(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void t2_outw(u16 b, unsigned long addr)
X {
X unsigned long w;
X
@@ -359,12 +359,12 @@
X mb();
X }
X
-__EXTERN_INLINE unsigned int t2_inl(unsigned long addr)
+__EXTERN_INLINE u32 t2_inl(unsigned long addr)
X {
X return *(vuip) ((addr << 5) + T2_IO + 0x18);
X }
X
-__EXTERN_INLINE void t2_outl(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void t2_outl(u32 b, unsigned long addr)
X {
X *(vuip) ((addr << 5) + T2_IO + 0x18) = b;
X mb();
@@ -402,7 +402,7 @@


X *
X */
X

-__EXTERN_INLINE unsigned long t2_readb(unsigned long addr)
+__EXTERN_INLINE u8 t2_readb(unsigned long addr)
X {
X unsigned long result, msb;
X
@@ -414,7 +414,7 @@
X return __kernel_extbl(result, addr & 3);
X }
X
-__EXTERN_INLINE unsigned long t2_readw(unsigned long addr)
+__EXTERN_INLINE u16 t2_readw(unsigned long addr)
X {
X unsigned long result, msb;
X
@@ -427,7 +427,7 @@
X }
X
X /* On SABLE with T2, we must use SPARSE memory even for 32-bit access. */
-__EXTERN_INLINE unsigned long t2_readl(unsigned long addr)
+__EXTERN_INLINE u32 t2_readl(unsigned long addr)
X {
X unsigned long msb;
X
@@ -438,7 +438,7 @@
X return *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18);
X }
X
-__EXTERN_INLINE unsigned long t2_readq(unsigned long addr)
+__EXTERN_INLINE u64 t2_readq(unsigned long addr)
X {
X unsigned long r0, r1, work, msb;
X
@@ -452,7 +452,7 @@
X return r1 << 32 | r0;
X }
X
-__EXTERN_INLINE void t2_writeb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void t2_writeb(u8 b, unsigned long addr)
X {
X unsigned long msb, w;
X
@@ -464,7 +464,7 @@
X *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) = w;
X }
X
-__EXTERN_INLINE void t2_writew(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void t2_writew(u16 b, unsigned long addr)
X {
X unsigned long msb, w;
X
@@ -477,7 +477,7 @@
X }
X
X /* On SABLE with T2, we must use SPARSE memory even for 32-bit access. */
-__EXTERN_INLINE void t2_writel(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void t2_writel(u32 b, unsigned long addr)
X {
X unsigned long msb;
X
@@ -488,7 +488,7 @@
X *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b;
X }
X
-__EXTERN_INLINE void t2_writeq(unsigned long b, unsigned long addr)
+__EXTERN_INLINE void t2_writeq(u64 b, unsigned long addr)
X {
X unsigned long msb, work;
X
diff -u --recursive --new-file v2.4.14/linux/include/asm-alpha/core_titan.h linux/include/asm-alpha/core_titan.h
--- v2.4.14/linux/include/asm-alpha/core_titan.h Tue Oct 23 22:48:53 2001
+++ linux/include/asm-alpha/core_titan.h Fri Nov 9 13:45:35 2001
@@ -379,7 +379,7 @@
X #define vuip volatile unsigned int *
X #define vulp volatile unsigned long *
X
-__EXTERN_INLINE unsigned int titan_inb(unsigned long addr)
+__EXTERN_INLINE u8 titan_inb(unsigned long addr)
X {
X /* ??? I wish I could get rid of this. But there's no ioremap
X equivalent for I/O space. PCI I/O can be forced into the
@@ -390,33 +390,33 @@
X return __kernel_ldbu(*(vucp)addr);
X }
X
-__EXTERN_INLINE void titan_outb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void titan_outb(u8 b, unsigned long addr)
X {
X addr += TITAN_IO_BIAS;
X __kernel_stb(b, *(vucp)addr);
X mb();
X }
X
-__EXTERN_INLINE unsigned int titan_inw(unsigned long addr)
+__EXTERN_INLINE u16 titan_inw(unsigned long addr)
X {
X addr += TITAN_IO_BIAS;
X return __kernel_ldwu(*(vusp)addr);
X }
X
-__EXTERN_INLINE void titan_outw(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void titan_outw(u16 b, unsigned long addr)
X {
X addr += TITAN_IO_BIAS;
X __kernel_stw(b, *(vusp)addr);
X mb();
X }
X
-__EXTERN_INLINE unsigned int titan_inl(unsigned long addr)
+__EXTERN_INLINE u32 titan_inl(unsigned long addr)
X {
X addr += TITAN_IO_BIAS;
X return *(vuip)addr;
X }
X
-__EXTERN_INLINE void titan_outl(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void titan_outl(u32 b, unsigned long addr)
X {
X addr += TITAN_IO_BIAS;
X *(vuip)addr = b;
@@ -444,42 +444,42 @@
X return addr >= TITAN_BASE;
X }
X
-__EXTERN_INLINE unsigned long titan_readb(unsigned long addr)
+__EXTERN_INLINE u8 titan_readb(unsigned long addr)
X {
X return __kernel_ldbu(*(vucp)addr);
X }
X
-__EXTERN_INLINE unsigned long titan_readw(unsigned long addr)
+__EXTERN_INLINE u16 titan_readw(unsigned long addr)
X {
X return __kernel_ldwu(*(vusp)addr);
X }
X
-__EXTERN_INLINE unsigned long titan_readl(unsigned long addr)
+__EXTERN_INLINE u32 titan_readl(unsigned long addr)
X {
- return *(vuip)addr;
+ return (*(vuip)addr) & 0xffffffff;
X }
X
-__EXTERN_INLINE unsigned long titan_readq(unsigned long addr)
+__EXTERN_INLINE u64 titan_readq(unsigned long addr)
X {
X return *(vulp)addr;
X }
X
-__EXTERN_INLINE void titan_writeb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void titan_writeb(u8 b, unsigned long addr)
X {
X __kernel_stb(b, *(vucp)addr);
X }
X
-__EXTERN_INLINE void titan_writew(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void titan_writew(u16 b, unsigned long addr)
X {
X __kernel_stw(b, *(vusp)addr);
X }
X
-__EXTERN_INLINE void titan_writel(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void titan_writel(u32 b, unsigned long addr)
X {
X *(vuip)addr = b;
X }
X
-__EXTERN_INLINE void titan_writeq(unsigned long b, unsigned long addr)
+__EXTERN_INLINE void titan_writeq(u64 b, unsigned long addr)
X {
X *(vulp)addr = b;
X }
diff -u --recursive --new-file v2.4.14/linux/include/asm-alpha/core_tsunami.h linux/include/asm-alpha/core_tsunami.h


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

echo 'End of part 105'
echo 'File patch-2.4.15 is continued in part 106'
echo "106" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:11 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part095

#!/bin/sh -x
# this is part 095 of a 115 - part archive


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

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

+ read_lock(&fset->fset_kml.fd_lock);


+
+ EXIT;
+ out_complete:
+ path_release(&nd);
+ return error;
+}
+

+
+
+/* given a path, write an LML record for it - thus must have root's
+ group array settings, since lento is doing this
+*/
+int lento_write_lml(char *path,


+ __u64 remote_ino,
+ __u32 remote_generation,
+ __u32 remote_version,

+ struct presto_version *remote_file_version)


+{
+ struct nameidata nd;

+ struct rec_info rec;
+ struct dentry *dentry;
+ struct file file;


+ int error;
+ struct presto_file_set *fset;
+ ENTRY;
+
+ error = presto_walk(path, &nd);
+ if (error) {
+ EXIT;
+ return error;
+ }
+ dentry = nd.dentry;
+

+ file.f_dentry = dentry;
+ file.private_data = NULL;


+
+ error = -ENXIO;
+ if ( !presto_ispresto(dentry->d_inode) ) {
+ EXIT;

+ goto out_lml;


+ }
+
+ fset = presto_fset(dentry);
+ error = -EINVAL;
+ if ( !fset ) {
+ printk("No fileset!\n");
+ EXIT;

+ goto out_lml;
+ }
+
+
+ /* setting offset to -1 appends */
+ rec.offset = -1;
+ /* this only requires a transaction below which is automatic */
+ error = presto_write_lml_close(&rec,
+ fset,
+ &file,
+ remote_ino,
+ remote_generation,
+ remote_version,
+ remote_file_version);
+
+ EXIT;
+ out_lml:


+ path_release(&nd);
+ return error;
+}
+

+/* given a path: write a close record and cancel an LML record, finally
+ call truncate LML. Lento is doing this so it goes in with uid/gid's
+ root.
+*/
+int lento_cancel_lml(char *path,
+ __u64 lml_offset,

+ __u64 remote_ino,
+ __u32 remote_generation,
+ __u32 remote_version,

+ struct lento_vfs_context *info)


+{
+ struct nameidata nd;

+ struct rec_info rec;


+ struct dentry *dentry;
+ int error;
+ struct presto_file_set *fset;

+ void *handle;
+ struct presto_version new_ver;


+ ENTRY;
+
+
+ error = presto_walk(path, &nd);
+ if (error) {
+ EXIT;
+ return error;
+ }
+ dentry = nd.dentry;
+
+ error = -ENXIO;
+ if ( !presto_ispresto(dentry->d_inode) ) {
+ EXIT;

+ goto out_cancel_lml;


+ }
+
+ fset = presto_fset(dentry);
+

+ error=-EINVAL;
+ if (fset==NULL) {


+ printk("No fileset!\n");
+ EXIT;

+ goto out_cancel_lml;
+ }
+
+ /* this only requires a transaction below which is automatic */
+ handle = presto_trans_start(fset, dentry->d_inode, PRESTO_OP_RELEASE);

+ if ( !handle ) {

+ error = -ENOMEM;
+ EXIT;
+ goto out_cancel_lml;
+ }
+
+ if (info->flags & LENTO_FL_CANCEL_LML) {
+ error = presto_clear_lml_close(fset, lml_offset);


+ if ( error ) {

+ presto_trans_commit(fset, handle);
+ EXIT;

+ goto out_cancel_lml;
+ }
+ }
+
+
+ if (info->flags & LENTO_FL_WRITE_KML) {
+ struct file file;


+ file.private_data = NULL;
+ file.f_dentry = dentry;

+ presto_getversion(&new_ver, dentry->d_inode);
+ error = presto_journal_close(&rec, fset, &file, dentry,
+ &new_ver);


+ if ( error ) {

+ EXIT;
+ presto_trans_commit(fset, handle);

+ goto out_cancel_lml;
+ }
+ }
+
+ if (info->flags & LENTO_FL_WRITE_EXPECT) {


+ error = presto_write_last_rcvd(&rec, fset, info);

+ if ( error ) {

+ EXIT;
+ presto_trans_commit(fset, handle);

+ goto out_cancel_lml;
+ }
+ }
+
+ presto_trans_commit(fset, handle);
+
+ if (info->flags & LENTO_FL_CANCEL_LML) {
+ presto_truncate_lml(fset);
+ }
+
+
+ out_cancel_lml:
+ EXIT;


+ path_release(&nd);
+ return error;
+}
+
+

+/* given a path, operate on the flags in its dentry. Used by downcalls */
+int presto_mark_dentry(const char *name, int and_flag, int or_flag,
+ int *res)


+{
+ struct nameidata nd;
+ struct dentry *dentry;
+ int error;
+

+ error = presto_walk(name, &nd);

+ if (error)
+ return error;

+ dentry = nd.dentry;
+

+ CDEBUG(D_INODE, "name: %s, and flag %x, or flag %x, dd_flags %x\n",
+ name, and_flag, or_flag, presto_d2d(dentry)->dd_flags);
+
+


+ error = -ENXIO;
+ if ( !presto_ispresto(dentry->d_inode) )

+ goto out;
+
+ error = 0;
+
+ presto_d2d(dentry)->dd_flags &= and_flag;
+ presto_d2d(dentry)->dd_flags |= or_flag;
+ if (res)
+ *res = presto_d2d(dentry)->dd_flags;
+
+ // XXX this check makes no sense as d_count can change anytime.
+ /* indicate if we were the only users while changing the flag */
+ if ( atomic_read(&dentry->d_count) > 1 )


+ error = -EBUSY;
+

+out:


+ path_release(&nd);
+ return error;
+}
+

+/* given a path, operate on the flags in its cache. Used by mark_ioctl */
+int presto_mark_cache(const char *name, int and_flag, int or_flag,
+ int *res)


+{
+ struct nameidata nd;
+ struct dentry *dentry;

+ struct presto_cache *cache;
+ int error;
+
+ CDEBUG(D_INODE,
+ "presto_mark_cache :: name: %s, and flag %x, or flag %x\n",
+ name, and_flag, or_flag);


+
+ error = presto_walk(name, &nd);

+ if (error)
+ return error;
+
+ dentry = nd.dentry;

+ error = -ENXIO;
+ if ( !presto_ispresto(dentry->d_inode) )

+ goto out;


+
+ error = -EBADF;

+ cache = presto_get_cache(dentry->d_inode);


+ if ( !cache ) {

+ printk("PRESTO: BAD: cannot find cache in presto_mark_cache\n");
+ make_bad_inode(dentry->d_inode);
+ goto out;
+ }
+ error = 0;
+ ((int)cache->cache_flags) &= and_flag;
+ ((int)cache->cache_flags) |= or_flag;
+ if (res) {
+ *res = (int)cache->cache_flags;
+ }
+
+out:


+ path_release(&nd);
+ return error;
+}
+

+int presto_mark_fset_dentry(struct dentry *dentry, int and_flag, int or_flag,
+ int * res)
+{


+ int error;
+ struct presto_file_set *fset;
+

+ error = -ENXIO;
+ if ( !presto_ispresto(dentry->d_inode) )

+ return error;


+
+ error = -EBADF;

+ fset = presto_fset(dentry);


+ if ( !fset ) {

+ printk("PRESTO: BAD: cannot find cache in presto_mark_cache\n");
+ make_bad_inode(dentry->d_inode);
+ return error;
+ }
+ error = 0;
+ ((int)fset->fset_flags) &= and_flag;
+ ((int)fset->fset_flags) |= or_flag;
+ if (res) {
+ *res = (int)fset->fset_flags;
+ }
+


+ return error;
+}
+

+/* given a path, operate on the flags in its cache. Used by mark_ioctl */
+inline int presto_mark_fset(const char *name, int and_flag, int or_flag,
+ int * res)


+{
+ struct nameidata nd;
+ struct dentry *dentry;
+ int error;

+ ENTRY;
+
+ error = presto_walk(name, &nd);

+ if (error)
+ return error;
+
+

+ dentry = nd.dentry;
+ error = presto_mark_fset_dentry(dentry, and_flag, or_flag, res);
+


+ path_release(&nd);
+ return error;
+}
+
+

+/* talk to Lento about the permit */
+static int presto_permit_upcall(struct dentry *dentry)
+{
+ int rc;
+ char *path, *buffer;
+ int pathlen;
+ int minor;
+ int fsetnamelen;
+ struct presto_file_set *fset = NULL;
+
+ if ( (minor = presto_i2m(dentry->d_inode)) < 0)
+ return -EINVAL;


+
+ fset = presto_fset(dentry);

+ if (!fset) {
+ EXIT;
+ return -ENOTCONN;
+ }
+
+ if ( !presto_lento_up(minor) ) {
+ if ( fset->fset_flags & FSET_STEAL_PERMIT ) {
+ return 0;
+ } else {
+ return -ENOTCONN;
+ }
+ }
+


+ PRESTO_ALLOC(buffer, char *, PAGE_SIZE);
+ if ( !buffer ) {
+ printk("PRESTO: out of memory!\n");

+ return -ENOMEM;
+ }
+ path = presto_path(dentry, fset->fset_mtpt, buffer, PAGE_SIZE);
+ pathlen = MYPATHLEN(buffer, path);
+ fsetnamelen = strlen(fset->fset_name);
+ rc = lento_permit(minor, pathlen, fsetnamelen, path, fset->fset_name);
+ PRESTO_FREE(buffer, PAGE_SIZE);


+ return rc;
+}
+

+/* get a write permit for the fileset of this inode
+ * - if this returns a negative value there was an error
+ * - if 0 is returned the permit was already in the kernel -- or --
+ * Lento gave us the permit without reintegration
+ * - lento returns the number of records it reintegrated
+ */
+int presto_get_permit(struct inode * inode)
+{
+ struct dentry *de;
+ struct presto_file_set *fset;


+ int minor = presto_i2m(inode);

+ int rc;
+
+ ENTRY;
+ if (minor < 0) {


+ EXIT;
+ return -1;
+ }
+

+ if ( ISLENTO(minor) ) {
+ EXIT;


+ return -EINVAL;
+ }
+

+ if (list_empty(&inode->i_dentry)) {
+ printk("No alias for inode %d\n", (int) inode->i_ino);
+ EXIT;
+ return -EINVAL;
+ }
+
+ de = list_entry(inode->i_dentry.next, struct dentry, d_alias);
+
+ fset = presto_fset(de);


+ if ( !fset ) {

+ printk("Presto: no fileset in presto_get_permit!\n");
+ EXIT;


+ return -EINVAL;
+ }
+

+ if (fset->fset_flags & FSET_HASPERMIT) {
+ lock_kernel();
+ fset->fset_permit_count++;
+ CDEBUG(D_INODE, "permit count now %d, inode %lx\n",
+ fset->fset_permit_count, inode->i_ino);
+ unlock_kernel();


+ EXIT;
+ return 0;

+ } else {
+ /* Allow reintegration to proceed without locks -SHP */
+ rc = presto_permit_upcall(fset->fset_mtpt);
+ lock_kernel();


+ if ( !rc ) {

+ presto_mark_fset_dentry
+ (fset->fset_mtpt, ~0, FSET_HASPERMIT, NULL);
+ fset->fset_permit_count++;
+ }
+ CDEBUG(D_INODE, "permit count now %d, ino %lx (likely 1), rc %d\n",
+ fset->fset_permit_count, inode->i_ino, rc);
+ unlock_kernel();


+ EXIT;
+ return rc;
+ }
+}
+

+int presto_put_permit(struct inode * inode)
+{
+ struct dentry *de;
+ struct presto_file_set *fset;
+ int minor = presto_i2m(inode);
+
+ ENTRY;
+ if (minor < 0) {


+ EXIT;
+ return -1;
+ }
+

+ if ( ISLENTO(minor) ) {
+ EXIT;


+ return -1;
+ }
+

+ if (list_empty(&inode->i_dentry)) {
+ printk("No alias for inode %d\n", (int) inode->i_ino);


+ EXIT;
+ return -1;
+ }
+

+ de = list_entry(inode->i_dentry.next, struct dentry, d_alias);
+
+ fset = presto_fset(de);


+ if ( !fset ) {

+ printk("Presto: no fileset in presto_get_permit!\n");
+ EXIT;


+ return -1;
+ }
+

+ lock_kernel();
+ if (fset->fset_flags & FSET_HASPERMIT) {
+ if (fset->fset_permit_count > 0) fset->fset_permit_count--;
+ else printk("Put permit while permit count is 0, inode %lx!\n",
+ inode->i_ino);
+ } else {
+ fset->fset_permit_count=0;
+ printk("Put permit while no permit, inode %lx, flags %x!\n",
+ inode->i_ino, fset->fset_flags);
+ }
+
+ CDEBUG(D_INODE, "permit count now %d, inode %lx\n",
+ fset->fset_permit_count, inode->i_ino);
+
+ if (fset->fset_flags & FSET_PERMIT_WAITING &&
+ fset->fset_permit_count == 0) {
+ CDEBUG(D_INODE, "permit count now 0, ino %lx, notify Lento\n",
+ inode->i_ino);
+ presto_mark_fset_dentry(fset->fset_mtpt, ~FSET_PERMIT_WAITING, 0, NULL);
+ presto_mark_fset_dentry(fset->fset_mtpt, ~FSET_HASPERMIT, 0, NULL);
+ lento_release_permit(fset->fset_cache->cache_psdev->uc_minor,
+ fset->fset_permit_cookie);
+ fset->fset_permit_cookie = 0;
+ }
+ unlock_kernel();
+
+ EXIT;
+ return 0;
+}
+
+
+void presto_getversion(struct presto_version * presto_version,
+ struct inode * inode)
+{
+ presto_version->pv_mtime = cpu_to_le64((__u64)inode->i_mtime);
+ presto_version->pv_ctime = cpu_to_le64((__u64)inode->i_ctime);
+ presto_version->pv_size = cpu_to_le64((__u64)inode->i_size);
+}
+
+/*
+ * note: this routine "pins" a dentry for a fileset root
+ */
+int presto_set_fsetroot(char *path, char *fsetname, unsigned int fsetid,
+ unsigned int flags)
+{
+ struct presto_file_set *fset;
+ struct presto_file_set *fset2;
+ struct dentry *dentry;
+ struct presto_cache *cache;


+ int error;
+
+ ENTRY;
+

+ PRESTO_ALLOC(fset, struct presto_file_set *, sizeof(*fset));
+ error = -ENOMEM;


+ if ( !fset ) {

+ printk(KERN_ERR "No memory allocating fset for %s\n", fsetname);


+ EXIT;
+ return -ENOMEM;
+ }

+ CDEBUG(D_INODE, "fset at %p\n", fset);
+
+ printk("presto: fsetroot: path %s, fileset name %s\n", path, fsetname);
+ error = presto_walk(path, &fset->fset_nd);
+ CDEBUG(D_INODE, "\n");


+ if (error) {
+ EXIT;

+ goto out_free;
+ }
+ dentry = fset->fset_nd.dentry;
+ CDEBUG(D_INODE, "\n");


+
+ error = -ENXIO;
+ if ( !presto_ispresto(dentry->d_inode) ) {
+ EXIT;

+ goto out_dput;
+ }
+
+ CDEBUG(D_INODE, "\n");
+ cache = presto_get_cache(dentry->d_inode);
+ if (!cache) {
+ printk(KERN_ERR "No cache found for %s\n", path);


+ EXIT;
+ goto out_dput;
+ }
+

+ CDEBUG(D_INODE, "\n");
+ error = -EINVAL;
+ if ( !cache->cache_mtpt) {
+ printk(KERN_ERR "Presto - no mountpoint: fsetroot fails!\n");
+ EXIT;
+ goto out_dput;
+ }


+ CDEBUG(D_INODE, "\n");
+

+ if (!cache->cache_root_fileset) {
+ printk(KERN_ERR "Presto - no file set: fsetroot fails!\n");
+ EXIT;
+ goto out_dput;
+ }
+
+ error = -EEXIST;


+ CDEBUG(D_INODE, "\n");
+

+ fset2 = presto_fset(dentry);
+ if (fset2 && (fset2->fset_mtpt == dentry) ) {
+ printk(KERN_ERR "Fsetroot already set (path %s)\n", path);


+ EXIT;
+ goto out_dput;
+ }
+

+ fset->fset_cache = cache;
+ fset->fset_mtpt = dentry;
+ fset->fset_name = fsetname;
+ fset->fset_chunkbits = CHUNK_BITS;
+ fset->fset_flags = flags;
+ fset->fset_file_maxio = FSET_DEFAULT_MAX_FILEIO;
+
+ presto_d2d(dentry)->dd_fset = fset;
+ list_add(&fset->fset_list, &cache->cache_fset_list);
+
+ error = presto_init_kml_file(fset);


+ if ( error ) {

+ EXIT;
+ CDEBUG(D_JOURNAL, "Error init_kml %d\n", error);
+ goto out_list_del;
+ }
+
+ error = presto_init_last_rcvd_file(fset);


+ if ( error ) {

+ int rc;
+ EXIT;
+ rc = presto_close_journal_file(fset);
+ CDEBUG(D_JOURNAL, "Error init_lastrcvd %d, cleanup %d\n", error, rc);
+ goto out_list_del;
+ }
+
+ error = presto_init_lml_file(fset);


+ if ( error ) {

+ int rc;
+ EXIT;
+ rc = presto_close_journal_file(fset);
+ CDEBUG(D_JOURNAL, "Error init_lml %d, cleanup %d\n", error, rc);
+ goto out_list_del;
+ }
+
+#ifdef CONFIG_KREINT
+ /* initialize kml reint buffer */
+ error = kml_init (fset);

+ if ( error ) {

+ int rc;
+ EXIT;
+ rc = presto_close_journal_file(fset);
+ CDEBUG(D_JOURNAL, "Error init kml reint %d, cleanup %d\n",
+ error, rc);
+ goto out_list_del;
+ }
+#endif
+ if ( dentry->d_inode == dentry->d_inode->i_sb->s_root->d_inode) {
+ cache->cache_flags |= CACHE_FSETROOT_SET;
+ }
+
+ CDEBUG(D_PIOCTL, "-------> fset at %p, dentry at %p, mtpt %p, fset %s, cache %p, presto_d2d(dentry)->dd_fset %p\n",
+ fset, dentry, fset->fset_mtpt, fset->fset_name, cache, presto_d2d(dentry)->dd_fset);
+
+ EXIT;
+ return 0;
+
+ out_list_del:
+ list_del(&fset->fset_list);
+ presto_d2d(dentry)->dd_fset = NULL;
+ out_dput:
+ path_release(&fset->fset_nd);
+ out_free:
+ PRESTO_FREE(fset, sizeof(*fset));


+ return error;
+}
+

+int presto_get_kmlsize(char *path, size_t *size)


+{
+ struct nameidata nd;

+ struct presto_file_set *fset;


+ struct dentry *dentry;
+ int error;
+

+ ENTRY;


+ error = presto_walk(path, &nd);
+ if (error) {
+ EXIT;
+ return error;
+ }
+ dentry = nd.dentry;
+
+ error = -ENXIO;
+ if ( !presto_ispresto(dentry->d_inode) ) {
+ EXIT;

+ goto kml_out;
+ }
+
+ error = -EINVAL;
+ if ( ! presto_dentry2fset(dentry)) {
+ EXIT;
+ goto kml_out;
+ }
+
+ fset = presto_dentry2fset(dentry);
+ if (!fset) {
+ EXIT;
+ goto kml_out;


+ }
+ error = 0;

+ *size = fset->fset_kml.fd_offset;
+
+ kml_out:


+ path_release(&nd);
+ return error;
+}
+

+static void presto_cleanup_fset(struct presto_file_set *fset)
+{
+ int error;
+ struct presto_cache *cache;
+
+ ENTRY;
+#ifdef CONFIG_KREINT
+ error = kml_cleanup (fset);


+ if ( error ) {

+ printk("InterMezzo: Closing kml for fset %s: %d\n",
+ fset->fset_name, error);
+ }
+#endif
+
+ error = presto_close_journal_file(fset);


+ if ( error ) {

+ printk("InterMezzo: Closing journal for fset %s: %d\n",
+ fset->fset_name, error);
+ }
+ cache = fset->fset_cache;
+ cache->cache_flags &= ~CACHE_FSETROOT_SET;
+
+ list_del(&fset->fset_list);
+
+ presto_d2d(fset->fset_mtpt)->dd_fset = NULL;
+ path_release(&fset->fset_nd);
+
+ fset->fset_mtpt = NULL;
+ PRESTO_FREE(fset->fset_name, strlen(fset->fset_name) + 1);
+ PRESTO_FREE(fset, sizeof(*fset));
+ EXIT;
+}
+
+int presto_clear_fsetroot(char *path)


+{
+ struct nameidata nd;

+ struct presto_file_set *fset;


+ struct dentry *dentry;
+ int error;
+

+ ENTRY;


+ error = presto_walk(path, &nd);
+ if (error) {
+ EXIT;
+ return error;
+ }
+ dentry = nd.dentry;
+
+ error = -ENXIO;
+ if ( !presto_ispresto(dentry->d_inode) ) {
+ EXIT;

+ goto put_out;
+ }
+
+ error = -EINVAL;
+ if ( ! presto_dentry2fset(dentry)) {
+ EXIT;
+ goto put_out;
+ }
+
+ fset = presto_dentry2fset(dentry);
+ if (!fset) {
+ EXIT;
+ goto put_out;
+ }
+
+ presto_cleanup_fset(fset);
+ EXIT;
+
+put_out:
+ path_release(&nd); /* for our lookup */


+ return error;
+}
+

+int presto_clear_all_fsetroots(char *path)


+{
+ struct nameidata nd;

+ struct presto_file_set *fset;
+ struct dentry *dentry;
+ struct presto_cache *cache;
+ int error;
+ struct list_head *tmp,*tmpnext;
+
+
+ ENTRY;


+ error = presto_walk(path, &nd);
+ if (error) {
+ EXIT;
+ return error;
+ }
+ dentry = nd.dentry;
+
+ error = -ENXIO;
+ if ( !presto_ispresto(dentry->d_inode) ) {
+ EXIT;

+ goto put_out;
+ }
+
+ error = -EINVAL;
+ if ( ! presto_dentry2fset(dentry)) {
+ EXIT;
+ goto put_out;
+ }
+
+ fset = presto_dentry2fset(dentry);
+ if (!fset) {
+ EXIT;
+ goto put_out;
+ }
+
+ error = 0;
+ cache = fset->fset_cache;
+ cache->cache_flags &= ~CACHE_FSETROOT_SET;
+
+ tmp = &cache->cache_fset_list;
+ tmpnext = tmp->next;
+ while ( tmpnext != &cache->cache_fset_list) {
+ tmp = tmpnext;
+ tmpnext = tmp->next;
+ fset = list_entry(tmp, struct presto_file_set, fset_list);
+
+ presto_cleanup_fset(fset);
+ }
+
+ EXIT;
+ put_out:
+ path_release(&nd); /* for our lookup */


+ return error;
+}
+
+

+int presto_get_lastrecno(char *path, off_t *recno)


+{
+ struct nameidata nd;

+ struct presto_file_set *fset;


+ struct dentry *dentry;
+ int error;

+ ENTRY;
+


+ error = presto_walk(path, &nd);
+ if (error) {
+ EXIT;
+ return error;
+ }
+
+ dentry = nd.dentry;
+
+ error = -ENXIO;
+ if ( !presto_ispresto(dentry->d_inode) ) {
+ EXIT;

+ goto kml_out;
+ }
+
+ error = -EINVAL;
+ if ( ! presto_dentry2fset(dentry)) {
+ EXIT;
+ goto kml_out;
+ }
+
+ fset = presto_dentry2fset(dentry);
+ if (!fset) {
+ EXIT;
+ goto kml_out;


+ }
+ error = 0;

+ *recno = fset->fset_kml.fd_recno;
+
+ kml_out:


+ path_release(&nd);
+ return error;
+}
+
+/*

+ if *cookie != 0, lento must wait for this cookie
+ before releasing the permit, operations are in progress.
+*/
+int presto_permit_downcall( const char * path, int *cookie )
+{
+ int result;


+ struct presto_file_set *fset;
+

+ fset = presto_path2fileset(path);
+ if (IS_ERR(fset)) {
+ EXIT;
+ return PTR_ERR(fset);
+ }
+
+ lock_kernel();
+ if (fset->fset_permit_count != 0) {
+ /* is there are previous cookie? */
+ if (fset->fset_permit_cookie == 0) {
+ CDEBUG(D_CACHE, "presto installing cookie 0x%x, %s\n",
+ *cookie, path);
+ fset->fset_permit_cookie = *cookie;
+ } else {
+ *cookie = fset->fset_permit_cookie;
+ CDEBUG(D_CACHE, "presto has cookie 0x%x, %s\n",
+ *cookie, path);
+ }
+ result = presto_mark_fset(path, 0, FSET_PERMIT_WAITING, NULL);
+ } else {
+ *cookie = 0;
+ CDEBUG(D_CACHE, "presto releasing permit %s\n", path);
+ result = presto_mark_fset(path, ~FSET_HASPERMIT, 0, NULL);
+ }
+ unlock_kernel();
+
+ return result;
+}
+
+inline int presto_is_read_only(struct presto_file_set * fset)
+{
+ int minor, mask;


+ struct presto_cache *cache = fset->fset_cache;
+

+ minor= cache->cache_psdev->uc_minor;
+ mask= (ISLENTO(minor)? FSET_LENTO_RO : FSET_CLIENT_RO);
+ if ( fset->fset_flags & mask )
+ return 1;
+ mask= (ISLENTO(minor)? CACHE_LENTO_RO : CACHE_CLIENT_RO);
+ return ((cache->cache_flags & mask)? 1 : 0);
+}
+
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/psdev.c linux/fs/intermezzo/psdev.c
--- v2.4.14/linux/fs/intermezzo/psdev.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/psdev.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,1665 @@
+/*
+ * An implementation of a loadable kernel mode driver providing
+ * multiple kernel/user space bidirectional communications links.
+ *
+ * Author: Alan Cox <al...@cymru.net>
+ *


+ * 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.
+ *
+ * Adapted to become the Linux 2.0 Coda pseudo device
+ * Peter Braam <br...@maths.ox.ac.uk>
+ * Michael Callahan <m...@emmy.smith.edu>
+ *
+ * Changes for Linux 2.1
+ * Copyright (c) 1997 Carnegie-Mellon University
+ *
+ * Redone again for InterMezzo
+ * Copyright (c) 1998 Peter J. Braam
+ * Copyright (c) 2000 Mountain View Data, Inc.
+ * Copyright (c) 2000 Tacitus Systems, Inc.
+ * Copyright (c) 2001 Cluster File Systems, Inc.
+ *


+ * Extended attribute support

+ * Copyright (c) 2001 Shirish. H. Phatak
+ * Copyright (c) 2001 Tacit Networks, Inc.
+ */
+
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/lp.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <asm/io.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/poll.h>


+#include <asm/uaccess.h>
+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+#include <linux/intermezzo_kml.h>
+
+

+#ifdef PRESTO_DEVEL
+int presto_print_entry = 1;
+int presto_debug = 4095;
+#else
+int presto_print_entry = 0;
+int presto_debug = 0;
+#endif
+
+/* Like inode.c (presto_sym_iops), the initializer is just to prevent
+ upc_comms from appearing as a COMMON symbol (and therefore
+ interfering with other modules that use the same variable name. */
+struct upc_comm upc_comms[MAX_PRESTODEV] = {{0}};
+
+/*
+ * Device operations: map file to upcall structure
+ */
+static inline struct upc_comm *presto_psdev_f2u(struct file *file)


+{
+ int minor;
+

+ if ( MAJOR(file->f_dentry->d_inode->i_rdev) != PRESTO_PSDEV_MAJOR ) {
+ EXIT;
+ return NULL;
+ }
+
+ minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ if ( minor < 0 || minor >= MAX_PRESTODEV ) {
+ EXIT;


+ return NULL;
+ }
+

+ return &(upc_comms[minor]);
+}
+
+inline int presto_lento_up(int minor)
+{
+ return upc_comms[minor].uc_pid;
+}
+
+
+static unsigned int presto_psdev_poll(struct file *file, poll_table * wait)
+{
+ struct upc_comm *upccom;
+ unsigned int mask = POLLOUT | POLLWRNORM;
+ /* ENTRY; this will flood you */
+
+ if ( ! (upccom = presto_psdev_f2u(file)) ) {
+ kdev_t dev = file->f_dentry->d_inode->i_rdev;
+ printk("InterMezzo: %s, bad device %s\n",
+ __FUNCTION__, kdevname(dev));
+ }
+
+ poll_wait(file, &(upccom->uc_waitq), wait);
+
+ if (!list_empty(&upccom->uc_pending)) {
+ CDEBUG(D_PSDEV, "Non-empty pending list.\n");
+ mask |= POLLIN | POLLRDNORM;
+ }
+
+ /* EXIT; will flood you */
+ return mask;


+}
+
+
+
+/*

+ * Receive a message written by Lento to the psdev
+ */
+static ssize_t presto_psdev_write(struct file *file, const char *buf,
+ size_t count, loff_t *off)
+{
+ struct upc_comm *upccom;
+ struct upc_req *req = NULL;
+ struct upc_req *tmp;
+ struct list_head *lh;
+ struct lento_down_hdr hdr;
+ int error;
+
+ if ( ! (upccom = presto_psdev_f2u(file)) ) {
+ kdev_t dev = file->f_dentry->d_inode->i_rdev;
+ printk("InterMezzo: %s, bad device %s\n",
+ __FUNCTION__, kdevname(dev));
+ }
+
+ /* Peek at the opcode, uniquefier */
+ if ( count < sizeof(hdr) ) {
+ printk("presto_psdev_write: Lento didn't write full hdr.\n");
+ return -EINVAL;
+ }
+
+ error = copy_from_user(&hdr, buf, sizeof(hdr));


+ if ( error )

+ return error;
+
+ CDEBUG(D_PSDEV, "(process,opc,uniq)=(%d,%d,%d)\n",
+ current->pid, hdr.opcode, hdr.unique);
+
+ /* Look for the message on the processing queue. */
+ lh = &upccom->uc_processing;
+ while ( (lh = lh->next) != &upccom->uc_processing ) {
+ tmp = list_entry(lh, struct upc_req , rq_chain);
+ if (tmp->rq_unique == hdr.unique) {
+ req = tmp;
+ /* unlink here: keeps search length minimal */
+ list_del(&req->rq_chain);
+ INIT_LIST_HEAD(&req->rq_chain);
+ CDEBUG(D_PSDEV,"Eureka opc %d uniq %d!\n",
+ hdr.opcode, hdr.unique);
+ break;
+ }
+ }
+ if (!req) {
+ printk("psdev_write: msg (%d, %d) not found\n",
+ hdr.opcode, hdr.unique);
+ return(-ESRCH);
+ }
+
+ /* move data into response buffer. */
+ if (req->rq_bufsize < count) {
+ printk("psdev_write: too much cnt: %d, cnt: %d, "
+ "opc: %d, uniq: %d.\n",
+ req->rq_bufsize, count, hdr.opcode, hdr.unique);
+ count = req->rq_bufsize; /* don't have more space! */
+ }
+ error = copy_from_user(req->rq_data, buf, count);


+ if ( error )

+ return error;
+
+ /* adjust outsize: good upcalls can be aware of this */
+ req->rq_rep_size = count;
+ req->rq_flags |= REQ_WRITE;
+
+ wake_up(&req->rq_sleep);
+ return(count);
+}
+
+/*
+ * Read a message from the kernel to Lento
+ */
+static ssize_t presto_psdev_read(struct file * file, char * buf,
+ size_t count, loff_t *off)
+{
+ struct upc_comm *upccom;
+ struct upc_req *req;
+ int result = count;
+
+ if ( ! (upccom = presto_psdev_f2u(file)) ) {
+ kdev_t dev = file->f_dentry->d_inode->i_rdev;
+ printk("InterMezzo: %s, bad device %s\n",
+ __FUNCTION__, kdevname(dev));
+ }
+
+ CDEBUG(D_PSDEV, "count %d\n", count);
+ if (list_empty(&(upccom->uc_pending))) {
+ CDEBUG(D_UPCALL, "Empty pending list in read, not good\n");


+ return -EINVAL;
+ }
+

+ req = list_entry((upccom->uc_pending.next), struct upc_req, rq_chain);
+ list_del(&(req->rq_chain));
+ if (! (req->rq_flags & REQ_ASYNC) ) {
+ list_add(&(req->rq_chain), upccom->uc_processing.prev);
+ }
+ req->rq_flags |= REQ_READ;
+
+ /* Move the input args into userspace */
+ if (req->rq_bufsize <= count) {
+ result = req->rq_bufsize;
+ }
+
+ if (count < req->rq_bufsize) {
+ printk ("psdev_read: buffer too small, read %d of %d bytes\n",
+ count, req->rq_bufsize);
+ }
+
+ if ( copy_to_user(buf, req->rq_data, result) ) {
+ return -EFAULT;
+ }
+
+ /* If request was asynchronous don't enqueue, but free */
+ if (req->rq_flags & REQ_ASYNC) {
+ CDEBUG(D_PSDEV, "psdev_read: async msg (%d, %d), result %d\n",
+ req->rq_opcode, req->rq_unique, result);


+ PRESTO_FREE(req->rq_data, req->rq_bufsize);

+ PRESTO_FREE(req, sizeof(*req));


+ return result;
+ }
+
+ return result;
+}
+

+static int presto_psdev_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct upc_comm *upccom;
+ /* XXX is this rdev or dev? */
+ kdev_t dev = inode->i_rdev;
+
+ ENTRY;
+ upccom = presto_psdev_f2u(file);
+ if ( !upccom) {
+ printk("InterMezzo: %s, bad device %s\n",
+ __FUNCTION__, kdevname(dev));
+ EXIT;


+ return -ENODEV;
+ }
+

+ switch(cmd) {
+
+ case TCGETS:
+ return -EINVAL;
+
+ case PRESTO_GETMOUNT: {
+ /* return all the mounts for this device. */
+ int minor = 0;
+ int len, outlen;
+ struct readmount readmount;
+ struct readmount *user_readmount = (struct readmount *) arg;
+ char * tmp;
+ int error;
+
+ error = copy_from_user(&readmount, (void *)arg,
+ sizeof(readmount));


+ if ( error ) {

+ printk("psdev: can't copy %d bytes from %p to %p\n",
+ sizeof(readmount), (struct readmount *) arg,
+ &readmount);


+ EXIT;
+ return error;
+ }
+

+ len = readmount.io_len;
+ minor = MINOR(dev);
+ PRESTO_ALLOC(tmp, char *, len);
+ if (!tmp) {


+ EXIT;
+ return -ENOMEM;
+ }
+

+ outlen = presto_sprint_mounts(tmp, len, minor);
+ CDEBUG(D_PSDEV, "presto_sprint_mounts returns %d bytes\n",
+ outlen);
+
+ /* as this came out on 1/3/2000, it could NEVER work.
+ * So fix it ... RGM
+ * I mean, let's let the compiler do a little work ...
+ * gcc suggested the extra ()
+ */
+ error = copy_to_user(readmount.io_string, tmp, outlen);


+ if ( error ) {

+ CDEBUG(D_PSDEV, "Copy_to_user string 0x%p failed\n",
+ readmount.io_string);
+ }
+ if ((!error) && (error = copy_to_user(&(user_readmount->io_len),
+ &outlen, sizeof(int))) ) {
+ CDEBUG(D_PSDEV, "Copy_to_user len @0x%p failed\n",
+ &(user_readmount->io_len));
+ }
+
+ PRESTO_FREE(tmp, len);


+ EXIT;
+ return error;
+ }
+

+ case PRESTO_SETPID: {
+ /*
+ * This ioctl is performed by each Lento that starts up
+ * and wants to do further communication with presto.
+ */
+ CDEBUG(D_PSDEV, "Setting current pid to %d\n", current->pid);
+ upccom->uc_pid = current->pid;
+ if ( !list_empty(&upccom->uc_processing) ) {
+ struct list_head *lh;
+ struct upc_req *req;
+ printk("WARNING: setpid & processing not empty!\n");
+ lh = &upccom->uc_processing;
+ while ( (lh = lh->next) != &upccom->uc_processing) {
+ req = list_entry(lh, struct upc_req, rq_chain);
+ /* freeing of req and data is done by the sleeper */
+ wake_up(&req->rq_sleep);
+ }
+ }
+ if ( !list_empty(&upccom->uc_processing) ) {
+ printk("BAD: FAILDED TO CLEAN PROCESSING LIST!\n");
+ }
+ EXIT;
+ return 0;
+ }
+
+ case PRESTO_CLEAR_FSETROOT: {
+ /*
+ * Close KML files.
+ */
+ int error;
+ int saved_pid = upccom->uc_pid;
+ char *path;
+ struct {
+ char *path;
+ int path_len;
+ } input;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;


+ return error;
+ }
+

+ PRESTO_ALLOC(path, char *, input.path_len + 1);
+ if ( !path ) {
+ EXIT;
+ return -ENOMEM;
+ }
+ error = copy_from_user(path, input.path, input.path_len);


+ if ( error ) {

+ PRESTO_FREE(path, input.path_len + 1);


+ EXIT;
+ return error;
+ }

+ path[input.path_len] = '\0';
+ CDEBUG(D_PSDEV, "clear_fsetroot: path %s\n", path);
+
+ upccom->uc_pid = current->pid;
+ error = presto_clear_fsetroot(path);
+ upccom->uc_pid = saved_pid;
+ PRESTO_FREE(path, input.path_len + 1);


+ EXIT;
+ return error;
+ }
+
+

+ case PRESTO_CLEAR_ALL_FSETROOTS: {
+ /*
+ * Close KML files.
+ */
+ int error;
+ int saved_pid = upccom->uc_pid;
+ char *path;
+ struct {
+ char *path;
+ int path_len;
+ } input;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;


+ return error;
+ }
+

+ PRESTO_ALLOC(path, char *, input.path_len + 1);
+ if ( !path ) {
+ EXIT;
+ return -ENOMEM;
+ }
+ error = copy_from_user(path, input.path, input.path_len);


+ if ( error ) {

+ PRESTO_FREE(path, input.path_len + 1);


+ EXIT;
+ return error;
+ }

+ path[input.path_len] = '\0';
+ CDEBUG(D_PSDEV, "clear_all_fsetroot: path %s\n", path);
+
+ upccom->uc_pid = current->pid;
+ error = presto_clear_all_fsetroots(path);
+ upccom->uc_pid = saved_pid;
+ PRESTO_FREE(path, input.path_len + 1);


+ EXIT;
+ return error;
+ }
+

+ case PRESTO_GET_KMLSIZE: {
+ int error;
+ int saved_pid = upccom->uc_pid;
+ char *path;
+ size_t size = 0;
+ struct {
+ __u64 size;
+ char *path;
+ int path_len;
+ } input;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;


+ return error;
+ }
+

+ PRESTO_ALLOC(path, char *, input.path_len + 1);
+ if ( !path ) {
+ EXIT;
+ return -ENOMEM;
+ }
+ error = copy_from_user(path, input.path, input.path_len);


+ if ( error ) {

+ PRESTO_FREE(path, input.path_len + 1);


+ EXIT;
+ return error;
+ }

+ path[input.path_len] = '\0';
+ CDEBUG(D_PSDEV, "get_kmlsize: len %d path %s\n",
+ input.path_len, path);
+
+ upccom->uc_pid = current->pid;
+ error = presto_get_kmlsize(path, &size);
+ PRESTO_FREE(path, input.path_len + 1);


+ if (error) {
+ EXIT;
+ return error;
+ }

+ input.size = size;
+ upccom->uc_pid = saved_pid;
+
+ CDEBUG(D_PSDEV, "get_kmlsize: size = %d\n", size);
+
+ EXIT;
+ return copy_to_user((char *)arg, &input, sizeof(input));
+ }
+
+ case PRESTO_GET_RECNO: {
+ int error;
+ int saved_pid = upccom->uc_pid;
+ char *path;
+ off_t recno = 0;
+ struct {
+ __u64 recno;
+ char *path;
+ int path_len;
+ } input;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;


+ return error;
+ }
+

+ PRESTO_ALLOC(path, char *, input.path_len + 1);
+ if ( !path ) {
+ EXIT;
+ return -ENOMEM;
+ }
+ error = copy_from_user(path, input.path, input.path_len);


+ if ( error ) {

+ PRESTO_FREE(path, input.path_len + 1);


+ EXIT;
+ return error;
+ }

+ path[input.path_len] = '\0';
+ CDEBUG(D_PSDEV, "get_recno: len %d path %s\n",
+ input.path_len, path);
+
+ upccom->uc_pid = current->pid;
+ error = presto_get_lastrecno(path, &recno);
+ PRESTO_FREE(path, input.path_len + 1);


+ if (error) {
+ EXIT;
+ return error;
+ }

+ input.recno = recno;
+ upccom->uc_pid = saved_pid;
+
+ CDEBUG(D_PSDEV, "get_recno: recno = %d\n", (int) recno);
+
+ EXIT;
+ return copy_to_user((char *)arg, &input, sizeof(input));
+ }
+
+ case PRESTO_SET_FSETROOT: {
+ /*
+ * Save information about the cache, and initialize "special"
+ * cache files (KML, etc).
+ */
+ int error;
+ int saved_pid = upccom->uc_pid;
+ char *fsetname;
+ char *path;
+ struct {
+ char *path;
+ int path_len;
+ char *name;
+ int name_len;
+ int id;
+ int flags;
+ } input;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;


+ return error;
+ }
+

+ PRESTO_ALLOC(path, char *, input.path_len + 1);
+ if ( !path ) {
+ EXIT;
+ return -ENOMEM;
+ }
+ error = copy_from_user(path, input.path, input.path_len);
+ if ( error ) {
+ EXIT;
+ goto exit_free_path;
+ }
+ path[input.path_len] = '\0';
+
+ PRESTO_ALLOC(fsetname, char *, input.name_len + 1);
+ if ( !fsetname ) {
+ error = -ENOMEM;
+ EXIT;
+ goto exit_free_path;
+ }
+ error = copy_from_user(fsetname, input.name, input.name_len);
+ if ( error ) {
+ EXIT;
+ goto exit_free_fsetname;
+ }
+ fsetname[input.name_len] = '\0';
+
+ CDEBUG(D_PSDEV,
+ "set_fsetroot: path %s name %s, id %d, flags %x\n",
+ path, fsetname, input.id, input.flags);
+ upccom->uc_pid = current->pid;
+ error = presto_set_fsetroot(path, fsetname, input.id,input.flags);
+ upccom->uc_pid = saved_pid;
+ if ( error ) {
+ EXIT;
+ goto exit_free_fsetname;
+ }
+ /* fsetname is kept in the fset, so don't free it now */
+ PRESTO_FREE(path, input.path_len + 1);


+ EXIT;
+ return 0;
+

+ exit_free_fsetname:
+ PRESTO_FREE(fsetname, input.name_len + 1);
+ exit_free_path:
+ PRESTO_FREE(path, input.path_len + 1);


+ return error;
+ }
+

+ case PRESTO_CLOSE_JOURNALF: {
+ int saved_pid = upccom->uc_pid;
+ int error;
+
+ CDEBUG(D_SUPER, "HELLO\n");
+
+ /* pretend we are lento: we should lock something */
+ upccom->uc_pid = current->pid;
+ error = presto_close_journal_file(NULL);
+ CDEBUG(D_PSDEV, "error is %d\n", error);
+ upccom->uc_pid = saved_pid;


+ EXIT;
+ return error;
+ }
+

+ case PRESTO_GETOPT:
+ case PRESTO_SETOPT: {
+ /* return all the mounts for this device. */
+ int dosetopt(int, struct psdev_opt *);
+ int dogetopt(int, struct psdev_opt *);
+ int minor = 0;
+ struct psdev_opt kopt;
+ struct psdev_opt *user_opt = (struct psdev_opt *) arg;
+ int error;
+
+ error = copy_from_user(&kopt, (void *)arg, sizeof(kopt));


+ if ( error ) {

+ printk("psdev: can't copyin %d bytes from %p to %p\n",
+ sizeof(kopt), (struct kopt *) arg, &kopt);


+ EXIT;
+ return error;
+ }

+ minor = MINOR(dev);
+ if (cmd == PRESTO_SETOPT)
+ error = dosetopt(minor, &kopt);
+


+ if ( error ) {

+ CDEBUG(D_PSDEV,
+ "dosetopt failed minor %d, opt %d, val %d\n",
+ minor, kopt.optname, kopt.optval);


+ EXIT;
+ return error;
+ }
+

+ error = dogetopt(minor, &kopt);
+


+ if ( error ) {

+ CDEBUG(D_PSDEV,
+ "dogetopt failed minor %d, opt %d, val %d\n",
+ minor, kopt.optname, kopt.optval);


+ EXIT;
+ return error;
+ }
+

+ error = copy_to_user(user_opt, &kopt, sizeof(kopt));


+ if ( error ) {

+ CDEBUG(D_PSDEV, "Copy_to_user opt 0x%p failed\n",
+ user_opt);


+ EXIT;
+ return error;
+ }

+ CDEBUG(D_PSDEV, "dosetopt minor %d, opt %d, val %d return %d\n",
+ minor, kopt.optname, kopt.optval, error);


+ EXIT;
+ return 0;
+ }
+

+ case PRESTO_VFS_SETATTR: {
+ int error;
+ struct lento_input_attr input;


+ struct iattr iattr;
+

+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;
+ return error;
+ }
+ iattr.ia_valid = input.valid;
+ iattr.ia_mode = (umode_t)input.mode;
+ iattr.ia_uid = (uid_t)input.uid;
+ iattr.ia_gid = (gid_t)input.gid;
+ iattr.ia_size = (off_t)input.size;
+ iattr.ia_atime = (time_t)input.atime;
+ iattr.ia_mtime = (time_t)input.mtime;
+ iattr.ia_ctime = (time_t)input.ctime;
+ iattr.ia_attr_flags = input.attr_flags;
+
+ error = lento_setattr(input.name, &iattr, &input.info);


+ EXIT;
+ return error;
+ }
+

+ case PRESTO_VFS_CREATE: {
+ int error;
+ struct lento_input_mode input;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ error = lento_create(input.name, input.mode, &input.info);


+ EXIT;
+ return error;
+ }
+

+ case PRESTO_VFS_LINK: {
+ int error;
+ struct lento_input_old_new input;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ error = lento_link(input.oldname, input.newname, &input.info);


+ EXIT;
+ return error;
+ }
+

+ case PRESTO_VFS_UNLINK: {
+ int error;
+ struct lento_input input;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ error = lento_unlink(input.name, &input.info);


+ EXIT;
+ return error;
+ }
+

+ case PRESTO_VFS_SYMLINK: {
+ int error;
+ struct lento_input_old_new input;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ error = lento_symlink(input.oldname, input.newname,&input.info);


+ EXIT;
+ return error;
+ }
+

+ case PRESTO_VFS_MKDIR: {
+ int error;
+ struct lento_input_mode input;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ error = lento_mkdir(input.name, input.mode, &input.info);


+ EXIT;
+ return error;
+ }
+

+ case PRESTO_VFS_RMDIR: {
+ int error;
+ struct lento_input input;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ error = lento_rmdir(input.name, &input.info);


+ EXIT;
+ return error;
+ }
+

+ case PRESTO_VFS_MKNOD: {
+ int error;
+ struct lento_input_dev input;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ error = lento_mknod(input.name, input.mode,
+ MKDEV(input.major,input.minor),&input.info);


+ EXIT;
+ return error;
+ }
+

+ case PRESTO_VFS_RENAME: {
+ int error;
+ struct lento_input_old_new input;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ error = lento_rename(input.oldname, input.newname, &input.info);


+ EXIT;
+ return error;
+ }
+

+#ifdef CONFIG_FS_EXT_ATTR
+ /* IOCTL to create/modify an extended attribute */
+ case PRESTO_VFS_SETEXTATTR: {
+ int error;
+ struct lento_input_ext_attr input;
+ char *name;
+ char *buffer;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ /* Now setup the input parameters */
+ PRESTO_ALLOC(name, char *, input.name_len+1);
+ /* We need null terminated strings for attr names */
+ name[input.name_len] = '\0';
+ error=copy_from_user(name, input.name, input.name_len);


+ if ( error ) {

+ EXIT;
+ PRESTO_FREE(name,input.name_len+1);


+ return error;
+ }
+

+ PRESTO_ALLOC(buffer, char *, input.buffer_len+1);
+ error=copy_from_user(buffer, input.buffer, input.buffer_len);


+ if ( error ) {

+ EXIT;
+ PRESTO_FREE(name,input.name_len+1);
+ PRESTO_FREE(buffer,input.buffer_len+1);
+ return error;
+ }
+ /* Make null terminated for easy printing */
+ buffer[input.buffer_len]='\0';
+
+ CDEBUG(D_PSDEV," setextattr params: name %s, valuelen %d,"
+ " value %s, attr flags %x, mode %o, slot offset %d,"
+ " recno %d, kml offset %lu, flags %x, time %d\n",
+ name, input.buffer_len, buffer, input.flags, input.mode,
+ input.info.slot_offset, input.info.recno,
+ (unsigned long) input.info.kml_offset, input.info.flags,
+ input.info.updated_time);
+
+ error=lento_set_ext_attr
+ (input.path,name,buffer,input.buffer_len,
+ input.flags, input.mode, &input.info);
+
+ PRESTO_FREE(name,input.name_len+1);
+ PRESTO_FREE(buffer,input.buffer_len+1);


+ EXIT;
+ return error;
+ }
+

+ /* IOCTL to delete an extended attribute */
+ case PRESTO_VFS_DELEXTATTR: {
+ int error;
+ struct lento_input_ext_attr input;
+ char *name;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

+ if ( error ) {
+ EXIT;
+ return error;
+ }
+
+ /* Now setup the input parameters */
+ PRESTO_ALLOC(name, char *, input.name_len+1);
+ /* We need null terminated strings for attr names */
+ name[input.name_len] = '\0';
+ error=copy_from_user(name, input.name, input.name_len);


+ if ( error ) {

+ EXIT;
+ PRESTO_FREE(name,input.name_len+1);


+ return error;
+ }
+

+ CDEBUG(D_PSDEV," delextattr params: name %s,"
+ " attr flags %x, mode %o, slot offset %d, recno %d,"
+ " kml offset %lu, flags %x, time %d\n",
+ name, input.flags, input.mode,
+ input.info.slot_offset, input.info.recno,
+ (unsigned long) input.info.kml_offset, input.info.flags,
+ input.info.updated_time);
+
+ error=lento_set_ext_attr
+ (input.path,name,NULL,0,input.flags,
+ input.mode,&input.info);
+ PRESTO_FREE(name,input.name_len+1);


+ EXIT;
+ return error;
+ }

+#endif
+
+ case PRESTO_VFS_IOPEN: {
+ struct lento_input_iopen input;
+ int error;
+


+ error = copy_from_user(&input, (char *)arg, sizeof(input));

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

echo 'End of part 095'
echo 'File patch-2.4.15 is continued in part 096'
echo "096" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:17 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part101

#!/bin/sh -x
# this is part 101 of a 115 - part archive


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

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

+ * manually rather than reading off disk), then we need to keep the
+ * buffer_head locked until it has been completely filled with new
+ * data. In this case, we should be able to make the assertion that
+ * the bh is not already part of an existing transaction.
+ *
+ * The buffer should already be locked by the caller by this point.
+ * There is no lock ranking violation: it was a newly created,
+ * unlocked buffer beforehand. */
+
+int journal_get_create_access (handle_t *handle, struct buffer_head *bh)
+{
+ transaction_t *transaction = handle->h_transaction;
+ journal_t *journal = transaction->t_journal;
+ struct journal_head *jh = journal_add_journal_head(bh);
+ int err;
+
+ jbd_debug(5, "journal_head %p\n", jh);
+ lock_journal(journal);
+ err = -EROFS;
+ if (is_handle_aborted(handle))
+ goto out;
+ err = 0;


+
+ JBUFFER_TRACE(jh, "entry");

+ /* The buffer may already belong to this transaction due to
+ * pre-zeroing in the filesystem's new_block code. It may also
+ * be on the previous, committing transaction's lists, but it
+ * HAS to be in Forget state in that case: the transaction must
+ * have deleted the buffer for it to be reused here. */
+ J_ASSERT_JH(jh, (jh->b_transaction == transaction ||
+ jh->b_transaction == NULL ||
+ (jh->b_transaction == journal->j_committing_transaction &&
+ jh->b_jlist == BJ_Forget)));
+


+ J_ASSERT_JH(jh, jh->b_next_transaction == NULL);

+ J_ASSERT_JH(jh, buffer_locked(jh2bh(jh)));
+
+ J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
+ handle->h_buffer_credits--;
+
+ spin_lock(&journal_datalist_lock);
+ if (jh->b_transaction == NULL) {
+ jh->b_transaction = transaction;
+ JBUFFER_TRACE(jh, "file as BJ_Reserved");
+ __journal_file_buffer(jh, transaction, BJ_Reserved);
+ JBUFFER_TRACE(jh, "refile");
+ refile_buffer(jh2bh(jh));
+ } else if (jh->b_transaction == journal->j_committing_transaction) {
+ JBUFFER_TRACE(jh, "set next transaction");
+ jh->b_next_transaction = transaction;
+ }
+ spin_unlock(&journal_datalist_lock);
+
+ /*
+ * akpm: I added this. ext3_alloc_branch can pick up new indirect
+ * blocks which contain freed but then revoked metadata. We need
+ * to cancel the revoke in case we end up freeing it yet again
+ * and the reallocating as data - this would cause a second revoke,
+ * which hits an assertion error.
+ */
+ JBUFFER_TRACE(jh, "cancelling revoke");
+ journal_cancel_revoke(handle, jh);
+ journal_unlock_journal_head(jh);
+out:


+ unlock_journal(journal);
+ return err;

+}
+
+
+
+/*

+ * journal_get_undo_access: Notify intent to modify metadata with non-
+ * rewindable consequences
+ *
+ * Sometimes there is a need to distinguish between metadata which has
+ * been committed to disk and that which has not. The ext3fs code uses
+ * this for freeing and allocating space: we have to make sure that we
+ * do not reuse freed space until the deallocation has been committed,
+ * since if we overwrote that space we would make the delete
+ * un-rewindable in case of a crash.
+ *
+ * To deal with that, journal_get_undo_access requests write access to a
+ * buffer for parts of non-rewindable operations such as delete
+ * operations on the bitmaps. The journaling code must keep a copy of
+ * the buffer's contents prior to the undo_access call until such time
+ * as we know that the buffer has definitely been committed to disk.
+ *
+ * We never need to know which transaction the committed data is part
+ * of: buffers touched here are guaranteed to be dirtied later and so
+ * will be committed to a new transaction in due course, at which point
+ * we can discard the old committed data pointer.
+ *
+ * Returns error number or 0 on success.
+ */
+
+int journal_get_undo_access (handle_t *handle, struct buffer_head *bh)
+{
+ journal_t *journal = handle->h_transaction->t_journal;
+ int err;
+ struct journal_head *jh = journal_add_journal_head(bh);


+
+ JBUFFER_TRACE(jh, "entry");

+ lock_journal(journal);
+
+ /* Do this first --- it can drop the journal lock, so we want to
+ * make sure that obtaining the committed_data is done
+ * atomically wrt. completion of any outstanding commits. */
+ err = do_get_write_access (handle, jh, 1);
+ if (err)
+ goto out;
+
+ if (!jh->b_committed_data) {
+ /* Copy out the current buffer contents into the
+ * preserved, committed copy. */
+ JBUFFER_TRACE(jh, "generate b_committed data");
+ jh->b_committed_data = jbd_kmalloc(jh2bh(jh)->b_size,
+ GFP_NOFS);
+ if (!jh->b_committed_data) {
+ printk(KERN_EMERG __FUNCTION__
+ ": No memory for committed data!\n");
+ err = -ENOMEM;


+ goto out;
+ }
+

+ memcpy (jh->b_committed_data, jh2bh(jh)->b_data,
+ jh2bh(jh)->b_size);
+ }
+
+out:
+ if (!err)
+ J_ASSERT_JH(jh, jh->b_committed_data);
+ journal_unlock_journal_head(jh);


+ unlock_journal(journal);
+ return err;

+}
+
+/*
+ * journal_dirty_data: mark a buffer as containing dirty data which
+ * needs to be flushed before we can commit the current transaction.
+ *
+ * The buffer is placed on the transaction's data list and is marked as
+ * belonging to the transaction.
+ *
+ * If `async' is set then the writebask will be initiated by the caller
+ * using submit_bh -> end_buffer_io_async. We put the buffer onto
+ * t_async_datalist.
+ *
+ * Returns error number or 0 on success.
+ *
+ * journal_dirty_data() can be called via page_launder->ext3_writepage
+ * by kswapd. So it cannot block. Happily, there's nothing here
+ * which needs lock_journal if `async' is set.
+ *
+ * When the buffer is on the current transaction we freely move it
+ * between BJ_AsyncData and BJ_SyncData according to who tried to
+ * change its state last.
+ */
+
+int journal_dirty_data (handle_t *handle, struct buffer_head *bh, int async)
+{
+ journal_t *journal = handle->h_transaction->t_journal;
+ int need_brelse = 0;
+ int wanted_jlist = async ? BJ_AsyncData : BJ_SyncData;


+ struct journal_head *jh;
+

+ if (is_handle_aborted(handle))
+ return 0;
+
+ jh = journal_add_journal_head(bh);
+ JBUFFER_TRACE(jh, "entry");
+
+ /*
+ * The buffer could *already* be dirty. Writeout can start
+ * at any time.
+ */
+ jbd_debug(4, "jh: %p, tid:%d\n", jh, handle->h_transaction->t_tid);
+
+ /*
+ * What if the buffer is already part of a running transaction?
+ *
+ * There are two cases:
+ * 1) It is part of the current running transaction. Refile it,
+ * just in case we have allocated it as metadata, deallocated
+ * it, then reallocated it as data.
+ * 2) It is part of the previous, still-committing transaction.
+ * If all we want to do is to guarantee that the buffer will be
+ * written to disk before this new transaction commits, then
+ * being sure that the *previous* transaction has this same
+ * property is sufficient for us! Just leave it on its old
+ * transaction.
+ *
+ * In case (2), the buffer must not already exist as metadata
+ * --- that would violate write ordering (a transaction is free
+ * to write its data at any point, even before the previous
+ * committing transaction has committed). The caller must
+ * never, ever allow this to happen: there's nothing we can do
+ * about it in this layer.
+ */
+ spin_lock(&journal_datalist_lock);
+ if (jh->b_transaction) {
+ JBUFFER_TRACE(jh, "has transaction");
+ if (jh->b_transaction != handle->h_transaction) {
+ JBUFFER_TRACE(jh, "belongs to older transaction");


+ J_ASSERT_JH(jh, jh->b_transaction ==

+ journal->j_committing_transaction);
+
+ /* @@@ IS THIS TRUE ? */
+ /*
+ * Not any more. Scenario: someone does a write()
+ * in data=journal mode. The buffer's transaction has
+ * moved into commit. Then someone does another
+ * write() to the file. We do the frozen data copyout
+ * and set b_next_transaction to point to j_running_t.
+ * And while we're in that state, someone does a
+ * writepage() in an attempt to pageout the same area
+ * of the file via a shared mapping. At present that
+ * calls journal_dirty_data(), and we get right here.
+ * It may be too late to journal the data. Simply
+ * falling through to the next test will suffice: the
+ * data will be dirty and wil be checkpointed. The
+ * ordering comments in the next comment block still
+ * apply.
+ */
+ //J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
+
+ /*
+ * If we're journalling data, and this buffer was
+ * subject to a write(), it could be metadata, forget
+ * or shadow against the committing transaction. Now,
+ * someone has dirtied the same darn page via a mapping
+ * and it is being writepage()'d.
+ * We *could* just steal the page from commit, with some
+ * fancy locking there. Instead, we just skip it -
+ * don't tie the page's buffers to the new transaction
+ * at all.
+ * Implication: if we crash before the writepage() data
+ * is written into the filesystem, recovery will replay
+ * the write() data.
+ */
+ if (jh->b_jlist != BJ_None &&
+ jh->b_jlist != BJ_SyncData &&
+ jh->b_jlist != BJ_AsyncData) {
+ JBUFFER_TRACE(jh, "Not stealing");
+ goto no_journal;
+ }
+
+ /*
+ * This buffer may be undergoing writeout in commit. We
+ * can't return from here and let the caller dirty it
+ * again because that can cause the write-out loop in
+ * commit to never terminate.
+ */
+ if (!async && buffer_dirty(bh)) {


+ atomic_inc(&bh->b_count);
+ spin_unlock(&journal_datalist_lock);

+ need_brelse = 1;


+ ll_rw_block(WRITE, 1, &bh);
+ wait_on_buffer(bh);

+ spin_lock(&journal_datalist_lock);
+ /* The buffer may become locked again at any
+ time if it is redirtied */
+ }
+
+ /* journal_clean_data_list() may have got there first */


+ if (jh->b_transaction != NULL) {

+ JBUFFER_TRACE(jh, "unfile from commit");


+ __journal_unfile_buffer(jh);
+ jh->b_transaction = NULL;
+ }

+ /* The buffer will be refiled below */
+
+ }
+ /*
+ * Special case --- the buffer might actually have been
+ * allocated and then immediately deallocated in the previous,
+ * committing transaction, so might still be left on that
+ * transaction's metadata lists.
+ */
+ if (jh->b_jlist != wanted_jlist) {
+ JBUFFER_TRACE(jh, "not on correct data list: unfile");
+ J_ASSERT_JH(jh, jh->b_jlist != BJ_Shadow);


+ __journal_unfile_buffer(jh);
+ jh->b_transaction = NULL;

+ JBUFFER_TRACE(jh, "file as data");
+ __journal_file_buffer(jh, handle->h_transaction,
+ wanted_jlist);
+ }
+ } else {
+ JBUFFER_TRACE(jh, "not on a transaction");
+ __journal_file_buffer(jh, handle->h_transaction, wanted_jlist);
+ }
+ /*
+ * We need to mark the buffer dirty and refile it inside the lock to
+ * protect it from release by journal_try_to_free_buffer()
+ *
+ * We set ->b_flushtime to something small enough to typically keep
+ * kupdate away from the buffer.
+ *
+ * We don't need to do a balance_dirty() - __block_commit_write()
+ * does that.
+ */
+ if (!async && !atomic_set_buffer_dirty(jh2bh(jh))) {
+ jh2bh(jh)->b_flushtime =
+ jiffies + journal->j_commit_interval + 1 * HZ;
+ refile_buffer(jh2bh(jh));
+ }
+no_journal:
+ spin_unlock(&journal_datalist_lock);
+ if (need_brelse) {


+ BUFFER_TRACE(bh, "brelse");
+ __brelse(bh);
+ }

+ JBUFFER_TRACE(jh, "exit");
+ journal_unlock_journal_head(jh);


+ return 0;
+}
+

+/*
+ * journal_dirty_metadata: mark a buffer as containing dirty metadata
+ * which needs to be journaled as part of the current transaction.
+ *
+ * The buffer is placed on the transaction's metadata list and is marked
+ * as belonging to the transaction.
+ *
+ * Special care needs to be taken if the buffer already belongs to the
+ * current committing transaction (in which case we should have frozen
+ * data present for that commit). In that case, we don't relink the
+ * buffer: that only gets done when the old transaction finally
+ * completes its commit.
+ *
+ * Returns error number or 0 on success.
+ */
+
+int journal_dirty_metadata (handle_t *handle, struct buffer_head *bh)
+{
+ transaction_t *transaction = handle->h_transaction;
+ journal_t *journal = transaction->t_journal;


+ struct journal_head *jh = bh2jh(bh);
+

+ jbd_debug(5, "journal_head %p\n", jh);
+ JBUFFER_TRACE(jh, "entry");
+ lock_journal(journal);
+ if (is_handle_aborted(handle))
+ goto out_unlock;
+
+ spin_lock(&journal_datalist_lock);
+ set_bit(BH_JBDDirty, &bh->b_state);
+ set_buffer_flushtime(bh);
+


+ J_ASSERT_JH(jh, jh->b_transaction != NULL);

+
+ /*
+ * Metadata already on the current transaction list doesn't
+ * need to be filed. Metadata on another transaction's list must
+ * be committing, and will be refiled once the commit completes:
+ * leave it alone for now.
+ */
+
+ if (jh->b_transaction != transaction) {
+ JBUFFER_TRACE(jh, "already on other transaction");


+ J_ASSERT_JH(jh, jh->b_transaction ==

+ journal->j_committing_transaction);
+ J_ASSERT_JH(jh, jh->b_next_transaction == transaction);
+ /* And this case is illegal: we can't reuse another
+ * transaction's data buffer, ever. */
+ /* FIXME: writepage() should be journalled */
+ J_ASSERT_JH(jh, jh->b_jlist != BJ_SyncData);
+ goto done_locked;
+ }
+
+ /* That test should have eliminated the following case: */
+ J_ASSERT_JH(jh, jh->b_frozen_data == 0);
+
+ JBUFFER_TRACE(jh, "file as BJ_Metadata");
+ __journal_file_buffer(jh, handle->h_transaction, BJ_Metadata);
+
+done_locked:
+ spin_unlock(&journal_datalist_lock);
+ JBUFFER_TRACE(jh, "exit");
+out_unlock:
+ unlock_journal(journal);


+ return 0;
+}
+

+#if 0
+/*
+ * journal_release_buffer: undo a get_write_access without any buffer
+ * updates, if the update decided in the end that it didn't need access.
+ *
+ * journal_get_write_access() can block, so it is quite possible for a
+ * journaling component to decide after the write access is returned
+ * that global state has changed and the update is no longer required. */
+
+void journal_release_buffer (handle_t *handle, struct buffer_head *bh)
+{
+ transaction_t *transaction = handle->h_transaction;
+ journal_t *journal = transaction->t_journal;


+ struct journal_head *jh = bh2jh(bh);
+

+ lock_journal(journal);


+ JBUFFER_TRACE(jh, "entry");
+

+ /* If the buffer is reserved but not modified by this
+ * transaction, then it is safe to release it. In all other
+ * cases, just leave the buffer as it is. */
+
+ spin_lock(&journal_datalist_lock);
+ if (jh->b_jlist == BJ_Reserved && jh->b_transaction == transaction &&
+ !buffer_jdirty(jh2bh(jh))) {
+ JBUFFER_TRACE(jh, "unused: refiling it");
+ handle->h_buffer_credits++;
+ __journal_refile_buffer(jh);
+ }
+ spin_unlock(&journal_datalist_lock);
+
+ JBUFFER_TRACE(jh, "exit");
+ unlock_journal(journal);
+}
+#endif
+
+/*
+ * journal_forget: bforget() for potentially-journaled buffers. We can
+ * only do the bforget if there are no commits pending against the
+ * buffer. If the buffer is dirty in the current running transaction we
+ * can safely unlink it.
+ *
+ * bh may not be a journalled buffer at all - it may be a non-JBD
+ * buffer which came off the hashtable. Check for this.
+ *
+ * Decrements bh->b_count by one.
+ *
+ * Allow this call even if the handle has aborted --- it may be part of
+ * the caller's cleanup after an abort.
+ */
+
+void journal_forget (handle_t *handle, struct buffer_head *bh)
+{
+ transaction_t *transaction = handle->h_transaction;
+ journal_t *journal = transaction->t_journal;


+ struct journal_head *jh;
+

+ BUFFER_TRACE(bh, "entry");
+


+ lock_journal(journal);
+ spin_lock(&journal_datalist_lock);
+

+ if (!buffer_jbd(bh))
+ goto not_jbd;
+ jh = bh2jh(bh);
+
+ if (jh->b_transaction == handle->h_transaction) {
+ J_ASSERT_JH(jh, !jh->b_frozen_data);
+
+ /* If we are forgetting a buffer which is already part
+ * of this transaction, then we can just drop it from
+ * the transaction immediately. */
+ clear_bit(BH_Dirty, &bh->b_state);
+ clear_bit(BH_JBDDirty, &bh->b_state);
+
+ JBUFFER_TRACE(jh, "belongs to current transaction: unfile");
+ J_ASSERT_JH(jh, !jh->b_committed_data);
+
+ __journal_unfile_buffer(jh);
+ jh->b_transaction = 0;
+
+ /*
+ * We are no longer going to journal this buffer.
+ * However, the commit of this transaction is still
+ * important to the buffer: the delete that we are now
+ * processing might obsolete an old log entry, so by
+ * committing, we can satisfy the buffer's checkpoint.
+ *
+ * So, if we have a checkpoint on the buffer, we should
+ * now refile the buffer on our BJ_Forget list so that
+ * we know to remove the checkpoint after we commit.
+ */
+
+ if (jh->b_cp_transaction) {
+ __journal_file_buffer(jh, transaction, BJ_Forget);
+ } else {
+ __journal_remove_journal_head(bh);
+ __brelse(bh);
+ if (!buffer_jbd(bh)) {
+ spin_unlock(&journal_datalist_lock);
+ unlock_journal(journal);
+ __bforget(bh);
+ return;
+ }
+ }
+
+ } else if (jh->b_transaction) {
+ J_ASSERT_JH(jh, (jh->b_transaction ==
+ journal->j_committing_transaction));
+ /* However, if the buffer is still owned by a prior
+ * (committing) transaction, we can't drop it yet... */
+ JBUFFER_TRACE(jh, "belongs to older transaction");
+ /* ... but we CAN drop it from the new transaction if we
+ * have also modified it since the original commit. */


+
+ if (jh->b_next_transaction) {

+ J_ASSERT(jh->b_next_transaction == transaction);
+ jh->b_next_transaction = NULL;
+ }
+ }
+
+not_jbd:
+ spin_unlock(&journal_datalist_lock);
+ unlock_journal(journal);
+ __brelse(bh);
+ return;
+}
+
+#if 0 /* Unused */
+/*
+ * journal_sync_buffer: flush a potentially-journaled buffer to disk.
+ *
+ * Used for O_SYNC filesystem operations. If the buffer is journaled,
+ * we need to complete the O_SYNC by waiting for the transaction to
+ * complete. It is an error to call journal_sync_buffer before
+ * journal_stop!
+ */
+
+void journal_sync_buffer(struct buffer_head *bh)


+{
+ transaction_t *transaction;
+ journal_t *journal;

+ long sequence;


+ struct journal_head *jh;
+

+ /* If the buffer isn't journaled, this is easy: just sync it to
+ * disk. */
+ BUFFER_TRACE(bh, "entry");
+
+ spin_lock(&journal_datalist_lock);
+ if (!buffer_jbd(bh)) {
+ spin_unlock(&journal_datalist_lock);
+ return;
+ }
+ jh = bh2jh(bh);
+ if (jh->b_transaction == NULL) {
+ /* If the buffer has already been journaled, then this
+ * is a noop. */
+ if (jh->b_cp_transaction == NULL) {
+ spin_unlock(&journal_datalist_lock);
+ return;
+ }


+ atomic_inc(&bh->b_count);
+ spin_unlock(&journal_datalist_lock);

+ ll_rw_block (WRITE, 1, &bh);
+ wait_on_buffer(bh);
+ __brelse(bh);


+ goto out;
+ }
+

+ /* Otherwise, just wait until the transaction is synced to disk. */
+ transaction = jh->b_transaction;


+ journal = transaction->t_journal;

+ sequence = transaction->t_tid;
+ spin_unlock(&journal_datalist_lock);
+
+ jbd_debug(2, "requesting commit for jh %p\n", jh);
+ log_start_commit (journal, transaction);
+
+ while (tid_gt(sequence, journal->j_commit_sequence)) {
+ wake_up(&journal->j_wait_done_commit);
+ sleep_on(&journal->j_wait_done_commit);
+ }
+ JBUFFER_TRACE(jh, "exit");


+out:
+ return;
+}
+#endif
+
+/*

+ * All done for a particular handle.
+ *
+ * There is not much action needed here. We just return any remaining
+ * buffer credits to the transaction and remove the handle. The only
+ * complication is that we need to start a commit operation if the
+ * filesystem is marked for synchronous update.
+ *
+ * journal_stop itself will not usually return an error, but it may
+ * do so in unusual circumstances. In particular, expect it to
+ * return -EIO if a journal_abort has been executed since the
+ * transaction began.
+ */
+
+int journal_stop(handle_t *handle)
+{
+ transaction_t *transaction = handle->h_transaction;
+ journal_t *journal = transaction->t_journal;
+ int old_handle_count, err;
+
+ if (!handle)
+ return 0;
+
+ J_ASSERT (transaction->t_updates > 0);
+ J_ASSERT (journal_current_handle() == handle);
+
+ if (is_handle_aborted(handle))
+ err = -EIO;
+ else
+ err = 0;
+
+ if (--handle->h_ref > 0) {
+ jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1,
+ handle->h_ref);


+ return err;
+ }
+

+ jbd_debug(4, "Handle %p going down\n", handle);
+
+ /*
+ * Implement synchronous transaction batching. If the handle
+ * was synchronous, don't force a commit immediately. Let's
+ * yield and let another thread piggyback onto this transaction.
+ * Keep doing that while new threads continue to arrive.
+ * It doesn't cost much - we're about to run a commit and sleep
+ * on IO anyway. Speeds up many-threaded, many-dir operations
+ * by 30x or more...
+ */
+ if (handle->h_sync) {
+ do {
+ old_handle_count = transaction->t_handle_count;
+ set_current_state(TASK_RUNNING);


+ current->policy |= SCHED_YIELD;
+ schedule();

+ } while (old_handle_count != transaction->t_handle_count);
+ }
+
+ current->journal_info = NULL;
+ transaction->t_outstanding_credits -= handle->h_buffer_credits;
+ transaction->t_updates--;
+ if (!transaction->t_updates) {
+ wake_up(&journal->j_wait_updates);
+ if (journal->j_barrier_count)
+ wake_up(&journal->j_wait_transaction_locked);
+ }
+
+ /*
+ * If the handle is marked SYNC, we need to set another commit
+ * going! We also want to force a commit if the current
+ * transaction is occupying too much of the log, or if the
+ * transaction is too old now.
+ */
+ if (handle->h_sync ||
+ transaction->t_outstanding_credits >
+ journal->j_max_transaction_buffers ||
+ time_after_eq(jiffies, transaction->t_expires)) {
+ /* Do this even for aborted journals: an abort still
+ * completes the commit thread, it just doesn't write
+ * anything to disk. */


+ tid_t tid = transaction->t_tid;
+

+ jbd_debug(2, "transaction too old, requesting commit for "
+ "handle %p\n", handle);
+ /* This is non-blocking */
+ log_start_commit(journal, transaction);
+
+ /*
+ * Special case: JFS_SYNC synchronous updates require us
+ * to wait for the commit to complete.
+ */
+ if (handle->h_sync && !(current->flags & PF_MEMALLOC))
+ log_wait_commit(journal, tid);
+ }
+ kfree(handle);
+ return err;
+}
+
+/*
+ * For synchronous operations: force any uncommitted trasnactions
+ * to disk. May seem kludgy, but it reuses all the handle batching
+ * code in a very simple manner.
+ */
+int journal_force_commit(journal_t *journal)
+{
+ handle_t *handle;


+ int ret = 0;
+

+ lock_kernel();
+ handle = journal_start(journal, 1);
+ if (IS_ERR(handle)) {
+ ret = PTR_ERR(handle);
+ goto out;
+ }


+ handle->h_sync = 1;

+ journal_stop(handle);
+out:
+ unlock_kernel();
+ return ret;


+}
+
+/*
+ *

+ * List management code snippets: various functions for manipulating the
+ * transaction buffer lists.
+ *
+ */
+
+/*
+ * Append a buffer to a transaction list, given the transaction's list head
+ * pointer.
+ * journal_datalist_lock is held.


+ */
+
+static inline void

+__blist_add_buffer(struct journal_head **list, struct journal_head *jh)
+{
+ if (!*list) {
+ jh->b_tnext = jh->b_tprev = jh;
+ *list = jh;
+ } else {
+ /* Insert at the tail of the list to preserve order */
+ struct journal_head *first = *list, *last = first->b_tprev;
+ jh->b_tprev = last;
+ jh->b_tnext = first;
+ last->b_tnext = first->b_tprev = jh;
+ }
+}
+
+/*
+ * Remove a buffer from a transaction list, given the transaction's list
+ * head pointer.
+ *
+ * Called with journal_datalist_lock held, and the journal may not
+ * be locked.


+ */
+
+static inline void

+__blist_del_buffer(struct journal_head **list, struct journal_head *jh)
+{
+ if (*list == jh) {
+ *list = jh->b_tnext;
+ if (*list == jh)
+ *list = 0;
+ }
+ jh->b_tprev->b_tnext = jh->b_tnext;
+ jh->b_tnext->b_tprev = jh->b_tprev;
+}
+
+/*
+ * Remove a buffer from the appropriate transaction list.
+ *
+ * Note that this function can *change* the value of
+ * bh->b_transaction->t_sync_datalist, t_async_datalist, t_buffers, t_forget,
+ * t_iobuf_list, t_shadow_list, t_log_list or t_reserved_list. If the caller
+ * is holding onto a copy of one of thee pointers, it could go bad.
+ * Generally the caller needs to re-read the pointer from the transaction_t.
+ *
+ * If bh->b_jlist is BJ_SyncData or BJ_AsyncData then we may have been called
+ * via journal_try_to_free_buffer() or journal_clean_data_list(). In that
+ * case, journal_datalist_lock will be held, and the journal may not be locked.
+ */
+void __journal_unfile_buffer(struct journal_head *jh)
+{
+ struct journal_head **list = 0;


+ transaction_t * transaction;
+

+ assert_spin_locked(&journal_datalist_lock);
+ transaction = jh->b_transaction;
+
+#ifdef __SMP__
+ J_ASSERT (current->lock_depth >= 0);
+#endif
+ J_ASSERT_JH(jh, jh->b_jlist < BJ_Types);
+
+ if (jh->b_jlist != BJ_None)
+ J_ASSERT_JH(jh, transaction != 0);
+
+ switch (jh->b_jlist) {
+ case BJ_None:
+ return;
+ case BJ_SyncData:
+ list = &transaction->t_sync_datalist;
+ break;
+ case BJ_AsyncData:
+ list = &transaction->t_async_datalist;
+ break;
+ case BJ_Metadata:
+ transaction->t_nr_buffers--;
+ J_ASSERT_JH(jh, transaction->t_nr_buffers >= 0);
+ list = &transaction->t_buffers;
+ break;
+ case BJ_Forget:
+ list = &transaction->t_forget;
+ break;
+ case BJ_IO:
+ list = &transaction->t_iobuf_list;
+ break;
+ case BJ_Shadow:
+ list = &transaction->t_shadow_list;
+ break;
+ case BJ_LogCtl:
+ list = &transaction->t_log_list;
+ break;
+ case BJ_Reserved:
+ list = &transaction->t_reserved_list;
+ break;
+ }
+
+ __blist_del_buffer(list, jh);
+ jh->b_jlist = BJ_None;
+ if (test_and_clear_bit(BH_JBDDirty, &jh2bh(jh)->b_state)) {
+ set_bit(BH_Dirty, &jh2bh(jh)->b_state);
+ }
+}
+
+void journal_unfile_buffer(struct journal_head *jh)
+{
+ spin_lock(&journal_datalist_lock);
+ __journal_unfile_buffer(jh);
+ spin_unlock(&journal_datalist_lock);
+}
+
+/*
+ * Called from journal_try_to_free_buffers(). The journal is not
+ * locked. lru_list_lock is not held.
+ *
+ * Here we see why journal_datalist_lock is global and not per-journal.
+ * We cannot get back to this buffer's journal pointer without locking
+ * out journal_clean_data_list() in some manner.
+ *
+ * One could use journal_datalist_lock to get unracy access to a
+ * per-journal lock.


+ *
+ * Called with journal_datalist_lock held.
+ *

+ * Returns non-zero iff we were able to free the journal_head.
+ */
+static int __journal_try_to_free_buffer(struct buffer_head *bh,
+ int *locked_or_dirty)
+{


+ struct journal_head *jh;
+

+ assert_spin_locked(&journal_datalist_lock);
+
+ if (!buffer_jbd(bh))
+ return 1;


+ jh = bh2jh(bh);
+

+ if (buffer_locked(bh) || buffer_dirty(bh)) {
+ *locked_or_dirty = 1;


+ goto out;
+ }
+

+ if (!buffer_uptodate(bh))
+ goto out;
+
+ if (jh->b_next_transaction != 0)
+ goto out;
+
+ if (jh->b_transaction != 0 && jh->b_cp_transaction == 0) {
+ if (jh->b_jlist == BJ_SyncData || jh->b_jlist==BJ_AsyncData) {
+ /* A written-back ordered data buffer */
+ JBUFFER_TRACE(jh, "release data");
+ __journal_unfile_buffer(jh);
+ jh->b_transaction = 0;
+ __journal_remove_journal_head(bh);
+ __brelse(bh);
+ }
+ }
+ else if (jh->b_cp_transaction != 0 && jh->b_transaction == 0) {
+ /* written-back checkpointed metadata buffer */
+ if (jh->b_jlist == BJ_None) {


+ JBUFFER_TRACE(jh, "remove from checkpoint list");
+ __journal_remove_checkpoint(jh);
+ __journal_remove_journal_head(bh);

+ __brelse(bh);
+ }
+ }
+ return !buffer_jbd(bh);
+
+out:


+ return 0;
+}
+

+/*
+ * journal_try_to_free_buffers(). For all the buffers on this page,
+ * if they are fully written out ordered data, move them onto BUF_CLEAN
+ * so try_to_free_buffers() can reap them. Called with lru_list_lock
+ * not held. Does its own locking.
+ *
+ * This complicates JBD locking somewhat. We aren't protected by the
+ * BKL here. We wish to remove the buffer from its committing or
+ * running transaction's ->t_datalist via __journal_unfile_buffer.
+ *
+ * This may *change* the value of transaction_t->t_datalist, so anyone
+ * who looks at t_datalist needs to lock against this function.
+ *
+ * Even worse, someone may be doing a journal_dirty_data on this
+ * buffer. So we need to lock against that. journal_dirty_data()
+ * will come out of the lock with the buffer dirty, which makes it
+ * ineligible for release here.
+ *
+ * Who else is affected by this? hmm... Really the only contender
+ * is do_get_write_access() - it could be looking at the buffer while
+ * journal_try_to_free_buffer() is changing its state. But that
+ * cannot happen because we never reallocate freed data as metadata
+ * while the data is part of a transaction. Yes?
+ *
+ * This function returns non-zero if we wish try_to_free_buffers()
+ * to be called. We do this is the page is releasable by try_to_free_buffers().
+ * We also do it if the page has locked or dirty buffers and the caller wants
+ * us to perform sync or async writeout.
+ */
+int journal_try_to_free_buffers(journal_t *journal,
+ struct page *page, int gfp_mask)
+{
+ struct buffer_head *bh;
+ struct buffer_head *tmp;
+ int locked_or_dirty = 0;
+ int call_ttfb = 1;
+
+ J_ASSERT(PageLocked(page));
+


+ bh = page->buffers;

+ tmp = bh;
+ spin_lock(&journal_datalist_lock);
+ do {
+ struct buffer_head *p = tmp;
+
+ tmp = tmp->b_this_page;
+ if (buffer_jbd(p))
+ if (!__journal_try_to_free_buffer(p, &locked_or_dirty))
+ call_ttfb = 0;
+ } while (tmp != bh);
+ spin_unlock(&journal_datalist_lock);
+
+ if (!(gfp_mask & (__GFP_IO|__GFP_WAIT)))
+ goto out;
+ if (!locked_or_dirty)
+ goto out;
+ /*
+ * The VM wants us to do writeout, or to block on IO, or both.
+ * So we allow try_to_free_buffers to be called even if the page
+ * still has journalled buffers.
+ */
+ call_ttfb = 1;
+out:
+ return call_ttfb;
+}
+
+/*
+ * This buffer is no longer needed. If it is on an older transaction's
+ * checkpoint list we need to record it on this transaction's forget list
+ * to pin this buffer (and hence its checkpointing transaction) down until
+ * this transaction commits. If the buffer isn't on a checkpoint list, we
+ * release it.
+ * Returns non-zero if JBD no longer has an interest in the buffer.
+ */
+static int dispose_buffer(struct journal_head *jh,
+ transaction_t *transaction)
+{
+ int may_free = 1;


+ struct buffer_head *bh = jh2bh(jh);
+

+ spin_lock(&journal_datalist_lock);
+ __journal_unfile_buffer(jh);
+ jh->b_transaction = 0;
+
+ if (jh->b_cp_transaction) {
+ JBUFFER_TRACE(jh, "on running+cp transaction");
+ __journal_file_buffer(jh, transaction, BJ_Forget);
+ clear_bit(BH_JBDDirty, &bh->b_state);
+ may_free = 0;
+ } else {
+ JBUFFER_TRACE(jh, "on running transaction");


+ __journal_remove_journal_head(bh);
+ __brelse(bh);
+ }
+ spin_unlock(&journal_datalist_lock);

+ return may_free;
+}
+
+/*
+ * journal_flushpage
+ *
+ * This code is tricky. It has a number of cases to deal with.
+ *
+ * There are two invariants which this code relies on:
+ *
+ * i_size must be updated on disk before we start calling flushpage on the
+ * data.
+ *
+ * This is done in ext3 by defining an ext3_setattr method which
+ * updates i_size before truncate gets going. By maintaining this
+ * invariant, we can be sure that it is safe to throw away any buffers
+ * attached to the current transaction: once the transaction commits,
+ * we know that the data will not be needed.
+ *
+ * Note however that we can *not* throw away data belonging to the
+ * previous, committing transaction!
+ *
+ * Any disk blocks which *are* part of the previous, committing
+ * transaction (and which therefore cannot be discarded immediately) are
+ * not going to be reused in the new running transaction
+ *
+ * The bitmap committed_data images guarantee this: any block which is
+ * allocated in one transaction and removed in the next will be marked
+ * as in-use in the committed_data bitmap, so cannot be reused until
+ * the next transaction to delete the block commits. This means that
+ * leaving committing buffers dirty is quite safe: the disk blocks
+ * cannot be reallocated to a different file and so buffer aliasing is
+ * not possible.
+ *
+ *
+ * The above applies mainly to ordered data mode. In writeback mode we
+ * don't make guarantees about the order in which data hits disk --- in
+ * particular we don't guarantee that new dirty data is flushed before
+ * transaction commit --- so it is always safe just to discard data
+ * immediately in that mode. --sct
+ */
+
+/*
+ * The journal_unmap_buffer helper function returns zero if the buffer
+ * concerned remains pinned as an anonymous buffer belonging to an older
+ * transaction.
+ *
+ * We're outside-transaction here. Either or both of j_running_transaction
+ * and j_committing_transaction may be NULL.
+ */
+static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
+{
+ transaction_t *transaction;
+ struct journal_head *jh;
+ int may_free = 1;
+
+ BUFFER_TRACE(bh, "entry");
+
+ if (!buffer_mapped(bh))
+ return 1;
+
+ /* It is safe to proceed here without the
+ * journal_datalist_spinlock because the buffers cannot be
+ * stolen by try_to_free_buffers as long as we are holding the
+ * page lock. --sct */
+
+ if (!buffer_jbd(bh))
+ goto zap_buffer;
+
+ jh = bh2jh(bh);
+ transaction = jh->b_transaction;


+ if (transaction == NULL) {

+ /* First case: not on any transaction. If it
+ * has no checkpoint link, then we can zap it:
+ * it's a writeback-mode buffer so we don't care
+ * if it hits disk safely. */
+ if (!jh->b_cp_transaction) {
+ JBUFFER_TRACE(jh, "not on any transaction: zap");
+ goto zap_buffer;
+ }
+
+ if (!buffer_dirty(bh)) {
+ /* bdflush has written it. We can drop it now */
+ goto zap_buffer;
+ }
+
+ /* OK, it must be in the journal but still not
+ * written fully to disk: it's metadata or
+ * journaled data... */
+
+ if (journal->j_running_transaction) {
+ /* ... and once the current transaction has
+ * committed, the buffer won't be needed any
+ * longer. */
+ JBUFFER_TRACE(jh, "checkpointed: add to BJ_Forget");
+ return dispose_buffer(jh,
+ journal->j_running_transaction);
+ } else {
+ /* There is no currently-running transaction. So the
+ * orphan record which we wrote for this file must have
+ * passed into commit. We must attach this buffer to
+ * the committing transaction, if it exists. */
+ if (journal->j_committing_transaction) {
+ JBUFFER_TRACE(jh, "give to committing trans");
+ return dispose_buffer(jh,
+ journal->j_committing_transaction);
+ } else {
+ /* The orphan record's transaction has
+ * committed. We can cleanse this buffer */
+ clear_bit(BH_JBDDirty, &bh->b_state);
+ goto zap_buffer;
+ }
+ }
+ } else if (transaction == journal->j_committing_transaction) {
+ /* If it is committing, we simply cannot touch it. We
+ * can remove it's next_transaction pointer from the
+ * running transaction if that is set, but nothing
+ * else. */
+ JBUFFER_TRACE(jh, "on committing transaction");
+ if (jh->b_next_transaction) {
+ J_ASSERT(jh->b_next_transaction ==
+ journal->j_running_transaction);
+ jh->b_next_transaction = NULL;
+ }


+ return 0;
+ } else {

+ /* Good, the buffer belongs to the running transaction.
+ * We are writing our own transaction's data, not any
+ * previous one's, so it is safe to throw it away
+ * (remember that we expect the filesystem to have set
+ * i_size already for this truncate so recovery will not
+ * expose the disk blocks we are discarding here.) */
+ J_ASSERT_JH(jh, transaction == journal->j_running_transaction);
+ may_free = dispose_buffer(jh, transaction);
+ }
+
+zap_buffer:
+ if (buffer_dirty(bh))
+ mark_buffer_clean(bh);
+ J_ASSERT_BH(bh, !buffer_jdirty(bh));
+ clear_bit(BH_Uptodate, &bh->b_state);
+ clear_bit(BH_Mapped, &bh->b_state);
+ clear_bit(BH_Req, &bh->b_state);
+ clear_bit(BH_New, &bh->b_state);
+ return may_free;
+}
+
+/*
+ * Return non-zero if the page's buffers were successfully reaped
+ */
+int journal_flushpage(journal_t *journal,
+ struct page *page,

+ unsigned long offset)
+{

+ struct buffer_head *head, *bh, *next;
+ unsigned int curr_off = 0;
+ int may_free = 1;
+
+ if (!PageLocked(page))
+ BUG();
+ if (!page->buffers)
+ return 1;
+
+ /* We will potentially be playing with lists other than just the
+ * data lists (especially for journaled data mode), so be
+ * cautious in our locking. */
+ lock_journal(journal);
+
+ head = bh = page->buffers;
+ do {
+ unsigned int next_off = curr_off + bh->b_size;
+ next = bh->b_this_page;
+
+ /* AKPM: doing lock_buffer here may be overly paranoid */
+ if (offset <= curr_off) {
+ /* This block is wholly outside the truncation point */
+ lock_buffer(bh);
+ may_free &= journal_unmap_buffer(journal, bh);
+ unlock_buffer(bh);
+ }
+ curr_off = next_off;
+ bh = next;
+
+ } while (bh != head);
+
+ unlock_journal(journal);
+
+ if (!offset) {
+ if (!may_free || !try_to_free_buffers(page, 0))
+ return 0;
+ J_ASSERT(page->buffers == NULL);
+ }
+ return 1;
+}
+
+/*
+ * File a buffer on the given transaction list.
+ */
+void __journal_file_buffer(struct journal_head *jh,
+ transaction_t *transaction, int jlist)
+{
+ struct journal_head **list = 0;
+
+ assert_spin_locked(&journal_datalist_lock);
+
+#ifdef __SMP__
+ J_ASSERT (current->lock_depth >= 0);
+#endif
+ J_ASSERT_JH(jh, jh->b_jlist < BJ_Types);
+ J_ASSERT_JH(jh, jh->b_transaction == transaction ||
+ jh->b_transaction == 0);
+
+ if (jh->b_transaction) {
+ if (jh->b_jlist == jlist)
+ return;
+ __journal_unfile_buffer(jh);
+ } else {
+ jh->b_transaction = transaction;
+ }
+
+ switch (jlist) {
+ case BJ_None:
+ J_ASSERT_JH(jh, !jh->b_committed_data);
+ J_ASSERT_JH(jh, !jh->b_frozen_data);
+ return;
+ case BJ_SyncData:
+ list = &transaction->t_sync_datalist;
+ break;
+ case BJ_AsyncData:
+ list = &transaction->t_async_datalist;
+ break;
+ case BJ_Metadata:
+ transaction->t_nr_buffers++;
+ list = &transaction->t_buffers;
+ break;
+ case BJ_Forget:
+ list = &transaction->t_forget;
+ break;
+ case BJ_IO:
+ list = &transaction->t_iobuf_list;
+ break;
+ case BJ_Shadow:
+ list = &transaction->t_shadow_list;
+ break;
+ case BJ_LogCtl:
+ list = &transaction->t_log_list;
+ break;
+ case BJ_Reserved:
+ list = &transaction->t_reserved_list;
+ break;
+ }
+
+ __blist_add_buffer(list, jh);
+ jh->b_jlist = jlist;
+
+ if (jlist == BJ_Metadata || jlist == BJ_Reserved ||
+ jlist == BJ_Shadow || jlist == BJ_Forget) {
+ if (atomic_set_buffer_clean(jh2bh(jh))) {
+ set_bit(BH_JBDDirty, &jh2bh(jh)->b_state);
+ }
+ }
+}
+
+void journal_file_buffer(struct journal_head *jh,
+ transaction_t *transaction, int jlist)
+{
+ spin_lock(&journal_datalist_lock);
+ __journal_file_buffer(jh, transaction, jlist);
+ spin_unlock(&journal_datalist_lock);
+}
+
+/*
+ * Remove a buffer from its current buffer list in preparation for
+ * dropping it from its current transaction entirely. If the buffer has
+ * already started to be used by a subsequent transaction, refile the
+ * buffer on that transaction's metadata list.
+ */
+
+void __journal_refile_buffer(struct journal_head *jh)
+{
+ assert_spin_locked(&journal_datalist_lock);
+#ifdef __SMP__
+ J_ASSERT_JH(jh, current->lock_depth >= 0);
+#endif
+ __journal_unfile_buffer(jh);
+
+ /* If the buffer is now unused, just drop it. If it has been
+ modified by a later transaction, add it to the new
+ transaction's metadata list. */
+
+ jh->b_transaction = jh->b_next_transaction;
+ jh->b_next_transaction = NULL;
+


+ if (jh->b_transaction != NULL) {

+ __journal_file_buffer(jh, jh->b_transaction, BJ_Metadata);
+ J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING);
+ } else {
+ /* Onto BUF_DIRTY for writeback */
+ refile_buffer(jh2bh(jh));
+ }
+}
+
+/*
+ * For the unlocked version of this call, also make sure that any
+ * hanging journal_head is cleaned up if necessary.
+ *
+ * __journal_refile_buffer is usually called as part of a single locked
+ * operation on a buffer_head, in which the caller is probably going to
+ * be hooking the journal_head onto other lists. In that case it is up
+ * to the caller to remove the journal_head if necessary. For the
+ * unlocked journal_refile_buffer call, the caller isn't going to be
+ * doing anything else to the buffer so we need to do the cleanup
+ * ourselves to avoid a jh leak.
+ *
+ * *** The journal_head may be freed by this call! ***
+ */
+void journal_refile_buffer(struct journal_head *jh)
+{
+ struct buffer_head *bh;
+
+ spin_lock(&journal_datalist_lock);


+ bh = jh2bh(jh);
+

+ __journal_refile_buffer(jh);
+ __journal_remove_journal_head(bh);
+
+ spin_unlock(&journal_datalist_lock);
+ __brelse(bh);
+}
diff -u --recursive --new-file v2.4.14/linux/fs/jffs2/nodelist.c linux/fs/jffs2/nodelist.c
--- v2.4.14/linux/fs/jffs2/nodelist.c Tue Oct 9 17:06:53 2001
+++ linux/fs/jffs2/nodelist.c Wed Nov 14 08:19:40 2001
@@ -31,7 +31,7 @@
X * provisions above, a recipient may use your version of this file
X * under either the RHEPL or the GPL.
X *
- * $Id: nodelist.c,v 1.29 2001/09/19 00:06:35 dwmw2 Exp $
+ * $Id: nodelist.c,v 1.30 2001/11/14 10:35:21 dwmw2 Exp $


X *
X */
X

@@ -41,26 +41,6 @@
X #include <linux/mtd/mtd.h>
X #include "nodelist.h"
X
-#if 0
-/**
- * jffs2_add_raw_node_ref - Add a jffs2_raw_node_ref to the cached
- * node list for the filesystem
- * @sb: Pointer to filesystem information structure
- * @ref: New node to add
- *
- * Adds a new node reference to the filesystem\'s node cache, which
- * is the only permanent storage required for the filesystem.
- */
-void jffs2_add_raw_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref)
-{
- /* Sort the list, hash it or do _something_ useful with it */
- spin_lock(&c->nodelist_lock);
- ref->next = c->nodelist;
- c->nodelist = ref;
- spin_unlock(&c->nodelist_lock);
- return 0;
-}
-#endif
X void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list)
X {
X struct jffs2_full_dirent **prev = list;
@@ -92,7 +72,7 @@
X D1(while(*list) {
X printk(KERN_DEBUG "Dirent \"%s\" (hash 0x%08x, ino #%u\n", (*list)->name, (*list)->nhash, (*list)->ino);
X list = &(*list)->next;
- })
+ });
X }
X
X /* Put a new tmp_dnode_info into the list, keeping the list in
diff -u --recursive --new-file v2.4.14/linux/fs/minix/file.c linux/fs/minix/file.c
--- v2.4.14/linux/fs/minix/file.c Sun Sep 23 11:41:00 2001
+++ linux/fs/minix/file.c Tue Nov 20 21:34:13 2001
@@ -30,8 +30,10 @@
X int minix_sync_file(struct file * file, struct dentry *dentry, int datasync)
X {
X struct inode *inode = dentry->d_inode;
- int err = fsync_inode_buffers(inode);
+ int err;
X
+ err = fsync_inode_buffers(inode);
+ err |= fsync_inode_data_buffers(inode);
X if (!(inode->i_state & I_DIRTY))
X return err;
X if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
diff -u --recursive --new-file v2.4.14/linux/fs/namespace.c linux/fs/namespace.c
--- v2.4.14/linux/fs/namespace.c Tue Oct 23 22:48:53 2001
+++ linux/fs/namespace.c Sun Nov 11 11:23:14 2001
@@ -22,6 +22,7 @@
X #include <linux/nfs_fs.h>
X #include <linux/nfs_fs_sb.h>
X #include <linux/nfs_mount.h>
+#include <linux/seq_file.h>
X
X struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data);
X int do_remount_sb(struct super_block *sb, int flags, void * data);
@@ -167,159 +168,131 @@
X kill_super(sb);
X }
X
-/* Use octal escapes, like mount does, for embedded spaces etc. */
-static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' };
+/* iterator */
+static void *m_start(struct seq_file *m, loff_t *pos)
+{
+ struct list_head *p;
+ loff_t n = *pos;
X
-static int
-mangle(const unsigned char *s, char *buf, int len) {
- char *sp;
- int n;
-
- sp = buf;
- while(*s && sp-buf < len-3) {
- for (n = 0; n < sizeof(need_escaping); n++) {
- if (*s == need_escaping[n]) {
- *sp++ = '\\';
- *sp++ = '0' + ((*s & 0300) >> 6);
- *sp++ = '0' + ((*s & 070) >> 3);
- *sp++ = '0' + (*s & 07);
- goto next;
- }
- }
- *sp++ = *s;
- next:
- s++;
- }
- return sp - buf; /* no trailing NUL */
-}
-
-static struct proc_fs_info {
- int flag;
- char *str;
-} fs_info[] = {
- { MS_SYNCHRONOUS, ",sync" },
- { MS_MANDLOCK, ",mand" },
- { MS_NOATIME, ",noatime" },
- { MS_NODIRATIME, ",nodiratime" },
- { 0, NULL }
-};
+ down(&mount_sem);
+ list_for_each(p, &vfsmntlist)
+ if (!n--)
+ return list_entry(p, struct vfsmount, mnt_list);
+ return NULL;
+}
X
-static struct proc_fs_info mnt_info[] = {
- { MNT_NOSUID, ",nosuid" },
- { MNT_NODEV, ",nodev" },
- { MNT_NOEXEC, ",noexec" },
- { 0, NULL }
-};
+static void *m_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ struct list_head *p = ((struct vfsmount *)v)->mnt_list.next;
+ (*pos)++;
+ return p==&vfsmntlist ? NULL : list_entry(p, struct vfsmount, mnt_list);
+}
X
-static struct proc_nfs_info {
- int flag;
- char *str;
- char *nostr;
-} nfs_info[] = {
- { NFS_MOUNT_SOFT, ",soft", ",hard" },
- { NFS_MOUNT_INTR, ",intr", "" },
- { NFS_MOUNT_POSIX, ",posix", "" },
- { NFS_MOUNT_TCP, ",tcp", ",udp" },
- { NFS_MOUNT_NOCTO, ",nocto", "" },
- { NFS_MOUNT_NOAC, ",noac", "" },
- { NFS_MOUNT_NONLM, ",nolock", ",lock" },
- { NFS_MOUNT_BROKEN_SUID, ",broken_suid", "" },
- { 0, NULL, NULL }
-};
+static void m_stop(struct seq_file *m, void *v)
+{
+ up(&mount_sem);
+}
X
-int get_filesystem_info( char *buf )
+static inline void mangle(struct seq_file *m, const char *s)
X {
- struct list_head *p;
- struct proc_fs_info *fs_infop;
+ seq_escape(m, s, " \t\n\\");
+}
+
+static void show_nfs_mount(struct seq_file *m, struct vfsmount *mnt)
+{
+ static struct proc_nfs_info {
+ int flag;
+ char *str;
+ char *nostr;
+ } nfs_info[] = {
+ { NFS_MOUNT_SOFT, ",soft", ",hard" },
+ { NFS_MOUNT_INTR, ",intr", "" },
+ { NFS_MOUNT_POSIX, ",posix", "" },
+ { NFS_MOUNT_TCP, ",tcp", ",udp" },
+ { NFS_MOUNT_NOCTO, ",nocto", "" },
+ { NFS_MOUNT_NOAC, ",noac", "" },
+ { NFS_MOUNT_NONLM, ",nolock", ",lock" },
+ { NFS_MOUNT_BROKEN_SUID, ",broken_suid", "" },
+ { 0, NULL, NULL }
+ };
X struct proc_nfs_info *nfs_infop;
- struct nfs_server *nfss;
- int len, prevlen;
- char *path, *buffer = (char *) __get_free_page(GFP_KERNEL);
-
- if (!buffer) return 0;
- len = prevlen = 0;
-
-#define FREEROOM ((int)PAGE_SIZE-200-len)
-#define MANGLE(s) len += mangle((s), buf+len, FREEROOM);
-
- for (p = vfsmntlist.next; p != &vfsmntlist; p = p->next) {
- struct vfsmount *tmp = list_entry(p, struct vfsmount, mnt_list);
- path = d_path(tmp->mnt_root, tmp, buffer, PAGE_SIZE);
- if (!path)
- continue;
- MANGLE(tmp->mnt_devname ? tmp->mnt_devname : "none");
- buf[len++] = ' ';
- MANGLE(path);
- buf[len++] = ' ';
- MANGLE(tmp->mnt_sb->s_type->name);
- len += sprintf(buf+len, " %s",
- tmp->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw");
- for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
- if (tmp->mnt_sb->s_flags & fs_infop->flag)
- MANGLE(fs_infop->str);
- }
- for (fs_infop = mnt_info; fs_infop->flag; fs_infop++) {
- if (tmp->mnt_flags & fs_infop->flag)
- MANGLE(fs_infop->str);
- }
- if (!strcmp("nfs", tmp->mnt_sb->s_type->name)) {
- nfss = &tmp->mnt_sb->u.nfs_sb.s_server;
- len += sprintf(buf+len, ",v%d", nfss->rpc_ops->version);
-
- len += sprintf(buf+len, ",rsize=%d", nfss->rsize);
-
- len += sprintf(buf+len, ",wsize=%d", nfss->wsize);
-#if 0
- if (nfss->timeo != 7*HZ/10) {
- len += sprintf(buf+len, ",timeo=%d",
- nfss->timeo*10/HZ);
- }
- if (nfss->retrans != 3) {
- len += sprintf(buf+len, ",retrans=%d",
- nfss->retrans);
- }
-#endif
- if (nfss->acregmin != 3*HZ) {
- len += sprintf(buf+len, ",acregmin=%d",
- nfss->acregmin/HZ);
- }
- if (nfss->acregmax != 60*HZ) {
- len += sprintf(buf+len, ",acregmax=%d",
- nfss->acregmax/HZ);
- }
- if (nfss->acdirmin != 30*HZ) {
- len += sprintf(buf+len, ",acdirmin=%d",
- nfss->acdirmin/HZ);
- }
- if (nfss->acdirmax != 60*HZ) {
- len += sprintf(buf+len, ",acdirmax=%d",
- nfss->acdirmax/HZ);
- }
- for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
- char *str;
- if (nfss->flags & nfs_infop->flag)
- str = nfs_infop->str;
- else
- str = nfs_infop->nostr;
- MANGLE(str);
- }
- len += sprintf(buf+len, ",addr=");
- MANGLE(nfss->hostname);
- }
- len += sprintf(buf + len, " 0 0\n");
- if (FREEROOM <= 3) {
- len = prevlen;
- len += sprintf(buf+len, "# truncated\n");
- break;
- }
- prevlen = len;
+ struct nfs_server *nfss = &mnt->mnt_sb->u.nfs_sb.s_server;
+
+ seq_printf(m, ",v%d", nfss->rpc_ops->version);
+ seq_printf(m, ",rsize=%d", nfss->rsize);
+ seq_printf(m, ",wsize=%d", nfss->wsize);
+ if (nfss->acregmin != 3*HZ)
+ seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
+ if (nfss->acregmax != 60*HZ)
+ seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
+ if (nfss->acdirmin != 30*HZ)
+ seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
+ if (nfss->acdirmax != 60*HZ)
+ seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
+ for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
+ if (nfss->flags & nfs_infop->flag)
+ seq_puts(m, nfs_infop->str);
+ else
+ seq_puts(m, nfs_infop->nostr);
X }
+ seq_puts(m, ",addr=");
+ mangle(m, nfss->hostname);
+}
X
- free_page((unsigned long) buffer);
- return len;
-#undef MANGLE
-#undef FREEROOM
+static int show_vfsmnt(struct seq_file *m, void *v)
+{
+ struct vfsmount *mnt = v;
+ static struct proc_fs_info {
+ int flag;
+ char *str;
+ } fs_info[] = {
+ { MS_SYNCHRONOUS, ",sync" },
+ { MS_MANDLOCK, ",mand" },
+ { MS_NOATIME, ",noatime" },
+ { MS_NODIRATIME, ",nodiratime" },
+ { 0, NULL }
+ };
+ static struct proc_fs_info mnt_info[] = {
+ { MNT_NOSUID, ",nosuid" },
+ { MNT_NODEV, ",nodev" },
+ { MNT_NOEXEC, ",noexec" },
+ { 0, NULL }
+ };
+ struct proc_fs_info *fs_infop;
+ char *path_buf, *path;
+
+ path_buf = (char *) __get_free_page(GFP_KERNEL);
+ if (!path_buf)
+ return -ENOMEM;
+ path = d_path(mnt->mnt_root, mnt, path_buf, PAGE_SIZE);
+
+ mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
+ seq_putc(m, ' ');
+ mangle(m, path);
+ free_page((unsigned long) path_buf);
+ seq_putc(m, ' ');
+ mangle(m, mnt->mnt_sb->s_type->name);
+ seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? " ro" : " rw");
+ for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
+ if (mnt->mnt_sb->s_flags & fs_infop->flag)
+ seq_puts(m, fs_infop->str);
+ }
+ for (fs_infop = mnt_info; fs_infop->flag; fs_infop++) {
+ if (mnt->mnt_flags & fs_infop->flag)
+ seq_puts(m, fs_infop->str);
+ }
+ if (strcmp("nfs", mnt->mnt_sb->s_type->name) == 0)
+ show_nfs_mount(m, mnt);
+ seq_puts(m, " 0 0\n");
+ return 0;
X }
+
+struct seq_operations mounts_op = {
+ start: m_start,
+ next: m_next,
+ stop: m_stop,
+ show: show_vfsmnt
+};
X
X /*
X * Doesn't take quota and stuff into account. IOW, in some cases it will
diff -u --recursive --new-file v2.4.14/linux/fs/nfs/Makefile linux/fs/nfs/Makefile
--- v2.4.14/linux/fs/nfs/Makefile Fri Dec 29 14:07:23 2000
+++ linux/fs/nfs/Makefile Fri Nov 9 14:28:15 2001
@@ -9,8 +9,8 @@
X
X O_TARGET := nfs.o
X
-obj-y := inode.o file.o read.o write.o dir.o symlink.o proc.o \
- nfs2xdr.o flushd.o unlink.o
+obj-y := dir.o file.o flushd.o inode.o nfs2xdr.o pagelist.o proc.o \
+ read.o symlink.o unlink.o write.o
X
X obj-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o
X obj-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
diff -u --recursive --new-file v2.4.14/linux/fs/nfs/flushd.c linux/fs/nfs/flushd.c
--- v2.4.14/linux/fs/nfs/flushd.c Sat May 19 17:47:55 2001
+++ linux/fs/nfs/flushd.c Fri Nov 9 14:28:15 2001
@@ -38,9 +38,9 @@
X
X #include <linux/nfs.h>
X #include <linux/nfs_fs.h>
+#include <linux/nfs_page.h>
X #include <linux/nfs_fs_sb.h>
X #include <linux/nfs_flushd.h>
-#include <linux/nfs_mount.h>
X
X /*
X * Various constants
@@ -111,13 +111,10 @@
X
X dprintk("NFS: reqlist_exit (ptr %p rpc %p)\n", cache, cache->task);
X
- while (cache->task || cache->inodes) {
- if (!cache->task) {
- nfs_reqlist_init(server);
- } else {
- cache->task->tk_status = -ENOMEM;
- rpc_wake_up_task(cache->task);
- }
+ while (cache->task) {
+ rpc_exit(cache->task, 0);
+ rpc_wake_up_task(cache->task);
+
X interruptible_sleep_on_timeout(&cache->request_wait, 1 * HZ);
X }
X out:
@@ -150,133 +147,47 @@
X }
X }
X
-void nfs_wake_flushd()
-{
- rpc_wake_up_status(&flushd_queue, -ENOMEM);
-}
-
-static void inode_append_flushd(struct inode *inode)
-{
- struct nfs_reqlist *cache = NFS_REQUESTLIST(inode);
- struct inode **q;
-
- if (NFS_FLAGS(inode) & NFS_INO_FLUSH)
- goto out;
- inode->u.nfs_i.hash_next = NULL;
-
- q = &cache->inodes;
- while (*q)
- q = &(*q)->u.nfs_i.hash_next;
- *q = inode;
-
- /* Note: we increase the inode i_count in order to prevent
- * it from disappearing when on the flush list
- */
- NFS_FLAGS(inode) |= NFS_INO_FLUSH;
- atomic_inc(&inode->i_count);
-out:;
-}
-
-/* Protect me using the BKL */
-void inode_remove_flushd(struct inode *inode)
-{
- struct nfs_reqlist *cache = NFS_REQUESTLIST(inode);
- struct inode **q;
-
- if (!(NFS_FLAGS(inode) & NFS_INO_FLUSH))
- return;
-
- q = &cache->inodes;
- while (*q && *q != inode)
- q = &(*q)->u.nfs_i.hash_next;
- if (*q) {
- *q = inode->u.nfs_i.hash_next;
- NFS_FLAGS(inode) &= ~NFS_INO_FLUSH;
- iput(inode);
- }
-}
-
-void inode_schedule_scan(struct inode *inode, unsigned long time)
-{
- struct nfs_reqlist *cache = NFS_REQUESTLIST(inode);
- struct rpc_task *task;
- unsigned long mintimeout;
-
- lock_kernel();
- if (time_after(NFS_NEXTSCAN(inode), time))
- NFS_NEXTSCAN(inode) = time;
- mintimeout = jiffies + 1 * HZ;
- if (time_before(mintimeout, NFS_NEXTSCAN(inode)))
- mintimeout = NFS_NEXTSCAN(inode);
- inode_append_flushd(inode);
-
- task = cache->task;
- if (!task) {
- nfs_reqlist_init(NFS_SERVER(inode));
- } else {
- if (time_after(cache->runat, mintimeout))
- rpc_wake_up_task(task);
- }
- unlock_kernel();
-}
-
-
+#define NFS_FLUSHD_TIMEOUT (30*HZ)
X static void
X nfs_flushd(struct rpc_task *task)
X {
X struct nfs_server *server;
X struct nfs_reqlist *cache;
- struct inode *inode, *next;
- unsigned long delay = jiffies + NFS_WRITEBACK_LOCKDELAY;
- int flush = (task->tk_status == -ENOMEM);
+ LIST_HEAD(head);
X
X dprintk("NFS: %4d flushd starting\n", task->tk_pid);
X server = (struct nfs_server *) task->tk_calldata;
X cache = server->rw_requests;
X
- next = cache->inodes;
- cache->inodes = NULL;
-
- while ((inode = next) != NULL) {
- next = next->u.nfs_i.hash_next;
- inode->u.nfs_i.hash_next = NULL;
- NFS_FLAGS(inode) &= ~NFS_INO_FLUSH;
-
- if (flush) {
- nfs_pagein_inode(inode, 0, 0);
- nfs_sync_file(inode, NULL, 0, 0, FLUSH_AGING);
- } else if (time_after(jiffies, NFS_NEXTSCAN(inode))) {
- NFS_NEXTSCAN(inode) = jiffies + NFS_WRITEBACK_LOCKDELAY;
- nfs_pagein_timeout(inode);
- nfs_flush_timeout(inode, FLUSH_AGING);
-#ifdef CONFIG_NFS_V3
- nfs_commit_timeout(inode, FLUSH_AGING);
-#endif
+ for(;;) {
+ spin_lock(&nfs_wreq_lock);
+ if (nfs_scan_lru_dirty_timeout(server, &head)) {
+ spin_unlock(&nfs_wreq_lock);
+ nfs_flush_list(&head, server->wpages, FLUSH_AGING);
+ continue;
X }
-
- if (nfs_have_writebacks(inode) || nfs_have_read(inode)) {
- inode_append_flushd(inode);
- if (time_after(delay, NFS_NEXTSCAN(inode)))
- delay = NFS_NEXTSCAN(inode);
+ if (nfs_scan_lru_read_timeout(server, &head)) {
+ spin_unlock(&nfs_wreq_lock);
+ nfs_pagein_list(&head, server->rpages);
+ continue;
X }
- iput(inode);
+#ifdef CONFIG_NFS_V3
+ if (nfs_scan_lru_commit_timeout(server, &head)) {
+ spin_unlock(&nfs_wreq_lock);
+ nfs_commit_list(&head, FLUSH_AGING);
+ continue;
+ }
+#endif
+ spin_unlock(&nfs_wreq_lock);
+ break;
X }
X
X dprintk("NFS: %4d flushd back to sleep\n", task->tk_pid);
- if (time_after(jiffies + 1 * HZ, delay))
- delay = 1 * HZ;
- else
- delay = delay - jiffies;
- task->tk_status = 0;
- task->tk_action = nfs_flushd;
- task->tk_timeout = delay;
- cache->runat = jiffies + task->tk_timeout;
-
- if (!atomic_read(&cache->nr_requests) && !cache->inodes) {
- cache->task = NULL;
- task->tk_action = NULL;
- } else
+ if (task->tk_action) {
+ task->tk_timeout = NFS_FLUSHD_TIMEOUT;
+ cache->runat = jiffies + task->tk_timeout;
X rpc_sleep_on(&flushd_queue, task, NULL, NULL);
+ }
X }
X
X static void
diff -u --recursive --new-file v2.4.14/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.4.14/linux/fs/nfs/inode.c Tue Oct 9 17:06:53 2001
+++ linux/fs/nfs/inode.c Fri Nov 9 14:28:15 2001
@@ -324,6 +324,10 @@
X if (!server->hostname)
X goto out_unlock;
X strcpy(server->hostname, data->hostname);
+ INIT_LIST_HEAD(&server->lru_read);
+ INIT_LIST_HEAD(&server->lru_dirty);
+ INIT_LIST_HEAD(&server->lru_commit);
+ INIT_LIST_HEAD(&server->lru_busy);
X
X nfsv3_try_again:
X /* Check NFS protocol revision and initialize RPC op vector
@@ -1072,6 +1076,8 @@
X extern void nfs_destroy_nfspagecache(void);
X extern int nfs_init_readpagecache(void);
X extern int nfs_destroy_readpagecache(void);
+extern int nfs_init_writepagecache(void);
+extern int nfs_destroy_writepagecache(void);
X
X /*
X * Initialize NFS
@@ -1088,6 +1094,10 @@


X if (err)
X return err;
X

+ err = nfs_init_writepagecache();


+ if (err)
+ return err;
+

X #ifdef CONFIG_PROC_FS
X rpc_proc_register(&nfs_rpcstat);
X #endif
@@ -1096,6 +1106,7 @@
X
X static void __exit exit_nfs_fs(void)
X {
+ nfs_destroy_writepagecache();
X nfs_destroy_readpagecache();
X nfs_destroy_nfspagecache();
X #ifdef CONFIG_PROC_FS
@@ -1107,6 +1118,7 @@
X EXPORT_NO_SYMBOLS;
X /* Not quite true; I just maintain it */
X MODULE_AUTHOR("Olaf Kirch <ok...@monad.swb.de>");


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

echo 'End of part 101'
echo 'File patch-2.4.15 is continued in part 102'
echo "102" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:12 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part096

#!/bin/sh -x
# this is part 096 of a 115 - part archive


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

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

+ if ( error ) {
+ EXIT;
+ return error;
+ }
+

+ input.fd = lento_iopen(input.name, (ino_t)input.ino,
+ input.generation, input.flags);
+ CDEBUG(D_PIOCTL, "lento_iopen file descriptor: %d\n", input.fd);
+ if (input.fd < 0) {
+ EXIT;
+ return input.fd;


+ }
+ EXIT;
+ return copy_to_user((char *)arg, &input, sizeof(input));
+ }
+

+ case PRESTO_VFS_CLOSE: {
+ int error;
+ struct lento_input_close input;


+
+ error = copy_from_user(&input, (char *)arg, sizeof(input));
+ if ( error ) {
+ EXIT;
+ return error;
+ }
+

+ CDEBUG(D_PIOCTL, "lento_close file descriptor: %d\n", input.fd);
+ error = lento_close(input.fd, &input.info);


+ EXIT;
+ return error;
+ }
+

+ case PRESTO_BACKFETCH_LML: {
+ char *user_path;
+ int error;
+ struct lml_arg {
+ char *path;
+ __u32 path_len;


+ __u64 remote_ino;
+ __u32 remote_generation;
+ __u32 remote_version;

+ struct presto_version remote_file_version;


+ } input;
+
+ error = copy_from_user(&input, (char *)arg, sizeof(input));
+ if ( error ) {
+ EXIT;
+ return error;
+ }

+ user_path = input.path;
+
+ PRESTO_ALLOC(input.path, char *, input.path_len + 1);
+ if ( !input.path ) {


+ EXIT;
+ return -ENOMEM;
+ }

+ error = copy_from_user(input.path, user_path, input.path_len);


+ if ( error ) {
+ EXIT;

+ PRESTO_FREE(input.path, input.path_len + 1);
+ return error;
+ }
+ input.path[input.path_len] = '\0';
+
+ CDEBUG(D_DOWNCALL, "lml name: %s\n", input.path);
+
+ return lento_write_lml(input.path,
+ input.remote_ino,
+ input.remote_generation,
+ input.remote_version,
+ &input.remote_file_version);
+
+ }
+
+
+ case PRESTO_CANCEL_LML: {
+ char *user_path;
+ int error;
+ struct lml_arg {
+ char *path;
+ __u64 lml_offset;
+ __u32 path_len;


+ __u64 remote_ino;
+ __u32 remote_generation;
+ __u32 remote_version;

+ struct lento_vfs_context info;


+ } input;
+
+ error = copy_from_user(&input, (char *)arg, sizeof(input));
+ if ( error ) {
+ EXIT;
+ return error;
+ }

+ user_path = input.path;
+
+ PRESTO_ALLOC(input.path, char *, input.path_len + 1);
+ if ( !input.path ) {


+ EXIT;
+ return -ENOMEM;
+ }

+ error = copy_from_user(input.path, user_path, input.path_len);


+ if ( error ) {
+ EXIT;

+ PRESTO_FREE(input.path, input.path_len + 1);
+ return error;
+ }
+ input.path[input.path_len] = '\0';
+
+ CDEBUG(D_DOWNCALL, "lml name: %s\n", input.path);
+
+ return lento_cancel_lml(input.path,
+ input.lml_offset,
+ input.remote_ino,
+ input.remote_generation,
+ input.remote_version,
+ &input.info);
+
+ }
+
+ case PRESTO_COMPLETE_CLOSES: {
+ char *user_path;
+ int error;
+ struct lml_arg {
+ char *path;
+ __u32 path_len;


+ } input;
+
+ error = copy_from_user(&input, (char *)arg, sizeof(input));
+ if ( error ) {
+ EXIT;
+ return error;
+ }

+ user_path = input.path;
+
+ PRESTO_ALLOC(input.path, char *, input.path_len + 1);
+ if ( !input.path ) {


+ EXIT;
+ return -ENOMEM;
+ }

+ error = copy_from_user(input.path, user_path, input.path_len);


+ if ( error ) {
+ EXIT;

+ PRESTO_FREE(input.path, input.path_len + 1);
+ return error;
+ }
+ input.path[input.path_len] = '\0';
+
+ CDEBUG(D_DOWNCALL, "lml name: %s\n", input.path);
+
+ error = lento_complete_closes(input.path);
+ PRESTO_FREE(input.path, input.path_len + 1);


+ return error;
+ }
+

+ case PRESTO_RESET_FSET: {
+ char *user_path;
+ int error;
+ struct lml_arg {
+ char *path;
+ __u32 path_len;
+ __u64 offset;
+ __u32 recno;


+ } input;
+
+ error = copy_from_user(&input, (char *)arg, sizeof(input));
+ if ( error ) {
+ EXIT;
+ return error;
+ }

+ user_path = input.path;
+
+ PRESTO_ALLOC(input.path, char *, input.path_len + 1);
+ if ( !input.path ) {


+ EXIT;
+ return -ENOMEM;
+ }

+ error = copy_from_user(input.path, user_path, input.path_len);


+ if ( error ) {
+ EXIT;

+ PRESTO_FREE(input.path, input.path_len + 1);
+ return error;
+ }
+ input.path[input.path_len] = '\0';
+
+ CDEBUG(D_DOWNCALL, "lml name: %s\n", input.path);
+
+ return lento_reset_fset(input.path, input.offset, input.recno);
+
+ }
+
+
+ case PRESTO_MARK: {
+ char *user_path;
+ int res = 0; /* resulting flags - returned to user */
+ int error;
+ struct {
+ int mark_what;
+ int and_flag;
+ int or_flag;
+ int path_len;
+ char *path;


+ } input;
+
+ error = copy_from_user(&input, (char *)arg, sizeof(input));
+ if ( error ) {
+ EXIT;
+ return error;
+ }

+ user_path = input.path;
+
+ PRESTO_ALLOC(input.path, char *, input.path_len + 1);
+ if ( !input.path ) {


+ EXIT;
+ return -ENOMEM;
+ }

+ error = copy_from_user(input.path, user_path, input.path_len);


+ if ( error ) {
+ EXIT;

+ PRESTO_FREE(input.path, input.path_len + 1);
+ return error;
+ }
+ input.path[input.path_len] = '\0';
+
+ CDEBUG(D_DOWNCALL, "mark name: %s, and: %x, or: %x, what %d\n",
+ input.path, input.and_flag, input.or_flag,
+ input.mark_what);
+
+ switch (input.mark_what) {
+ case MARK_DENTRY:
+ error = presto_mark_dentry(input.path,
+ input.and_flag,
+ input.or_flag, &res);
+ break;
+ case MARK_FSET:
+ error = presto_mark_fset(input.path,
+ input.and_flag,
+ input.or_flag, &res);
+ break;
+ case MARK_CACHE:
+ error = presto_mark_cache(input.path,
+ input.and_flag,
+ input.or_flag, &res);
+ break;
+ case MARK_GETFL: {
+ int fflags, cflags;
+ input.and_flag = 0xffffffff;
+ input.or_flag = 0;
+ error = presto_mark_dentry(input.path,
+ input.and_flag,
+ input.or_flag, &res);


+ if (error)
+ break;

+ error = presto_mark_fset(input.path,
+ input.and_flag,
+ input.or_flag, &fflags);


+ if (error)
+ break;

+ error = presto_mark_cache(input.path,
+ input.and_flag,
+ input.or_flag, &cflags);
+
+ if (error)
+ break;
+ input.and_flag = fflags;
+ input.or_flag = cflags;
+ break;
+ }
+ default:


+ error = -EINVAL;
+ }

+
+ PRESTO_FREE(input.path, input.path_len + 1);
+ if (error == -EBUSY) {
+ input.and_flag = error;


+ error = 0;
+ }

+ if (error) {
+ EXIT;
+ return error;
+ }

+ /* return the correct cookie to wait for */
+ input.mark_what = res;


+ return copy_to_user((char *)arg, &input, sizeof(input));
+ }
+

+#ifdef CONFIG_KREINT
+ case PRESTO_REINT_BEGIN:
+ return begin_kml_reint (file, arg);
+ case PRESTO_DO_REINT:
+ return do_kml_reint (file, arg);
+ case PRESTO_REINT_END:
+ return end_kml_reint (file, arg);
+#endif
+
+ case PRESTO_RELEASE_PERMIT: {
+ int error;
+ char *user_path;
+ struct {
+ int cookie;
+ int path_len;
+ char *path;
+ } permit;
+
+ error = copy_from_user(&permit, (char *)arg, sizeof(permit));


+ if ( error ) {
+ EXIT;
+ return error;
+ }

+ user_path = permit.path;
+
+ PRESTO_ALLOC(permit.path, char *, permit.path_len + 1);
+ if ( !permit.path ) {


+ EXIT;
+ return -ENOMEM;
+ }

+ error = copy_from_user(permit.path, user_path, permit.path_len);


+ if ( error ) {
+ EXIT;

+ PRESTO_FREE(permit.path, permit.path_len + 1);
+ return error;
+ }
+ permit.path[permit.path_len] = '\0';
+
+ CDEBUG(D_DOWNCALL, "release permit: %s, in cookie=%d\n",
+ permit.path, permit.cookie);
+ error = presto_permit_downcall(permit.path, &permit.cookie);
+
+ PRESTO_FREE(permit.path, permit.path_len + 1);


+ if (error) {
+ EXIT;
+ return error;
+ }

+ /* return the correct cookie to wait for */
+ return copy_to_user((char *)arg, &permit, sizeof(permit));
+ }
+
+ default:
+ CDEBUG(D_PSDEV, "bad ioctl 0x%x, \n", cmd);
+ CDEBUG(D_PSDEV, "valid are 0x%x - 0x%x, 0x%x - 0x%x \n",
+ PRESTO_GETMOUNT, PRESTO_GET_KMLSIZE,
+ PRESTO_VFS_SETATTR, PRESTO_VFS_IOPEN);
+ EXIT;
+ }
+


+ return -EINVAL;
+}
+
+

+static int presto_psdev_open(struct inode * inode, struct file * file)


+{
+ struct upc_comm *upccom;

+ ENTRY;


+
+ if ( ! (upccom = presto_psdev_f2u(file)) ) {
+ kdev_t dev = file->f_dentry->d_inode->i_rdev;
+ printk("InterMezzo: %s, bad device %s\n",
+ __FUNCTION__, kdevname(dev));

+ EXIT;
+ return -EINVAL;
+ }
+

+ MOD_INC_USE_COUNT;
+
+ CDEBUG(D_PSDEV, "Psdev_open: uc_pid: %d, caller: %d, flags: %d\n",
+ upccom->uc_pid, current->pid, file->f_flags);


+
+ EXIT;
+ return 0;
+}
+
+
+

+static int presto_psdev_release(struct inode * inode, struct file * file)


+{
+ struct upc_comm *upccom;
+ struct upc_req *req;

+ struct list_head *lh;
+ ENTRY;
+
+


+ if ( ! (upccom = presto_psdev_f2u(file)) ) {
+ kdev_t dev = file->f_dentry->d_inode->i_rdev;
+ printk("InterMezzo: %s, bad device %s\n",
+ __FUNCTION__, kdevname(dev));
+ }
+

+ if ( upccom->uc_pid != current->pid ) {
+ printk("psdev_release: Not lento.\n");
+ MOD_DEC_USE_COUNT;


+ return 0;
+ }
+

+ MOD_DEC_USE_COUNT;
+ CDEBUG(D_PSDEV, "Lento: pid %d\n", current->pid);
+ upccom->uc_pid = 0;
+
+ /* Wake up clients so they can return. */
+ CDEBUG(D_PSDEV, "Wake up clients sleeping for pending.\n");
+ lh = &upccom->uc_pending;
+ while ( (lh = lh->next) != &upccom->uc_pending) {


+ req = list_entry(lh, struct upc_req, rq_chain);
+

+ /* Async requests stay around for a new lento */


+ if (req->rq_flags & REQ_ASYNC) {

+ continue;
+ }
+ /* the sleeper will free the req and data */
+ req->rq_flags |= REQ_DEAD;

+ wake_up(&req->rq_sleep);
+ }
+

+ CDEBUG(D_PSDEV, "Wake up clients sleeping for processing\n");


+ lh = &upccom->uc_processing;
+ while ( (lh = lh->next) != &upccom->uc_processing) {
+ req = list_entry(lh, struct upc_req, rq_chain);
+ /* freeing of req and data is done by the sleeper */

+ req->rq_flags |= REQ_DEAD;
+ wake_up(&req->rq_sleep);
+ }
+ CDEBUG(D_PSDEV, "Done.\n");


+
+ EXIT;
+ return 0;
+}
+

+static struct file_operations presto_psdev_fops = {
+ read: presto_psdev_read,
+ write: presto_psdev_write,
+ poll: presto_psdev_poll,
+ ioctl: presto_psdev_ioctl,
+ open: presto_psdev_open,
+ release: presto_psdev_release
+};
+
+
+int presto_psdev_init(void)


+{
+ int i;
+

+#ifdef PRESTO_DEVEL
+ if (register_chrdev(PRESTO_PSDEV_MAJOR, "intermezzo_psdev_devel",
+ &presto_psdev_fops)) {
+ printk(KERN_ERR "presto_psdev: unable to get major %d\n",
+ PRESTO_PSDEV_MAJOR);
+ return -EIO;
+ }
+#else
+ if (register_chrdev(PRESTO_PSDEV_MAJOR, "intermezzo_psdev",
+ &presto_psdev_fops)) {
+ printk("presto_psdev: unable to get major %d\n",
+ PRESTO_PSDEV_MAJOR);
+ return -EIO;
+ }
+#endif
+
+ memset(&upc_comms, 0, sizeof(upc_comms));
+ for ( i = 0 ; i < MAX_PRESTODEV ; i++ ) {
+ char *name;
+ struct upc_comm *psdev = &upc_comms[i];
+ INIT_LIST_HEAD(&psdev->uc_pending);
+ INIT_LIST_HEAD(&psdev->uc_processing);
+ INIT_LIST_HEAD(&psdev->uc_cache_list);
+ init_waitqueue_head(&psdev->uc_waitq);
+ psdev->uc_hard = 0;
+ psdev->uc_no_filter = 0;
+ psdev->uc_no_journal = 0;
+ psdev->uc_no_upcall = 0;
+ psdev->uc_timeout = 30;
+ psdev->uc_errorval = 0;
+ psdev->uc_minor = i;
+ PRESTO_ALLOC(name, char *, strlen(PRESTO_PSDEV_NAME "256")+1);
+ if (!name) {
+ printk("Unable to allocate memory for device name\n");
+ continue;
+ }
+ sprintf(name, PRESTO_PSDEV_NAME "%d", i);
+ psdev->uc_devname = name;
+ }


+ return 0;
+}
+

+void presto_psdev_cleanup(void)


+{
+ int i;
+

+ for ( i = 0 ; i < MAX_PRESTODEV ; i++ ) {
+ struct upc_comm *psdev = &upc_comms[i];


+ struct list_head *lh;
+

+ if ( ! list_empty(&psdev->uc_pending)) {
+ printk("Weird, tell Peter: module cleanup and pending list not empty dev %d\n", i);
+ }
+ if ( ! list_empty(&psdev->uc_processing)) {
+ printk("Weird, tell Peter: module cleanup and processing list not empty dev %d\n", i);
+ }
+ if ( ! list_empty(&psdev->uc_cache_list)) {
+ printk("Weird, tell Peter: module cleanup and cache listnot empty dev %d\n", i);
+ }
+ if (psdev->uc_devname) {
+ PRESTO_FREE(psdev->uc_devname,
+ strlen(PRESTO_PSDEV_NAME "256")+1);
+ }


+ lh = psdev->uc_pending.next;
+ while ( lh != &psdev->uc_pending) {

+ struct upc_req *req;
+

+ req = list_entry(lh, struct upc_req, rq_chain);

+ lh = lh->next;

+ if ( req->rq_flags & REQ_ASYNC ) {
+ list_del(&(req->rq_chain));
+ CDEBUG(D_UPCALL, "free pending upcall type %d\n",
+ req->rq_opcode);


+ PRESTO_FREE(req->rq_data, req->rq_bufsize);

+ PRESTO_FREE(req, sizeof(struct upc_req));
+ } else {
+ req->rq_flags |= REQ_DEAD;

+ wake_up(&req->rq_sleep);
+ }
+ }

+ lh = &psdev->uc_processing;
+ while ( (lh = lh->next) != &psdev->uc_processing ) {
+ struct upc_req *req;


+ req = list_entry(lh, struct upc_req, rq_chain);

+ list_del(&(req->rq_chain));
+ req->rq_flags |= REQ_DEAD;

+ wake_up(&req->rq_sleep);
+ }
+ }
+}

+
+/*
+ * lento_upcall and lento_downcall routines
+ */
+static inline unsigned long lento_waitfor_upcall(struct upc_req *req,
+ int minor)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ unsigned long posttime;
+
+ req->rq_posttime = posttime = jiffies;
+
+ add_wait_queue(&req->rq_sleep, &wait);
+ for (;;) {
+ if ( upc_comms[minor].uc_hard == 0 )
+ current->state = TASK_INTERRUPTIBLE;
+ else
+ current->state = TASK_UNINTERRUPTIBLE;
+
+ /* got a reply */
+ if ( req->rq_flags & (REQ_WRITE | REQ_DEAD) )
+ break;
+
+ if ( !upc_comms[minor].uc_hard && signal_pending(current) ) {
+ /* if this process really wants to die, let it go */
+ if (sigismember(&(current->pending.signal), SIGKILL)||
+ sigismember(&(current->pending.signal), SIGINT) )
+ break;
+ /* signal is present: after timeout always return
+ really smart idea, probably useless ... */
+ if ( jiffies > req->rq_posttime +
+ upc_comms[minor].uc_timeout * HZ )
+ break;
+ }
+ schedule();
+
+ }


+ list_del(&req->rq_chain);
+ INIT_LIST_HEAD(&req->rq_chain);

+ remove_wait_queue(&req->rq_sleep, &wait);
+ current->state = TASK_RUNNING;
+
+ CDEBUG(D_SPECIAL, "posttime: %ld, returned: %ld\n",
+ posttime, jiffies-posttime);
+ return (jiffies - posttime);
+
+}
+
+/*
+ * lento_upcall will return an error in the case of
+ * failed communication with Lento _or_ will peek at Lento
+ * reply and return Lento's error.
+ *
+ * As lento has 2 types of errors, normal errors (positive) and internal
+ * errors (negative), normal errors are negated, while internal errors
+ * are all mapped to -EINTR, while showing a nice warning message. (jh)
+ *
+ * lento_upcall will always free buffer, either directly, when an upcall
+ * is read (in presto_psdev_read), when the filesystem is unmounted, or
+ * when the module is unloaded.
+ */
+int lento_upcall(int minor, int bufsize, int *rep_size, union up_args *buffer,
+ int async, struct upc_req *rq)
+{
+ unsigned long runtime;
+ struct upc_comm *upc_commp;
+ union down_args *out;
+ struct upc_req *req;
+ int error = 0;
+
+ ENTRY;
+ upc_commp = &(upc_comms[minor]);
+
+ if (upc_commp->uc_no_upcall) {
+ EXIT;
+ goto exit_buf;
+ }
+ if (!upc_commp->uc_pid && !async) {
+ EXIT;
+ error = -ENXIO;
+ goto exit_buf;
+ }
+
+ /* Format the request message. */
+ CDEBUG(D_UPCALL, "buffer at %p, size %d\n", buffer, bufsize);
+ PRESTO_ALLOC(req, struct upc_req *, sizeof(struct upc_req));
+ if ( !req ) {
+ EXIT;
+ error = -ENOMEM;
+ goto exit_buf;
+ }
+ req->rq_data = (void *)buffer;
+ req->rq_flags = 0;
+ req->rq_bufsize = bufsize;
+ req->rq_rep_size = 0;
+ req->rq_opcode = ((union up_args *)buffer)->uh.opcode;
+ req->rq_unique = ++upc_commp->uc_seq;
+ init_waitqueue_head(&req->rq_sleep);
+
+ /* Fill in the common input args. */
+ ((union up_args *)buffer)->uh.unique = req->rq_unique;
+ /* Append msg to pending queue and poke Lento. */
+ list_add(&req->rq_chain, upc_commp->uc_pending.prev);
+ CDEBUG(D_UPCALL,
+ "Proc %d waking Lento %d for(opc,uniq) =(%d,%d) msg at %p.\n",
+ current->pid, upc_commp->uc_pid, req->rq_opcode,
+ req->rq_unique, req);
+
+ wake_up_interruptible(&upc_commp->uc_waitq);
+
+ if ( async ) {
+ req->rq_flags = REQ_ASYNC;
+ if( rq != NULL ) {
+ *rq = *req; /* struct copying */
+ }
+ /* req, rq_data are freed in presto_psdev_read for async */


+ EXIT;
+ return 0;
+ }
+

+ /* We can be interrupted while we wait for Lento to process
+ * our request. If the interrupt occurs before Lento has read
+ * the request, we dequeue and return. If it occurs after the
+ * read but before the reply, we dequeue, send a signal
+ * message, and return. If it occurs after the reply we ignore
+ * it. In no case do we want to restart the syscall. If it
+ * was interrupted by a lento shutdown (psdev_close), return
+ * ENODEV. */
+
+ /* Go to sleep. Wake up on signals only after the timeout. */
+ runtime = lento_waitfor_upcall(req, minor);
+
+ CDEBUG(D_TIMING, "opc: %d time: %ld uniq: %d size: %d\n",
+ req->rq_opcode, jiffies - req->rq_posttime,
+ req->rq_unique, req->rq_rep_size);
+ CDEBUG(D_UPCALL,
+ "..process %d woken up by Lento for req at 0x%x, data at %x\n",
+ current->pid, (int)req, (int)req->rq_data);
+
+ if (upc_commp->uc_pid) { /* i.e. Lento is still alive */
+ /* Op went through, interrupt or not we go on */
+ if (req->rq_flags & REQ_WRITE) {
+ out = (union down_args *)req->rq_data;
+ /* here we map positive Lento errors to kernel errors */
+ if ( out->dh.result < 0 ) {
+ printk("Tell Peter: Lento returns negative error %d, for oc %d!\n",
+ out->dh.result, out->dh.opcode);
+ out->dh.result = EINVAL;
+ }
+ error = -out->dh.result;
+ CDEBUG(D_UPCALL, "upcall: (u,o,r) (%d, %d, %d) out at %p\n",
+ out->dh.unique, out->dh.opcode, out->dh.result, out);
+ *rep_size = req->rq_rep_size;
+ EXIT;
+ goto exit_req;
+ }
+ /* Interrupted before lento read it. */
+ if ( !(req->rq_flags & REQ_READ) && signal_pending(current)) {
+ CDEBUG(D_UPCALL,
+ "Interrupt before read: (op,un)=(%d,%d), flags %x\n",
+ req->rq_opcode, req->rq_unique, req->rq_flags);
+ /* perhaps the best way to convince the app to give up? */
+ error = -EINTR;
+ EXIT;
+ goto exit_req;
+ }
+
+ /* interrupted after Lento did its read, send signal */
+ if ( (req->rq_flags & REQ_READ) && signal_pending(current) ) {
+ union up_args *sigargs;
+ struct upc_req *sigreq;
+
+ CDEBUG(D_UPCALL,"Sending for: op = %d.%d, flags = %x\n",
+ req->rq_opcode, req->rq_unique, req->rq_flags);
+
+ error = -EINTR;
+
+ /* req, rq_data are freed in presto_psdev_read for async */
+ PRESTO_ALLOC(sigreq, struct upc_req *,
+ sizeof (struct upc_req));
+ if (!sigreq) {


+ error = -ENOMEM;
+ EXIT;

+ goto exit_req;
+ }
+ PRESTO_ALLOC((sigreq->rq_data), char *,
+ sizeof(struct lento_up_hdr));
+ if (!(sigreq->rq_data)) {
+ PRESTO_FREE(sigreq, sizeof (struct upc_req));


+ error = -ENOMEM;
+ EXIT;

+ goto exit_req;
+ }
+
+ sigargs = (union up_args *)sigreq->rq_data;
+ sigargs->uh.opcode = LENTO_SIGNAL;
+ sigargs->uh.unique = req->rq_unique;
+
+ sigreq->rq_flags = REQ_ASYNC;
+ sigreq->rq_opcode = sigargs->uh.opcode;
+ sigreq->rq_unique = sigargs->uh.unique;
+ sigreq->rq_bufsize = sizeof(struct lento_up_hdr);
+ sigreq->rq_rep_size = 0;
+ CDEBUG(D_UPCALL,
+ "presto_upcall: enqueing signal msg (%d, %d)\n",
+ sigreq->rq_opcode, sigreq->rq_unique);
+
+ /* insert at head of queue! */
+ list_add(&sigreq->rq_chain, &upc_commp->uc_pending);
+ wake_up_interruptible(&upc_commp->uc_waitq);
+ } else {
+ printk("Lento: Strange interruption - tell Peter.\n");
+ error = -EINTR;
+ }
+ } else { /* If lento died i.e. !UC_OPEN(upc_commp) */
+ printk("presto_upcall: Lento dead on (op,un) (%d.%d) flags %d\n",
+ req->rq_opcode, req->rq_unique, req->rq_flags);
+ error = -ENODEV;
+ }
+
+exit_req:
+ PRESTO_FREE(req, sizeof(struct upc_req));
+exit_buf:
+ PRESTO_FREE(buffer, bufsize);


+ return error;
+}
+
+

diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/super.c linux/fs/intermezzo/super.c
--- v2.4.14/linux/fs/intermezzo/super.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/super.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,528 @@
+/*
+ * presto's super.c
+ *
+ * Copyright (C) 1998 Peter J. Braam


+ * Copyright (C) 2000 Stelias Computing, Inc.

+ * Copyright (C) 2000 Red Hat, Inc.
+ *
+ *
+ */
+
+


+#include <stdarg.h>
+
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>

+#include <linux/slab.h>
+#include <linux/vmalloc.h>


+#include <linux/sched.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/locks.h>
+#include <linux/blkdev.h>
+#include <linux/init.h>
+#define __NO_VERSION__
+#include <linux/module.h>

+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+

+#ifdef PRESTO_DEBUG
+long presto_vmemory = 0;
+long presto_kmemory = 0;
+#endif
+
+extern struct presto_cache *presto_init_cache(void);
+extern inline void presto_cache_add(struct presto_cache *cache, kdev_t dev);
+extern inline void presto_init_cache_hash(void);
+
+int presto_remount(struct super_block *, int *, char *);
+extern ssize_t presto_file_write(struct file *file, const char *buf,
+ size_t size, loff_t *off);
+
+/*
+ * Reading the super block.


+ *
+ *
+ *

+ */
+
+/* returns an allocated string, copied out from data if opt is found */
+static char *read_opt(const char *opt, char *data)
+{
+ char *value;
+ char *retval;
+
+ CDEBUG(D_SUPER, "option: %s, data %s\n", opt, data);
+ if ( strncmp(opt, data, strlen(opt)) )
+ return NULL;
+
+ if ( (value = strchr(data, '=')) == NULL )
+ return NULL;
+
+ value++;
+ PRESTO_ALLOC(retval, char *, strlen(value) + 1);
+ if ( !retval ) {
+ printk("InterMezzo: Out of memory!\n");
+ return NULL;
+ }
+
+ strcpy(retval, value);
+ CDEBUG(D_SUPER, "Assigned option: %s, value %s\n", opt, retval);


+ return retval;
+}
+

+static void store_opt(char **dst, char *opt, char *defval)
+{
+ if (dst) {
+ if (*dst) {
+ PRESTO_FREE(*dst, strlen(*dst) + 1);
+ }
+ *dst = opt;
+ } else {
+ printk("presto: store_opt, error dst == NULL\n");
+ }
+
+
+ if (!opt && defval) {
+ char *def_alloced;
+ PRESTO_ALLOC(def_alloced, char *, strlen(defval)+1);
+ strcpy(def_alloced, defval);
+ *dst = def_alloced;
+ }
+}
+
+
+/* Find the options for InterMezzo in "options", saving them into the
+ * passed pointers. If the pointer is null, the option is discarded.
+ * Copy out all non-InterMezzo options into cache_data (to be passed
+ * to the read_super operation of the cache). The return value will
+ * be a pointer to the end of the cache_data.
+ */
+static char *presto_options(char *options, char *cache_data,
+ char **cache_type, char **fileset,
+ char **prestodev, char **mtpt)
+{
+ char *this_char;
+ char *cache_data_end = cache_data;
+
+ if (!options || !cache_data)
+ return cache_data_end;
+
+ /* set the defaults */
+ store_opt(cache_type, NULL, "ext3");
+ store_opt(prestodev, NULL, PRESTO_PSDEV_NAME "0");
+
+ CDEBUG(D_SUPER, "parsing options\n");


+ for (this_char = strtok (options, ",");
+ this_char != NULL;
+ this_char = strtok (NULL, ",")) {

+ char *opt;
+ CDEBUG(D_SUPER, "this_char %s\n", this_char);
+
+ if ( (opt = read_opt("fileset", this_char)) ) {
+ store_opt(fileset, opt, NULL);
+ continue;
+ }
+ if ( (opt = read_opt("cache_type", this_char)) ) {
+ store_opt(cache_type, opt, "ext3");
+ continue;
+ }
+ if ( (opt = read_opt("mtpt", this_char)) ) {
+ store_opt(mtpt, opt, NULL);
+ continue;
+ }
+ if ( (opt = read_opt("prestodev", this_char)) ) {
+ store_opt(prestodev, opt, PRESTO_PSDEV_NAME);
+ continue;
+ }
+
+ cache_data_end += sprintf(cache_data_end, "%s%s",
+ cache_data_end != cache_data ? ",":"",
+ this_char);
+ }
+
+ return cache_data_end;
+}
+
+/*
+ map a /dev/intermezzoX path to a minor:
+ used to validate mount options passed to InterMezzo
+ */
+static int presto_get_minor(char *dev_path, int *minor)


+{
+ struct nameidata nd;
+ struct dentry *dentry;

+ kdev_t devno = 0;


+ int error;
+ ENTRY;
+

+ /* Special case for root filesystem - use minor 0 always. */
+ if ( current->pid == 1 ) {
+ *minor = 0;


+ return 0;
+ }
+

+ error = presto_walk(dev_path, &nd);


+ if (error) {
+ EXIT;
+ return error;
+ }
+ dentry = nd.dentry;
+

+ error = -ENODEV;
+ if (!dentry->d_inode) {
+ EXIT;


+ goto out;
+ }
+

+ if (!S_ISCHR(dentry->d_inode->i_mode)) {
+ EXIT;


+ goto out;
+ }
+

+ devno = dentry->d_inode->i_rdev;
+ if ( MAJOR(devno) != PRESTO_PSDEV_MAJOR ) {
+ EXIT;
+ goto out;
+ }
+
+ if ( MINOR(devno) >= MAX_PRESTODEV ) {
+ EXIT;
+ goto out;
+ }
+
+ EXIT;
+ out:
+ *minor = MINOR(devno);
+ path_release(&nd);


+ return 0;
+}
+

+/* We always need to remove the presto options before passing to bottom FS */
+struct super_block * presto_read_super(struct super_block * presto_sb,
+ void * data, int silent)
+{
+ struct super_block *mysb = NULL;
+ struct file_system_type *fstype;
+ struct presto_cache *cache = NULL;
+ char *cache_data = NULL;
+ char *cache_data_end;
+ char *cache_type = NULL;
+ char *fileset = NULL;
+ char *presto_mtpt = NULL;
+ char *prestodev = NULL;
+ struct filter_fs *ops;
+ int minor;
+ struct upc_comm *psdev;
+
+ ENTRY;
+ CDEBUG(D_MALLOC, "before parsing: kmem %ld, vmem %ld\n",
+ presto_kmemory, presto_vmemory);
+
+ /* reserve space for the cache's data */
+ PRESTO_ALLOC(cache_data, void *, PAGE_SIZE);
+ if ( !cache_data ) {
+ printk("presto_read_super: Cannot allocate data page.\n");
+ EXIT;
+ goto out_err;
+ }
+
+ CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
+
+ /* read and validate options */
+ cache_data_end = presto_options(data, cache_data, &cache_type, &fileset,
+ &prestodev, &presto_mtpt);
+
+ /* was there anything for the cache filesystem in the data? */
+ if (cache_data_end == cache_data) {
+ PRESTO_FREE(cache_data, PAGE_SIZE);
+ cache_data = NULL;
+ } else {
+ CDEBUG(D_SUPER, "cache_data at %p is: %s\n", cache_data,
+ cache_data);
+ }
+
+ /* prepare the communication channel */
+ if ( presto_get_minor(prestodev, &minor) ) {
+ /* if (!silent) */
+ printk("InterMezzo: %s not a valid presto dev\n", prestodev);
+ EXIT;
+ goto out_err;
+ }
+ psdev = &upc_comms[minor];
+ CDEBUG(D_SUPER, "\n");
+ psdev->uc_no_filter = 1;
+
+ CDEBUG(D_SUPER, "presto minor is %d\n", minor);
+
+ /* set up the cache */
+ cache = presto_init_cache();


+ if ( !cache ) {

+ printk("presto_read_super: failure allocating cache.\n");
+ EXIT;
+ goto out_err;
+ }
+
+ /* no options were passed: likely we are "/" readonly */
+ if ( !presto_mtpt || !fileset ) {
+ cache->cache_flags |= CACHE_LENTO_RO | CACHE_CLIENT_RO;
+ }
+ cache->cache_psdev = psdev;
+ /* no options were passed: likely we are "/" readonly */
+ /* before the journaling infrastructure can work, these
+ need to be set; that happens in presto_remount */
+ if ( !presto_mtpt || !fileset ) {
+ if (!presto_mtpt)
+ printk("No mountpoint marking cache RO\n");
+ if (!fileset)
+ printk("No fileset marking cache RO\n");
+ cache->cache_flags |= CACHE_LENTO_RO | CACHE_CLIENT_RO;
+ }
+
+ cache->cache_mtpt = presto_mtpt;
+ cache->cache_root_fileset = fileset;
+ cache->cache_type = cache_type;
+
+ printk("Presto: type=%s, vol=%s, dev=%s (minor %d), mtpt %s, flags %x\n",
+ cache_type, fileset ? fileset : "NULL", prestodev, minor,
+ presto_mtpt ? presto_mtpt : "NULL", cache->cache_flags);
+
+
+ MOD_INC_USE_COUNT;
+ fstype = get_fs_type(cache_type);
+
+ cache->cache_filter = filter_get_filter_fs((const char *)cache_type);
+ if ( !fstype || !cache->cache_filter) {
+ printk("Presto: unrecognized fs type or cache type\n");
+ MOD_DEC_USE_COUNT;
+ EXIT;
+ goto out_err;
+ }
+ mysb = fstype->read_super(presto_sb, cache_data, silent);
+ /* this might have been freed above */
+ if (cache_data) {
+ PRESTO_FREE(cache_data, PAGE_SIZE);
+ cache_data = NULL;
+ }
+ if ( !mysb ) {
+ /* if (!silent) */
+ printk("InterMezzo: cache mount failure.\n");
+ MOD_DEC_USE_COUNT;
+ EXIT;


+ goto out_err;
+ }
+

+ cache->cache_sb = mysb;
+ ops = filter_get_filter_fs(cache_type);
+
+ filter_setup_journal_ops(cache->cache_filter, cache->cache_type);
+
+ /* we now know the dev of the cache: hash the cache */
+ presto_cache_add(cache, mysb->s_dev);
+
+ /* make sure we have our own super operations: mysb
+ still contains the cache operations */
+ filter_setup_super_ops(cache->cache_filter, mysb->s_op,
+ &presto_super_ops);
+ mysb->s_op = filter_c2usops(cache->cache_filter);
+
+ /* now get our own directory operations */
+ if ( mysb->s_root && mysb->s_root->d_inode ) {
+ CDEBUG(D_SUPER, "\n");
+ filter_setup_dir_ops(cache->cache_filter,
+ mysb->s_root->d_inode,
+ &presto_dir_iops, &presto_dir_fops);
+ mysb->s_root->d_inode->i_op = filter_c2udiops(cache->cache_filter);
+ CDEBUG(D_SUPER, "lookup at %p\n",
+ mysb->s_root->d_inode->i_op->lookup);
+ filter_setup_dentry_ops(cache->cache_filter,
+ mysb->s_root->d_op,
+ &presto_dentry_ops);
+ presto_sb->s_root->d_op = filter_c2udops(cache->cache_filter);
+ cache->cache_mtde = mysb->s_root;
+ presto_set_dd(mysb->s_root);
+ }
+
+ CDEBUG(D_MALLOC, "after mounting: kmem %ld, vmem %ld\n",
+ presto_kmemory, presto_vmemory);
+
+ EXIT;
+ return mysb;
+
+ out_err:
+ CDEBUG(D_SUPER, "out_err called\n");
+ if (cache)
+ PRESTO_FREE(cache, sizeof(struct presto_cache));
+ if (cache_data)
+ PRESTO_FREE(cache_data, PAGE_SIZE);
+ if (fileset)
+ PRESTO_FREE(fileset, strlen(fileset) + 1);
+ if (presto_mtpt)
+ PRESTO_FREE(presto_mtpt, strlen(presto_mtpt) + 1);
+ if (prestodev)
+ PRESTO_FREE(prestodev, strlen(prestodev) + 1);
+ if (cache_type)
+ PRESTO_FREE(cache_type, strlen(cache_type) + 1);
+
+ CDEBUG(D_MALLOC, "mount error exit: kmem %ld, vmem %ld\n",
+ presto_kmemory, presto_vmemory);


+ return NULL;
+}
+

+int presto_remount(struct super_block * sb, int *flags, char *data)
+{
+ char *cache_data = NULL;
+ char *cache_data_end;
+ char **type;
+ char **fileset;
+ char **mtpt;
+ char **prestodev;
+ struct super_operations *sops;
+ struct presto_cache *cache = NULL;
+ int err = 0;
+
+ ENTRY;
+ CDEBUG(D_MALLOC, "before remount: kmem %ld, vmem %ld\n",
+ presto_kmemory, presto_vmemory);
+ CDEBUG(D_SUPER, "remount opts: %s\n", data ? (char *)data : "(none)");
+ if (data) {
+ /* reserve space for the cache's data */
+ PRESTO_ALLOC(cache_data, void *, PAGE_SIZE);
+ if ( !cache_data ) {
+ err = -ENOMEM;
+ EXIT;
+ goto out_err;
+ }
+ }
+


+ cache = presto_find_cache(sb->s_dev);
+ if (!cache) {

+ printk(__FUNCTION__ ": cannot find cache on remount\n");
+ err = -ENODEV;
+ EXIT;
+ goto out_err;
+ }
+
+ /* If an option has not yet been set, we allow it to be set on
+ * remount. If an option already has a value, we pass NULL for
+ * the option pointer, which means that the InterMezzo option
+ * will be parsed but discarded.
+ */
+ type = cache->cache_type ? NULL : &cache->cache_type;
+ fileset = cache->cache_root_fileset ? NULL : &cache->cache_root_fileset;
+ prestodev = cache->cache_psdev ? NULL : &cache->cache_psdev->uc_devname;
+ mtpt = cache->cache_mtpt ? NULL : &cache->cache_mtpt;
+ cache_data_end = presto_options(data, cache_data, type, fileset,
+ prestodev, mtpt);
+
+ if (cache_data) {
+ if (cache_data_end == cache_data) {
+ PRESTO_FREE(cache_data, PAGE_SIZE);
+ cache_data = NULL;
+ } else {
+ CDEBUG(D_SUPER, "cache_data at %p is: %s\n", cache_data,
+ cache_data);
+ }
+ }
+
+ if (cache->cache_root_fileset && cache->cache_mtpt) {
+ cache->cache_flags &= ~(CACHE_LENTO_RO|CACHE_CLIENT_RO);
+ }


+
+ sops = filter_c2csops(cache->cache_filter);

+ if (sops->remount_fs) {
+ err = sops->remount_fs(sb, flags, cache_data);
+ }
+
+ CDEBUG(D_MALLOC, "after remount: kmem %ld, vmem %ld\n",
+ presto_kmemory, presto_vmemory);
+ EXIT;
+out_err:
+ if (cache_data)
+ PRESTO_FREE(cache_data, PAGE_SIZE);


+ return err;
+}
+

+struct file_system_type presto_fs_type = {
+#ifdef PRESTO_DEVEL
+ "izofs",
+#else
+ "intermezzo",
+#endif
+ FS_REQUIRES_DEV, /* can use Ibaskets when ext2 does */
+ presto_read_super,
+ NULL
+};
+
+
+int /* __init */ init_intermezzo_fs(void)
+{
+ int status;
+
+ printk(KERN_INFO "InterMezzo Kernel/Lento communications, "
+ "v1.04, br...@inter-mezzo.org\n");
+
+ status = presto_psdev_init();
+ if ( status ) {
+ printk("Problem (%d) in init_intermezzo_psdev\n", status);
+ return status;
+ }
+
+ status = init_intermezzo_sysctl();
+ if (status) {
+ printk("presto: failed in init_intermezzo_sysctl!\n");
+ }
+
+ presto_init_cache_hash();
+ presto_init_ddata_cache();
+
+ status = register_filesystem(&presto_fs_type);
+ if (status) {
+ printk("presto: failed in register_filesystem!\n");
+ }
+ return status;
+}
+
+
+#ifdef MODULE
+MODULE_AUTHOR("Peter J. Braam <br...@inter-mezzo.org>");
+MODULE_DESCRIPTION("InterMezzo Kernel/Lento communications, v1.0.5.1");
+
+int init_module(void)
+{
+ return init_intermezzo_fs();
+}
+
+
+void cleanup_module(void)
+{
+ int err;
+
+ ENTRY;
+
+ if ( (err = unregister_filesystem(&presto_fs_type)) != 0 ) {
+ printk("presto: failed to unregister filesystem\n");
+ }
+
+ presto_psdev_cleanup();
+ cleanup_intermezzo_sysctl();
+ presto_cleanup_ddata_cache();
+
+#ifdef PRESTO_DEVEL
+ unregister_chrdev(PRESTO_PSDEV_MAJOR, "intermezzo_psdev_devel");
+#else
+ unregister_chrdev(PRESTO_PSDEV_MAJOR, "intermezzo_psdev");
+#endif
+ CDEBUG(D_MALLOC, "after cleanup: kmem %ld, vmem %ld\n",
+ presto_kmemory, presto_vmemory);
+}
+
+#endif
+
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/sysctl.c linux/fs/intermezzo/sysctl.c
--- v2.4.14/linux/fs/intermezzo/sysctl.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/sysctl.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,361 @@
+/*
+ * Sysctrl entries for Intermezzo!


+ */
+
+#define __NO_VERSION__

+#include <linux/config.h> /* for CONFIG_PROC_FS */
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+#include <linux/swapctl.h>
+#include <linux/proc_fs.h>


+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/stat.h>

+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <asm/bitops.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/utsname.h>
+#include <linux/blk.h>
+
+
+#include <linux/intermezzo_fs.h>


+#include <linux/intermezzo_psdev.h>
+#include <linux/intermezzo_upcall.h>
+

+/* /proc entries */
+
+#ifdef CONFIG_PROC_FS
+struct proc_dir_entry *proc_fs_intermezzo;
+int intermezzo_mount_get_info( char * buffer, char ** start, off_t offset,
+ int length)
+{
+ int len=0;
+
+ /* this works as long as we are below 1024 characters! */
+ len += presto_sprint_mounts(buffer, length, -1);
+
+ *start = buffer + offset;
+ len -= offset;
+
+ if ( len < 0 )
+ return -EINVAL;
+
+ return len;


+}
+
+#endif
+
+

+/* SYSCTL below */
+
+static struct ctl_table_header *intermezzo_table_header = NULL;
+/* 0x100 to avoid any chance of collisions at any point in the tree with
+ * non-directories
+ */
+#define PSDEV_INTERMEZZO (0x100)
+
+#define PSDEV_DEBUG 1 /* control debugging */
+#define PSDEV_TRACE 2 /* control enter/leave pattern */
+#define PSDEV_TIMEOUT 3 /* timeout on upcalls to become intrble */
+#define PSDEV_HARD 4 /* mount type "hard" or "soft" */
+#define PSDEV_NO_FILTER 5 /* controls presto_chk */
+#define PSDEV_NO_JOURNAL 6 /* controls presto_chk */
+#define PSDEV_NO_UPCALL 7 /* controls lento_upcall */
+#define PSDEV_ERRORVAL 8 /* controls presto_debug_fail_blkdev */
+#define PSDEV_EXCL_GID 9 /* which GID is ignored by presto */
+#define PSDEV_ILOOKUP_UID 10 /* which UID bypasses file access perms */
+#define PSDEV_BYTES_TO_CLOSE 11 /* bytes to write before close */
+
+/* These are global presto control options */
+#define PRESTO_PRIMARY_CTLCNT 4
+static struct ctl_table presto_table[ PRESTO_PRIMARY_CTLCNT + MAX_PRESTODEV + 1] =
+{
+ {PSDEV_DEBUG, "debug", &presto_debug, sizeof(int), 0644, NULL, &proc_dointvec},
+ {PSDEV_TRACE, "trace", &presto_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
+ {PSDEV_EXCL_GID, "presto_excluded_gid", &presto_excluded_gid, sizeof(int), 0644, NULL, &proc_dointvec},
+ {PSDEV_ILOOKUP_UID, "presto_ilookup_uid", &presto_ilookup_uid, sizeof(int), 0644, NULL, &proc_dointvec},
+};
+
+/*
+ * Intalling the sysctl entries: strategy
+ * - have templates for each /proc/sys/intermezzo/ entry
+ * such an entry exists for each /dev/presto
+ * (proto_prestodev_entry)
+ * - have a template for the contents of such directories
+ * (proto_psdev_table)
+ * - have the master table (presto_table)
+ *
+ * When installing, malloc, memcpy and fix up the pointers to point to
+ * the appropriate constants in upc_comms[your_minor]
+ */
+
+static ctl_table proto_psdev_table[] = {
+ {PSDEV_HARD, "hard", 0, sizeof(int), 0644, NULL, &proc_dointvec},
+ {PSDEV_NO_FILTER, "no_filter", 0, sizeof(int), 0644, NULL, &proc_dointvec},
+ {PSDEV_NO_JOURNAL, "no_journal", NULL, sizeof(int), 0644, NULL, &proc_dointvec},
+ {PSDEV_NO_UPCALL, "no_upcall", NULL, sizeof(int), 0644, NULL, &proc_dointvec},
+ {PSDEV_TIMEOUT, "timeout", NULL, sizeof(int), 0644, NULL, &proc_dointvec},
+ {PSDEV_TRACE, "trace", NULL, sizeof(int), 0644, NULL, &proc_dointvec},
+ {PSDEV_DEBUG, "debug", NULL, sizeof(int), 0644, NULL, &proc_dointvec},
+#ifdef PRESTO_DEBUG
+ {PSDEV_ERRORVAL, "errorval", NULL, sizeof(int), 0644, NULL, &proc_dointvec},
+#endif
+ { 0 }
+};
+
+static ctl_table proto_prestodev_entry = {
+ PSDEV_INTERMEZZO, 0, NULL, 0, 0555, 0,
+};
+
+static ctl_table intermezzo_table[2] = {
+ {PSDEV_INTERMEZZO, "intermezzo", NULL, 0, 0555, presto_table},
+ {0}
+};
+
+/* support for external setting and getting of opts. */
+/* particularly via ioctl. The Right way to do this is via sysctl,
+ * but that will have to wait until intermezzo gets its own nice set of
+ * sysctl IDs
+ */
+/* we made these separate as setting may in future be more restricted
+ * than getting
+ */
+int dosetopt(int minor, struct psdev_opt *opt)
+{


+ int retval = 0;

+ int newval = opt->optval;
+
+ ENTRY;
+
+ switch(opt->optname) {
+
+ case PSDEV_TIMEOUT:
+ upc_comms[minor].uc_timeout = newval;
+ break;
+
+ case PSDEV_HARD:
+ upc_comms[minor].uc_hard = newval;
+ break;
+
+ case PSDEV_NO_FILTER:
+ upc_comms[minor].uc_no_filter = newval;
+ break;
+
+ case PSDEV_NO_JOURNAL:
+ upc_comms[minor].uc_no_journal = newval;
+ break;
+
+ case PSDEV_NO_UPCALL:
+ upc_comms[minor].uc_no_upcall = newval;
+ break;
+
+#ifdef PRESTO_DEBUG
+ case PSDEV_ERRORVAL: {
+ /* If we have a positive arg, set a breakpoint for that
+ * value. If we have a negative arg, make that device
+ * read-only. FIXME It would be much better to only
+ * allow setting the underlying device read-only for the
+ * current presto cache.
+ */


+ int errorval = upc_comms[minor].uc_errorval;

+ if (errorval < 0) {
+ if (newval == 0)
+ set_device_ro(-errorval, 0);
+ else
+ printk("device %s already read only\n",
+ kdevname(-errorval));
+ } else {
+ if (newval < 0)
+ set_device_ro(-newval, 1);
+ upc_comms[minor].uc_errorval = newval;
+ CDEBUG(D_PSDEV, "setting errorval to %d\n", newval);
+ }
+
+ break;
+ }
+#endif
+
+ case PSDEV_TRACE:
+ case PSDEV_DEBUG:
+ case PSDEV_BYTES_TO_CLOSE:
+ default:
+ CDEBUG(D_PSDEV,
+ "ioctl: dosetopt: minor %d, bad optname 0x%x, \n",
+ minor, opt->optname);
+
+ retval = -EINVAL;
+ }
+
+ EXIT;
+ return retval;
+}
+
+int dogetopt(int minor, struct psdev_opt *opt)
+{


+ int retval = 0;

+
+ ENTRY;
+
+ switch(opt->optname) {
+
+ case PSDEV_TIMEOUT:
+ opt->optval = upc_comms[minor].uc_timeout;
+ break;
+
+ case PSDEV_HARD:
+ opt->optval = upc_comms[minor].uc_hard;
+ break;
+
+ case PSDEV_NO_FILTER:
+ opt->optval = upc_comms[minor].uc_no_filter;
+ break;
+
+ case PSDEV_NO_JOURNAL:
+ opt->optval = upc_comms[minor].uc_no_journal;
+ break;
+
+ case PSDEV_NO_UPCALL:
+ opt->optval = upc_comms[minor].uc_no_upcall;
+ break;
+
+#ifdef PSDEV_DEBUG
+ case PSDEV_ERRORVAL: {


+ int errorval = upc_comms[minor].uc_errorval;

+ if (errorval < 0 && is_read_only(-errorval))
+ printk(KERN_INFO "device %s has been set read-only\n",
+ kdevname(-errorval));
+ opt->optval = upc_comms[minor].uc_errorval;
+ break;
+ }
+#endif
+
+ case PSDEV_TRACE:
+ case PSDEV_DEBUG:
+ case PSDEV_BYTES_TO_CLOSE:
+ default:
+ CDEBUG(D_PSDEV,
+ "ioctl: dogetopt: minor %d, bad optval 0x%x, \n",
+ minor, opt->optname);
+
+ retval = -EINVAL;
+ }
+
+ EXIT;
+ return retval;
+}
+
+
+
+int /* __init */ init_intermezzo_sysctl(void)
+{
+ int i;
+ extern struct upc_comm upc_comms[MAX_PRESTODEV];
+
+ /* allocate the tables for the presto devices. We need
+ * sizeof(proto_prestodev_table)/sizeof(proto_prestodev_table[0])
+ * entries for each dev
+ */
+ int total_dev = MAX_PRESTODEV;
+ int entries_per_dev = sizeof(proto_psdev_table) /
+ sizeof(proto_psdev_table[0]);
+ int total_entries = entries_per_dev * total_dev;
+ ctl_table *dev_ctl_table;
+
+ PRESTO_ALLOC(dev_ctl_table, ctl_table *,
+ sizeof(ctl_table) * total_entries);
+
+ if (! dev_ctl_table) {
+ printk("WARNING: presto couldn't allocate dev_ctl_table\n");
+ EXIT;
+ return -ENOMEM;
+ }
+
+ /* now fill in the entries ... we put the individual presto<x>
+ * entries at the end of the table, and the per-presto stuff
+ * starting at the front. We assume that the compiler makes
+ * this code more efficient, but really, who cares ... it
+ * happens once per reboot.
+ */
+ for(i = 0; i < total_dev; i++) {
+ /* entry for this /proc/sys/intermezzo/intermezzo"i" */
+ ctl_table *psdev = &presto_table[i + PRESTO_PRIMARY_CTLCNT];
+ /* entries for the individual "files" in this "directory" */
+ ctl_table *psdev_entries = &dev_ctl_table[i * entries_per_dev];
+ /* init the psdev and psdev_entries with the prototypes */
+ *psdev = proto_prestodev_entry;
+ memcpy(psdev_entries, proto_psdev_table,
+ sizeof(proto_psdev_table));
+ /* now specialize them ... */
+ /* the psdev has to point to psdev_entries, and fix the number */
+ psdev->ctl_name = psdev->ctl_name + i + 1; /* sorry */
+
+ psdev->procname = kmalloc(32, GFP_KERNEL);
+ if (!psdev->procname) {
+ PRESTO_FREE(dev_ctl_table,
+ sizeof(ctl_table) * total_entries);
+ return -ENOMEM;
+ }
+ sprintf((char *) psdev->procname, "intermezzo%d", i);
+ /* hook presto into */
+ psdev->child = psdev_entries;
+
+ /* now for each psdev entry ... */
+ psdev_entries[0].data = &(upc_comms[i].uc_hard);
+ psdev_entries[1].data = &(upc_comms[i].uc_no_filter);
+ psdev_entries[2].data = &(upc_comms[i].uc_no_journal);
+ psdev_entries[3].data = &(upc_comms[i].uc_no_upcall);
+ psdev_entries[4].data = &(upc_comms[i].uc_timeout);
+ psdev_entries[5].data = &presto_print_entry;
+ psdev_entries[6].data = &presto_debug;
+#ifdef PRESTO_DEBUG
+ psdev_entries[7].data = &(upc_comms[i].uc_errorval);
+#endif
+ }
+
+
+#ifdef CONFIG_SYSCTL
+ if ( !intermezzo_table_header )
+ intermezzo_table_header =
+ register_sysctl_table(intermezzo_table, 0);
+#endif
+#ifdef CONFIG_PROC_FS
+ proc_fs_intermezzo = proc_mkdir("intermezzo", proc_root_fs);
+ proc_fs_intermezzo->owner = THIS_MODULE;
+ create_proc_info_entry("mounts", 0, proc_fs_intermezzo,
+ intermezzo_mount_get_info);
+#endif


+ return 0;
+}
+

+void cleanup_intermezzo_sysctl() {
+ int total_dev = MAX_PRESTODEV;
+ int entries_per_dev = sizeof(proto_psdev_table) /
+ sizeof(proto_psdev_table[0]);
+ int total_entries = entries_per_dev * total_dev;
+ int i;
+
+#ifdef CONFIG_SYSCTL
+ if ( intermezzo_table_header )
+ unregister_sysctl_table(intermezzo_table_header);
+ intermezzo_table_header = NULL;
+#endif
+ for(i = 0; i < total_dev; i++) {
+ /* entry for this /proc/sys/intermezzo/intermezzo"i" */
+ ctl_table *psdev = &presto_table[i + PRESTO_PRIMARY_CTLCNT];
+ kfree(psdev->procname);
+ }
+ /* presto_table[PRESTO_PRIMARY_CTLCNT].child points to the
+ * dev_ctl_table previously allocated in init_intermezzo_psdev()
+ */
+ PRESTO_FREE(presto_table[PRESTO_PRIMARY_CTLCNT].child, sizeof(ctl_table) * total_entries);
+
+#if CONFIG_PROC_FS
+ remove_proc_entry("mounts", proc_fs_intermezzo);
+ remove_proc_entry("intermezzo", proc_root_fs);
+#endif
+}
+
diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/upcall.c linux/fs/intermezzo/upcall.c
--- v2.4.14/linux/fs/intermezzo/upcall.c Wed Dec 31 16:00:00 1969
+++ linux/fs/intermezzo/upcall.c Sun Nov 11 10:20:21 2001
@@ -0,0 +1,248 @@
+/*
+ * Mostly platform independent upcall operations to Venus:
+ * -- upcalls
+ * -- upcall routines
+ *
+ * Linux 2.0 version
+ * Copyright (C) 1996 Peter J. Braam <br...@cs.cmu.edu>,
+ * Michael Callahan <call...@maths.ox.ac.uk>
+ *
+ * Redone for Linux 2.1
+ * Copyright (C) 1997 Carnegie Mellon University


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

echo 'End of part 096'
echo 'File patch-2.4.15 is continued in part 097'
echo "097" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:26 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part110

#!/bin/sh -x
# this is part 110 of a 115 - part archive


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

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

+ * needs to take into account the fact that we may end up modifying two
+ * quota files too (one for the group, one for the user quota). The
+ * superblock only gets updated once, of course, so don't bother
+ * counting that again for the quota updates. */
+
+#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
+
+extern int ext3_writepage_trans_blocks(struct inode *inode);
+
+/* Delete operations potentially hit one directory's namespace plus an
+ * entire inode, plus arbitrary amounts of bitmap/indirection data. Be
+ * generous. We can grow the delete transaction later if necessary. */
+
+#define EXT3_DELETE_TRANS_BLOCKS (2 * EXT3_DATA_TRANS_BLOCKS + 64)
+
+/* Define an arbitrary limit for the amount of data we will anticipate
+ * writing to any given transaction. For unbounded transactions such as
+ * write(2) and truncate(2) we can write more than this, but we always
+ * start off at the maximum transaction size and grow the transaction
+ * optimistically as we go. */
+
+#define EXT3_MAX_TRANS_DATA 64
+
+/* We break up a large truncate or write transaction once the handle's
+ * buffer credits gets this low, we need either to extend the
+ * transaction or to start a new one. Reserve enough space here for
+ * inode, bitmap, superblock, group and indirection updates for at least
+ * one block, plus two quota updates. Quota allocations are not
+ * needed. */
+
+#define EXT3_RESERVE_TRANS_BLOCKS 12
+
+int
+ext3_mark_iloc_dirty(handle_t *handle,
+ struct inode *inode,
+ struct ext3_iloc *iloc);


+
+/*
+ * On success, We end up with an outstanding reference count against
+ * iloc->bh. This _must_ be cleaned up later.
+ */
+

+int ext3_reserve_inode_write(handle_t *handle, struct inode *inode,
+ struct ext3_iloc *iloc);
+
+int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode);
+
+/*
+ * Wrapper functions with which ext3 calls into JBD. The intent here is
+ * to allow these to be turned into appropriate stubs so ext3 can control
+ * ext2 filesystems, so ext2+ext3 systems only nee one fs. This work hasn't
+ * been done yet.
+ */
+
+static inline void ext3_journal_abort_handle(const char *caller,
+ const char *err_fn,
+ struct buffer_head *bh,
+ handle_t *handle,
+ int err)
+{
+ char nbuf[16];
+ const char *errstr = ext3_decode_error(NULL, err, nbuf);
+
+ printk(KERN_ERR "%s: aborting transaction: %s in %s",
+ caller, errstr, err_fn);
+
+ if (bh)
+ BUFFER_TRACE(bh, "abort");
+ journal_abort_handle(handle);
+ if (!handle->h_err)
+ handle->h_err = err;


+}
+
+static inline int

+__ext3_journal_get_undo_access(const char *where,
+ handle_t *handle, struct buffer_head *bh)
+{
+ int err = journal_get_undo_access(handle, bh);
+ if (err)
+ ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);


+ return err;
+}
+

+static inline int
+__ext3_journal_get_write_access(const char *where,
+ handle_t *handle, struct buffer_head *bh)
+{
+ int err = journal_get_write_access(handle, bh);
+ if (err)
+ ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);


+ return err;
+}
+

+static inline int
+__ext3_journal_dirty_data(const char *where,
+ handle_t *handle, struct buffer_head *bh, int async)
+{
+ int err = journal_dirty_data(handle, bh, async);
+ if (err)
+ ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);


+ return err;
+}
+

+static inline void
+ext3_journal_forget(handle_t *handle, struct buffer_head *bh)
+{
+ journal_forget(handle, bh);


+}
+
+static inline int

+__ext3_journal_revoke(const char *where, handle_t *handle,
+ unsigned long blocknr, struct buffer_head *bh)
+{
+ int err = journal_revoke(handle, blocknr, bh);
+ if (err)
+ ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);


+ return err;
+}
+

+static inline int
+__ext3_journal_get_create_access(const char *where,
+ handle_t *handle, struct buffer_head *bh)
+{
+ int err = journal_get_create_access(handle, bh);
+ if (err)
+ ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);


+ return err;
+}
+

+static inline int
+__ext3_journal_dirty_metadata(const char *where,
+ handle_t *handle, struct buffer_head *bh)
+{
+ int err = journal_dirty_metadata(handle, bh);
+ if (err)
+ ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);


+ return err;
+}
+
+

+#define ext3_journal_get_undo_access(handle, bh) \
+ __ext3_journal_get_undo_access(__FUNCTION__, (handle), (bh))
+#define ext3_journal_get_write_access(handle, bh) \
+ __ext3_journal_get_write_access(__FUNCTION__, (handle), (bh))
+#define ext3_journal_dirty_data(handle, bh, async) \
+ __ext3_journal_dirty_data(__FUNCTION__, (handle), (bh), (async))
+#define ext3_journal_revoke(handle, blocknr, bh) \
+ __ext3_journal_revoke(__FUNCTION__, (handle), (blocknr), (bh))
+#define ext3_journal_get_create_access(handle, bh) \
+ __ext3_journal_get_create_access(__FUNCTION__, (handle), (bh))
+#define ext3_journal_dirty_metadata(handle, bh) \
+ __ext3_journal_dirty_metadata(__FUNCTION__, (handle), (bh))
+
+
+
+/*
+ * Wrappers for journal_start/end.
+ *
+ * The only special thing we need to do here is to make sure that all
+ * journal_end calls result in the superblock being marked dirty, so
+ * that sync() will call the filesystem's write_super callback if
+ * appropriate.
+ */
+static inline handle_t *ext3_journal_start(struct inode *inode, int nblocks)
+{
+ if (inode->i_sb->s_flags & MS_RDONLY)
+ return ERR_PTR(-EROFS);
+ return journal_start(EXT3_JOURNAL(inode), nblocks);
+}
+
+static inline handle_t *
+ext3_journal_try_start(struct inode *inode, int nblocks)
+{
+ if (inode->i_sb->s_flags & MS_RDONLY)
+ return ERR_PTR(-EROFS);
+ return journal_try_start(EXT3_JOURNAL(inode), nblocks);
+}
+
+/*
+ * The only special thing we need to do here is to make sure that all
+ * journal_stop calls result in the superblock being marked dirty, so
+ * that sync() will call the filesystem's write_super callback if
+ * appropriate.
+ */
+static inline int __ext3_journal_stop(const char *where,
+ handle_t *handle, struct inode *inode)
+{
+ int err = handle->h_err;
+ int rc = journal_stop(handle);
+
+ inode->i_sb->s_dirt = 1;


+ if (!err)
+ err = rc;

+ if (err)
+ __ext3_std_error(inode->i_sb, where, err);
+ return err;
+}
+#define ext3_journal_stop(handle, inode) \
+ __ext3_journal_stop(__FUNCTION__, (handle), (inode))
+
+static inline handle_t *ext3_journal_current_handle(void)
+{
+ return journal_current_handle();


+}
+
+static inline void

+ext3_log_start_commit(journal_t *journal, transaction_t *transaction)
+{


+ log_start_commit(journal, transaction);
+}
+

+static inline void ext3_log_wait_commit(journal_t *journal, tid_t tid)
+{


+ log_wait_commit(journal, tid);
+}
+

+static inline int ext3_journal_extend(handle_t *handle, int nblocks)
+{
+ return journal_extend(handle, nblocks);
+}
+
+static inline int ext3_journal_restart(handle_t *handle, int nblocks)
+{
+ return journal_restart(handle, nblocks);
+}
+
+static inline int ext3_journal_blocks_per_page(struct inode *inode)
+{
+ return journal_blocks_per_page(inode);
+}
+
+static inline int ext3_journal_force_commit(journal_t *journal)
+{
+ return journal_force_commit(journal);
+}
+
+/* super.c */


+int ext3_force_commit(struct super_block *sb);
+

+static inline int ext3_should_journal_data(struct inode *inode)
+{
+ if (!S_ISREG(inode->i_mode))
+ return 1;
+ if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
+ return 1;
+ if (inode->u.ext3_i.i_flags & EXT3_JOURNAL_DATA_FL)
+ return 1;


+ return 0;
+}
+

+static inline int ext3_should_order_data(struct inode *inode)
+{
+ return (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA);
+}
+
+
+#endif /* _LINUX_EXT3_JBD_H */
diff -u --recursive --new-file v2.4.14/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.4.14/linux/include/linux/fs.h Mon Nov 5 15:55:35 2001
+++ linux/include/linux/fs.h Thu Nov 22 11:46:19 2001
@@ -216,6 +216,7 @@
X BH_Async, /* 1 if the buffer is under end_buffer_io_async I/O */
X BH_Wait_IO, /* 1 if we should write out this buffer */
X BH_launder, /* 1 if we should throttle on this buffer */
+ BH_JBD, /* 1 if it has an attached journal_head */
X
X BH_PrivateStart,/* not a state bit, but the first bit available
X * for private allocation by other entities
@@ -287,6 +288,7 @@
X #include <linux/pipe_fs_i.h>
X #include <linux/minix_fs_i.h>
X #include <linux/ext2_fs_i.h>
+#include <linux/ext3_fs_i.h>
X #include <linux/hpfs_fs_i.h>
X #include <linux/ntfs_fs_i.h>
X #include <linux/msdos_fs_i.h>
@@ -376,10 +378,16 @@
X int (*writepage)(struct page *);
X int (*readpage)(struct file *, struct page *);
X int (*sync_page)(struct page *);
+ /*
+ * ext3 requires that a successful prepare_write() call be followed
+ * by a commit_write() call - they must be balanced
+ */
X int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
X int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
X /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
X int (*bmap)(struct address_space *, long);
+ int (*flushpage) (struct page *, unsigned long);
+ int (*releasepage) (struct page *, int);
X #define KERNEL_HAS_O_DIRECT /* this is for modules out of the kernel */
X int (*direct_IO)(int, struct inode *, struct kiobuf *, unsigned long, int);
X };
@@ -470,6 +478,7 @@
X union {
X struct minix_inode_info minix_i;
X struct ext2_inode_info ext2_i;
+ struct ext3_inode_info ext3_i;
X struct hpfs_inode_info hpfs_i;
X struct ntfs_inode_info ntfs_i;
X struct msdos_inode_info msdos_i;
@@ -658,6 +667,7 @@
X
X #include <linux/minix_fs_sb.h>
X #include <linux/ext2_fs_sb.h>
+#include <linux/ext3_fs_sb.h>
X #include <linux/hpfs_fs_sb.h>
X #include <linux/ntfs_fs_sb.h>
X #include <linux/msdos_fs_sb.h>
@@ -714,6 +724,7 @@
X union {
X struct minix_sb_info minix_sb;
X struct ext2_sb_info ext2_sb;
+ struct ext3_sb_info ext3_sb;
X struct hpfs_sb_info hpfs_sb;
X struct ntfs_sb_info ntfs_sb;
X struct msdos_sb_info msdos_sb;
@@ -1088,6 +1099,7 @@
X
X extern int try_to_free_buffers(struct page *, unsigned int);
X extern void refile_buffer(struct buffer_head * buf);
+extern void create_empty_buffers(struct page *, kdev_t, unsigned long);
X extern void end_buffer_io_sync(struct buffer_head *bh, int uptodate);
X
X /* reiserfs_writepage needs this */
@@ -1170,6 +1182,7 @@
X buffer_insert_inode_queue(bh, inode);
X }
X
+extern void set_buffer_flushtime(struct buffer_head *);
X extern void balance_dirty(void);
X extern int check_disk_change(kdev_t);
X extern int invalidate_inodes(struct super_block *);
@@ -1349,12 +1362,15 @@
X extern int set_blocksize(kdev_t, int);
X extern struct buffer_head * bread(kdev_t, int, int);
X extern void wakeup_bdflush(void);
+extern void put_unused_buffer_head(struct buffer_head * bh);
+extern struct buffer_head * get_unused_buffer_head(int async);
X
X extern int brw_page(int, struct page *, kdev_t, int [], int);
X
X typedef int (get_block_t)(struct inode*,long,struct buffer_head*,int);
X
X /* Generic buffer handling for block filesystems.. */
+extern int try_to_release_page(struct page * page, int gfp_mask);
X extern int discard_bh_page(struct page *, unsigned long, int);
X #define block_flushpage(page, offset) discard_bh_page(page, offset, 1)
X #define block_invalidate_page(page) discard_bh_page(page, 0, 0)
@@ -1370,7 +1386,7 @@
X int generic_block_bmap(struct address_space *, long, get_block_t *);
X int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
X int block_truncate_page(struct address_space *, loff_t, get_block_t *);
-extern void create_empty_buffers(struct page *, kdev_t, unsigned long);
+extern int generic_direct_IO(int, struct inode *, struct kiobuf *, unsigned long, int, get_block_t *);
X
X extern int waitfor_one_page(struct page*);
X extern int generic_file_mmap(struct file *, struct vm_area_struct *);
@@ -1416,7 +1432,7 @@
X extern void mount_root(void);
X
X #ifdef CONFIG_BLK_DEV_INITRD
-extern kdev_t real_root_dev;
+extern unsigned int real_root_dev;
X extern int change_root(kdev_t, const char *);
X #endif
X
diff -u --recursive --new-file v2.4.14/linux/include/linux/fsfilter.h linux/include/linux/fsfilter.h
--- v2.4.14/linux/include/linux/fsfilter.h Wed Dec 31 16:00:00 1969
+++ linux/include/linux/fsfilter.h Sun Nov 11 10:20:21 2001
@@ -0,0 +1,129 @@
+#ifndef __FILTER_H_
+#define __FILTER_H_ 1
+
+#ifdef __KERNEL__
+
+/* cachetype.c */
+
+/*
+ * it is important that things like inode, super and file operations
+ * for intermezzo are not defined statically. If methods are NULL
+ * the VFS takes special action based on that. Given that different
+ * cache types have NULL ops at different slots, we must install opeation
+ * talbes for InterMezzo with NULL's in the same spot
+ */
+
+struct filter_ops {
+ struct super_operations filter_sops;
+
+ struct inode_operations filter_dir_iops;
+ struct inode_operations filter_file_iops;
+ struct inode_operations filter_sym_iops;
+
+ struct file_operations filter_dir_fops;
+ struct file_operations filter_file_fops;
+ struct file_operations filter_sym_fops;
+
+ struct dentry_operations filter_dentry_ops;
+};
+
+struct cache_ops {
+ /* operations on the file store */
+ struct super_operations *cache_sops;
+
+ struct inode_operations *cache_dir_iops;
+ struct inode_operations *cache_file_iops;
+ struct inode_operations *cache_sym_iops;
+
+ struct file_operations *cache_dir_fops;
+ struct file_operations *cache_file_fops;
+ struct file_operations *cache_sym_fops;
+
+ struct dentry_operations *cache_dentry_ops;
+};
+
+
+#define FILTER_DID_SUPER_OPS 0x1
+#define FILTER_DID_INODE_OPS 0x2
+#define FILTER_DID_FILE_OPS 0x4
+#define FILTER_DID_DENTRY_OPS 0x8
+#define FILTER_DID_DEV_OPS 0x10
+#define FILTER_DID_SYMLINK_OPS 0x20
+#define FILTER_DID_DIR_OPS 0x40
+
+struct filter_fs {
+ int o_flags;
+ struct filter_ops o_fops;
+ struct cache_ops o_caops;
+ struct journal_ops *o_trops;
+ struct snapshot_ops *o_snops;
+};
+
+#define FILTER_FS_TYPES 5
+#define FILTER_FS_EXT2 0
+#define FILTER_FS_EXT3 1
+#define FILTER_FS_REISERFS 2
+#define FILTER_FS_XFS 3
+#define FILTER_FS_OBDFS 4
+extern struct filter_fs filter_oppar[FILTER_FS_TYPES];
+
+struct filter_fs *filter_get_filter_fs(const char *cache_type);
+void filter_setup_journal_ops(struct filter_fs *ops, char *cache_type);
+inline struct super_operations *filter_c2usops(struct filter_fs *cache);
+inline struct inode_operations *filter_c2ufiops(struct filter_fs *cache);
+inline struct inode_operations *filter_c2udiops(struct filter_fs *cache);
+inline struct inode_operations *filter_c2usiops(struct filter_fs *cache);
+inline struct file_operations *filter_c2uffops(struct filter_fs *cache);
+inline struct file_operations *filter_c2udfops(struct filter_fs *cache);
+inline struct file_operations *filter_c2usfops(struct filter_fs *cache);
+inline struct super_operations *filter_c2csops(struct filter_fs *cache);
+inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache);
+inline struct inode_operations *filter_c2cdiops(struct filter_fs *cache);
+inline struct inode_operations *filter_c2csiops(struct filter_fs *cache);
+inline struct file_operations *filter_c2cffops(struct filter_fs *cache);
+inline struct file_operations *filter_c2cdfops(struct filter_fs *cache);
+inline struct file_operations *filter_c2csfops(struct filter_fs *cache);
+inline struct dentry_operations *filter_c2cdops(struct filter_fs *cache);


+inline struct dentry_operations *filter_c2udops(struct filter_fs *cache);
+

+void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *cache_ops, struct super_operations *filter_sops);
+void filter_setup_dir_ops(struct filter_fs *cache, struct inode *cache_inode, struct inode_operations *filter_iops, struct file_operations *ffops);
+void filter_setup_file_ops(struct filter_fs *cache, struct inode *cache_inode, struct inode_operations *filter_iops, struct file_operations *filter_op);
+void filter_setup_symlink_ops(struct filter_fs *cache, struct inode *cache_inode, struct inode_operations *filter_iops, struct file_operations *filter_op);
+void filter_setup_dentry_ops(struct filter_fs *cache, struct dentry_operations *cache_dop, struct dentry_operations *filter_dop);
+
+
+#define PRESTO_DEBUG
+#ifdef PRESTO_DEBUG
+/* debugging masks */
+#define D_SUPER 1 /* print results returned by Venus */
+#define D_INODE 2 /* print entry and exit into procedure */
+#define D_FILE 4
+#define D_CACHE 8 /* cache debugging */
+#define D_MALLOC 16 /* print malloc, de-alloc information */
+#define D_JOURNAL 32
+#define D_UPCALL 64 /* up and downcall debugging */
+#define D_PSDEV 128
+#define D_PIOCTL 256
+#define D_SPECIAL 512
+#define D_TIMING 1024
+#define D_DOWNCALL 2048
+
+#define FDEBUG(mask, format, a...) \
+ do { \
+ if (filter_debug & mask) { \
+ printk("(%s,l. %d): ", __FUNCTION__, __LINE__); \
+ printk(format, ##a); } \
+ } while (0)
+
+#define FENTRY \
+ if(filter_print_entry) \
+ printk("Process %d entered %s\n", current->pid, __FUNCTION__)
+
+#define FEXIT \
+ if(filter_print_entry) \
+ printk("Process %d leaving %s at %d\n", current->pid, \
+ __FUNCTION__,__LINE__)
+#endif
+#endif
+#endif
diff -u --recursive --new-file v2.4.14/linux/include/linux/i2o.h linux/include/linux/i2o.h
--- v2.4.14/linux/include/linux/i2o.h Tue Oct 23 22:48:53 2001
+++ linux/include/linux/i2o.h Fri Nov 9 14:11:15 2001
@@ -31,7 +31,6 @@
X #include <asm/semaphore.h> /* Needed for MUTEX init macros */
X #include <linux/config.h>
X #include <linux/notifier.h>
-#include <linux/ioport.h> /* Needed for struct resource */
X #include <asm/atomic.h>
X
X /*
@@ -82,7 +81,7 @@
X struct i2o_pci
X {
X int irq;
- int queue_buggy:1; /* Don't send a lot of messages */
+ int queue_buggy:3; /* Don't send a lot of messages */
X int short_req:1; /* Use small block sizes */
X int dpt:1; /* Don't quiesce */
X #ifdef CONFIG_MTRR
diff -u --recursive --new-file v2.4.14/linux/include/linux/if_bonding.h linux/include/linux/if_bonding.h
--- v2.4.14/linux/include/linux/if_bonding.h Tue Mar 6 19:44:37 2001
+++ linux/include/linux/if_bonding.h Wed Nov 7 14:39:36 2001
@@ -9,16 +9,94 @@
X * (c) Copyright 1999, Thomas Davis, tad...@lbl.gov
X *
X * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
+ * of the GNU Public License, incorporated herein by reference.


X *
X */
X

X #ifndef _LINUX_IF_BONDING_H
X #define _LINUX_IF_BONDING_H
X
-#define BOND_ENSLAVE (SIOCDEVPRIVATE)
-#define BOND_RELEASE (SIOCDEVPRIVATE + 1)
-#define BOND_SETHWADDR (SIOCDEVPRIVATE + 2)
+#ifdef __KERNEL__
+#include <linux/timer.h>
+#include <linux/if.h>
+#include <linux/proc_fs.h>
+#endif /* __KERNEL__ */
+
+#include <linux/types.h>
+
+/*
+ * We can remove these ioctl definitions in 2.5. People should use the
+ * SIOC*** versions of them instead
+ */
+#define BOND_ENSLAVE_OLD (SIOCDEVPRIVATE)
+#define BOND_RELEASE_OLD (SIOCDEVPRIVATE + 1)
+#define BOND_SETHWADDR_OLD (SIOCDEVPRIVATE + 2)
+#define BOND_SLAVE_INFO_QUERY_OLD (SIOCDEVPRIVATE + 11)
+#define BOND_INFO_QUERY_OLD (SIOCDEVPRIVATE + 12)
+#define BOND_CHANGE_ACTIVE_OLD (SIOCDEVPRIVATE + 13)
+
+#define BOND_CHECK_MII_STATUS (SIOCGMIIPHY)
+
+#define BOND_MODE_ROUNDROBIN 0
+#define BOND_MODE_ACTIVEBACKUP 1
+#define BOND_MODE_XOR 2
+
+/* each slave's link has 4 states */
+#define BOND_LINK_UP 0 /* link is up and running */
+#define BOND_LINK_FAIL 1 /* link has just gone down */
+#define BOND_LINK_DOWN 2 /* link has been down for too long time */
+#define BOND_LINK_BACK 3 /* link is going back */
+
+/* each slave has several states */
+#define BOND_STATE_ACTIVE 0 /* link is active */
+#define BOND_STATE_BACKUP 1 /* link is backup */
+
+#define MAX_BONDS 1 /* Maximum number of devices to support */
+
+typedef struct ifbond {
+ __s32 bond_mode;
+ __s32 num_slaves;
+ __s32 miimon;
+} ifbond;
+
+typedef struct ifslave
+{
+ __s32 slave_id; /* Used as an IN param to the BOND_SLAVE_INFO_QUERY ioctl */
+ char slave_name[IFNAMSIZ];
+ char link;
+ char state;
+ __u32 link_failure_count;
+} ifslave;
+
+#ifdef __KERNEL__
+typedef struct slave {
+ struct slave *next;
+ struct slave *prev;
+ struct net_device *dev;
+ short delay;
+ char link; /* one of BOND_LINK_XXXX */
+ char state; /* one of BOND_STATE_XXXX */
+ u32 link_failure_count;
+} slave_t;
+
+typedef struct bonding {
+ slave_t *next;
+ slave_t *prev;
+ slave_t *current_slave;
+ __s32 slave_cnt;
+ rwlock_t lock;
+ rwlock_t ptrlock;
+ struct timer_list mii_timer;
+ struct timer_list arp_timer;
+ struct net_device_stats *stats;
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *bond_proc_dir;
+ struct proc_dir_entry *bond_proc_info_file;
+#endif /* CONFIG_PROC_FS */
+ struct bonding *next_bond;
+ struct net_device *device;
+} bonding_t;
+#endif /* __KERNEL__ */
X
X #endif /* _LINUX_BOND_H */
X
diff -u --recursive --new-file v2.4.14/linux/include/linux/intermezzo_fs.h linux/include/linux/intermezzo_fs.h
--- v2.4.14/linux/include/linux/intermezzo_fs.h Wed Dec 31 16:00:00 1969
+++ linux/include/linux/intermezzo_fs.h Tue Nov 13 09:20:56 2001
@@ -0,0 +1,729 @@
+/*
+ *


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


+ * Copyright (C) 2000 Stelias Computing, Inc.
+ * Copyright (C) 2000 Red Hat, Inc.

+ * Copyright (C) 2000 TurboLinux, Inc.
+ * Copyright (C) 2000 Los Alamos National Laboratory.
+ * Copyright (C) 2001 Tacitus Systems, Inc.
+ * Copyright (C) 2001 Cluster File Systems, Inc.
+ */
+
+#ifndef __INTERMEZZO_FS_H_
+#define __INTERMEZZO_FS_H_ 1
+
+#ifdef __KERNEL__
+#include <linux/smp.h>
+#include <linux/fsfilter.h>
+
+/* fixups for fs.h */
+#ifndef fs_down
+#define fs_down(sem) down(sem)
+#endif
+
+#ifndef fs_up
+#define fs_up(sem) up(sem)
+#endif
+
+/* We will be more tolerant than the default ea patch with attr name sizes and
+ * the size of value. If these come via VFS from the default ea patches, the
+ * corresponding character strings will be truncated anyway. During journalling- * we journal length for both name and value. See journal_set_ext_attr.
+ */
+#define PRESTO_EXT_ATTR_NAME_MAX 128
+#define PRESTO_EXT_ATTR_VALUE_MAX 8192
+
+#define KML_IDLE 0
+#define KML_DECODE 1
+#define KML_OPTIMIZE 2
+#define KML_REINT 3
+
+#define KML_OPEN_REINT 0x0100
+#define KML_REINT_BEGIN 0x0200
+#define KML_BACKFETCH 0x0400
+#define KML_REINT_END 0x0800
+#define KML_CLOSE_REINT 0x1000
+#define FSET_GET_KMLDATA(fset) fset->fset_kmldata
+#define KML_REINT_MAXBUF (64 * 1024)
+
+struct kml_fsdata
+{
+ int kml_state;
+
+ /* kml optimize support */
+ struct list_head kml_kop_cache;


+
+ /* kml reint support */

+ int kml_reint_state;
+ struct list_head kml_reint_cache;
+ struct list_head *kml_reint_current;
+ int kml_maxsize; /* max buffer */
+ int kml_len;
+ char * kml_buf;
+ loff_t kml_reintpos;
+ int kml_count;
+};
+
+/* super.c */
+struct presto_cache *presto_find_cache(kdev_t dev) ;
+extern struct file_system_type presto_fs_type;
+extern int init_intermezzo_fs(void);
+
+#define CACHE_TYPE_LENGTH 16
+
+int presto_ispresto(struct inode *);
+
+#define CACHE_CLIENT_RO 0x4
+#define CACHE_LENTO_RO 0x8
+#define CACHE_FSETROOT_SET 0x10
+
+
+struct presto_cache {
+ spinlock_t cache_lock;
+ loff_t cache_reserved;
+ struct list_head cache_chain; /* for the dev/cache hash */
+
+ int cache_flags;
+ char *cache_root_fileset; /* fileset mounted on cache "/" */
+
+ kdev_t cache_dev; /* underlying block device */
+ struct super_block *cache_sb;
+ struct dentry *cache_mtde; /* unix mtpt of cache XXX NOT VALID XXX */
+ char *cache_mtpt; /* again */
+
+ char *cache_type; /* filesystem type of cache */
+ struct filter_fs *cache_filter;
+
+ struct upc_comm *cache_psdev; /* points to /dev/intermezzo? we use */
+ struct list_head cache_psdev_chain;
+
+ struct list_head cache_fset_list; /* filesets mounted in cache */


+};
+
+
+
+

+/* file sets */
+#define CHUNK_BITS 16
+
+struct presto_log_fd {
+ rwlock_t fd_lock;
+ loff_t fd_offset; /* offset where next record should go */
+ struct file *fd_file;
+ int fd_truncating;
+ unsigned int fd_recno; /* last recno written */
+ struct list_head fd_reservations;
+};
+
+struct presto_file_set {
+ struct list_head fset_list;
+ struct presto_log_fd fset_kml;
+ struct presto_log_fd fset_lml;
+ struct file *fset_last_rcvd;
+ struct dentry *fset_mtpt;
+ struct nameidata fset_nd;
+ struct presto_cache *fset_cache;
+
+ unsigned int fset_lento_recno; /* last recno mentioned to lento */
+ loff_t fset_lento_off; /* last offset mentioned to lento */
+ char * fset_name;
+
+ int fset_flags;
+ int fset_permit_count;
+ int fset_permit_cookie;
+ int fset_chunkbits;
+ struct kml_fsdata *fset_kmldata;
+ loff_t fset_file_maxio; /* writing more than this causes a close */
+};
+
+/* This is the default number of bytes written before a close is recorded*/
+#define FSET_DEFAULT_MAX_FILEIO (1024<<10)
+
+struct journal_ops {
+ loff_t (*tr_avail)(struct presto_cache *fset, struct super_block *);
+ void *(*tr_start)(struct presto_file_set *, struct inode *, int op);
+ void (*tr_commit)(struct presto_file_set *, void *handle);
+ void (*tr_journal_data)(struct inode *);
+};
+
+
+extern struct journal_ops presto_ext2_journal_ops;
+extern struct journal_ops presto_ext3_journal_ops;
+extern struct journal_ops presto_xfs_journal_ops;
+extern struct journal_ops presto_reiserfs_journal_ops;
+extern struct journal_ops presto_obdfs_journal_ops;
+struct lento_vfs_context {
+ __u32 slot_offset;
+ __u32 recno;
+ __u64 kml_offset;
+ __u32 flags;
+ __u32 updated_time;
+};
+
+
+#define LENTO_FL_KML 0x0001
+#define LENTO_FL_EXPECT 0x0002
+#define LENTO_FL_VFSCHECK 0x0004
+#define LENTO_FL_JUSTLOG 0x0008
+#define LENTO_FL_WRITE_KML 0x0010
+#define LENTO_FL_CANCEL_LML 0x0020
+#define LENTO_FL_WRITE_EXPECT 0x0040
+#define LENTO_FL_IGNORE_TIME 0x0080
+
+struct presto_cache *presto_get_cache(struct inode *inode) ;
+int presto_sprint_mounts(char *buf, int buflen, int minor);
+struct presto_file_set *presto_fset(struct dentry *de);
+int presto_journal(struct dentry *dentry, char *buf, size_t size);


+int presto_fwrite(struct file *file, const char *str, int len, loff_t *off);
+

+/* psdev.c */
+int presto_psdev_init(void);
+extern void presto_psdev_cleanup(void);


+inline int presto_lento_up(int minor);
+

+/* inode.c */
+extern struct super_operations presto_super_ops;
+extern int presto_excluded_gid;
+#define PRESTO_EXCL_GID 4711
+void presto_set_ops(struct inode *inode, struct filter_fs *filter);
+void presto_read_inode(struct inode *inode);
+void presto_put_super(struct super_block *);
+
+/* journal.c */
+void presto_trans_commit(struct presto_file_set *fset, void *handle);


+void *presto_trans_start(struct presto_file_set *fset, struct inode *inode,
+ int op);
+

+/* dcache.c */
+void presto_frob_dop(struct dentry *de) ;


+char * presto_path(struct dentry *dentry, struct dentry *root,

+ char *buffer, int buflen);
+void presto_set_dd(struct dentry *);
+void presto_init_ddata_cache(void);
+void presto_cleanup_ddata_cache(void);
+extern struct dentry_operations presto_dentry_ops;
+
+
+
+/* dir.c */
+extern struct inode_operations presto_dir_iops;
+extern struct inode_operations presto_file_iops;
+extern struct inode_operations presto_sym_iops;
+extern struct file_operations presto_dir_fops;
+extern struct file_operations presto_file_fops;
+extern struct file_operations presto_sym_fops;
+int presto_setattr(struct dentry *de, struct iattr *iattr);
+extern int presto_ilookup_uid;
+#define PRESTO_ILOOKUP_MAGIC "...ino:"
+#define PRESTO_ILOOKUP_SEP ':'


+
+struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry);
+

+/* file.c */
+struct presto_reservation_data {
+ unsigned int ri_recno;
+ loff_t ri_offset;
+ loff_t ri_size;
+ struct list_head ri_list;
+};
+
+
+struct presto_dentry_data {
+ int dd_count; /* how mnay dentries are using this dentry */
+ struct presto_file_set *dd_fset;
+ loff_t dd_kml_offset;
+ int dd_flags;
+
+};
+
+struct presto_file_data {
+ int fd_do_lml;
+ loff_t fd_lml_offset;
+ uid_t fd_fsuid;
+ gid_t fd_fsgid;
+ uid_t fd_uid;
+ gid_t fd_gid;
+ mode_t fd_mode;
+ int fd_ngroups;
+ size_t fd_bytes_written; /* Number of bytes written so far on this fd*/
+ gid_t fd_groups[NGROUPS_MAX];
+};
+
+
+/* presto.c and Lento::Downcall */
+struct presto_version {
+ __u64 pv_mtime;
+ __u64 pv_ctime;
+ __u64 pv_size;
+};
+inline struct presto_dentry_data *presto_d2d(struct dentry *);
+int presto_walk(const char *name, struct nameidata *nd);
+int presto_clear_fsetroot(char *path);
+int presto_clear_all_fsetroots(char *path);
+int presto_get_kmlsize(char *path, size_t *size);
+int presto_get_lastrecno(char *path, off_t *size);


+int presto_set_fsetroot(char *path, char *fsetname, unsigned int fsetid,

+ unsigned int flags);
+int presto_has_all_data(struct inode *inode);
+inline int presto_is_read_only(struct presto_file_set *);
+int presto_truncate_lml(struct presto_file_set *fset);


+int lento_write_lml(char *path,
+ __u64 remote_ino,
+ __u32 remote_generation,
+ __u32 remote_version,

+ struct presto_version *remote_file_version);
+int lento_reset_fset(char *path, __u64 offset, __u32 recno);
+int lento_complete_closes(char *path);


+int lento_cancel_lml(char *path,
+ __u64 lml_offset,
+ __u64 remote_ino,
+ __u32 remote_generation,
+ __u32 remote_version,

+ struct lento_vfs_context *info);


+inline int presto_f2m(struct presto_file_set *fset);
+

+/* cache.c */
+#define PRESTO_REQLOW (3 * 4096)
+#define PRESTO_REQHIGH (6 * 4096)
+void presto_release_space(struct presto_cache *cache, loff_t req);


+int presto_reserve_space(struct presto_cache *cache, loff_t req);
+

+/* NOTE: PRESTO_FSETROOT MUST be 0x1:
+ - if this bit is set dentry->d_fsdata points to a file_set
+ - the address of the file_set if d_fsdata - 1
+*/
+
+#define PRESTO_FSETROOT 0x00000001 /* dentry is fileset root */
+#define PRESTO_DATA 0x00000002 /* cached data is valid */
+#define PRESTO_ATTR 0x00000004 /* attributes cached */
+
+#define EISFSETROOT 0x2001
+
+
+struct presto_file_set *presto_path2fileset(const char *name);
+int presto_permit_downcall(const char *path, int *cookie);
+int presto_chk(struct dentry *dentry, int flag);
+void presto_set(struct dentry *dentry, int flag);
+int presto_get_permit(struct inode *inode);
+int presto_put_permit(struct inode *inode);
+int presto_mark_dentry(const char *path, int and, int or, int *res);
+int presto_mark_cache(const char *path, int and_bits, int or_bits, int *);
+int presto_mark_fset(const char *path, int and_bits, int or_bits, int *);
+void presto_getversion(struct presto_version *pv, struct inode *inode);
+int presto_i2m(struct inode *inode);
+int presto_c2m(struct presto_cache *cache);
+
+/* journal.c */
+struct rec_info {
+ loff_t offset;
+ int size;
+ int recno;
+ int is_kml;
+};
+void presto_trans_commit(struct presto_file_set *fset, void *handle);


+void *presto_trans_start(struct presto_file_set *fset, struct inode *inode,

+ int op);
+int presto_clear_lml_close(struct presto_file_set *fset,
+ loff_t lml_offset);


+int presto_write_lml_close(struct rec_info *rec,
+ struct presto_file_set *fset,
+ struct file *file,

+ __u64 remote_ino,
+ __u32 remote_generation,
+ __u32 remote_version,

+ struct presto_version *new_file_ver);


+int presto_complete_lml(struct presto_file_set *fset);
+

+/* vfs.c */


+int presto_do_setattr(struct presto_file_set *fset, struct dentry *dentry,

+ struct iattr *iattr, struct lento_vfs_context *info);


+int presto_do_create(struct presto_file_set *fset, struct dentry *dir,
+ struct dentry *dentry, int mode,

+ struct lento_vfs_context *info);
+int presto_do_link(struct presto_file_set *fset, struct dentry *dir,
+ struct dentry *old_dentry, struct dentry *new_dentry,
+ struct lento_vfs_context *info);


+int presto_do_unlink(struct presto_file_set *fset, struct dentry *dir,

+ struct dentry *dentry, struct lento_vfs_context *info);


+int presto_do_symlink(struct presto_file_set *fset, struct dentry *dir,

+ struct dentry *dentry, const char *name,
+ struct lento_vfs_context *info);


+int presto_do_mkdir(struct presto_file_set *fset, struct dentry *dir,
+ struct dentry *dentry, int mode,

+ struct lento_vfs_context *info);


+int presto_do_rmdir(struct presto_file_set *fset, struct dentry *dir,

+ struct dentry *dentry, struct lento_vfs_context *info);


+int presto_do_mknod(struct presto_file_set *fset, struct dentry *dir,
+ struct dentry *dentry, int mode, dev_t dev,

+ struct lento_vfs_context *info);
+int presto_do_rename(struct presto_file_set *fset, struct dentry *old_dir,
+ struct dentry *old_dentry, struct dentry *new_dir,


+ struct dentry *new_dentry, struct lento_vfs_context *info);
+

+int lento_setattr(const char *name, struct iattr *iattr,

+ struct lento_vfs_context *info);
+int lento_create(const char *name, int mode, struct lento_vfs_context *info);
+int lento_link(const char *oldname, const char *newname,
+ struct lento_vfs_context *info);
+int lento_unlink(const char *name, struct lento_vfs_context *info);
+int lento_symlink(const char *oldname,const char *newname,
+ struct lento_vfs_context *info);
+int lento_mkdir(const char *name, int mode, struct lento_vfs_context *info);
+int lento_rmdir(const char *name, struct lento_vfs_context *info);
+int lento_mknod(const char *name, int mode, dev_t dev,
+ struct lento_vfs_context *info);
+int lento_rename(const char *oldname, const char *newname,
+ struct lento_vfs_context *info);
+int lento_iopen(const char *name, ino_t ino, unsigned int generation,int flags);
+int lento_close(unsigned int fd, struct lento_vfs_context *info);
+
+
+/* journal.c */
+
+#define JOURNAL_PAGE_SZ PAGE_SIZE
+
+__inline__ int presto_no_journal(struct presto_file_set *fset);
+int journal_fetch(int minor);
+int presto_journal_write(struct rec_info *rec, struct presto_file_set *fset,
+ struct file *file);
+int presto_journal_setattr(struct rec_info *rec, struct presto_file_set *fset,
+ struct dentry *dentry,
+ struct presto_version *old_ver,
+ struct iattr *iattr);
+int presto_journal_create(struct rec_info *rec, struct presto_file_set *fset,
+ struct dentry *dentry,
+ struct presto_version *tgt_dir_ver,
+ struct presto_version *new_file_ver, int mode);
+int presto_journal_link(struct rec_info *rec, struct presto_file_set *fset,


+ struct dentry *src, struct dentry *tgt,
+ struct presto_version *tgt_dir_ver,

+ struct presto_version *new_link_ver);
+int presto_journal_unlink(struct rec_info *rec, struct presto_file_set *fset,
+ struct dentry *dentry,


+ struct presto_version *tgt_dir_ver,
+ struct presto_version *old_file_ver, int len,

+ const char *name);
+int presto_journal_symlink(struct rec_info *rec, struct presto_file_set *fset,
+ struct dentry *dentry, const char *target,
+ struct presto_version *tgt_dir_ver,
+ struct presto_version *new_link_ver);
+int presto_journal_mkdir(struct rec_info *rec, struct presto_file_set *fset,
+ struct dentry *dentry,
+ struct presto_version *tgt_dir_ver,
+ struct presto_version *new_dir_ver, int mode);
+int presto_journal_rmdir(struct rec_info *rec, struct presto_file_set *fset,
+ struct dentry *dentry,
+ struct presto_version *tgt_dir_ver,


+ struct presto_version *old_dir_ver, int len,

+ const char *name);
+int presto_journal_mknod(struct rec_info *rec, struct presto_file_set *fset,
+ struct dentry *dentry,
+ struct presto_version *tgt_dir_ver,


+ struct presto_version *new_node_ver, int mode,

+ int dmajor, int dminor);
+int presto_journal_rename(struct rec_info *rec, struct presto_file_set *fset,


+ struct dentry *src, struct dentry *tgt,

+ struct presto_version *src_dir_ver,
+ struct presto_version *tgt_dir_ver);
+int presto_journal_open(struct rec_info *rec, struct presto_file_set *fset,
+ struct dentry *dentry, struct presto_version *old_ver);
+int presto_journal_close(struct rec_info *rec, struct presto_file_set *fset,
+ struct file *file,
+ struct dentry *dentry,
+ struct presto_version *new_ver);
+int presto_close_journal_file(struct presto_file_set *fset);
+void presto_log_op(void *data, int len);


+int presto_write_last_rcvd(struct rec_info *recinfo,
+ struct presto_file_set *fset,

+ struct lento_vfs_context *info);
+

+/* journal_ext3.c */
+struct ext3_journal_data {
+ struct file *jd_file;
+};
+extern struct ext3_journal_data e3jd;
+
+
+
+
+/* sysctl.c */
+int init_intermezzo_sysctl(void);
+void cleanup_intermezzo_sysctl(void);
+
+/* ext_attr.c */
+#ifdef CONFIG_FS_EXT_ATTR
+/* XXX: Borrowed from vfs.c. Once the ea patch is into CVS
+ * move this prototype -SHP
+ */


+int presto_do_set_ext_attr(struct presto_file_set *fset,
+ struct dentry *dentry,
+ const char *name, void *buffer,
+ size_t buffer_len, int flags, mode_t *mode,

+ struct lento_vfs_context *info);
+int presto_set_ext_attr(struct inode *inode,


+ const char *name, void *buffer,

+ size_t buffer_len, int flags);
+int lento_set_ext_attr(const char *path, const char *name,


+ void *buffer, size_t buffer_len, int flags,

+ mode_t mode, struct lento_vfs_context *info);
+/* XXX: Borrowed from journal.c. Once the ea patch is into CVS
+ * move this prototype -SHP


+ */
+int presto_journal_set_ext_attr (struct rec_info *rec,

+ struct presto_file_set *fset,
+ struct dentry *dentry,


+ struct presto_version *ver, const char *name,
+ const char *buffer, int buffer_len,

+ int flags);
+#endif
+
+
+/* global variables */
+extern int presto_debug;
+extern int presto_print_entry;
+
+#define PRESTO_DEBUG
+#ifdef PRESTO_DEBUG
+/* debugging masks */
+#define D_SUPER 1 /* print results returned by Venus */
+#define D_INODE 2 /* print entry and exit into procedure */
+#define D_FILE 4
+#define D_CACHE 8 /* cache debugging */
+#define D_MALLOC 16 /* print malloc, de-alloc information */
+#define D_JOURNAL 32
+#define D_UPCALL 64 /* up and downcall debugging */
+#define D_PSDEV 128
+#define D_PIOCTL 256
+#define D_SPECIAL 512
+#define D_TIMING 1024
+#define D_DOWNCALL 2048
+#define D_KML 4096
+
+#define CDEBUG(mask, format, a...) \
+ do { \
+ if (presto_debug & mask) { \
+ printk("(%s:%s,l. %d %d): ", __FILE__, __FUNCTION__, __LINE__, current->pid); \
+ printk(format, ##a); } \
+ } while (0)
+
+#define ENTRY \
+ if(presto_print_entry) \
+ printk("Process %d entered %s\n", current->pid, __FUNCTION__)
+
+#define EXIT \
+ if(presto_print_entry) \
+ printk("Process %d leaving %s at %d\n", current->pid, \
+ __FUNCTION__,__LINE__)
+
+extern long presto_kmemory;
+extern long presto_vmemory;
+
+#define presto_kmem_inc(ptr, size) presto_kmemory += (size)
+#define presto_kmem_dec(ptr, size) presto_kmemory -= (size)
+#define presto_vmem_inc(ptr, size) presto_vmemory += (size)
+#define presto_vmem_dec(ptr, size) presto_vmemory -= (size)
+#else /* !PRESTO_DEBUG */
+#define CDEBUG(mask, format, a...) do {} while (0)
+#define ENTRY do {} while (0)
+#define EXIT do {} while (0)
+#define presto_kmem_inc(ptr, size) do {} while (0)
+#define presto_kmem_dec(ptr, size) do {} while (0)
+#define presto_vmem_inc(ptr, size) do {} while (0)
+#define presto_vmem_dec(ptr, size) do {} while (0)
+#endif /* PRESTO_DEBUG */
+
+
+#define PRESTO_ALLOC(ptr, cast, size) \
+do { \
+ if (size <= 4096) { \
+ ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL); \
+ CDEBUG(D_MALLOC, "kmalloced: %ld at %p.\n", (long)size, ptr); \
+ presto_kmem_inc(ptr, size); \
+ } else { \
+ ptr = (cast)vmalloc((unsigned long) size); \
+ CDEBUG(D_MALLOC, "vmalloced: %ld at %p.\n", (long)size, ptr); \
+ presto_vmem_inc(ptr, size); \
+ } \
+ if ((ptr) == 0) \
+ printk("PRESTO: out of memory at %s:%d\n", __FILE__, __LINE__); \
+ else \
+ memset( ptr, 0, size ); \
+} while (0)
+
+
+
+#define PRESTO_FREE(ptr,size) \
+do { \
+ if (!ptr) { \
+ printk("PRESTO: free NULL pointer (%ld bytes) at %s:%d\n", \
+ (long)size, __FILE__, __LINE__); \
+ break; \
+ } \
+ if (size <= 4096) { \
+ CDEBUG(D_MALLOC, "kfreed: %ld at %p.\n", (long)size, ptr); \
+ presto_kmem_dec(ptr, size); \
+ kfree((ptr)); \
+ } else { \
+ CDEBUG(D_MALLOC, "vfreed: %ld at %p.\n", (long)size, ptr); \
+ presto_vmem_dec(ptr, size); \
+ vfree((ptr)); \
+ } \
+} while (0)
+
+#define MYPATHLEN(buffer,path) (buffer + PAGE_SIZE - path - 1)
+
+#else /* __KERNEL__ */
+#include <asm/types.h>
+#include <sys/ioctl.h>
+struct lento_vfs_context {
+ __u32 slot_offset;
+ __u32 recno;
+ __u64 kml_offset;
+ __u32 flags;
+ __u32 updated_time;
+};
+#endif /* __KERNEL__*/
+
+
+/* marking flags for fsets */
+#define FSET_CLIENT_RO 0x00000001
+#define FSET_LENTO_RO 0x00000002
+#define FSET_HASPERMIT 0x00000004 /* we have a permit to WB */
+#define FSET_INSYNC 0x00000008 /* this fileset is in sync */
+#define FSET_PERMIT_WAITING 0x00000010 /* Lento is waiting for permit */
+#define FSET_STEAL_PERMIT 0x00000020 /* take permit if Lento is dead */
+#define FSET_JCLOSE_ON_WRITE 0x00000040 /* Journal closes on writes */
+
+
+/* what to mark indicator (ioctl parameter) */
+#define MARK_DENTRY 101
+#define MARK_FSET 102
+#define MARK_CACHE 103
+#define MARK_GETFL 104
+
+
+
+struct readmount {
+ int io_len; /* this is IN & OUT: true length of str is returned */
+ char *io_string;
+};
+
+/* modeled after setsockopt */
+/* so if you have no /proc, oh well. */
+/* for now it's all ints. We may grow this later for non-ints. */
+struct psdev_opt {
+ int optname;
+ int optval;
+};
+
+struct lento_input {
+ char *name;
+ struct lento_vfs_context info;
+};
+
+struct lento_input_attr {
+ char *name;
+#if BITS_PER_LONG < 64
+ __u32 dummy; /* XXX on 64-bit platforms, this is not needed */
+#endif
+ __u32 valid;
+ __u32 mode;
+ __u32 uid;
+ __u32 gid;
+ __u64 size;
+ __s64 atime;
+ __s64 mtime;
+ __s64 ctime;
+ __u32 attr_flags;
+ struct lento_vfs_context info;
+};
+
+struct lento_input_mode {
+ char *name;
+ __u32 mode;
+ struct lento_vfs_context info;
+};
+
+struct lento_input_old_new {
+ char *oldname;
+ char *newname;
+ struct lento_vfs_context info;
+};
+
+struct lento_input_dev {
+ char *name;
+ __u32 mode;
+ __u32 major;
+ __u32 minor;
+ struct lento_vfs_context info;
+};
+
+struct lento_input_iopen {
+ char *name;
+#if BITS_PER_LONG < 64
+ __u32 dummy; /* XXX on 64-bit platforms, this is not needed */
+#endif
+ __u64 ino;
+ __u32 generation;
+ __u32 flags;
+ __s32 fd;
+};
+
+struct lento_input_close {
+ __u32 fd;
+ struct lento_vfs_context info;
+};
+
+/* XXX: check for alignment */
+struct lento_input_ext_attr {
+ char *path;
+ char *name;
+ __u32 name_len;
+ char *buffer;
+ __u32 buffer_len;
+ __u32 flags;
+ __u32 mode;
+ struct lento_vfs_context info;
+};
+
+/* XXX should PRESTO_GET_* actually be of type _IOR, since we are reading? */
+#define PRESTO_GETMOUNT _IOW ('p',0x03, struct readmount *)
+#define PRESTO_SETPID _IOW ('p',0x04, struct readmount *)
+#define PRESTO_CLOSE_JOURNALF _IOW ('p',0x06, struct readmount *)
+#define PRESTO_SET_FSETROOT _IOW ('p',0x07, struct readmount *)
+#define PRESTO_CLEAR_FSETROOT _IOW ('p',0x08, struct readmount *)
+#define PRESTO_SETOPT _IOW ('p',0x09, struct psdev_opt *)
+#define PRESTO_GETOPT _IOW ('p',0x0a, struct psdev_opt *)
+#define PRESTO_GET_KMLSIZE _IOW ('p',0x0b, struct psdev_opt *)
+#define PRESTO_GET_RECNO _IOW ('p',0x0c, struct psdev_opt *)
+#define PRESTO_VFS_SETATTR _IOW ('p',0x10, struct lento_input_attr *)
+#define PRESTO_VFS_CREATE _IOW ('p',0x11, struct lento_input_mode *)
+#define PRESTO_VFS_LINK _IOW ('p',0x12, struct lento_input_old_new *)
+#define PRESTO_VFS_UNLINK _IOW ('p',0x13, struct lento_input *)
+#define PRESTO_VFS_SYMLINK _IOW ('p',0x14, struct lento_input_old_new *)
+#define PRESTO_VFS_MKDIR _IOW ('p',0x15, struct lento_input_mode *)
+#define PRESTO_VFS_RMDIR _IOW ('p',0x16, struct lento_input *)
+#define PRESTO_VFS_MKNOD _IOW ('p',0x17, struct lento_input_dev *)
+#define PRESTO_VFS_RENAME _IOW ('p',0x18, struct lento_input_old_new *)
+#define PRESTO_VFS_CLOSE _IOW ('p',0x1a, struct lento_input_close *)
+#define PRESTO_VFS_IOPEN _IOW ('p',0x1b, struct lento_input_iopen *)
+#define PRESTO_VFS_SETEXTATTR _IOW ('p',0x1c, struct lento_input_ext_attr *)
+#define PRESTO_VFS_DELEXTATTR _IOW ('p',0x1d, struct lento_input_ext_attr *)
+
+#define PRESTO_MARK _IOW ('p',0x20, struct lento_input_open *)
+#define PRESTO_RELEASE_PERMIT _IOW ('p',0x21, struct lento_input_open *)
+#define PRESTO_CLEAR_ALL_FSETROOTS _IOW ('p',0x22, struct readmount *)
+#define PRESTO_BACKFETCH_LML _IOW ('p',0x23, struct readmount *)
+#define PRESTO_REINT _IOW ('p',0x24, struct readmount *)
+#define PRESTO_CANCEL_LML _IOW ('p',0x25, struct readmount *)
+#define PRESTO_RESET_FSET _IOW ('p',0x26, struct readmount *)
+#define PRESTO_COMPLETE_CLOSES _IOW ('p',0x27, struct readmount *)
+
+#define PRESTO_REINT_BEGIN _IOW ('p',0x30, struct readmount *)
+#define PRESTO_DO_REINT _IOW ('p',0x31, struct readmount *)
+#define PRESTO_REINT_END _IOW ('p',0x32, struct readmount *)
+
+#endif
diff -u --recursive --new-file v2.4.14/linux/include/linux/intermezzo_journal.h linux/include/linux/intermezzo_journal.h
--- v2.4.14/linux/include/linux/intermezzo_journal.h Wed Dec 31 16:00:00 1969
+++ linux/include/linux/intermezzo_journal.h Sun Nov 11 10:20:21 2001
@@ -0,0 +1,26 @@
+#ifndef __PRESTO_JOURNAL_H
+#define __PRESTO_JOURNAL_H
+
+
+#include <linux/version.h>
+
+struct journal_prefix {
+ int len;
+ u32 version;
+ int pid;
+ int uid;
+ int fsuid;
+ int fsgid;
+ int opcode;
+ u32 ngroups;
+ u32 groups[0];
+};
+
+struct journal_suffix {
+ unsigned long prevrec; /* offset of previous record for dentry */
+ int recno;
+ int time;
+ int len;
+};
+
+#endif
diff -u --recursive --new-file v2.4.14/linux/include/linux/intermezzo_kml.h linux/include/linux/intermezzo_kml.h
--- v2.4.14/linux/include/linux/intermezzo_kml.h Wed Dec 31 16:00:00 1969
+++ linux/include/linux/intermezzo_kml.h Sun Nov 11 10:20:21 2001
@@ -0,0 +1,261 @@
+#ifndef __INTERMEZZO_KML_H
+#define __INTERMEZZO_KML_H
+
+#include <linux/version.h>
+#include <linux/intermezzo_psdev.h>
+#include <linux/fs.h>
+#include <linux/intermezzo_journal.h>
+
+#define PRESTO_KML_MAJOR_VERSION 0x00010000
+#define PRESTO_KML_MINOR_VERSION 0x00002001
+#define PRESTO_OP_NOOP 0
+#define PRESTO_OP_CREATE 1
+#define PRESTO_OP_MKDIR 2
+#define PRESTO_OP_UNLINK 3
+#define PRESTO_OP_RMDIR 4
+#define PRESTO_OP_CLOSE 5
+#define PRESTO_OP_SYMLINK 6
+#define PRESTO_OP_RENAME 7
+#define PRESTO_OP_SETATTR 8
+#define PRESTO_OP_LINK 9
+#define PRESTO_OP_OPEN 10
+#define PRESTO_OP_MKNOD 11
+#define PRESTO_OP_WRITE 12
+#define PRESTO_OP_RELEASE 13
+#define PRESTO_OP_TRUNC 14
+#define PRESTO_OP_SETEXTATTR 15
+#define PRESTO_OP_DELEXTATTR 16
+
+#define PRESTO_LML_DONE 1 /* flag to get first write to do LML */
+#define KML_KOP_MARK 0xffff
+
+struct presto_lml_data {
+ loff_t rec_offset;
+};
+
+struct big_journal_prefix {
+ u32 len;
+ u32 version;
+ u32 pid;
+ u32 uid;
+ u32 fsuid;
+ u32 fsgid;
+ u32 opcode;
+ u32 ngroups;
+ u32 groups[NGROUPS_MAX];
+};
+
+enum kml_opcode {
+ KML_CREATE = 1,
+ KML_MKDIR,
+ KML_UNLINK,
+ KML_RMDIR,
+ KML_CLOSE,
+ KML_SYMLINK,
+ KML_RENAME,
+ KML_SETATTR,
+ KML_LINK,
+ KML_OPEN,
+ KML_MKNOD,
+ KML_ENDMARK = 0xff
+};
+
+struct kml_create {
+ char *path;
+ struct presto_version new_objectv,
+ old_parentv,
+ new_parentv;
+ int mode;
+ int uid;
+ int gid;
+};
+
+struct kml_open {
+};
+
+struct kml_mkdir {
+ char *path;
+ struct presto_version new_objectv,
+ old_parentv,
+ new_parentv;
+ int mode;
+ int uid;
+ int gid;
+};
+
+struct kml_unlink {
+ char *path,
+ *name;
+ struct presto_version old_tgtv,
+ old_parentv,
+ new_parentv;
+};
+
+struct kml_rmdir {
+ char *path,
+ *name;
+ struct presto_version old_tgtv,
+ old_parentv,
+ new_parentv;
+};
+
+struct kml_close {
+ int open_mode,
+ open_uid,
+ open_gid;
+ char *path;
+ struct presto_version new_objectv;
+ __u64 ino;
+ int generation;
+};
+
+struct kml_symlink {
+ char *sourcepath,
+ *targetpath;
+ struct presto_version new_objectv,
+ old_parentv,
+ new_parentv;
+ int uid;
+ int gid;
+};
+
+struct kml_rename {
+ char *sourcepath,
+ *targetpath;
+ struct presto_version old_objectv,
+ new_objectv,
+ old_tgtv,
+ new_tgtv;
+};
+
+struct kml_setattr {
+ char *path;
+ struct presto_version old_objectv;


+ struct iattr iattr;
+};
+

+struct kml_link {
+ char *sourcepath,
+ *targetpath;
+ struct presto_version new_objectv,
+ old_parentv,
+ new_parentv;
+};
+
+struct kml_mknod {
+ char *path;
+ struct presto_version new_objectv,
+ old_parentv,
+ new_parentv;
+ int mode;
+ int uid;
+ int gid;
+ int major;


+ int minor;
+};
+

+/* kml record items for optimizing */
+struct kml_kop_node
+{
+ u32 kml_recno;
+ u32 kml_flag;
+ u32 kml_op;
+ nlink_t i_nlink;
+ u32 i_ino;
+};
+
+struct kml_kop_lnode
+{
+ struct list_head chains;
+ struct kml_kop_node node;
+};
+
+struct kml_endmark {
+ u32 total;
+ struct kml_kop_node *kop;
+};
+
+/* kml_flag */
+#define KML_REC_DELETE 1
+#define KML_REC_EXIST 0
+
+struct kml_optimize {
+ struct list_head kml_chains;
+ u32 kml_flag;
+ u32 kml_op;
+ nlink_t i_nlink;
+ u32 i_ino;
+};
+
+struct kml_rec {
+ /* attribute of this record */
+ int rec_size;
+ int rec_kml_offset;
+
+ struct big_journal_prefix rec_head;
+ union {
+ struct kml_create create;
+ struct kml_open open;
+ struct kml_mkdir mkdir;
+ struct kml_unlink unlink;
+ struct kml_rmdir rmdir;
+ struct kml_close close;
+ struct kml_symlink symlink;
+ struct kml_rename rename;
+ struct kml_setattr setattr;
+ struct kml_mknod mknod;
+ struct kml_link link;
+ struct kml_endmark endmark;
+ } rec_kml;
+ struct journal_suffix rec_tail;
+
+ /* for kml optimize only */
+ struct kml_optimize kml_optimize;
+};
+
+/* kml record items for optimizing */
+extern void kml_kop_init (struct presto_file_set *fset);
+extern void kml_kop_addrec (struct presto_file_set *fset,
+ struct inode *ino, u32 op, u32 flag);
+extern int kml_kop_flush (struct presto_file_set *fset);
+
+/* defined in kml_setup.c */
+extern int kml_init (struct presto_file_set *fset);
+extern int kml_cleanup (struct presto_file_set *fset);
+
+/* defined in kml.c */
+extern int begin_kml_reint (struct file *file, unsigned long arg);
+extern int do_kml_reint (struct file *file, unsigned long arg);
+extern int end_kml_reint (struct file *file, unsigned long arg);
+
+/* kml_utils.c */
+extern char *dlogit (void *tbuf, const void *sbuf, int size);
+extern char * bdup_printf (char *format, ...);
+
+/* defined in kml_decode.c */
+/* printop */
+#define PRINT_KML_PREFIX 0x1
+#define PRINT_KML_SUFFIX 0x2
+#define PRINT_KML_REC 0x4
+#define PRINT_KML_OPTIMIZE 0x8
+#define PRINT_KML_EXIST 0x10
+#define PRINT_KML_DELETE 0x20
+extern void kml_printrec (struct kml_rec *rec, int printop);
+extern int print_allkmlrec (struct list_head *head, int printop);


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

echo 'End of part 110'
echo 'File patch-2.4.15 is continued in part 111'
echo "111" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:29 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part113

#!/bin/sh -x
# this is part 113 of a 115 - part archive


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

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

X * modify it under the terms of the GNU General Public License as
@@ -47,7 +48,9 @@
X * duration of the P-timer.
X */
X #define WD_TIMEOUT (POLL_TIMEOUT*2)
+
X #define MEDIABUSY_TIMEOUT (500*HZ/1000) /* 500 msec */
+#define SMALLBUSY_TIMEOUT (100*HZ/1000) /* 100 msec - IrLAP 6.13.4 */
X
X /*
X * Slot timer must never exceed 85 ms, and must always be at least 25 ms,
@@ -75,7 +78,7 @@
X inline void irlap_start_wd_timer(struct irlap_cb *self, int timeout);
X inline void irlap_start_backoff_timer(struct irlap_cb *self, int timeout);
X
-void irlap_start_mbusy_timer(struct irlap_cb *);
+void irlap_start_mbusy_timer(struct irlap_cb *self, int timeout);
X void irlap_stop_mbusy_timer(struct irlap_cb *);
X
X struct lsap_cb;
diff -u --recursive --new-file v2.4.14/linux/init/main.c linux/init/main.c
--- v2.4.14/linux/init/main.c Tue Oct 23 22:48:53 2001
+++ linux/init/main.c Fri Nov 9 14:15:00 2001
@@ -119,7 +119,7 @@
X int rows, cols;
X
X #ifdef CONFIG_BLK_DEV_INITRD
-kdev_t real_root_dev;
+unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */
X #endif
X
X int root_mountflags = MS_RDONLY;
diff -u --recursive --new-file v2.4.14/linux/init/version.c linux/init/version.c
--- v2.4.14/linux/init/version.c Mon Oct 2 11:57:01 2000
+++ linux/init/version.c Fri Nov 9 14:11:15 2001


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

- * linux/version.c
+ * linux/init/version.c
X *
X * Copyright (C) 1992 Theodore Ts'o
X *
diff -u --recursive --new-file v2.4.14/linux/kernel/exec_domain.c linux/kernel/exec_domain.c
--- v2.4.14/linux/kernel/exec_domain.c Mon Nov 5 15:55:35 2001
+++ linux/kernel/exec_domain.c Sun Nov 11 10:20:21 2001
@@ -77,7 +77,6 @@
X lookup_exec_domain(u_long personality)
X {
X struct exec_domain * ep;
- char buffer[30];
X u_long pers = personality(personality);
X
X read_lock(&exec_domains_lock);
@@ -89,8 +88,11 @@
X
X #ifdef CONFIG_KMOD
X read_unlock(&exec_domains_lock);
- sprintf(buffer, "personality-%ld", pers);
- request_module(buffer);
+ {
+ char buffer[30];
+ sprintf(buffer, "personality-%ld", pers);
+ request_module(buffer);
+ }
X read_lock(&exec_domains_lock);
X
X for (ep = exec_domains; ep; ep = ep->next) {
diff -u --recursive --new-file v2.4.14/linux/kernel/exit.c linux/kernel/exit.c
--- v2.4.14/linux/kernel/exit.c Tue Oct 23 22:48:53 2001
+++ linux/kernel/exit.c Wed Nov 21 14:42:27 2001
@@ -35,12 +35,13 @@
X */
X for (;;) {
X task_lock(p);
- if (!p->has_cpu)
+ if (!task_has_cpu(p))
X break;
X task_unlock(p);
X do {
+ cpu_relax();
X barrier();
- } while (p->has_cpu);
+ } while (task_has_cpu(p));
X }
X task_unlock(p);
X #endif
diff -u --recursive --new-file v2.4.14/linux/kernel/fork.c linux/kernel/fork.c
--- v2.4.14/linux/kernel/fork.c Sun Sep 23 11:41:01 2001
+++ linux/kernel/fork.c Wed Nov 21 10:18:42 2001
@@ -638,7 +638,7 @@
X #ifdef CONFIG_SMP
X {
X int i;
- p->has_cpu = 0;
+ p->cpus_runnable = ~0UL;
X p->processor = current->processor;
X /* ?? should we just memset this ?? */
X for(i = 0; i < smp_num_cpus; i++)
diff -u --recursive --new-file v2.4.14/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.4.14/linux/kernel/ksyms.c Mon Nov 5 15:55:35 2001
+++ linux/kernel/ksyms.c Wed Nov 21 14:07:25 2001
@@ -199,6 +199,7 @@
X EXPORT_SYMBOL(unlock_buffer);
X EXPORT_SYMBOL(__wait_on_buffer);
X EXPORT_SYMBOL(___wait_on_page);
+EXPORT_SYMBOL(generic_direct_IO);
X EXPORT_SYMBOL(block_write_full_page);
X EXPORT_SYMBOL(block_read_full_page);
X EXPORT_SYMBOL(block_prepare_write);
diff -u --recursive --new-file v2.4.14/linux/kernel/module.c linux/kernel/module.c
--- v2.4.14/linux/kernel/module.c Sun Sep 23 11:41:01 2001
+++ linux/kernel/module.c Sun Nov 11 11:23:14 2001
@@ -9,6 +9,7 @@
X #include <linux/init.h>
X #include <linux/slab.h>
X #include <linux/kmod.h>
+#include <linux/seq_file.h>
X
X /*
X * Originally by Anonymous (as far as I know...)
@@ -1156,51 +1157,83 @@
X * Called by the /proc file system to return a current list of ksyms.
X */
X
-int
-get_ksyms_list(char *buf, char **start, off_t offset, int length)
-{
+struct mod_sym {
X struct module *mod;
- char *p = buf;
- int len = 0; /* code from net/ipv4/proc.c */
- off_t pos = 0;
- off_t begin = 0;
-
- for (mod = module_list; mod; mod = mod->next) {
- unsigned i;
- struct module_symbol *sym;
+ int index;
+};
X
- if (!MOD_CAN_QUERY(mod))
- continue;
+/* iterator */
X
- for (i = mod->nsyms, sym = mod->syms; i > 0; --i, ++sym) {
- p = buf + len;
- if (*mod->name) {
- len += sprintf(p, "%0*lx %s\t[%s]\n",
- (int)(2*sizeof(void*)),
- sym->value, sym->name,
- mod->name);
- } else {
- len += sprintf(p, "%0*lx %s\n",
- (int)(2*sizeof(void*)),
- sym->value, sym->name);
- }
- pos = begin + len;
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
- pos = begin + len;
- if (pos > offset+length)
- goto leave_the_loop;
+static void *s_start(struct seq_file *m, loff_t *pos)
+{
+ struct mod_sym *p = kmalloc(sizeof(*p), GFP_KERNEL);
+ struct module *v;


+ loff_t n = *pos;

+
+ if (!p)
+ return ERR_PTR(-ENOMEM);
+ lock_kernel();
+ for (v = module_list, n = *pos; v; n -= v->nsyms, v = v->next) {
+ if (n < v->nsyms) {
+ p->mod = v;
+ p->index = n;
+ return p;
X }
X }
-leave_the_loop:
- *start = buf + (offset - begin);
- len -= (offset - begin);
- if (len > length)
- len = length;
- return len;
+ unlock_kernel();
+ kfree(p);


+ return NULL;
+}
+

+static void *s_next(struct seq_file *m, void *p, loff_t *pos)
+{
+ struct mod_sym *v = p;
+ (*pos)++;
+ if (++v->index >= v->mod->nsyms) {
+ do {
+ v->mod = v->mod->next;
+ if (!v->mod) {
+ unlock_kernel();
+ kfree(p);
+ return NULL;
+ }
+ } while (!v->mod->nsyms);
+ v->index = 0;
+ }
+ return p;
+}
+
+static void s_stop(struct seq_file *m, void *p)
+{
+ if (p && !IS_ERR(p)) {
+ unlock_kernel();
+ kfree(p);
+ }
+}
+
+static int s_show(struct seq_file *m, void *p)
+{
+ struct mod_sym *v = p;
+ struct module_symbol *sym;
+
+ if (!MOD_CAN_QUERY(v->mod))
+ return 0;
+ sym = &v->mod->syms[v->index];
+ if (*v->mod->name)
+ seq_printf(m, "%0*lx %s\t[%s]\n", (int)(2*sizeof(void*)),
+ sym->value, sym->name, v->mod->name);
+ else
+ seq_printf(m, "%0*lx %s\n", (int)(2*sizeof(void*)),
+ sym->value, sym->name);


+ return 0;
X }
+

+struct seq_operations ksyms_op = {
+ start: s_start,
+ next: s_next,
+ stop: s_stop,
+ show: s_show
+};
X
X #else /* CONFIG_MODULES */
X
diff -u --recursive --new-file v2.4.14/linux/kernel/printk.c linux/kernel/printk.c
--- v2.4.14/linux/kernel/printk.c Mon Nov 5 15:55:35 2001
+++ linux/kernel/printk.c Sun Nov 11 10:20:21 2001
@@ -535,6 +535,18 @@
X }
X EXPORT_SYMBOL(console_print);
X
+void console_unblank(void)
+{
+ struct console *c;
+
+ acquire_console_sem();
+ for (c = console_drivers; c != NULL; c = c->next)
+ if ((c->flags & CON_ENABLED) && c->unblank)
+ c->unblank();
+ release_console_sem();
+}
+EXPORT_SYMBOL(console_unblank);
+
X /*
X * The console driver calls this routine during kernel initialization
X * to register the console printing procedure with printk() and to
diff -u --recursive --new-file v2.4.14/linux/kernel/ptrace.c linux/kernel/ptrace.c
--- v2.4.14/linux/kernel/ptrace.c Sun Sep 23 11:41:01 2001
+++ linux/kernel/ptrace.c Wed Nov 21 14:43:01 2001
@@ -16,6 +16,42 @@
X #include <asm/pgtable.h>
X #include <asm/uaccess.h>
X
+/*
+ * Check that we have indeed attached to the thing..
+ */
+int ptrace_check_attach(struct task_struct *child, int kill)
+{
+ if (!(child->ptrace & PT_PTRACED))
+ return -ESRCH;
+
+ if (child->p_pptr != current)
+ return -ESRCH;
+
+ if (!kill) {
+ if (child->state != TASK_STOPPED)
+ return -ESRCH;
+#ifdef CONFIG_SMP
+ /* Make sure the child gets off its CPU.. */
+ for (;;) {
+ task_lock(child);
+ if (!task_has_cpu(child))
+ break;
+ task_unlock(child);
+ do {
+ if (child->state != TASK_STOPPED)
+ return -ESRCH;
+ barrier();
+ cpu_relax();
+ } while (task_has_cpu(child));
+ }
+ task_unlock(child);
+#endif
+ }
+
+ /* All systems go.. */


+ return 0;
+}
+

X int ptrace_attach(struct task_struct *task)
X {
X task_lock(task);
diff -u --recursive --new-file v2.4.14/linux/kernel/sched.c linux/kernel/sched.c
--- v2.4.14/linux/kernel/sched.c Tue Oct 23 22:48:53 2001
+++ linux/kernel/sched.c Wed Nov 21 16:25:48 2001
@@ -28,6 +28,7 @@
X #include <linux/kernel_stat.h>
X #include <linux/completion.h>
X #include <linux/prefetch.h>
+#include <linux/compiler.h>
X
X #include <asm/uaccess.h>
X #include <asm/mmu_context.h>
@@ -114,8 +115,8 @@
X #ifdef CONFIG_SMP
X
X #define idle_task(cpu) (init_tasks[cpu_number_map(cpu)])
-#define can_schedule(p,cpu) ((!(p)->has_cpu) && \
- ((p)->cpus_allowed & (1 << cpu)))
+#define can_schedule(p,cpu) \
+ ((p)->cpus_runnable & (p)->cpus_allowed & (1 << cpu))
X
X #else
X
@@ -455,11 +456,11 @@
X
X /*
X * prev->policy can be written from here only before `prev'
- * can be scheduled (before setting prev->has_cpu to zero).
+ * can be scheduled (before setting prev->cpus_runnable to ~0UL).
X * Of course it must also be read before allowing prev
X * to be rescheduled, but since the write depends on the read
X * to complete, wmb() is enough. (the spin_lock() acquired
- * before setting has_cpu is not enough because the spin_lock()
+ * before setting cpus_runnable is not enough because the spin_lock()
X * common code semantics allows code outside the critical section
X * to enter inside the critical section)
X */
@@ -468,12 +469,12 @@
X wmb();
X
X /*
- * fast path falls through. We have to clear has_cpu before
- * checking prev->state to avoid a wakeup race - thus we
- * also have to protect against the task exiting early.
+ * fast path falls through. We have to clear cpus_runnable before
+ * checking prev->state to avoid a wakeup race. Protect against
+ * the task exiting early.
X */
X task_lock(prev);
- prev->has_cpu = 0;
+ task_release_cpu(prev);
X mb();
X if (prev->state == TASK_RUNNING)
X goto needs_resched;
@@ -505,7 +506,7 @@
X goto out_unlock;
X
X spin_lock_irqsave(&runqueue_lock, flags);
- if ((prev->state == TASK_RUNNING) && !prev->has_cpu)
+ if ((prev->state == TASK_RUNNING) && !task_has_cpu(prev))
X reschedule_idle(prev);
X spin_unlock_irqrestore(&runqueue_lock, flags);
X goto out_unlock;
@@ -515,7 +516,7 @@
X #endif /* CONFIG_SMP */
X }
X
-void schedule_tail(struct task_struct *prev)
+asmlinkage void schedule_tail(struct task_struct *prev)
X {
X __schedule_tail(prev);
X }
@@ -545,8 +546,10 @@
X prev = current;
X this_cpu = prev->processor;
X
- if (in_interrupt())
- goto scheduling_in_interrupt;
+ if (unlikely(in_interrupt())) {
+ printk("Scheduling in interrupt\n");
+ BUG();
+ }
X
X release_kernel_lock(prev, this_cpu);
X
@@ -559,9 +562,11 @@
X spin_lock_irq(&runqueue_lock);
X
X /* move an exhausted RR process to be last.. */
- if (prev->policy == SCHED_RR)
- goto move_rr_last;
-move_rr_back:
+ if (unlikely(prev->policy == SCHED_RR))
+ if (!prev->counter) {
+ prev->counter = NICE_TO_TICKS(prev->nice);
+ move_last_runqueue(prev);
+ }
X
X switch (prev->state) {
X case TASK_INTERRUPTIBLE:
@@ -585,10 +590,6 @@
X */
X next = idle_task(this_cpu);
X c = -1000;
- if (prev->state == TASK_RUNNING)
- goto still_running;
-
-still_running_back:
X list_for_each(tmp, &runqueue_head) {
X p = list_entry(tmp, struct task_struct, run_list);
X if (can_schedule(p, this_cpu)) {
@@ -599,21 +600,28 @@
X }
X
X /* Do we need to re-calculate counters? */
- if (!c)
- goto recalculate;
+ if (unlikely(!c)) {
+ struct task_struct *p;
+
+ spin_unlock_irq(&runqueue_lock);
+ read_lock(&tasklist_lock);
+ for_each_task(p)
+ p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice);
+ read_unlock(&tasklist_lock);
+ spin_lock_irq(&runqueue_lock);
+ goto repeat_schedule;
+ }
+
X /*
X * from this point on nothing can prevent us from
X * switching to the next task, save this fact in
X * sched_data.
X */
X sched_data->curr = next;
-#ifdef CONFIG_SMP
- next->has_cpu = 1;
- next->processor = this_cpu;
-#endif
+ task_set_cpu(next, this_cpu);
X spin_unlock_irq(&runqueue_lock);
X
- if (prev == next) {
+ if (unlikely(prev == next)) {
X /* We won't go through the normal tail, so do this by hand */
X prev->policy &= ~SCHED_YIELD;
X goto same_process;
@@ -678,38 +686,6 @@
X reacquire_kernel_lock(current);
X if (current->need_resched)
X goto need_resched_back;
-
- return;
-
-recalculate:
- {
- struct task_struct *p;
- spin_unlock_irq(&runqueue_lock);
- read_lock(&tasklist_lock);
- for_each_task(p)
- p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice);
- read_unlock(&tasklist_lock);
- spin_lock_irq(&runqueue_lock);
- }
- goto repeat_schedule;
-
-still_running:
- if (!(prev->cpus_allowed & (1UL << this_cpu)))
- goto still_running_back;
- c = goodness(prev, this_cpu, prev->active_mm);
- next = prev;
- goto still_running_back;
-
-move_rr_last:
- if (!prev->counter) {
- prev->counter = NICE_TO_TICKS(prev->nice);
- move_last_runqueue(prev);
- }
- goto move_rr_back;
-
-scheduling_in_interrupt:
- printk("Scheduling in interrupt\n");
- BUG();
X return;
X }
X
@@ -1072,6 +1048,10 @@
X if (current->policy == SCHED_OTHER)
X current->policy |= SCHED_YIELD;
X current->need_resched = 1;
+
+ spin_lock_irq(&runqueue_lock);
+ move_last_runqueue(current);
+ spin_unlock_irq(&runqueue_lock);


X }
X return 0;
X }

@@ -1176,13 +1156,10 @@
X else
X printk(" (NOTLB)\n");
X
-#if defined(CONFIG_X86) || defined(CONFIG_SPARC64) || defined(CONFIG_ARM) || defined(CONFIG_ALPHA)
-/* This is very useful, but only works on ARM, x86 and sparc64 right now */
X {
X extern void show_trace_task(struct task_struct *tsk);
X show_trace_task(p);
X }
-#endif
X }
X
X char * render_sigset_t(sigset_t *set, char *buffer)
@@ -1250,11 +1227,6 @@
X SET_LINKS(this_task);
X
X /* Set the exit signal to SIGCHLD so we signal init on exit */
- if (this_task->exit_signal != 0) {
- printk(KERN_ERR "task `%s' exit_signal %d in "
- __FUNCTION__ "\n",
- this_task->comm, this_task->exit_signal);
- }
X this_task->exit_signal = SIGCHLD;
X
X /* We also take the runqueue_lock while altering task fields
diff -u --recursive --new-file v2.4.14/linux/kernel/signal.c linux/kernel/signal.c
--- v2.4.14/linux/kernel/signal.c Sun Sep 23 11:41:01 2001
+++ linux/kernel/signal.c Wed Nov 21 16:26:27 2001
@@ -479,7 +479,7 @@
X * other than doing an extra (lightweight) IPI interrupt.
X */
X spin_lock(&runqueue_lock);
- if (t->has_cpu && t->processor != smp_processor_id())
+ if (task_has_cpu(t) && t->processor != smp_processor_id())
X smp_send_reschedule(t->processor);
X spin_unlock(&runqueue_lock);
X #endif /* CONFIG_SMP */
diff -u --recursive --new-file v2.4.14/linux/lib/brlock.c linux/lib/brlock.c
--- v2.4.14/linux/lib/brlock.c Tue Jul 3 17:08:22 2001
+++ linux/lib/brlock.c Fri Nov 9 14:11:15 2001
@@ -54,6 +54,7 @@
X if (__brlock_array[cpu_logical_map(i)][idx] != 0) {
X spin_unlock(&__br_write_locks[idx].lock);
X barrier();
+ cpu_relax();
X goto again;
X }
X }
diff -u --recursive --new-file v2.4.14/linux/mm/filemap.c linux/mm/filemap.c
--- v2.4.14/linux/mm/filemap.c Mon Nov 5 15:55:35 2001
+++ linux/mm/filemap.c Wed Nov 21 14:07:25 2001
@@ -209,19 +209,26 @@
X spin_unlock(&pagemap_lru_lock);
X }
X
+static int do_flushpage(struct page *page, unsigned long offset)
+{


+ int (*flushpage) (struct page *, unsigned long);

+ flushpage = page->mapping->a_ops->flushpage;
+ if (flushpage)
+ return (*flushpage)(page, offset);
+ return block_flushpage(page, offset);
+}
+
X static inline void truncate_partial_page(struct page *page, unsigned partial)
X {
X memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial);
-
X if (page->buffers)
- block_flushpage(page, partial);
-
+ do_flushpage(page, partial);
X }
X
X static void truncate_complete_page(struct page *page)
X {
X /* Leave it on the LRU if it gets converted into anonymous buffers */
- if (!page->buffers || block_flushpage(page, 0))
+ if (!page->buffers || do_flushpage(page, 0))
X lru_cache_del(page);
X
X /*
@@ -548,8 +555,13 @@
X */
X int fail_writepage(struct page *page)
X {
- activate_page(page);
- SetPageReferenced(page);
+ /* Only activate on memory-pressure, not fsync.. */
+ if (PageLaunder(page)) {
+ activate_page(page);
+ SetPageReferenced(page);
+ }
+
+ /* Set the page dirty again, unlock */
X SetPageDirty(page);
X UnlockPage(page);
X return 0;
@@ -1469,6 +1481,87 @@
X UPDATE_ATIME(inode);
X }
X
+static ssize_t generic_file_direct_IO(int rw, struct file * filp, char * buf, size_t count, loff_t offset)
+{
+ ssize_t retval;
+ int new_iobuf, chunk_size, blocksize_mask, blocksize, blocksize_bits, iosize, progress;
+ struct kiobuf * iobuf;
+ struct inode * inode = filp->f_dentry->d_inode;
+ struct address_space * mapping = inode->i_mapping;
+
+ new_iobuf = 0;
+ iobuf = filp->f_iobuf;
+ if (test_and_set_bit(0, &filp->f_iobuf_lock)) {
+ /*
+ * A parallel read/write is using the preallocated iobuf
+ * so just run slow and allocate a new one.
+ */
+ retval = alloc_kiovec(1, &iobuf);
+ if (retval)
+ goto out;
+ new_iobuf = 1;
+ }
+
+ blocksize = 1 << inode->i_blkbits;
+ blocksize_bits = inode->i_blkbits;
+ blocksize_mask = blocksize - 1;
+ chunk_size = KIO_MAX_ATOMIC_IO << 10;


+
+ retval = -EINVAL;

+ if ((offset & blocksize_mask) || (count & blocksize_mask))
+ goto out_free;
+ if (!mapping->a_ops->direct_IO)
+ goto out_free;
+
+ /*
+ * Flush to disk exlusively the _data_, metadata must remains
+ * completly asynchronous or performance will go to /dev/null.
+ */
+ filemap_fdatasync(mapping);
+ retval = fsync_inode_data_buffers(inode);
+ filemap_fdatawait(mapping);
+ if (retval < 0)
+ goto out_free;
+
+ progress = retval = 0;
+ while (count > 0) {
+ iosize = count;
+ if (iosize > chunk_size)
+ iosize = chunk_size;
+
+ retval = map_user_kiobuf(rw, iobuf, (unsigned long) buf, iosize);
+ if (retval)
+ break;
+
+ retval = mapping->a_ops->direct_IO(rw, inode, iobuf, (offset+progress) >> blocksize_bits, blocksize);
+
+ if (rw == READ && retval > 0)
+ mark_dirty_kiobuf(iobuf, retval);
+
+ if (retval >= 0) {
+ count -= retval;
+ buf += retval;
+ progress += retval;
+ }
+
+ unmap_kiobuf(iobuf);
+
+ if (retval != iosize)
+ break;
+ }
+
+ if (progress)
+ retval = progress;
+
+ out_free:
+ if (!new_iobuf)
+ clear_bit(0, &filp->f_iobuf_lock);
+ else
+ free_kiovec(1, &iobuf);
+ out:

+ return retval;
+}
+

X int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
X {
X char *kaddr;
@@ -1502,6 +1595,9 @@
X if ((ssize_t) count < 0)
X return -EINVAL;
X
+ if (filp->f_flags & O_DIRECT)
+ goto o_direct;
+
X retval = -EFAULT;
X if (access_ok(VERIFY_WRITE, buf, count)) {
X retval = 0;
@@ -1520,7 +1616,29 @@
X retval = desc.error;
X }
X }
+ out:
X return retval;
+
+ o_direct:
+ {
+ loff_t pos = *ppos, size;
+ struct address_space *mapping = filp->f_dentry->d_inode->i_mapping;
+ struct inode *inode = mapping->host;
+
+ retval = 0;
+ if (!count)
+ goto out; /* skip atime */
+ size = inode->i_size;
+ if (pos < size) {
+ if (pos + count > size)
+ count = size - pos;
+ retval = generic_file_direct_IO(READ, filp, buf, count, pos);
+ if (retval > 0)
+ *ppos = pos + retval;
+ }
+ UPDATE_ATIME(filp->f_dentry->d_inode);
+ goto out;
+ }
X }
X
X static int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset , unsigned long size)
@@ -2758,7 +2876,8 @@
X
X written = 0;
X
- if (file->f_flags & O_APPEND)
+ /* FIXME: this is for backwards compatibility with 2.4 */
+ if (!S_ISBLK(inode->i_mode) && file->f_flags & O_APPEND)
X pos = inode->i_size;
X
X /*
@@ -2838,6 +2957,9 @@
X inode->i_ctime = inode->i_mtime = CURRENT_TIME;
X mark_inode_dirty_sync(inode);
X
+ if (file->f_flags & O_DIRECT)
+ goto o_direct;
+
X do {
X unsigned long index, offset;
X long page_fault;
@@ -2909,9 +3031,12 @@
X
X /* For now, when the user asks for O_SYNC, we'll actually
X * provide O_DSYNC. */
- if ((status >= 0) && (file->f_flags & O_SYNC))
- status = generic_osync_inode(inode, OSYNC_METADATA|OSYNC_DATA);
+ if (status >= 0) {
+ if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
+ status = generic_osync_inode(inode, OSYNC_METADATA|OSYNC_DATA);
+ }
X
+out_status:
X err = written ? written : status;
X out:
X
@@ -2920,6 +3045,25 @@
X fail_write:
X status = -EFAULT;
X goto unlock;
+
+o_direct:
+ written = generic_file_direct_IO(WRITE, file, (char *) buf, count, pos);
+ if (written > 0) {
+ loff_t end = pos + written;
+ if (end > inode->i_size && !S_ISBLK(inode->i_mode)) {
+ inode->i_size = end;
+ mark_inode_dirty(inode);
+ }
+ *ppos = end;
+ invalidate_inode_pages2(mapping);
+ }
+ /*
+ * Sync the fs metadata but not the minor inode changes and
+ * of course not the data as we did direct DMA for the IO.
+ */
+ if (written >= 0 && file->f_flags & O_SYNC)
+ status = generic_osync_inode(inode, OSYNC_METADATA);
+ goto out_status;
X }
X
X void __init page_cache_init(unsigned long mempages)
diff -u --recursive --new-file v2.4.14/linux/mm/memory.c linux/mm/memory.c
--- v2.4.14/linux/mm/memory.c Mon Nov 5 15:55:35 2001
+++ linux/mm/memory.c Thu Nov 15 10:03:06 2001
@@ -520,7 +520,7 @@
X map = get_page_map(map);
X if (map) {
X flush_dcache_page(map);
- atomic_inc(&map->count);
+ page_cache_get(map);
X } else
X printk (KERN_INFO "Mapped page missing [%d]\n", i);
X spin_unlock(&mm->page_table_lock);
@@ -588,7 +588,7 @@
X if (map) {
X if (iobuf->locked)
X UnlockPage(map);
- __free_page(map);
+ page_cache_release(map);
X }
X }
X
diff -u --recursive --new-file v2.4.14/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.4.14/linux/mm/page_alloc.c Mon Nov 5 15:55:35 2001
+++ linux/mm/page_alloc.c Mon Nov 19 16:35:40 2001
@@ -27,7 +27,7 @@
X pg_data_t *pgdat_list;
X
X static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" };
-static int zone_balance_ratio[MAX_NR_ZONES] __initdata = { 32, 128, 128, };
+static int zone_balance_ratio[MAX_NR_ZONES] __initdata = { 128, 128, 128, };
X static int zone_balance_min[MAX_NR_ZONES] __initdata = { 20 , 20, 20, };
X static int zone_balance_max[MAX_NR_ZONES] __initdata = { 255 , 255, 255, };
X
@@ -80,9 +80,9 @@
X BUG();
X if (PageLocked(page))
X BUG();
- if (PageActive(page))
+ if (PageLRU(page))
X BUG();
- if (PageInactive(page))
+ if (PageActive(page))
X BUG();
X page->flags &= ~((1<<PG_referenced) | (1<<PG_dirty));
X
@@ -203,7 +203,10 @@
X set_page_count(page, 1);
X if (BAD_RANGE(zone,page))
X BUG();
- DEBUG_LRU_PAGE(page);
+ if (PageLRU(page))
+ BUG();
+ if (PageActive(page))
+ BUG();
X return page;
X }
X curr_order++;
@@ -268,9 +271,9 @@
X BUG();
X if (PageLocked(page))
X BUG();
- if (PageActive(page))
+ if (PageLRU(page))
X BUG();
- if (PageInactive(page))
+ if (PageActive(page))
X BUG();
X if (PageDirty(page))
X BUG();
@@ -296,29 +299,26 @@
X return page;
X }
X
-static inline unsigned long zone_free_pages(zone_t * zone, unsigned int order)
-{
- long free = zone->free_pages - (1UL << order);
- return free >= 0 ? free : 0;
-}
-
X /*
X * This is the 'heart' of the zoned buddy allocator:
X */
X struct page * __alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_t *zonelist)
X {
+ unsigned long min;
X zone_t **zone, * classzone;
X struct page * page;
X int freed;
X
X zone = zonelist->zones;
X classzone = *zone;
+ min = 1UL << order;
X for (;;) {
X zone_t *z = *(zone++);
X if (!z)
X break;
X
- if (zone_free_pages(z, order) > z->pages_low) {
+ min += z->pages_low;
+ if (z->free_pages > min) {
X page = rmqueue(z, order);
X if (page)
X return page;
@@ -331,16 +331,18 @@
X wake_up_interruptible(&kswapd_wait);
X
X zone = zonelist->zones;
+ min = 1UL << order;
X for (;;) {
- unsigned long min;
+ unsigned long local_min;
X zone_t *z = *(zone++);
X if (!z)
X break;
X
- min = z->pages_min;
+ local_min = z->pages_min;
X if (!(gfp_mask & __GFP_WAIT))
- min >>= 2;
- if (zone_free_pages(z, order) > min) {
+ local_min >>= 2;
+ min += local_min;
+ if (z->free_pages > min) {
X page = rmqueue(z, order);
X if (page)
X return page;
@@ -373,12 +375,14 @@
X return page;
X
X zone = zonelist->zones;
+ min = 1UL << order;
X for (;;) {
X zone_t *z = *(zone++);
X if (!z)
X break;
X
- if (zone_free_pages(z, order) > z->pages_min) {
+ min += z->pages_min;
+ if (z->free_pages > min) {
X page = rmqueue(z, order);
X if (page)
X return page;
@@ -425,7 +429,7 @@
X void page_cache_release(struct page *page)
X {
X if (!PageReserved(page) && put_page_testzero(page)) {
- if (PageActive(page) || PageInactive(page))
+ if (PageLRU(page))
X lru_cache_del(page);
X __free_pages_ok(page, 0);
X }
diff -u --recursive --new-file v2.4.14/linux/mm/page_io.c linux/mm/page_io.c
--- v2.4.14/linux/mm/page_io.c Mon Nov 5 15:55:35 2001
+++ linux/mm/page_io.c Mon Nov 19 15:19:42 2001
@@ -41,7 +41,6 @@
X kdev_t dev = 0;
X int block_size;
X struct inode *swapf = 0;
- int wait = 0;
X
X if (rw == READ) {
X ClearPageUptodate(page);
@@ -78,14 +77,6 @@
X * decrementing the page count, and unlocking the page in the
X * swap lock map - in the IO completion handler.
X */
- if (!wait)
- return 1;
-
- wait_on_page(page);
- /* This shouldn't happen, but check to be sure. */
- if (page_count(page) == 0)
- printk(KERN_ERR "rw_swap_page: page unused while waiting!\n");
-
X return 1;
X }
X
diff -u --recursive --new-file v2.4.14/linux/mm/shmem.c linux/mm/shmem.c
--- v2.4.14/linux/mm/shmem.c Mon Nov 5 15:55:35 2001
+++ linux/mm/shmem.c Wed Nov 21 09:57:57 2001
@@ -428,11 +428,15 @@
X
X if (!PageLocked(page))
X BUG();
+ if (!PageLaunder(page))
+ return fail_writepage(page);
X
X mapping = page->mapping;
X index = page->index;
X inode = mapping->host;
X info = SHMEM_I(inode);
+ if (info->locked)
+ return fail_writepage(page);
X getswap:
X swap = get_swap_page();
X if (!swap.val)
@@ -579,8 +583,6 @@
X
X /* We have the page */
X SetPageUptodate(page);
- if (info->locked)
- page_cache_get(page);
X return page;
X no_space:
X spin_unlock (&sbinfo->stat_lock);
@@ -639,26 +641,9 @@
X {
X struct inode * inode = file->f_dentry->d_inode;
X struct shmem_inode_info * info = SHMEM_I(inode);
- struct page * page;
- unsigned long idx, size;
X
X down(&info->sem);
- if (info->locked == lock)
- goto out;
X info->locked = lock;
- size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
- for (idx = 0; idx < size; idx++) {
- page = find_lock_page(inode->i_mapping, idx);
- if (!page)
- continue;
- if (!lock) {
- /* release the extra count and our reference */
- page_cache_release(page);
- page_cache_release(page);
- }
- UnlockPage(page);
- }
-out:
X up(&info->sem);
X }
X
diff -u --recursive --new-file v2.4.14/linux/mm/swap.c linux/mm/swap.c
--- v2.4.14/linux/mm/swap.c Mon Nov 5 15:55:35 2001
+++ linux/mm/swap.c Tue Nov 6 22:44:20 2001
@@ -38,7 +38,7 @@
X */
X static inline void activate_page_nolock(struct page * page)
X {
- if (PageInactive(page)) {
+ if (PageLRU(page) && !PageActive(page)) {
X del_page_from_inactive_list(page);
X add_page_to_active_list(page);
X }
@@ -57,7 +57,7 @@
X */
X void lru_cache_add(struct page * page)
X {
- if (!PageActive(page) && !PageInactive(page)) {
+ if (!TestSetPageLRU(page)) {
X spin_lock(&pagemap_lru_lock);
X add_page_to_inactive_list(page);
X spin_unlock(&pagemap_lru_lock);
@@ -73,12 +73,12 @@
X */
X void __lru_cache_del(struct page * page)
X {
- if (PageActive(page)) {
- del_page_from_active_list(page);
- } else if (PageInactive(page)) {
- del_page_from_inactive_list(page);
- } else {
-// printk("VM: __lru_cache_del, found unknown page ?!\n");
+ if (TestClearPageLRU(page)) {
+ if (PageActive(page)) {
+ del_page_from_active_list(page);
+ } else {
+ del_page_from_inactive_list(page);
+ }
X }
X }
X
diff -u --recursive --new-file v2.4.14/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.4.14/linux/mm/vmscan.c Mon Nov 5 15:55:35 2001
+++ linux/mm/vmscan.c Sat Nov 17 19:18:17 2001
@@ -7,7 +7,6 @@
X * kswapd added: 7.1.96 sct
X * Removed kswapd_ctl limits, and swap out as many pages as needed
X * to bring the system back to freepages.high: 2.4.97, Rik van Riel.
- * Version: $Id: vmscan.c,v 1.5 1998/02/23 22:14:28 sct Exp $
X * Zone aware kswapd started 02/00, Kanoj Sarcar (ka...@sgi.com).
X * Multiqueue VM started 5.8.00, Rik van Riel.
X */
@@ -117,6 +116,13 @@
X goto drop_pte;
X
X /*
+ * Anonymous buffercache pages can be left behind by
+ * concurrent truncate and pagefault.
+ */
+ if (page->buffers)
+ goto preserve;
+
+ /*
X * This is a dirty, swappable page. First of all,
X * get a suitable swap entry for it, and make sure
X * we have the swap cache set up to associate the
@@ -140,6 +146,7 @@
X }
X
X /* No swap space left */
+preserve:
X set_pte(page_table, pte);
X UnlockPage(page);
X return 0;
@@ -347,7 +354,9 @@
X
X page = list_entry(entry, struct page, lru);
X
- if (unlikely(!PageInactive(page)))
+ if (unlikely(!PageLRU(page)))
+ BUG();
+ if (unlikely(PageActive(page)))
X BUG();
X
X list_del(entry);
@@ -419,7 +428,7 @@
X /* avoid to free a locked page */
X page_cache_get(page);
X
- if (try_to_free_buffers(page, gfp_mask)) {
+ if (try_to_release_page(page, gfp_mask)) {
X if (!page->mapping) {
X /*
X * We must not allow an anon page
@@ -440,7 +449,7 @@
X } else {
X /*
X * The page is still in pagecache so undo the stuff
- * before the try_to_free_buffers since we've not
+ * before the try_to_release_page since we've not
X * finished and we can now try the next step.
X */
X page_cache_release(page);
diff -u --recursive --new-file v2.4.14/linux/net/802/cl2llc.pre linux/net/802/cl2llc.pre
--- v2.4.14/linux/net/802/cl2llc.pre Fri Apr 6 10:51:19 2001
+++ linux/net/802/cl2llc.pre Fri Nov 9 14:11:15 2001
@@ -28,7 +28,7 @@
X
X #include <linux/types.h>
X #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
X #include <linux/netdevice.h>
X #include <linux/skbuff.h>
X #include <net/p8022.h>
diff -u --recursive --new-file v2.4.14/linux/net/8021q/vlanproc.c linux/net/8021q/vlanproc.c
--- v2.4.14/linux/net/8021q/vlanproc.c Mon Nov 5 15:55:35 2001
+++ linux/net/8021q/vlanproc.c Tue Nov 13 09:19:41 2001
@@ -21,7 +21,7 @@
X #include <linux/stddef.h> /* offsetof(), etc. */
X #include <linux/errno.h> /* return codes */
X #include <linux/kernel.h>
-#include <linux/malloc.h> /* kmalloc(), kfree() */
+#include <linux/slab.h> /* kmalloc(), kfree() */
X #include <linux/mm.h> /* verify_area(), etc. */
X #include <linux/string.h> /* inline mem*, str* functions */
X #include <linux/init.h> /* __initfunc et al. */
diff -u --recursive --new-file v2.4.14/linux/net/atm/Makefile linux/net/atm/Makefile
--- v2.4.14/linux/net/atm/Makefile Mon Mar 26 15:36:30 2001
+++ linux/net/atm/Makefile Fri Nov 9 14:11:15 2001
@@ -33,6 +33,7 @@
X
X obj-$(CONFIG_ATM_LANE) += lec.o
X obj-$(CONFIG_ATM_MPOA) += mpoa.o
+obj-$(CONFIG_PPPOATM) += pppoatm.o
X
X include $(TOPDIR)/Rules.make
X
diff -u --recursive --new-file v2.4.14/linux/net/atm/common.c linux/net/atm/common.c
--- v2.4.14/linux/net/atm/common.c Tue Oct 9 17:06:53 2001
+++ linux/net/atm/common.c Fri Nov 9 14:11:15 2001
@@ -58,6 +58,11 @@
X #endif
X #endif
X
+#if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE)
+int (*pppoatm_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
+EXPORT_SYMBOL(pppoatm_ioctl_hook);
+#endif
+
X #include "resources.h" /* atm_find_dev */
X #include "common.h" /* prototypes */
X #include "protocols.h" /* atm_init_<transport> */
@@ -773,6 +778,13 @@
X default:
X break;
X }
+#if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE)
+ if (pppoatm_ioctl_hook) {
+ ret_val = pppoatm_ioctl_hook(vcc, cmd, arg);
+ if (ret_val != -ENOIOCTLCMD)
+ goto done;
+ }
+#endif
X if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) {
X ret_val = -EFAULT;
X goto done;
diff -u --recursive --new-file v2.4.14/linux/net/atm/pppoatm.c linux/net/atm/pppoatm.c
--- v2.4.14/linux/net/atm/pppoatm.c Wed Dec 31 16:00:00 1969
+++ linux/net/atm/pppoatm.c Fri Nov 9 14:11:15 2001
@@ -0,0 +1,365 @@
+/* net/atm/pppoatm.c - RFC2364 PPP over ATM/AAL5 */
+
+/* Copyright 1999-2000 by Mitchell Blank Jr */
+/* Based on clip.c; 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+/* And on ppp_async.c; Copyright 1999 Paul Mackerras */
+/* And help from Jens Axboe */
+
+/*


+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License

+ * as published by the Free Software Foundation; either version

+ * 2 of the License, or (at your option) any later version.
+ *
+ * This driver provides the encapsulation and framing for sending
+ * and receiving PPP frames in ATM AAL5 PDUs.
+ */
+
+/*
+ * One shortcoming of this driver is that it does not comply with
+ * section 8 of RFC2364 - we are supposed to detect a change
+ * in encapsulation and immediately abort the connection (in order
+ * to avoid a black-hole being created if our peer loses state
+ * and changes encapsulation unilaterally. However, since the
+ * ppp_generic layer actually does the decapsulation, we need
+ * a way of notifying it when we _think_ there might be a problem)
+ * There's two cases:
+ * 1. LLC-encapsulation was missing when it was enabled. In
+ * this case, we should tell the upper layer "tear down
+ * this session if this skb looks ok to you"
+ * 2. LLC-encapsulation was present when it was disabled. Then
+ * we need to tell the upper layer "this packet may be
+ * ok, but if its in error tear down the session"
+ * These hooks are not yet available in ppp_generic


+ */
+
+#include <linux/module.h>

+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/atm.h>
+#include <linux/atmdev.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/ppp_channel.h>
+#include <linux/atmppp.h>
+
+#if 0
+#define DPRINTK(format, args...) \
+ printk(KERN_DEBUG "pppoatm: " format, ##args)
+#else
+#define DPRINTK(format, args...)
+#endif
+
+enum pppoatm_encaps {
+ e_autodetect = PPPOATM_ENCAPS_AUTODETECT,
+ e_vc = PPPOATM_ENCAPS_VC,
+ e_llc = PPPOATM_ENCAPS_LLC,
+};
+
+struct pppoatm_vcc {
+ struct atm_vcc *atmvcc; /* VCC descriptor */
+ void (*old_push)(struct atm_vcc *, struct sk_buff *);
+ void (*old_pop)(struct atm_vcc *, struct sk_buff *);
+ /* keep old push/pop for detaching */
+ enum pppoatm_encaps encaps;
+ int flags; /* SC_COMP_PROT - compress protocol */
+ struct ppp_channel chan; /* interface to generic ppp layer */
+ struct tasklet_struct wakeup_tasklet;
+};
+
+/*
+ * Header used for LLC Encapsulated PPP (4 bytes) followed by the LCP protocol
+ * ID (0xC021) used in autodetection
+ */
+static const unsigned char pppllc[6] = { 0xFE, 0xFE, 0x03, 0xCF, 0xC0, 0x21 };
+#define LLC_LEN (4)
+
+static inline struct pppoatm_vcc *atmvcc_to_pvcc(const struct atm_vcc *atmvcc)
+{
+ return (struct pppoatm_vcc *) (atmvcc->user_back);
+}
+
+static inline struct pppoatm_vcc *chan_to_pvcc(const struct ppp_channel *chan)
+{
+ return (struct pppoatm_vcc *) (chan->private);
+}
+
+/*
+ * We can't do this directly from our _pop handler, since the ppp code
+ * doesn't want to be called in interrupt context, so we do it from
+ * a tasklet
+ */
+static void pppoatm_wakeup_sender(unsigned long arg)
+{
+ ppp_output_wakeup((struct ppp_channel *) arg);
+}
+
+/*
+ * This gets called every time the ATM card has finished sending our
+ * skb. The ->old_pop will take care up normal atm flow control,
+ * but we also need to wake up the device if we blocked it
+ */
+static void pppoatm_pop(struct atm_vcc *atmvcc, struct sk_buff *skb)
+{
+ struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
+ pvcc->old_pop(atmvcc, skb);
+ /*
+ * We don't really always want to do this since it's
+ * really inefficient - it would be much better if we could
+ * test if we had actually throttled the generic layer.
+ * Unfortunately then there would be a nasty SMP race where
+ * we could clear that flag just as we refuse another packet.
+ * For now we do the safe thing.
+ */
+ tasklet_schedule(&pvcc->wakeup_tasklet);
+}
+
+/*
+ * Unbind from PPP - currently we only do this when closing the socket,
+ * but we could put this into an ioctl if need be
+ */
+static void pppoatm_unassign_vcc(struct atm_vcc *atmvcc)
+{
+ struct pppoatm_vcc *pvcc;
+ pvcc = atmvcc_to_pvcc(atmvcc);
+ atmvcc->push = pvcc->old_push;
+ atmvcc->pop = pvcc->old_pop;
+ tasklet_disable(&pvcc->wakeup_tasklet);
+ ppp_unregister_channel(&pvcc->chan);
+ atmvcc->user_back = NULL;
+ kfree(pvcc);
+ /* Gee, I hope we have the big kernel lock here... */
+ MOD_DEC_USE_COUNT;
+}
+
+/* Called when an AAL5 PDU comes in */
+static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
+{
+ struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
+ DPRINTK("pppoatm push\n");
+ if (skb == NULL) { /* VCC was closed */
+ DPRINTK("removing ATMPPP VCC %p\n", pvcc);
+ pppoatm_unassign_vcc(atmvcc);
+ atmvcc->push(atmvcc, NULL); /* Pass along bad news */
+ return;
+ }
+ atm_return(atmvcc, skb->truesize);
+ switch (pvcc->encaps) {
+ case e_llc:
+ if (skb->len < LLC_LEN ||
+ memcmp(skb->data, pppllc, LLC_LEN))
+ goto error;
+ skb_pull(skb, LLC_LEN);
+ break;
+ case e_autodetect:
+ if (pvcc->chan.ppp == NULL) { /* Not bound yet! */
+ kfree_skb(skb);
+ return;
+ }
+ if (skb->len >= sizeof(pppllc) &&
+ !memcmp(skb->data, pppllc, sizeof(pppllc))) {
+ pvcc->encaps = e_llc;
+ skb_pull(skb, LLC_LEN);
+ break;
+ }
+ if (skb->len >= (sizeof(pppllc) - LLC_LEN) &&
+ !memcmp(skb->data, &pppllc[LLC_LEN],
+ sizeof(pppllc) - LLC_LEN)) {
+ pvcc->encaps = e_vc;
+ pvcc->chan.mtu += LLC_LEN;
+ break;
+ }
+ DPRINTK("(unit %d): Couldn't autodetect yet "
+ "(skb: %02X %02X %02X %02X %02X %02X)\n",
+ pvcc->chan.unit,
+ skb->data[0], skb->data[1], skb->data[2],
+ skb->data[3], skb->data[4], skb->data[5]);
+ goto error;
+ case e_vc:
+ break;
+ }
+ ppp_input(&pvcc->chan, skb);
+ return;
+ error:
+ kfree_skb(skb);
+ ppp_input_error(&pvcc->chan, 0);
+}
+
+/*
+ * Called by the ppp_generic.c to send a packet - returns true if packet
+ * was accepted. If we return false, then it's our job to call
+ * ppp_output_wakeup(chan) when we're feeling more up to it.
+ * Note that in the ENOMEM case (as opposed to the !atm_may_send case)
+ * we should really drop the packet, but the generic layer doesn't
+ * support this yet. We just return 'DROP_PACKET' which we actually define
+ * as success, just to be clear what we're really doing.
+ */
+#define DROP_PACKET 1
+static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
+{
+ struct pppoatm_vcc *pvcc = chan_to_pvcc(chan);
+ ATM_SKB(skb)->vcc = pvcc->atmvcc;
+ DPRINTK("(unit %d): pppoatm_send (skb=0x%p, vcc=0x%p)\n",
+ pvcc->chan.unit, skb, pvcc->atmvcc);
+ if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT))
+ (void) skb_pull(skb, 1);
+ switch (pvcc->encaps) { /* LLC encapsulation needed */
+ case e_llc:
+ if (skb_headroom(skb) < LLC_LEN) {
+ struct sk_buff *n;
+ n = skb_realloc_headroom(skb, LLC_LEN);
+ if (n != NULL &&
+ !atm_may_send(pvcc->atmvcc, n->truesize)) {
+ kfree_skb(n);
+ goto nospace;
+ }
+ kfree_skb(skb);
+ if ((skb = n) == NULL)
+ return DROP_PACKET;
+ } else if (!atm_may_send(pvcc->atmvcc, skb->truesize))
+ goto nospace;
+ memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN);
+ break;
+ case e_vc:
+ if (!atm_may_send(pvcc->atmvcc, skb->truesize))
+ goto nospace;
+ break;
+ case e_autodetect:
+ DPRINTK("(unit %d): Trying to send without setting encaps!\n",
+ pvcc->chan.unit);
+ kfree_skb(skb);
+ return 1;
+ }
+ atomic_add(skb->truesize, &ATM_SKB(skb)->vcc->tx_inuse);
+ ATM_SKB(skb)->iovcnt = 0;
+ ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
+ DPRINTK("(unit %d): atm_skb(%p)->vcc(%p)->dev(%p)\n",
+ pvcc->chan.unit, skb, ATM_SKB(skb)->vcc,
+ ATM_SKB(skb)->vcc->dev);
+ return ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
+ ? DROP_PACKET : 1;
+ nospace:
+ /*
+ * We don't have space to send this SKB now, but we might have
+ * already applied SC_COMP_PROT compression, so may need to undo
+ */
+ if ((pvcc->flags & SC_COMP_PROT) && skb_headroom(skb) > 0 &&
+ skb->data[-1] == '\0')
+ (void) skb_push(skb, 1);


+ return 0;
+}
+

+/* This handles ioctls sent to the /dev/ppp interface */
+static int pppoatm_devppp_ioctl(struct ppp_channel *chan, unsigned int cmd,
+ unsigned long arg)
+{
+ switch (cmd) {
+ case PPPIOCGFLAGS:
+ return put_user(chan_to_pvcc(chan)->flags, (int *) arg)
+ ? -EFAULT : 0;
+ case PPPIOCSFLAGS:
+ return get_user(chan_to_pvcc(chan)->flags, (int *) arg)
+ ? -EFAULT : 0;
+ }


+ return -ENOTTY;
+}
+

+static /*const*/ struct ppp_channel_ops pppoatm_ops = {
+ start_xmit: pppoatm_send,
+ ioctl: pppoatm_devppp_ioctl,
+};
+
+static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, unsigned long arg)
+{
+ struct atm_backend_ppp be;
+ struct pppoatm_vcc *pvcc;


+ int err;
+ /*

+ * Each PPPoATM instance has its own tasklet - this is just a
+ * prototypical one used to initialize them
+ */
+ static const DECLARE_TASKLET(tasklet_proto, pppoatm_wakeup_sender, 0);
+ if (copy_from_user(&be, (void *) arg, sizeof be))
+ return -EFAULT;
+ if (be.encaps != PPPOATM_ENCAPS_AUTODETECT &&
+ be.encaps != PPPOATM_ENCAPS_VC && be.encaps != PPPOATM_ENCAPS_LLC)
+ return -EINVAL;
+ MOD_INC_USE_COUNT;
+ pvcc = kmalloc(sizeof(*pvcc), GFP_KERNEL);
+ if (pvcc == NULL) {
+ MOD_DEC_USE_COUNT;
+ return -ENOMEM;
+ }
+ memset(pvcc, 0, sizeof(*pvcc));
+ pvcc->atmvcc = atmvcc;
+ pvcc->old_push = atmvcc->push;
+ pvcc->old_pop = atmvcc->pop;
+ pvcc->encaps = (enum pppoatm_encaps) be.encaps;
+ pvcc->chan.private = pvcc;
+ pvcc->chan.ops = &pppoatm_ops;
+ pvcc->chan.mtu = atmvcc->qos.txtp.max_sdu - PPP_HDRLEN -
+ (be.encaps == e_vc ? 0 : LLC_LEN);
+ pvcc->wakeup_tasklet = tasklet_proto;
+ pvcc->wakeup_tasklet.data = (unsigned long) &pvcc->chan;
+ if ((err = ppp_register_channel(&pvcc->chan)) != 0) {
+ kfree(pvcc);
+ return err;
+ }
+ atmvcc->user_back = pvcc;
+ atmvcc->push = pppoatm_push;
+ atmvcc->pop = pppoatm_pop;


+ return 0;
+}
+

+/*
+ * This handles ioctls actually performed on our vcc - we must return
+ * -ENOIOCTLCMD for any unrecognized ioctl
+ */
+static int pppoatm_ioctl(struct atm_vcc *atmvcc, unsigned int cmd,
+ unsigned long arg)
+{
+ if (cmd != ATM_SETBACKEND && atmvcc->push != pppoatm_push)
+ return -ENOIOCTLCMD;
+ switch (cmd) {
+ case ATM_SETBACKEND: {
+ atm_backend_t b;
+ if (get_user(b, (atm_backend_t *) arg))
+ return -EFAULT;
+ if (b != ATM_BACKEND_PPP)
+ return -ENOIOCTLCMD;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ return pppoatm_assign_vcc(atmvcc, arg);
+ }
+ case PPPIOCGCHAN:
+ return put_user(ppp_channel_index(&atmvcc_to_pvcc(atmvcc)->
+ chan), (int *) arg) ? -EFAULT : 0;
+ case PPPIOCGUNIT:
+ return put_user(ppp_unit_number(&atmvcc_to_pvcc(atmvcc)->
+ chan), (int *) arg) ? -EFAULT : 0;
+ }
+ return -ENOIOCTLCMD;
+}
+
+/* the following avoids some spurious warnings from the compiler */
+#define UNUSED __attribute__((unused))
+
+extern int (*pppoatm_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
+
+static int __init UNUSED pppoatm_init(void)
+{
+ pppoatm_ioctl_hook = pppoatm_ioctl;


+ return 0;
+}
+

+static void __exit UNUSED pppoatm_exit(void)
+{
+ pppoatm_ioctl_hook = NULL;
+}
+
+module_init(pppoatm_init);
+module_exit(pppoatm_exit);
+
+MODULE_AUTHOR("Mitchell Blank Jr <mi...@sfgoth.com>");
+MODULE_DESCRIPTION("RFC2364 PPP over ATM/AAL5");
diff -u --recursive --new-file v2.4.14/linux/net/atm/resources.c linux/net/atm/resources.c
--- v2.4.14/linux/net/atm/resources.c Fri Dec 29 14:35:47 2000
+++ linux/net/atm/resources.c Fri Nov 9 14:11:15 2001
@@ -36,13 +36,18 @@
X if (!dev) return NULL;
X memset(dev,0,sizeof(*dev));
X dev->type = type;
- dev->prev = last_dev;
X dev->signal = ATM_PHY_SIG_UNKNOWN;
X dev->link_rate = ATM_OC3_PCR;
X dev->next = NULL;
+
+ spin_lock(&atm_dev_lock);
+
+ dev->prev = last_dev;
+
X if (atm_devs) last_dev->next = dev;
X else atm_devs = dev;
X last_dev = dev;
+ spin_unlock(&atm_dev_lock);
X return dev;
X }
X
diff -u --recursive --new-file v2.4.14/linux/net/bluetooth/hci_core.c linux/net/bluetooth/hci_core.c
--- v2.4.14/linux/net/bluetooth/hci_core.c Tue Oct 9 17:06:53 2001
+++ linux/net/bluetooth/hci_core.c Fri Nov 9 14:21:21 2001
@@ -891,7 +891,7 @@
X
X /* Limit inquiry time, also avoid overflows */
X
- if(ir.length > 2048)
+ if(ir.length > 2048 || ir.num_rsp > 2048)
X {
X err = -EINVAL;
X goto done;
diff -u --recursive --new-file v2.4.14/linux/net/bridge/br_stp_bpdu.c linux/net/bridge/br_stp_bpdu.c
--- v2.4.14/linux/net/bridge/br_stp_bpdu.c Mon Feb 21 17:35:06 2000
+++ linux/net/bridge/br_stp_bpdu.c Tue Nov 13 09:16:05 2001
@@ -5,7 +5,7 @@
X * Authors:
X * Lennert Buytenhek <buy...@gnu.org>
X *
- * $Id: br_stp_bpdu.c,v 1.2 2000/02/21 15:51:34 davem Exp $
+ * $Id: br_stp_bpdu.c,v 1.3 2001/11/10 02:35:25 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
@@ -14,6 +14,7 @@
X */
X
X #include <linux/kernel.h>
+#include <linux/if_ether.h>
X #include <linux/if_bridge.h>
X #include "br_private.h"
X #include "br_private_stp.h"
@@ -42,6 +43,7 @@
X }
X
X skb->dev = dev;
+ skb->protocol = htons(ETH_P_802_2);
X skb->mac.raw = skb_put(skb, size);
X memcpy(skb->mac.raw, bridge_ula, ETH_ALEN);
X memcpy(skb->mac.raw+ETH_ALEN, dev->dev_addr, ETH_ALEN);
diff -u --recursive --new-file v2.4.14/linux/net/core/dev.c linux/net/core/dev.c
--- v2.4.14/linux/net/core/dev.c Mon Nov 5 15:55:36 2001
+++ linux/net/core/dev.c Wed Nov 7 14:39:36 2001
@@ -565,11 +565,11 @@
X
X /*
X * Verify the string as this thing may have come from
- * the user. There must be one "%d" and no other "%"
- * characters.
+ * the user. There must be either one "%d" and no other "%"
+ * characters, or no "%" characters at all.
X */
X p = strchr(name, '%');
- if (!p || p[1] != 'd' || strchr(p+2, '%'))
+ if (p && (p[1] != 'd' || strchr(p+2, '%')))
X return -EINVAL;
X
X /*
@@ -2221,6 +2221,12 @@
X default:
X if ((cmd >= SIOCDEVPRIVATE &&
X cmd <= SIOCDEVPRIVATE + 15) ||
+ cmd == SIOCBONDENSLAVE ||
+ cmd == SIOCBONDRELEASE ||
+ cmd == SIOCBONDSETHWADDR ||
+ cmd == SIOCBONDSLAVEINFOQUERY ||
+ cmd == SIOCBONDINFOQUERY ||
+ cmd == SIOCBONDCHANGEACTIVE ||
X cmd == SIOCETHTOOL ||
X cmd == SIOCGMIIPHY ||
X cmd == SIOCGMIIREG ||
@@ -2372,6 +2378,12 @@
X case SIOCSIFTXQLEN:
X case SIOCSIFNAME:
X case SIOCSMIIREG:
+ case SIOCBONDENSLAVE:
+ case SIOCBONDRELEASE:
+ case SIOCBONDSETHWADDR:
+ case SIOCBONDSLAVEINFOQUERY:
+ case SIOCBONDINFOQUERY:
+ case SIOCBONDCHANGEACTIVE:
X if (!capable(CAP_NET_ADMIN))
X return -EPERM;
X dev_load(ifr.ifr_name);
diff -u --recursive --new-file v2.4.14/linux/net/decnet/af_decnet.c linux/net/decnet/af_decnet.c
--- v2.4.14/linux/net/decnet/af_decnet.c Tue Jul 3 17:08:22 2001
+++ linux/net/decnet/af_decnet.c Fri Nov 9 14:12:54 2001
@@ -1003,6 +1003,9 @@
X if (DN_SK(newsk)->segsize_rem < 230)
X DN_SK(newsk)->segsize_rem = 230;
X
+ if ((DN_SK(newsk)->services_rem & NSP_FC_MASK) == NSP_FC_NONE)
+ DN_SK(newsk)->max_window = decnet_no_fc_max_cwnd;
+
X newsk->state = TCP_LISTEN;
X newsk->zapped = 0;
X
@@ -1072,7 +1075,9 @@
X lock_sock(sk);
X
X if (peer) {
- if (sock->state != SS_CONNECTED && scp->accept_mode == ACC_IMMED)
+ if ((sock->state != SS_CONNECTED &&
+ sock->state != SS_CONNECTING) &&
+ scp->accept_mode == ACC_IMMED)
X return -ENOTCONN;
X
X memcpy(sa, &scp->peer, sizeof(struct sockaddr_dn));
@@ -2145,6 +2150,7 @@
X EXPORT_NO_SYMBOLS;
X MODULE_DESCRIPTION("The Linux DECnet Network Protocol");
X MODULE_AUTHOR("Linux DECnet Project Team");
+MODULE_LICENSE("GPL");
X
X static int addr[2] = {0, 0};
X
@@ -2152,7 +2158,7 @@
X MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node");
X #endif
X
-static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.4.0-test12s (C) 1995-2000 Linux DECnet Project Team\n";
+static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.4.9s (C) 1995-2001 Linux DECnet Project Team\n";
X
X static int __init decnet_init(void)
X {
diff -u --recursive --new-file v2.4.14/linux/net/decnet/dn_nsp_in.c linux/net/decnet/dn_nsp_in.c
--- v2.4.14/linux/net/decnet/dn_nsp_in.c Mon Jan 22 13:32:10 2001
+++ linux/net/decnet/dn_nsp_in.c Fri Nov 9 14:12:54 2001
@@ -355,6 +355,9 @@
X scp->info_rem = cb->info;
X scp->segsize_rem = cb->segsize;
X
+ if ((scp->services_rem & NSP_FC_MASK) == NSP_FC_NONE)
+ scp->max_window = decnet_no_fc_max_cwnd;
+
X if (skb->len > 0) {
X unsigned char dlen = *skb->data;
X if ((dlen <= 16) && (dlen <= skb->len)) {
diff -u --recursive --new-file v2.4.14/linux/net/decnet/dn_route.c linux/net/decnet/dn_route.c
--- v2.4.14/linux/net/decnet/dn_route.c Mon Jan 22 13:32:10 2001
+++ linux/net/decnet/dn_route.c Fri Nov 9 14:12:54 2001
@@ -638,8 +638,8 @@
X {
X struct dn_skb_cb *cb = DN_SKB_CB(skb);
X struct dst_entry *dst = skb->dst;
- struct net_device *dev = skb->dev;
X struct neighbour *neigh;
+ struct net_device *dev = skb->dev;
X int err = -EINVAL;
X
X if ((neigh = dst->neighbour) == NULL)
diff -u --recursive --new-file v2.4.14/linux/net/decnet/sysctl_net_decnet.c linux/net/decnet/sysctl_net_decnet.c
--- v2.4.14/linux/net/decnet/sysctl_net_decnet.c Wed Jul 25 17:10:26 2001
+++ linux/net/decnet/sysctl_net_decnet.c Fri Nov 9 14:12:54 2001
@@ -33,6 +33,7 @@
X int decnet_di_count = 3;
X int decnet_dr_count = 3;
X int decnet_log_martians = 1;
+int decnet_no_fc_max_cwnd = NSP_MIN_WINDOW;
X
X #ifdef CONFIG_SYSCTL
X extern int decnet_dst_gc_interval;
@@ -42,6 +43,8 @@
X static int max_state_count[] = { NSP_MAXRXTSHIFT };
X static int min_decnet_dst_gc_interval[] = { 1 };
X static int max_decnet_dst_gc_interval[] = { 60 };
+static int min_decnet_no_fc_max_cwnd[] = { NSP_MIN_WINDOW };
+static int max_decnet_no_fc_max_cwnd[] = { NSP_MAX_WINDOW };
X static char node_name[7] = "???";
X
X static struct ctl_table_header *dn_table_header = NULL;
@@ -344,6 +347,10 @@
X sizeof(int), 0644,
X NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
X &min_decnet_dst_gc_interval, &max_decnet_dst_gc_interval},
+ {NET_DECNET_NO_FC_MAX_CWND, "no_fc_max_cwnd", &decnet_no_fc_max_cwnd,
+ sizeof(int), 0644,
+ NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
+ &min_decnet_no_fc_max_cwnd, &max_decnet_no_fc_max_cwnd},
X {NET_DECNET_DEBUG_LEVEL, "debug", &decnet_debug_level,
X sizeof(int), 0644,
X NULL, &proc_dointvec, &sysctl_intvec, NULL,
diff -u --recursive --new-file v2.4.14/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.4.14/linux/net/ipv4/icmp.c Sun Sep 23 11:41:01 2001
+++ linux/net/ipv4/icmp.c Wed Nov 7 14:39:36 2001
@@ -3,7 +3,7 @@
X *
X * Alan Cox, <al...@redhat.com>
X *
- * Version: $Id: icmp.c,v 1.81 2001/09/01 00:31:50 davem Exp $
+ * Version: $Id: icmp.c,v 1.82 2001/11/01 23:44:31 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
@@ -139,7 +139,7 @@
X { EHOSTUNREACH, 1 } /* ICMP_PREC_CUTOFF */
X };
X
-/* Control parameters for ECHO relies. */
+/* Control parameters for ECHO replies. */
X int sysctl_icmp_echo_ignore_all;
X int sysctl_icmp_echo_ignore_broadcasts;
X
diff -u --recursive --new-file v2.4.14/linux/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c
--- v2.4.14/linux/net/ipv4/ip_input.c Thu Apr 12 12:11:39 2001
+++ linux/net/ipv4/ip_input.c Wed Nov 7 14:39:36 2001
@@ -5,7 +5,7 @@
X *
X * The Internet Protocol (IP) module.
X *
- * Version: $Id: ip_input.c,v 1.53 2000/12/18 19:01:50 davem Exp $
+ * Version: $Id: ip_input.c,v 1.54 2001/11/06 22:33:52 davem Exp $
X *
X * Authors: Ross Biro, <bi...@leland.Stanford.Edu>
X * Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -383,7 +383,7 @@
X */
X int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
X {
- struct iphdr *iph = skb->nh.iph;
+ struct iphdr *iph;
X
X /* When the interface is in promisc. mode, drop all the crap
X * that it receives, do not try to analyse it.
@@ -417,6 +417,8 @@
X
X if (!pskb_may_pull(skb, iph->ihl*4))
X goto inhdr_error;
+
+ iph = skb->nh.iph;
X
X if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
X goto inhdr_error;
diff -u --recursive --new-file v2.4.14/linux/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c
--- v2.4.14/linux/net/ipv4/ipconfig.c Mon Nov 5 15:55:36 2001
+++ linux/net/ipv4/ipconfig.c Tue Nov 20 15:47:27 2001


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

- * $Id: ipconfig.c,v 1.40 2001/10/30 03:08:02 davem Exp $
+ * $Id: ipconfig.c,v 1.42 2001/11/10 07:23:12 davem Exp $
X *
X * Automatic Configuration of IP -- use DHCP, BOOTP, RARP, or
X * user-supplied information to configure own IP address and routes.
@@ -53,6 +53,7 @@
X
X #include <asm/uaccess.h>
X #include <asm/checksum.h>
+#include <asm/processor.h>
X
X /* Define this to allow debugging output */
X #undef IPCONFIG_DEBUG
@@ -194,8 +195,10 @@
X printk(KERN_ERR "IP-Config: Failed to open %s\n", dev->name);
X continue;
X }
- if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL)))
+ if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) {
+ rtnl_shunlock();
X return -1;
+ }
X d->dev = dev;
X *last = d;
X last = &d->next;
@@ -605,6 +608,12 @@
X *e++ = 17; /* Boot path */
X *e++ = 40;
X e += 40;
+
+ *e++ = 57; /* set extension buffer size for reply */
+ *e++ = 2;
+ *e++ = 1; /* 128+236+8+20+14, see dhcpd sources */
+ *e++ = 150;
+
X *e++ = 255; /* End of the list */
X }
X
@@ -630,7 +639,7 @@
X /*
X * Send DHCP/BOOTP request to single interface.
X */
-static void __init ic_bootp_send_if(struct ic_device *d, u32 jiffies)
+static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_diff)
X {
X struct net_device *dev = d->dev;
X struct sk_buff *skb;
@@ -677,7 +686,7 @@
X b->your_ip = INADDR_NONE;
X b->server_ip = INADDR_NONE;
X memcpy(b->hw_addr, dev->dev_addr, dev->addr_len);
- b->secs = htons(jiffies / HZ);
+ b->secs = htons(jiffies_diff / HZ);
X b->xid = d->xid;
X
X /* add DHCP options or BOOTP extensions */
@@ -1000,8 +1009,10 @@
X #endif
X
X jiff = jiffies + (d->next ? CONF_INTER_TIMEOUT : timeout);
- while (jiffies < jiff && !ic_got_reply)
+ while (time_before(jiffies, jiff) && !ic_got_reply) {
X barrier();
+ cpu_relax();
+ }
X #ifdef IPCONFIG_DHCP
X /* DHCP isn't done until we get a DHCPACK. */
X if ((ic_got_reply & IC_BOOTP)
@@ -1113,7 +1124,7 @@
X try_try_again:
X /* Give hardware a chance to settle */
X jiff = jiffies + CONF_PRE_OPEN;
- while (jiffies < jiff)
+ while (time_before(jiffies, jiff))
X ;
X
X /* Setup all network devices */


@@ -1122,7 +1133,7 @@
X

X /* Give drivers a chance to settle */
X jiff = jiffies + CONF_POST_OPEN;
- while (jiffies < jiff)
+ while (time_before(jiffies, jiff))
X ;
X
X /*
@@ -1133,7 +1144,9 @@
X */
X if (ic_myaddr == INADDR_NONE ||
X #ifdef CONFIG_ROOT_NFS
- (root_server_addr == INADDR_NONE && ic_servaddr == INADDR_NONE) ||
+ (MAJOR(ROOT_DEV) == UNNAMED_MAJOR
+ && root_server_addr == INADDR_NONE
+ && ic_servaddr == INADDR_NONE) ||
X #endif
X ic_first_dev->next) {
X #ifdef IPCONFIG_DYNAMIC
diff -u --recursive --new-file v2.4.14/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.4.14/linux/net/ipv4/tcp_input.c Mon Nov 5 15:55:36 2001
+++ linux/net/ipv4/tcp_input.c Tue Nov 13 21:04:15 2001
@@ -2462,7 +2462,7 @@
X
X /* Zap this SACK, by moving forward any other SACKS. */
X for (i=this_sack+1; i < num_sacks; i++)
- sp[i-1] = sp[i];
+ tp->selective_acks[i-1] = tp->selective_acks[i];
X num_sacks--;
X continue;
X }
diff -u --recursive --new-file v2.4.14/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.4.14/linux/net/irda/af_irda.c Tue Oct 9 17:06:53 2001
+++ linux/net/irda/af_irda.c Fri Nov 9 14:22:17 2001
@@ -11,7 +11,7 @@
X * Sources: af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
X *
X * Copyright (c) 1999 Dag Brattli <da...@cs.uit.no>
- * Copyright (c) 1999 Jean Tourrilhes <j...@hpl.hp.com>
+ * Copyright (c) 1999-2001 Jean Tourrilhes <j...@hpl.hp.com>
X * All Rights Reserved.
X *
X * This program is free software; you can redistribute it and/or
@@ -134,33 +134,41 @@
X
X IRDA_DEBUG(2, __FUNCTION__ "(%p)\n", self);
X
+ /* Don't care about it, but let's not leak it */
+ if(skb)
+ dev_kfree_skb(skb);
+
X sk = self->sk;
X if (sk == NULL)
X return;
X
- sk->state = TCP_CLOSE;
- sk->err = ECONNRESET;
- sk->shutdown |= SEND_SHUTDOWN;
- if (!sk->dead) {
+ /* Prevent race conditions with irda_release() and irda_shutdown() */
+ if ((!sk->dead) && (sk->state != TCP_CLOSE)) {
+ sk->state = TCP_CLOSE;
+ sk->err = ECONNRESET;
+ sk->shutdown |= SEND_SHUTDOWN;
+
X sk->state_change(sk);
- sk->dead = 1;
- }
+ sk->dead = 1; /* Uh-oh... Should use sock_orphan ? */
X
- /* Close our TSAP.
- * If we leave it open, IrLMP put it back into the list of
- * unconnected LSAPs. The problem is that any incoming request
- * can then be matched to this socket (and it will be, because
- * it is at the head of the list). This would prevent any
- * listening socket waiting on the same TSAP to get those requests.


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

echo 'End of part 113'
echo 'File patch-2.4.15 is continued in part 114'
echo "114" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:20 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part104

#!/bin/sh -x
# this is part 104 of a 115 - part archive


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

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

X sb = inode->i_sb;
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;

X usb1 = ubh_get_usb_first(USPI_UBH);
X *err = -ENOSPC;
X
X lock_super (sb);


X
- tmp = SWAB32(*p);
+ tmp = fs32_to_cpu(sb, *p);

X if (count + ufs_fragnum(fragment) > uspi->s_fpb) {
X ufs_warning (sb, "ufs_new_fragments", "internal warning"
X " fragment %u, count %u", fragment, count);
@@ -310,7 +307,7 @@
X if (oldcount == 0) {
X result = ufs_alloc_fragments (inode, cgno, goal, count, err);
X if (result) {
- *p = SWAB32(result);
+ *p = cpu_to_fs32(sb, result);
X *err = 0;
X inode->i_blocks += count << uspi->s_nspfshift;
X inode->u.ufs_i.i_lastfrag = max_t(u32, inode->u.ufs_i.i_lastfrag, fragment + count);
@@ -338,23 +335,23 @@
X /*
X * allocate new block and move data
X */
- switch (SWAB32(usb1->fs_optim)) {
+ switch (fs32_to_cpu(sb, usb1->fs_optim)) {
X case UFS_OPTSPACE:
X request = newcount;
- if (uspi->s_minfree < 5 || SWAB32(usb1->fs_cstotal.cs_nffree)
+ if (uspi->s_minfree < 5 || fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree)
X > uspi->s_dsize * uspi->s_minfree / (2 * 100) )
X break;
- usb1->fs_optim = SWAB32(UFS_OPTTIME);
+ usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
X break;
X default:
- usb1->fs_optim = SWAB32(UFS_OPTTIME);
+ usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
X
X case UFS_OPTTIME:
X request = uspi->s_fpb;
- if (SWAB32(usb1->fs_cstotal.cs_nffree) < uspi->s_dsize *
+ if (fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree) < uspi->s_dsize *
X (uspi->s_minfree - 2) / 100)
X break;
- usb1->fs_optim = SWAB32(UFS_OPTSPACE);
+ usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
X break;
X }
X result = ufs_alloc_fragments (inode, cgno, goal, request, err);
@@ -378,7 +375,7 @@


X return 0;
X }
X }

- *p = SWAB32(result);
+ *p = cpu_to_fs32(sb, result);
X *err = 0;
X inode->i_blocks += count << uspi->s_nspfshift;
X inode->u.ufs_i.i_lastfrag = max_t(u32, inode->u.ufs_i.i_lastfrag, fragment + count);
@@ -405,12 +402,10 @@
X struct ufs_cg_private_info * ucpi;
X struct ufs_cylinder_group * ucg;
X unsigned cgno, fragno, fragoff, count, fragsize, i;
- unsigned swab;
X
X UFSD(("ENTER, fragment %u, oldcount %u, newcount %u\n", fragment, oldcount, newcount))


X
X sb = inode->i_sb;
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;

X usb1 = ubh_get_usb_first (USPI_UBH);

X count = newcount - oldcount;
@@ -424,7 +419,7 @@
X if (!ucpi)
X return 0;
X ucg = ubh_get_ucg (UCPI_UBH);
- if (!ufs_cg_chkmagic(ucg)) {
+ if (!ufs_cg_chkmagic(sb, ucg)) {
X ufs_panic (sb, "ufs_add_fragments",
X "internal error, bad magic number on cg %u", cgno);
X return 0;
@@ -438,26 +433,27 @@
X /*
X * Block can be extended
X */
- ucg->cg_time = SWAB32(CURRENT_TIME);
+ ucg->cg_time = cpu_to_fs32(sb, CURRENT_TIME);
X for (i = newcount; i < (uspi->s_fpb - fragoff); i++)
X if (ubh_isclr (UCPI_UBH, ucpi->c_freeoff, fragno + i))
X break;
X fragsize = i - oldcount;
- if (!SWAB32(ucg->cg_frsum[fragsize]))
+ if (!fs32_to_cpu(sb, ucg->cg_frsum[fragsize]))
X ufs_panic (sb, "ufs_add_fragments",
X "internal error or corrupted bitmap on cg %u", cgno);
- DEC_SWAB32(ucg->cg_frsum[fragsize]);
+ fs32_sub(sb, &ucg->cg_frsum[fragsize], 1);
X if (fragsize != count)
- INC_SWAB32(ucg->cg_frsum[fragsize - count]);
+ fs32_add(sb, &ucg->cg_frsum[fragsize - count], 1);
X for (i = oldcount; i < newcount; i++)
X ubh_clrbit (UCPI_UBH, ucpi->c_freeoff, fragno + i);
X if(DQUOT_ALLOC_BLOCK(inode, count)) {
X *err = -EDQUOT;
X return 0;
X }
- SUB_SWAB32(ucg->cg_cs.cs_nffree, count);
- SUB_SWAB32(sb->fs_cs(cgno).cs_nffree, count);
- SUB_SWAB32(usb1->fs_cstotal.cs_nffree, count);
+
+ fs32_sub(sb, &ucg->cg_cs.cs_nffree, count);
+ fs32_sub(sb, &sb->fs_cs(cgno).cs_nffree, count);
+ fs32_sub(sb, &usb1->fs_cstotal.cs_nffree, count);
X
X ubh_mark_buffer_dirty (USPI_UBH);
X ubh_mark_buffer_dirty (UCPI_UBH);
@@ -474,10 +470,10 @@
X
X #define UFS_TEST_FREE_SPACE_CG \
X ucg = (struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[cgno]->b_data; \
- if (SWAB32(ucg->cg_cs.cs_nbfree)) \
+ if (fs32_to_cpu(sb, ucg->cg_cs.cs_nbfree)) \
X goto cg_found; \
X for (k = count; k < uspi->s_fpb; k++) \
- if (SWAB32(ucg->cg_frsum[k])) \
+ if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \
X goto cg_found;
X
X unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
@@ -489,12 +485,10 @@
X struct ufs_cg_private_info * ucpi;
X struct ufs_cylinder_group * ucg;
X unsigned oldcg, i, j, k, result, allocsize;
- unsigned swab;
X
X UFSD(("ENTER, ino %lu, cgno %u, goal %u, count %u\n", inode->i_ino, cgno, goal, count))


X
X sb = inode->i_sb;
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;

X usb1 = ubh_get_usb_first(USPI_UBH);
X oldcg = cgno;
@@ -534,10 +528,10 @@
X if (!ucpi)
X return 0;
X ucg = ubh_get_ucg (UCPI_UBH);
- if (!ufs_cg_chkmagic(ucg))
+ if (!ufs_cg_chkmagic(sb, ucg))
X ufs_panic (sb, "ufs_alloc_fragments",
X "internal error, bad magic number on cg %u", cgno);
- ucg->cg_time = SWAB32(CURRENT_TIME);
+ ucg->cg_time = cpu_to_fs32(sb, CURRENT_TIME);
X
X if (count == uspi->s_fpb) {
X result = ufs_alloccg_block (inode, ucpi, goal, err);
@@ -547,7 +541,7 @@
X }
X
X for (allocsize = count; allocsize < uspi->s_fpb; allocsize++)
- if (SWAB32(ucg->cg_frsum[allocsize]) != 0)
+ if (fs32_to_cpu(sb, ucg->cg_frsum[allocsize]) != 0)
X break;
X
X if (allocsize == uspi->s_fpb) {
@@ -559,10 +553,11 @@
X ubh_setbit (UCPI_UBH, ucpi->c_freeoff, goal + i);
X i = uspi->s_fpb - count;
X DQUOT_FREE_BLOCK(inode, i);
- ADD_SWAB32(ucg->cg_cs.cs_nffree, i);
- ADD_SWAB32(usb1->fs_cstotal.cs_nffree, i);
- ADD_SWAB32(sb->fs_cs(cgno).cs_nffree, i);
- INC_SWAB32(ucg->cg_frsum[i]);
+
+ fs32_add(sb, &ucg->cg_cs.cs_nffree, i);
+ fs32_add(sb, &usb1->fs_cstotal.cs_nffree, i);
+ fs32_add(sb, &sb->fs_cs(cgno).cs_nffree, i);
+ fs32_add(sb, &ucg->cg_frsum[i], 1);
X goto succed;
X }
X
@@ -575,12 +570,14 @@
X }
X for (i = 0; i < count; i++)
X ubh_clrbit (UCPI_UBH, ucpi->c_freeoff, result + i);
- SUB_SWAB32(ucg->cg_cs.cs_nffree, count);
- SUB_SWAB32(usb1->fs_cstotal.cs_nffree, count);
- SUB_SWAB32(sb->fs_cs(cgno).cs_nffree, count);
- DEC_SWAB32(ucg->cg_frsum[allocsize]);
+
+ fs32_sub(sb, &ucg->cg_cs.cs_nffree, count);
+ fs32_sub(sb, &usb1->fs_cstotal.cs_nffree, count);
+ fs32_sub(sb, &sb->fs_cs(cgno).cs_nffree, count);
+ fs32_sub(sb, &ucg->cg_frsum[allocsize], 1);
+
X if (count != allocsize)
- INC_SWAB32(ucg->cg_frsum[allocsize - count]);
+ fs32_add(sb, &ucg->cg_frsum[allocsize - count], 1);
X
X succed:
X ubh_mark_buffer_dirty (USPI_UBH);
@@ -604,12 +601,10 @@


X struct ufs_super_block_first * usb1;

X struct ufs_cylinder_group * ucg;
X unsigned result, cylno, blkno;
- unsigned swab;
X
X UFSD(("ENTER, goal %u\n", goal))


X
X sb = inode->i_sb;
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;

X usb1 = ubh_get_usb_first(USPI_UBH);
X ucg = ubh_get_ucg(UCPI_UBH);
@@ -643,12 +638,13 @@
X *err = -EDQUOT;
X return (unsigned)-1;
X }
- DEC_SWAB32(ucg->cg_cs.cs_nbfree);
- DEC_SWAB32(usb1->fs_cstotal.cs_nbfree);
- DEC_SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nbfree);
+
+ fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1);
+ fs32_sub(sb, &usb1->fs_cstotal.cs_nbfree, 1);
+ fs32_sub(sb, &sb->fs_cs(ucpi->c_cgx).cs_nbfree, 1);
X cylno = ufs_cbtocylno(result);
- DEC_SWAB16(ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(result)));
- DEC_SWAB32(ubh_cg_blktot(ucpi, cylno));
+ fs16_sub(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(result)), 1);
+ fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1);
X
X UFSD(("EXIT, result %u\n", result))
X
@@ -663,11 +659,9 @@
X struct ufs_cylinder_group * ucg;
X unsigned start, length, location, result;
X unsigned possition, fragsize, blockmap, mask;
- unsigned swab;
X
X UFSD(("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count))


X
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;
X usb1 = ubh_get_usb_first (USPI_UBH);

X ucg = ubh_get_ucg(UCPI_UBH);
@@ -733,12 +727,8 @@


X {
X struct ufs_sb_private_info * uspi;

X int i, start, end, forw, back;
- unsigned swab;
-

X
X uspi = sb->u.ufs_sb.s_uspi;
- swab = sb->u.ufs_sb.s_swab;

-
X if (uspi->s_contigsumsize <= 0)
X return;
X
@@ -778,11 +768,11 @@
X i = back + forw + 1;
X if (i > uspi->s_contigsumsize)
X i = uspi->s_contigsumsize;
- ADD_SWAB32(*((u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (i << 2))), cnt);
+ fs32_add(sb, (u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (i << 2)), cnt);
X if (back > 0)
- SUB_SWAB32(*((u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (back << 2))), cnt);
+ fs32_sub(sb, (u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (back << 2)), cnt);
X if (forw > 0)
- SUB_SWAB32(*((u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (forw << 2))), cnt);
+ fs32_sub(sb, (u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (forw << 2)), cnt);
X }
X
X
diff -u --recursive --new-file v2.4.14/linux/fs/ufs/cylinder.c linux/fs/ufs/cylinder.c
--- v2.4.14/linux/fs/ufs/cylinder.c Tue Sep 5 14:07:30 2000
+++ linux/fs/ufs/cylinder.c Mon Nov 19 14:55:46 2001
@@ -41,10 +41,8 @@
X struct ufs_cg_private_info * ucpi;
X struct ufs_cylinder_group * ucg;
X unsigned i, j;
- unsigned swab;
X
X UFSD(("ENTER, cgno %u, bitmap_nr %u\n", cgno, bitmap_nr))


- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;

X ucpi = sb->u.ufs_sb.s_ucpi[bitmap_nr];
X ucg = (struct ufs_cylinder_group *)sb->u.ufs_sb.s_ucg[cgno]->b_data;
@@ -60,21 +58,21 @@
X goto failed;
X sb->u.ufs_sb.s_cgno[bitmap_nr] = cgno;
X
- ucpi->c_cgx = SWAB32(ucg->cg_cgx);
- ucpi->c_ncyl = SWAB16(ucg->cg_ncyl);
- ucpi->c_niblk = SWAB16(ucg->cg_niblk);
- ucpi->c_ndblk = SWAB32(ucg->cg_ndblk);
- ucpi->c_rotor = SWAB32(ucg->cg_rotor);
- ucpi->c_frotor = SWAB32(ucg->cg_frotor);
- ucpi->c_irotor = SWAB32(ucg->cg_irotor);
- ucpi->c_btotoff = SWAB32(ucg->cg_btotoff);
- ucpi->c_boff = SWAB32(ucg->cg_boff);
- ucpi->c_iusedoff = SWAB32(ucg->cg_iusedoff);
- ucpi->c_freeoff = SWAB32(ucg->cg_freeoff);
- ucpi->c_nextfreeoff = SWAB32(ucg->cg_nextfreeoff);
- ucpi->c_clustersumoff = SWAB32(ucg->cg_u.cg_44.cg_clustersumoff);
- ucpi->c_clusteroff = SWAB32(ucg->cg_u.cg_44.cg_clusteroff);
- ucpi->c_nclusterblks = SWAB32(ucg->cg_u.cg_44.cg_nclusterblks);
+ ucpi->c_cgx = fs32_to_cpu(sb, ucg->cg_cgx);
+ ucpi->c_ncyl = fs16_to_cpu(sb, ucg->cg_ncyl);
+ ucpi->c_niblk = fs16_to_cpu(sb, ucg->cg_niblk);
+ ucpi->c_ndblk = fs32_to_cpu(sb, ucg->cg_ndblk);
+ ucpi->c_rotor = fs32_to_cpu(sb, ucg->cg_rotor);
+ ucpi->c_frotor = fs32_to_cpu(sb, ucg->cg_frotor);
+ ucpi->c_irotor = fs32_to_cpu(sb, ucg->cg_irotor);
+ ucpi->c_btotoff = fs32_to_cpu(sb, ucg->cg_btotoff);
+ ucpi->c_boff = fs32_to_cpu(sb, ucg->cg_boff);
+ ucpi->c_iusedoff = fs32_to_cpu(sb, ucg->cg_iusedoff);
+ ucpi->c_freeoff = fs32_to_cpu(sb, ucg->cg_freeoff);
+ ucpi->c_nextfreeoff = fs32_to_cpu(sb, ucg->cg_nextfreeoff);
+ ucpi->c_clustersumoff = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_clustersumoff);
+ ucpi->c_clusteroff = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_clusteroff);
+ ucpi->c_nclusterblks = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_nclusterblks);
X UFSD(("EXIT\n"))
X return;
X
@@ -95,11 +93,9 @@
X struct ufs_cg_private_info * ucpi;
X struct ufs_cylinder_group * ucg;
X unsigned i;
- unsigned swab;
X
X UFSD(("ENTER, bitmap_nr %u\n", bitmap_nr))


X
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;

X if (sb->u.ufs_sb.s_cgno[bitmap_nr] == UFS_CGNO_EMPTY) {
X UFSD(("EXIT\n"))
@@ -116,9 +112,9 @@
X * rotor is not so important data, so we put it to disk
X * at the end of working with cylinder
X */
- ucg->cg_rotor = SWAB32(ucpi->c_rotor);
- ucg->cg_frotor = SWAB32(ucpi->c_frotor);
- ucg->cg_irotor = SWAB32(ucpi->c_irotor);
+ ucg->cg_rotor = cpu_to_fs32(sb, ucpi->c_rotor);
+ ucg->cg_frotor = cpu_to_fs32(sb, ucpi->c_frotor);
+ ucg->cg_irotor = cpu_to_fs32(sb, ucpi->c_irotor);
X ubh_mark_buffer_dirty (UCPI_UBH);
X for (i = 1; i < UCPI_UBH->count; i++) {
X brelse (UCPI_UBH->bh[i]);
diff -u --recursive --new-file v2.4.14/linux/fs/ufs/dir.c linux/fs/ufs/dir.c
--- v2.4.14/linux/fs/ufs/dir.c Tue Oct 23 22:48:53 2001
+++ linux/fs/ufs/dir.c Mon Nov 19 15:00:26 2001
@@ -29,15 +29,17 @@
X #define UFSD(x)
X #endif
X
+
+
X /*
X * NOTE! unlike strncmp, ufs_match returns 1 for success, 0 for failure.
X *
X * len <= UFS_MAXNAMLEN and de != NULL are guaranteed by caller.
X */
-static inline int ufs_match (int len, const char * const name,
- struct ufs_dir_entry * de, unsigned flags, unsigned swab)
+static inline int ufs_match(struct super_block *sb, int len,
+ const char * const name, struct ufs_dir_entry * de)
X {
- if (len != ufs_get_de_namlen(de))
+ if (len != ufs_get_de_namlen(sb, de))
X return 0;
X if (!de->d_ino)
X return 0;
@@ -58,10 +60,9 @@
X struct ufs_dir_entry * de;


X struct super_block * sb;

X int de_reclen;


- unsigned flags, swab;
+ unsigned flags;
X

X sb = inode->i_sb;
- swab = sb->u.ufs_sb.s_swab;

X flags = sb->u.ufs_sb.s_flags;
X

X UFSD(("ENTER, ino %lu f_pos %lu\n", inode->i_ino, (unsigned long) filp->f_pos))
@@ -96,7 +97,7 @@
X * least that it is non-zero. A
X * failure will be detected in the
X * dirent test below. */
- de_reclen = SWAB16(de->d_reclen);
+ de_reclen = fs16_to_cpu(sb, de->d_reclen);
X if (de_reclen < 1)
X break;
X i += de_reclen;
@@ -111,8 +112,7 @@
X && offset < sb->s_blocksize) {
X de = (struct ufs_dir_entry *) (bh->b_data + offset);
X /* XXX - put in a real ufs_check_dir_entry() */
- if ((de->d_reclen == 0) || (ufs_get_de_namlen(de) == 0)) {
- /* SWAB16() was unneeded -- compare to 0 */
+ if ((de->d_reclen == 0) || (ufs_get_de_namlen(sb, de) == 0)) {
X filp->f_pos = (filp->f_pos &
X (sb->s_blocksize - 1)) +
X sb->s_blocksize;
@@ -129,9 +129,8 @@
X brelse (bh);
X return stored;
X }
- offset += SWAB16(de->d_reclen);
+ offset += fs16_to_cpu(sb, de->d_reclen);
X if (de->d_ino) {
- /* SWAB16() was unneeded -- compare to 0 */
X /* We might block in the next section
X * if the data destination is
X * currently swapped out. So, use a
@@ -141,19 +140,22 @@
X unsigned long version = filp->f_version;
X unsigned char d_type = DT_UNKNOWN;
X
- UFSD(("filldir(%s,%u)\n", de->d_name, SWAB32(de->d_ino)))
- UFSD(("namlen %u\n", ufs_get_de_namlen(de)))
+ UFSD(("filldir(%s,%u)\n", de->d_name,
+ fs32_to_cpu(sb, de->d_ino)))
+ UFSD(("namlen %u\n", ufs_get_de_namlen(sb, de)))
+
X if ((flags & UFS_DE_MASK) == UFS_DE_44BSD)
X d_type = de->d_u.d_44.d_type;
- error = filldir(dirent, de->d_name, ufs_get_de_namlen(de),
- filp->f_pos, SWAB32(de->d_ino), d_type);
+ error = filldir(dirent, de->d_name,
+ ufs_get_de_namlen(sb, de), filp->f_pos,
+ fs32_to_cpu(sb, de->d_ino), d_type);
X if (error)
X break;
X if (version != filp->f_version)
X goto revalidate;
X stored ++;
X }
- filp->f_pos += SWAB16(de->d_reclen);
+ filp->f_pos += fs16_to_cpu(sb, de->d_reclen);
X }
X offset = 0;
X brelse (bh);
@@ -186,7 +188,6 @@
X struct buffer_head * bh_read[NAMEI_RA_SIZE];
X unsigned long offset;
X int block, toread, i, err;
- unsigned flags, swab;
X struct inode *dir = dentry->d_parent->d_inode;
X const char *name = dentry->d_name.name;
X int namelen = dentry->d_name.len;
@@ -196,8 +197,6 @@
X *res_bh = NULL;
X

X sb = dir->i_sb;

- flags = sb->u.ufs_sb.s_flags;


- swab = sb->u.ufs_sb.s_swab;
X

X if (namelen > UFS_MAXNAMLEN)
X return NULL;
@@ -248,7 +247,7 @@
X int de_len;
X
X if ((char *) de + namelen <= dlimit &&
- ufs_match (namelen, name, de, flags, swab)) {
+ ufs_match(sb, namelen, name, de)) {
X /* found a match -
X just to be sure, do a full check */
X if (!ufs_check_dir_entry("ufs_find_entry",
@@ -262,7 +261,7 @@
X return de;
X }
X /* prevent looping on a bad block */
- de_len = SWAB16(de->d_reclen);
+ de_len = fs16_to_cpu(sb, de->d_reclen);
X if (de_len <= 0)
X goto failed;
X offset += de_len;
@@ -290,33 +289,28 @@
X struct ufs_dir_entry * de, struct buffer_head * bh,
X unsigned long offset)
X {
- struct super_block * sb;
- const char * error_msg;
- unsigned flags, swab;
-
- sb = dir->i_sb;
- flags = sb->u.ufs_sb.s_flags;


- swab = sb->u.ufs_sb.s_swab;

- error_msg = NULL;
-
- if (SWAB16(de->d_reclen) < UFS_DIR_REC_LEN(1))
+ struct super_block *sb = dir->i_sb;
+ const char *error_msg = NULL;
+ int rlen = fs16_to_cpu(sb, de->d_reclen);
+
+ if (rlen < UFS_DIR_REC_LEN(1))
X error_msg = "reclen is smaller than minimal";
- else if (SWAB16(de->d_reclen) % 4 != 0)


+ else if (rlen % 4 != 0)

X error_msg = "reclen % 4 != 0";
- else if (SWAB16(de->d_reclen) < UFS_DIR_REC_LEN(ufs_get_de_namlen(de)))
+ else if (rlen < UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)))
X error_msg = "reclen is too small for namlen";
- else if (dir && ((char *) de - bh->b_data) + SWAB16(de->d_reclen) >
- dir->i_sb->s_blocksize)
+ else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
X error_msg = "directory entry across blocks";
- else if (dir && SWAB32(de->d_ino) > (sb->u.ufs_sb.s_uspi->s_ipg * sb->u.ufs_sb.s_uspi->s_ncg))
+ else if (fs32_to_cpu(sb, de->d_ino) > (sb->u.ufs_sb.s_uspi->s_ipg *
+ sb->u.ufs_sb.s_uspi->s_ncg))
X error_msg = "inode out of bounds";
X
X if (error_msg != NULL)
X ufs_error (sb, function, "bad entry in directory #%lu, size %Lu: %s - "
X "offset=%lu, inode=%lu, reclen=%d, namlen=%d",
X dir->i_ino, dir->i_size, error_msg, offset,
- (unsigned long) SWAB32(de->d_ino),
- SWAB16(de->d_reclen), ufs_get_de_namlen(de));
+ (unsigned long)fs32_to_cpu(sb, de->d_ino),
+ rlen, ufs_get_de_namlen(sb, de));
X
X return (error_msg == NULL ? 1 : 0);
X }
@@ -328,25 +322,22 @@
X struct ufs_dir_entry *res = NULL;
X
X if (bh) {
- unsigned swab = dir->i_sb->u.ufs_sb.s_swab;
-
X res = (struct ufs_dir_entry *) bh->b_data;
X res = (struct ufs_dir_entry *)((char *)res +
- SWAB16(res->d_reclen));
+ fs16_to_cpu(dir->i_sb, res->d_reclen));
X }
X *p = bh;
X return res;
X }
X ino_t ufs_inode_by_name(struct inode * dir, struct dentry *dentry)
X {
- unsigned swab = dir->i_sb->u.ufs_sb.s_swab;
X ino_t res = 0;
X struct ufs_dir_entry * de;
X struct buffer_head *bh;
X
X de = ufs_find_entry (dentry, &bh);
X if (de) {
- res = SWAB32(de->d_ino);
+ res = fs32_to_cpu(dir->i_sb, de->d_ino);
X brelse(bh);
X }
X return res;
@@ -355,9 +346,8 @@
X void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
X struct buffer_head *bh, struct inode *inode)
X {
- unsigned swab = dir->i_sb->u.ufs_sb.s_swab;
X dir->i_version = ++event;
- de->d_ino = SWAB32(inode->i_ino);
+ de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino);
X mark_buffer_dirty(bh);
X if (IS_SYNC(dir)) {
X ll_rw_block (WRITE, 1, &bh);
@@ -381,7 +371,6 @@
X unsigned short rec_len;


X struct buffer_head * bh;

X struct ufs_dir_entry * de, * de1;
- unsigned flags, swab;
X struct inode *dir = dentry->d_parent->d_inode;
X const char *name = dentry->d_name.name;
X int namelen = dentry->d_name.len;
@@ -390,8 +379,6 @@
X UFSD(("ENTER, name %s, namelen %u\n", name, namelen))
X

X sb = dir->i_sb;

- flags = sb->u.ufs_sb.s_flags;


- swab = sb->u.ufs_sb.s_swab;

X uspi = sb->u.ufs_sb.s_uspi;
X

X if (!namelen)
@@ -420,9 +407,9 @@
X return -ENOENT;
X }
X de = (struct ufs_dir_entry *) (bh->b_data + fragoff);
- de->d_ino = SWAB32(0);
- de->d_reclen = SWAB16(UFS_SECTOR_SIZE);
- ufs_set_de_namlen(de,0);
+ de->d_ino = 0;
+ de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE);
+ ufs_set_de_namlen(sb, de, 0);
X dir->i_size = offset + UFS_SECTOR_SIZE;
X mark_inode_dirty(dir);
X } else {
@@ -433,32 +420,35 @@
X brelse (bh);
X return -ENOENT;
X }
- if (ufs_match (namelen, name, de, flags, swab)) {
+ if (ufs_match(sb, namelen, name, de)) {
X brelse (bh);
X return -EEXIST;
X }
- if (SWAB32(de->d_ino) == 0 && SWAB16(de->d_reclen) >= rec_len)
+ if (de->d_ino == 0 && fs16_to_cpu(sb, de->d_reclen) >= rec_len)
X break;
X
- if (SWAB16(de->d_reclen) >= UFS_DIR_REC_LEN(ufs_get_de_namlen(de)) + rec_len)
+ if (fs16_to_cpu(sb, de->d_reclen) >=
+ UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)) + rec_len)
X break;
- offset += SWAB16(de->d_reclen);
- de = (struct ufs_dir_entry *) ((char *) de + SWAB16(de->d_reclen));
+ offset += fs16_to_cpu(sb, de->d_reclen);
+ de = (struct ufs_dir_entry *) ((char *) de + fs16_to_cpu(sb, de->d_reclen));
X }
X
- if (SWAB32(de->d_ino)) {
+ if (de->d_ino) {
X de1 = (struct ufs_dir_entry *) ((char *) de +
- UFS_DIR_REC_LEN(ufs_get_de_namlen(de)));
- de1->d_reclen = SWAB16(SWAB16(de->d_reclen) -
- UFS_DIR_REC_LEN(ufs_get_de_namlen(de)));
- de->d_reclen = SWAB16(UFS_DIR_REC_LEN(ufs_get_de_namlen(de)));
+ UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
+ de1->d_reclen =
+ cpu_to_fs16(sb, fs16_to_cpu(sb, de->d_reclen) -
+ UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
+ de->d_reclen =
+ cpu_to_fs16(sb, UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
X de = de1;
X }
- de->d_ino = SWAB32(0);
- ufs_set_de_namlen(de, namelen);
+ de->d_ino = 0;
+ ufs_set_de_namlen(sb, de, namelen);
X memcpy (de->d_name, name, namelen + 1);
- de->d_ino = SWAB32(inode->i_ino);
- ufs_set_de_type (de, inode->i_mode);
+ de->d_ino = cpu_to_fs32(sb, inode->i_ino);
+ ufs_set_de_type(sb, de, inode->i_mode);
X mark_buffer_dirty(bh);
X if (IS_SYNC(dir)) {
X ll_rw_block (WRITE, 1, &bh);
@@ -484,19 +474,18 @@


X struct super_block * sb;

X struct ufs_dir_entry * de, * pde;
X unsigned i;
- unsigned flags, swab;


X
X UFSD(("ENTER\n"))
X
X sb = inode->i_sb;

- flags = sb->u.ufs_sb.s_flags;


- swab = sb->u.ufs_sb.s_swab;

X i = 0;
X pde = NULL;
X de = (struct ufs_dir_entry *) bh->b_data;
X
- UFSD(("ino %u, reclen %u, namlen %u, name %s\n", SWAB32(de->d_ino),
- SWAB16(de->d_reclen), ufs_get_de_namlen(de), de->d_name))
+ UFSD(("ino %u, reclen %u, namlen %u, name %s\n",
+ fs32_to_cpu(sb, de->d_ino),
+ fs16to_cpu(sb, de->d_reclen),
+ ufs_get_de_namlen(sb, de), de->d_name))
X
X while (i < bh->b_size) {
X if (!ufs_check_dir_entry ("ufs_delete_entry", inode, de, bh, i)) {
@@ -505,10 +494,9 @@
X }
X if (de == dir) {
X if (pde)
- pde->d_reclen =
- SWAB16(SWAB16(pde->d_reclen) +
- SWAB16(dir->d_reclen));
- dir->d_ino = SWAB32(0);
+ fs16_add(sb, &pde->d_reclen,
+ fs16_to_cpu(sb, dir->d_reclen));
+ dir->d_ino = 0;
X inode->i_version = ++event;


X inode->i_ctime = inode->i_mtime = CURRENT_TIME;

X mark_inode_dirty(inode);
@@ -521,12 +509,12 @@
X UFSD(("EXIT\n"))
X return 0;
X }
- i += SWAB16(de->d_reclen);
+ i += fs16_to_cpu(sb, de->d_reclen);
X if (i == UFS_SECTOR_SIZE) pde = NULL;
X else pde = de;
X de = (struct ufs_dir_entry *)
- ((char *) de + SWAB16(de->d_reclen));
- if (i == UFS_SECTOR_SIZE && SWAB16(de->d_reclen) == 0)
+ ((char *) de + fs16_to_cpu(sb, de->d_reclen));
+ if (i == UFS_SECTOR_SIZE && de->d_reclen == 0)
X break;
X }
X UFSD(("EXIT\n"))
@@ -537,8 +525,6 @@
X int ufs_make_empty(struct inode * inode, struct inode *dir)
X {
X struct super_block * sb = dir->i_sb;
- unsigned flags = sb->u.ufs_sb.s_flags;
- unsigned swab = sb->u.ufs_sb.s_swab;
X struct buffer_head * dir_block;
X struct ufs_dir_entry * de;
X int err;
@@ -549,16 +535,17 @@
X
X inode->i_blocks = sb->s_blocksize / UFS_SECTOR_SIZE;
X de = (struct ufs_dir_entry *) dir_block->b_data;
- de->d_ino = SWAB32(inode->i_ino);
- ufs_set_de_type (de, inode->i_mode);
- ufs_set_de_namlen(de,1);
- de->d_reclen = SWAB16(UFS_DIR_REC_LEN(1));
+ de->d_ino = cpu_to_fs32(sb, inode->i_ino);
+ ufs_set_de_type(sb, de, inode->i_mode);
+ ufs_set_de_namlen(sb, de, 1);
+ de->d_reclen = cpu_to_fs16(sb, UFS_DIR_REC_LEN(1));
X strcpy (de->d_name, ".");
- de = (struct ufs_dir_entry *) ((char *) de + SWAB16(de->d_reclen));
- de->d_ino = SWAB32(dir->i_ino);
- ufs_set_de_type (de, dir->i_mode);
- de->d_reclen = SWAB16(UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1));
- ufs_set_de_namlen(de,2);
+ de = (struct ufs_dir_entry *)
+ ((char *)de + fs16_to_cpu(sb, de->d_reclen));
+ de->d_ino = cpu_to_fs32(sb, dir->i_ino);
+ ufs_set_de_type(sb, de, dir->i_mode);
+ de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1));
+ ufs_set_de_namlen(sb, de, 2);
X strcpy (de->d_name, "..");
X mark_buffer_dirty(dir_block);
X brelse (dir_block);
@@ -576,10 +563,8 @@


X struct buffer_head * bh;

X struct ufs_dir_entry * de, * de1;
X int err;
- unsigned swab;
X

X sb = inode->i_sb;
- swab = sb->u.ufs_sb.s_swab;
X

X if (inode->i_size < UFS_DIR_REC_LEN(1) + UFS_DIR_REC_LEN(2) ||
X !(bh = ufs_bread (inode, 0, 0, &err))) {
@@ -589,16 +574,18 @@
X return 1;
X }
X de = (struct ufs_dir_entry *) bh->b_data;
- de1 = (struct ufs_dir_entry *) ((char *) de + SWAB16(de->d_reclen));
- if (SWAB32(de->d_ino) != inode->i_ino || !SWAB32(de1->d_ino) ||
- strcmp (".", de->d_name) || strcmp ("..", de1->d_name)) {
+ de1 = (struct ufs_dir_entry *)
+ ((char *)de + fs16_to_cpu(sb, de->d_reclen));
+ if (fs32_to_cpu(sb, de->d_ino) != inode->i_ino || de1->d_ino == 0 ||
+ strcmp (".", de->d_name) || strcmp ("..", de1->d_name)) {
X ufs_warning (inode->i_sb, "empty_dir",
X "bad directory (dir #%lu) - no `.' or `..'",
X inode->i_ino);
X return 1;
X }
- offset = SWAB16(de->d_reclen) + SWAB16(de1->d_reclen);
- de = (struct ufs_dir_entry *) ((char *) de1 + SWAB16(de1->d_reclen));
+ offset = fs16_to_cpu(sb, de->d_reclen) + fs16_to_cpu(sb, de1->d_reclen);
+ de = (struct ufs_dir_entry *)
+ ((char *)de1 + fs16_to_cpu(sb, de1->d_reclen));
X while (offset < inode->i_size ) {
X if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
X brelse (bh);
@@ -616,12 +603,13 @@
X brelse (bh);
X return 1;
X }
- if (SWAB32(de->d_ino)) {
+ if (de->d_ino) {
X brelse (bh);
X return 0;
X }
- offset += SWAB16(de->d_reclen);
- de = (struct ufs_dir_entry *) ((char *) de + SWAB16(de->d_reclen));
+ offset += fs16_to_cpu(sb, de->d_reclen);
+ de = (struct ufs_dir_entry *)
+ ((char *)de + fs16_to_cpu(sb, de->d_reclen));
X }
X brelse (bh);
X return 1;
diff -u --recursive --new-file v2.4.14/linux/fs/ufs/ialloc.c linux/fs/ufs/ialloc.c
--- v2.4.14/linux/fs/ufs/ialloc.c Tue Oct 23 22:48:53 2001
+++ linux/fs/ufs/ialloc.c Mon Nov 19 14:55:46 2001
@@ -66,12 +66,10 @@
X struct ufs_cylinder_group * ucg;
X int is_directory;
X unsigned ino, cg, bit;
- unsigned swab;
X
X UFSD(("ENTER, ino %lu\n", inode->i_ino))


X
X sb = inode->i_sb;
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;

X usb1 = ubh_get_usb_first(USPI_UBH);
X
@@ -93,10 +91,10 @@
X return;
X }
X ucg = ubh_get_ucg(UCPI_UBH);
- if (!ufs_cg_chkmagic(ucg))
+ if (!ufs_cg_chkmagic(sb, ucg))
X ufs_panic (sb, "ufs_free_fragments", "internal error, bad cg magic number");
X
- ucg->cg_time = SWAB32(CURRENT_TIME);
+ ucg->cg_time = cpu_to_fs32(sb, CURRENT_TIME);
X
X is_directory = S_ISDIR(inode->i_mode);
X
@@ -111,16 +109,17 @@
X ubh_clrbit (UCPI_UBH, ucpi->c_iusedoff, bit);
X if (ino < ucpi->c_irotor)
X ucpi->c_irotor = ino;
- INC_SWAB32(ucg->cg_cs.cs_nifree);
- INC_SWAB32(usb1->fs_cstotal.cs_nifree);
- INC_SWAB32(sb->fs_cs(cg).cs_nifree);
+ fs32_add(sb, &ucg->cg_cs.cs_nifree, 1);
+ fs32_add(sb, &usb1->fs_cstotal.cs_nifree, 1);
+ fs32_add(sb, &sb->fs_cs(cg).cs_nifree, 1);
X
X if (is_directory) {
- DEC_SWAB32(ucg->cg_cs.cs_ndir);
- DEC_SWAB32(usb1->fs_cstotal.cs_ndir);
- DEC_SWAB32(sb->fs_cs(cg).cs_ndir);
+ fs32_sub(sb, &ucg->cg_cs.cs_ndir, 1);
+ fs32_sub(sb, &usb1->fs_cstotal.cs_ndir, 1);
+ fs32_sub(sb, &sb->fs_cs(cg).cs_ndir, 1);
X }
X }
+
X ubh_mark_buffer_dirty (USPI_UBH);
X ubh_mark_buffer_dirty (UCPI_UBH);
X if (sb->s_flags & MS_SYNCHRONOUS) {
@@ -152,7 +151,6 @@
X struct ufs_cylinder_group * ucg;
X struct inode * inode;
X unsigned cg, bit, i, j, start;


- unsigned swab;
X
X UFSD(("ENTER\n"))
X

@@ -163,7 +161,6 @@


X inode = new_inode(sb);
X if (!inode)

X return ERR_PTR(-ENOMEM);


- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;
X usb1 = ubh_get_usb_first(USPI_UBH);
X

@@ -173,7 +170,7 @@
X * Try to place the inode in its parent directory
X */
X i = ufs_inotocg(dir->i_ino);
- if (SWAB32(sb->fs_cs(i).cs_nifree)) {
+ if (sb->fs_cs(i).cs_nifree) {
X cg = i;
X goto cg_found;
X }
@@ -185,7 +182,7 @@
X i += j;
X if (i >= uspi->s_ncg)
X i -= uspi->s_ncg;
- if (SWAB32(sb->fs_cs(i).cs_nifree)) {
+ if (sb->fs_cs(i).cs_nifree) {
X cg = i;
X goto cg_found;
X }
@@ -199,7 +196,7 @@
X i++;
X if (i >= uspi->s_ncg)
X i = 0;
- if (SWAB32(sb->fs_cs(i).cs_nifree)) {
+ if (sb->fs_cs(i).cs_nifree) {
X cg = i;
X goto cg_found;
X }
@@ -212,7 +209,7 @@
X if (!ucpi)
X goto failed;
X ucg = ubh_get_ucg(UCPI_UBH);
- if (!ufs_cg_chkmagic(ucg))
+ if (!ufs_cg_chkmagic(sb, ucg))
X ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number");
X
X start = ucpi->c_irotor;
@@ -233,14 +230,14 @@
X goto failed;
X }
X
- DEC_SWAB32(ucg->cg_cs.cs_nifree);
- DEC_SWAB32(usb1->fs_cstotal.cs_nifree);
- DEC_SWAB32(sb->fs_cs(cg).cs_nifree);
+ fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1);
+ fs32_sub(sb, &usb1->fs_cstotal.cs_nifree, 1);
+ fs32_sub(sb, &sb->fs_cs(cg).cs_nifree, 1);
X
X if (S_ISDIR(mode)) {
- INC_SWAB32(ucg->cg_cs.cs_ndir);
- INC_SWAB32(usb1->fs_cstotal.cs_ndir);
- INC_SWAB32(sb->fs_cs(cg).cs_ndir);
+ fs32_add(sb, &ucg->cg_cs.cs_ndir, 1);
+ fs32_add(sb, &usb1->fs_cstotal.cs_ndir, 1);
+ fs32_add(sb, &sb->fs_cs(cg).cs_ndir, 1);
X }
X
X ubh_mark_buffer_dirty (USPI_UBH);
diff -u --recursive --new-file v2.4.14/linux/fs/ufs/inode.c linux/fs/ufs/inode.c
--- v2.4.14/linux/fs/ufs/inode.c Tue Oct 23 22:48:53 2001
+++ linux/fs/ufs/inode.c Mon Nov 19 14:55:46 2001
@@ -50,17 +50,6 @@
X #define UFSD(x)
X #endif
X
-static inline unsigned int ufs_block_bmap1(struct buffer_head * bh, unsigned nr,
- struct ufs_sb_private_info * uspi, unsigned swab)
-{
- unsigned int tmp;
- if (!bh)
- return 0;
- tmp = SWAB32(((u32 *) bh->b_data)[nr]);
- brelse (bh);
- return tmp;
-}
-
X static int ufs_block_to_path(struct inode *inode, long i_block, int offsets[4])
X {
X struct ufs_sb_private_info *uspi = inode->i_sb->u.ufs_sb.s_uspi;
@@ -97,7 +86,6 @@
X {
X struct super_block *sb = inode->i_sb;
X struct ufs_sb_private_info *uspi = sb->u.ufs_sb.s_uspi;
- unsigned int swab = sb->u.ufs_sb.s_swab;
X int mask = uspi->s_apbmask>>uspi->s_fpbshift;
X int shift = uspi->s_apbshift-uspi->s_fpbshift;
X int offsets[4], *p;
@@ -118,7 +106,7 @@
X struct buffer_head *bh;
X int n = *p++;
X
- bh = bread(sb->s_dev, uspi->s_sbbase+SWAB32(block)+(n>>shift),
+ bh = bread(sb->s_dev, uspi->s_sbbase + fs32_to_cpu(sb, block)+(n>>shift),
X sb->s_blocksize);
X if (!bh)
X goto out;
@@ -127,7 +115,7 @@
X if (!block)
X goto out;
X }
- ret = uspi->s_sbbase + SWAB32(block) + (frag & uspi->s_fpbmask);
+ ret = uspi->s_sbbase + fs32_to_cpu(sb, block) + (frag & uspi->s_fpbmask);
X out:
X unlock_kernel();
X return ret;
@@ -143,13 +131,11 @@
X unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
X unsigned tmp, goal;
X u32 * p, * p2;
- unsigned int swab;
X
X UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n",
X inode->i_ino, fragment, new_fragment, required))

X
X sb = inode->i_sb;
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;

X block = ufs_fragstoblks (fragment);
X blockoff = ufs_fragnum (fragment);
@@ -157,13 +143,13 @@
X goal = 0;
X
X repeat:


- tmp = SWAB32(*p);
+ tmp = fs32_to_cpu(sb, *p);

X lastfrag = inode->u.ufs_i.i_lastfrag;
X if (tmp && fragment < lastfrag) {
X if (metadata) {
X result = getblk (sb->s_dev, uspi->s_sbbase + tmp + blockoff,
X sb->s_blocksize);
- if (tmp == SWAB32(*p)) {
+ if (tmp == fs32_to_cpu(sb, *p)) {
X UFSD(("EXIT, result %u\n", tmp + blockoff))
X return result;
X }
@@ -187,7 +173,7 @@
X if (lastblockoff) {
X p2 = inode->u.ufs_i.i_u1.i_data + lastblock;
X tmp = ufs_new_fragments (inode, p2, lastfrag,
- SWAB32(*p2), uspi->s_fpb - lastblockoff, err);
+ fs32_to_cpu(sb, *p2), uspi->s_fpb - lastblockoff, err);
X if (!tmp) {
X if (lastfrag != inode->u.ufs_i.i_lastfrag)
X goto repeat;
@@ -197,7 +183,7 @@
X lastfrag = inode->u.ufs_i.i_lastfrag;
X
X }
- goal = SWAB32(inode->u.ufs_i.i_u1.i_data[lastblock]) + uspi->s_fpb;
+ goal = fs32_to_cpu(sb, inode->u.ufs_i.i_u1.i_data[lastblock]) + uspi->s_fpb;
X tmp = ufs_new_fragments (inode, p, fragment - blockoff,
X goal, required + blockoff, err);
X }
@@ -206,19 +192,19 @@
X */
X else if (lastblock == block) {
X tmp = ufs_new_fragments (inode, p, fragment - (blockoff - lastblockoff),
- SWAB32(*p), required + (blockoff - lastblockoff), err);
+ fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff), err);
X }
X /*
X * We will allocate new block before last allocated block
X */
X else /* (lastblock > block) */ {
- if (lastblock && (tmp = SWAB32(inode->u.ufs_i.i_u1.i_data[lastblock-1])))
+ if (lastblock && (tmp = fs32_to_cpu(sb, inode->u.ufs_i.i_u1.i_data[lastblock-1])))
X goal = tmp + uspi->s_fpb;
X tmp = ufs_new_fragments (inode, p, fragment - blockoff,
X goal, uspi->s_fpb, err);
X }
X if (!tmp) {
- if ((!blockoff && SWAB32(*p)) ||
+ if ((!blockoff && *p) ||
X (blockoff && lastfrag != inode->u.ufs_i.i_lastfrag))
X goto repeat;
X *err = -ENOSPC;
@@ -255,10 +241,8 @@
X struct buffer_head * result;
X unsigned tmp, goal, block, blockoff;
X u32 * p;
- unsigned int swab;


X
X sb = inode->i_sb;
- swab = sb->u.ufs_sb.s_swab;
X uspi = sb->u.ufs_sb.s_uspi;

X block = ufs_fragstoblks (fragment);
X blockoff = ufs_fragnum (fragment);
@@ -277,12 +261,12 @@
X
X p = (u32 *) bh->b_data + block;
X repeat:


- tmp = SWAB32(*p);
+ tmp = fs32_to_cpu(sb, *p);

X if (tmp) {
X if (metadata) {
X result = getblk (bh->b_dev, uspi->s_sbbase + tmp + blockoff,
X sb->s_blocksize);
- if (tmp == SWAB32(*p))
+ if (tmp == fs32_to_cpu(sb, *p))
X goto out;
X brelse (result);
X goto repeat;
@@ -292,13 +276,13 @@
X }
X }
X
- if (block && (tmp = SWAB32(((u32*)bh->b_data)[block-1]) + uspi->s_fpb))
+ if (block && (tmp = fs32_to_cpu(sb, ((u32*)bh->b_data)[block-1]) + uspi->s_fpb))
X goal = tmp + uspi->s_fpb;
X else
X goal = bh->b_blocknr + uspi->s_fpb;
X tmp = ufs_new_fragments (inode, p, ufs_blknum(new_fragment), goal, uspi->s_fpb, err);
X if (!tmp) {
- if (SWAB32(*p))
+ if (fs32_to_cpu(sb, *p))
X goto repeat;
X goto out;
X }
@@ -332,13 +316,11 @@


X struct super_block * sb;

X struct ufs_sb_private_info * uspi;

X struct buffer_head * bh;
- unsigned int swab;
X int ret, err, new;
X unsigned long ptr, phys;


X
X sb = inode->i_sb;

X uspi = sb->u.ufs_sb.s_uspi;
- swab = sb->u.ufs_sb.s_swab;
X

X if (!create) {
X phys = ufs_frag_map(inode, fragment);
@@ -504,14 +486,13 @@
X struct ufs_inode * ufs_inode;

X struct buffer_head * bh;

X unsigned i;


- unsigned flags, swab;
+ unsigned flags;
X

X UFSD(("ENTER, ino %lu\n", inode->i_ino))


X
X sb = inode->i_sb;

X uspi = sb->u.ufs_sb.s_uspi;
X flags = sb->u.ufs_sb.s_flags;
- swab = sb->u.ufs_sb.s_swab;
X

X if (inode->i_ino < UFS_ROOTINO ||
X inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
@@ -529,37 +510,29 @@
X /*
X * Copy data to the in-core inode.
X */
- inode->i_mode = SWAB16(ufs_inode->ui_mode);
- inode->i_nlink = SWAB16(ufs_inode->ui_nlink);
+ inode->i_mode = fs16_to_cpu(sb, ufs_inode->ui_mode);
+ inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink);
X if (inode->i_nlink == 0)
X ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
X
X /*
X * Linux now has 32-bit uid and gid, so we can support EFT.
X */
- inode->i_uid = ufs_get_inode_uid(ufs_inode);
- inode->i_gid = ufs_get_inode_gid(ufs_inode);
-
- /*
- * Linux i_size can be 32 on some architectures. We will mark
- * big files as read only and let user access first 32 bits.
- */
- inode->u.ufs_i.i_size = SWAB64(ufs_inode->ui_size);
- inode->i_size = (off_t) inode->u.ufs_i.i_size;
- if (sizeof(off_t) == 4 && (inode->u.ufs_i.i_size >> 32))
- inode->i_size = (__u32)-1;
-
- inode->i_atime = SWAB32(ufs_inode->ui_atime.tv_sec);
- inode->i_ctime = SWAB32(ufs_inode->ui_ctime.tv_sec);
- inode->i_mtime = SWAB32(ufs_inode->ui_mtime.tv_sec);
- inode->i_blocks = SWAB32(ufs_inode->ui_blocks);
+ inode->i_uid = ufs_get_inode_uid(sb, ufs_inode);
+ inode->i_gid = ufs_get_inode_gid(sb, ufs_inode);
+
+ inode->i_size = fs64_to_cpu(sb, ufs_inode->ui_size);
+ inode->i_atime = fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec);
+ inode->i_ctime = fs32_to_cpu(sb, ufs_inode->ui_ctime.tv_sec);
+ inode->i_mtime = fs32_to_cpu(sb, ufs_inode->ui_mtime.tv_sec);
+ inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks);
X inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat) */
X inode->i_version = ++event;
X
- inode->u.ufs_i.i_flags = SWAB32(ufs_inode->ui_flags);
- inode->u.ufs_i.i_gen = SWAB32(ufs_inode->ui_gen);
- inode->u.ufs_i.i_shadow = SWAB32(ufs_inode->ui_u3.ui_sun.ui_shadow);
- inode->u.ufs_i.i_oeftflag = SWAB32(ufs_inode->ui_u3.ui_sun.ui_oeftflag);
+ inode->u.ufs_i.i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags);
+ inode->u.ufs_i.i_gen = fs32_to_cpu(sb, ufs_inode->ui_gen);
+ inode->u.ufs_i.i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
+ inode->u.ufs_i.i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
X inode->u.ufs_i.i_lastfrag = (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
X
X if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
@@ -590,7 +563,7 @@
X }
X } else
X init_special_inode(inode, inode->i_mode,
- SWAB32(ufs_inode->ui_u2.ui_addr.ui_db[0]));
+ fs32_to_cpu(sb, ufs_inode->ui_u2.ui_addr.ui_db[0]));
X
X brelse (bh);
X
@@ -604,14 +577,13 @@


X struct buffer_head * bh;

X struct ufs_inode * ufs_inode;
X unsigned i;


- unsigned flags, swab;
+ unsigned flags;
X

X UFSD(("ENTER, ino %lu\n", inode->i_ino))


X
X sb = inode->i_sb;

X uspi = sb->u.ufs_sb.s_uspi;
X flags = sb->u.ufs_sb.s_flags;
- swab = sb->u.ufs_sb.s_swab;
X

X if (inode->i_ino < UFS_ROOTINO ||
X inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
@@ -626,30 +598,30 @@
X }
X ufs_inode = (struct ufs_inode *) (bh->b_data + ufs_inotofsbo(inode->i_ino) * sizeof(struct ufs_inode));
X
- ufs_inode->ui_mode = SWAB16(inode->i_mode);
- ufs_inode->ui_nlink = SWAB16(inode->i_nlink);
+ ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode);
+ ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink);
X
- ufs_set_inode_uid (ufs_inode, inode->i_uid);
- ufs_set_inode_gid (ufs_inode, inode->i_gid);
+ ufs_set_inode_uid(sb, ufs_inode, inode->i_uid);
+ ufs_set_inode_gid(sb, ufs_inode, inode->i_gid);
X
- ufs_inode->ui_size = SWAB64((u64)inode->i_size);
- ufs_inode->ui_atime.tv_sec = SWAB32(inode->i_atime);
- ufs_inode->ui_atime.tv_usec = SWAB32(0);
- ufs_inode->ui_ctime.tv_sec = SWAB32(inode->i_ctime);
- ufs_inode->ui_ctime.tv_usec = SWAB32(0);
- ufs_inode->ui_mtime.tv_sec = SWAB32(inode->i_mtime);
- ufs_inode->ui_mtime.tv_usec = SWAB32(0);
- ufs_inode->ui_blocks = SWAB32(inode->i_blocks);
- ufs_inode->ui_flags = SWAB32(inode->u.ufs_i.i_flags);
- ufs_inode->ui_gen = SWAB32(inode->u.ufs_i.i_gen);
+ ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size);
+ ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime);
+ ufs_inode->ui_atime.tv_usec = 0;
+ ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime);
+ ufs_inode->ui_ctime.tv_usec = 0;
+ ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime);
+ ufs_inode->ui_mtime.tv_usec = 0;
+ ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks);
+ ufs_inode->ui_flags = cpu_to_fs32(sb, inode->u.ufs_i.i_flags);
+ ufs_inode->ui_gen = cpu_to_fs32(sb, inode->u.ufs_i.i_gen);
X
X if ((flags & UFS_UID_MASK) == UFS_UID_EFT) {
- ufs_inode->ui_u3.ui_sun.ui_shadow = SWAB32(inode->u.ufs_i.i_shadow);
- ufs_inode->ui_u3.ui_sun.ui_oeftflag = SWAB32(inode->u.ufs_i.i_oeftflag);
+ ufs_inode->ui_u3.ui_sun.ui_shadow = cpu_to_fs32(sb, inode->u.ufs_i.i_shadow);
+ ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, inode->u.ufs_i.i_oeftflag);
X }
X
X if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- ufs_inode->ui_u2.ui_addr.ui_db[0] = SWAB32(kdev_t_to_nr(inode->i_rdev));
+ ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, kdev_t_to_nr(inode->i_rdev));
X else if (inode->i_blocks) {
X for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
X ufs_inode->ui_u2.ui_addr.ui_db[i] = inode->u.ufs_i.i_u1.i_data[i];
diff -u --recursive --new-file v2.4.14/linux/fs/ufs/super.c linux/fs/ufs/super.c
--- v2.4.14/linux/fs/ufs/super.c Wed May 16 10:31:27 2001
+++ linux/fs/ufs/super.c Mon Nov 19 14:55:46 2001
@@ -97,44 +97,45 @@
X /*
X * Print contents of ufs_super_block, useful for debugging
X */
-void ufs_print_super_stuff(struct ufs_super_block_first * usb1,
+void ufs_print_super_stuff(struct super_block *sb,
+ struct ufs_super_block_first * usb1,
X struct ufs_super_block_second * usb2,
- struct ufs_super_block_third * usb3, unsigned swab)
+ struct ufs_super_block_third * usb3)
X {
X printk("ufs_print_super_stuff\n");
X printk("size of usb: %u\n", sizeof(struct ufs_super_block));
- printk(" magic: 0x%x\n", SWAB32(usb3->fs_magic));
- printk(" sblkno: %u\n", SWAB32(usb1->fs_sblkno));
- printk(" cblkno: %u\n", SWAB32(usb1->fs_cblkno));
- printk(" iblkno: %u\n", SWAB32(usb1->fs_iblkno));
- printk(" dblkno: %u\n", SWAB32(usb1->fs_dblkno));
- printk(" cgoffset: %u\n", SWAB32(usb1->fs_cgoffset));
- printk(" ~cgmask: 0x%x\n", ~SWAB32(usb1->fs_cgmask));
- printk(" size: %u\n", SWAB32(usb1->fs_size));
- printk(" dsize: %u\n", SWAB32(usb1->fs_dsize));
- printk(" ncg: %u\n", SWAB32(usb1->fs_ncg));
- printk(" bsize: %u\n", SWAB32(usb1->fs_bsize));
- printk(" fsize: %u\n", SWAB32(usb1->fs_fsize));
- printk(" frag: %u\n", SWAB32(usb1->fs_frag));
- printk(" fragshift: %u\n", SWAB32(usb1->fs_fragshift));
- printk(" ~fmask: %u\n", ~SWAB32(usb1->fs_fmask));
- printk(" fshift: %u\n", SWAB32(usb1->fs_fshift));
- printk(" sbsize: %u\n", SWAB32(usb1->fs_sbsize));
- printk(" spc: %u\n", SWAB32(usb1->fs_spc));
- printk(" cpg: %u\n", SWAB32(usb1->fs_cpg));
- printk(" ipg: %u\n", SWAB32(usb1->fs_ipg));
- printk(" fpg: %u\n", SWAB32(usb1->fs_fpg));
- printk(" csaddr: %u\n", SWAB32(usb1->fs_csaddr));
- printk(" cssize: %u\n", SWAB32(usb1->fs_cssize));
- printk(" cgsize: %u\n", SWAB32(usb1->fs_cgsize));
- printk(" fstodb: %u\n", SWAB32(usb1->fs_fsbtodb));
- printk(" contigsumsize: %d\n", SWAB32(usb3->fs_u2.fs_44.fs_contigsumsize));
- printk(" postblformat: %u\n", SWAB32(usb3->fs_postblformat));
- printk(" nrpos: %u\n", SWAB32(usb3->fs_nrpos));
- printk(" ndir %u\n", SWAB32(usb1->fs_cstotal.cs_ndir));
- printk(" nifree %u\n", SWAB32(usb1->fs_cstotal.cs_nifree));
- printk(" nbfree %u\n", SWAB32(usb1->fs_cstotal.cs_nbfree));
- printk(" nffree %u\n", SWAB32(usb1->fs_cstotal.cs_nffree));
+ printk(" magic: 0x%x\n", fs32_to_cpu(sb, usb3->fs_magic));
+ printk(" sblkno: %u\n", fs32_to_cpu(sb, usb1->fs_sblkno));
+ printk(" cblkno: %u\n", fs32_to_cpu(sb, usb1->fs_cblkno));
+ printk(" iblkno: %u\n", fs32_to_cpu(sb, usb1->fs_iblkno));
+ printk(" dblkno: %u\n", fs32_to_cpu(sb, usb1->fs_dblkno));
+ printk(" cgoffset: %u\n", fs32_to_cpu(sb, usb1->fs_cgoffset));
+ printk(" ~cgmask: 0x%x\n", ~fs32_to_cpu(sb, usb1->fs_cgmask));
+ printk(" size: %u\n", fs32_to_cpu(sb, usb1->fs_size));
+ printk(" dsize: %u\n", fs32_to_cpu(sb, usb1->fs_dsize));
+ printk(" ncg: %u\n", fs32_to_cpu(sb, usb1->fs_ncg));
+ printk(" bsize: %u\n", fs32_to_cpu(sb, usb1->fs_bsize));
+ printk(" fsize: %u\n", fs32_to_cpu(sb, usb1->fs_fsize));
+ printk(" frag: %u\n", fs32_to_cpu(sb, usb1->fs_frag));
+ printk(" fragshift: %u\n", fs32_to_cpu(sb, usb1->fs_fragshift));
+ printk(" ~fmask: %u\n", ~fs32_to_cpu(sb, usb1->fs_fmask));
+ printk(" fshift: %u\n", fs32_to_cpu(sb, usb1->fs_fshift));
+ printk(" sbsize: %u\n", fs32_to_cpu(sb, usb1->fs_sbsize));
+ printk(" spc: %u\n", fs32_to_cpu(sb, usb1->fs_spc));
+ printk(" cpg: %u\n", fs32_to_cpu(sb, usb1->fs_cpg));
+ printk(" ipg: %u\n", fs32_to_cpu(sb, usb1->fs_ipg));
+ printk(" fpg: %u\n", fs32_to_cpu(sb, usb1->fs_fpg));
+ printk(" csaddr: %u\n", fs32_to_cpu(sb, usb1->fs_csaddr));
+ printk(" cssize: %u\n", fs32_to_cpu(sb, usb1->fs_cssize));
+ printk(" cgsize: %u\n", fs32_to_cpu(sb, usb1->fs_cgsize));
+ printk(" fstodb: %u\n", fs32_to_cpu(sb, usb1->fs_fsbtodb));
+ printk(" contigsumsize: %d\n", fs32_to_cpu(sb, usb3->fs_u2.fs_44.fs_contigsumsize));
+ printk(" postblformat: %u\n", fs32_to_cpu(sb, usb3->fs_postblformat));
+ printk(" nrpos: %u\n", fs32_to_cpu(sb, usb3->fs_nrpos));
+ printk(" ndir %u\n", fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir));
+ printk(" nifree %u\n", fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree));
+ printk(" nbfree %u\n", fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree));
+ printk(" nffree %u\n", fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree));
X printk("\n");
X }
X
@@ -142,36 +143,36 @@
X /*
X * Print contents of ufs_cylinder_group, useful for debugging
X */
-void ufs_print_cylinder_stuff(struct ufs_cylinder_group *cg, unsigned swab)
+void ufs_print_cylinder_stuff(struct super_block *sb, struct ufs_cylinder_group *cg)
X {
X printk("\nufs_print_cylinder_stuff\n");
X printk("size of ucg: %u\n", sizeof(struct ufs_cylinder_group));
- printk(" magic: %x\n", SWAB32(cg->cg_magic));
- printk(" time: %u\n", SWAB32(cg->cg_time));
- printk(" cgx: %u\n", SWAB32(cg->cg_cgx));
- printk(" ncyl: %u\n", SWAB16(cg->cg_ncyl));
- printk(" niblk: %u\n", SWAB16(cg->cg_niblk));
- printk(" ndblk: %u\n", SWAB32(cg->cg_ndblk));
- printk(" cs_ndir: %u\n", SWAB32(cg->cg_cs.cs_ndir));
- printk(" cs_nbfree: %u\n", SWAB32(cg->cg_cs.cs_nbfree));
- printk(" cs_nifree: %u\n", SWAB32(cg->cg_cs.cs_nifree));
- printk(" cs_nffree: %u\n", SWAB32(cg->cg_cs.cs_nffree));
- printk(" rotor: %u\n", SWAB32(cg->cg_rotor));
- printk(" frotor: %u\n", SWAB32(cg->cg_frotor));
- printk(" irotor: %u\n", SWAB32(cg->cg_irotor));
+ printk(" magic: %x\n", fs32_to_cpu(sb, cg->cg_magic));
+ printk(" time: %u\n", fs32_to_cpu(sb, cg->cg_time));
+ printk(" cgx: %u\n", fs32_to_cpu(sb, cg->cg_cgx));
+ printk(" ncyl: %u\n", fs16_to_cpu(sb, cg->cg_ncyl));
+ printk(" niblk: %u\n", fs16_to_cpu(sb, cg->cg_niblk));
+ printk(" ndblk: %u\n", fs32_to_cpu(sb, cg->cg_ndblk));
+ printk(" cs_ndir: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_ndir));
+ printk(" cs_nbfree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nbfree));
+ printk(" cs_nifree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nifree));
+ printk(" cs_nffree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nffree));
+ printk(" rotor: %u\n", fs32_to_cpu(sb, cg->cg_rotor));
+ printk(" frotor: %u\n", fs32_to_cpu(sb, cg->cg_frotor));
+ printk(" irotor: %u\n", fs32_to_cpu(sb, cg->cg_irotor));
X printk(" frsum: %u, %u, %u, %u, %u, %u, %u, %u\n",
- SWAB32(cg->cg_frsum[0]), SWAB32(cg->cg_frsum[1]),
- SWAB32(cg->cg_frsum[2]), SWAB32(cg->cg_frsum[3]),
- SWAB32(cg->cg_frsum[4]), SWAB32(cg->cg_frsum[5]),
- SWAB32(cg->cg_frsum[6]), SWAB32(cg->cg_frsum[7]));
- printk(" btotoff: %u\n", SWAB32(cg->cg_btotoff));
- printk(" boff: %u\n", SWAB32(cg->cg_boff));
- printk(" iuseoff: %u\n", SWAB32(cg->cg_iusedoff));
- printk(" freeoff: %u\n", SWAB32(cg->cg_freeoff));
- printk(" nextfreeoff: %u\n", SWAB32(cg->cg_nextfreeoff));
- printk(" clustersumoff %u\n", SWAB32(cg->cg_u.cg_44.cg_clustersumoff));
- printk(" clusteroff %u\n", SWAB32(cg->cg_u.cg_44.cg_clusteroff));
- printk(" nclusterblks %u\n", SWAB32(cg->cg_u.cg_44.cg_nclusterblks));
+ fs32_to_cpu(sb, cg->cg_frsum[0]), fs32_to_cpu(sb, cg->cg_frsum[1]),
+ fs32_to_cpu(sb, cg->cg_frsum[2]), fs32_to_cpu(sb, cg->cg_frsum[3]),
+ fs32_to_cpu(sb, cg->cg_frsum[4]), fs32_to_cpu(sb, cg->cg_frsum[5]),
+ fs32_to_cpu(sb, cg->cg_frsum[6]), fs32_to_cpu(sb, cg->cg_frsum[7]));
+ printk(" btotoff: %u\n", fs32_to_cpu(sb, cg->cg_btotoff));
+ printk(" boff: %u\n", fs32_to_cpu(sb, cg->cg_boff));
+ printk(" iuseoff: %u\n", fs32_to_cpu(sb, cg->cg_iusedoff));
+ printk(" freeoff: %u\n", fs32_to_cpu(sb, cg->cg_freeoff));
+ printk(" nextfreeoff: %u\n", fs32_to_cpu(sb, cg->cg_nextfreeoff));
+ printk(" clustersumoff %u\n", fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clustersumoff));
+ printk(" clusteroff %u\n", fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clusteroff));
+ printk(" nclusterblks %u\n", fs32_to_cpu(sb, cg->cg_u.cg_44.cg_nclusterblks));
X printk("\n");
X }
X #endif /* UFS_SUPER_DEBUG_MORE */
@@ -320,12 +321,10 @@
X struct ufs_buffer_head * ubh;
X unsigned char * base, * space;
X unsigned size, blks, i;


- unsigned swab;
X
X UFSD(("ENTER\n"))
X
X uspi = sb->u.ufs_sb.s_uspi;
- swab = sb->u.ufs_sb.s_swab;

X
X /*
X * Read cs structures from (usually) first data block
@@ -366,10 +365,10 @@
X UFSD(("read cg %u\n", i))
X if (!(sb->u.ufs_sb.s_ucg[i] = bread (sb->s_dev, ufs_cgcmin(i), sb->s_blocksize)))
X goto failed;
- if (!ufs_cg_chkmagic ((struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data))
+ if (!ufs_cg_chkmagic (sb, (struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data))
X goto failed;
X #ifdef UFS_SUPER_DEBUG_MORE
- ufs_print_cylinder_stuff((struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data, swab);
+ ufs_print_cylinder_stuff(sb, (struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data);
X #endif
X }
X for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) {
@@ -444,12 +443,11 @@


X struct ufs_super_block_third * usb3;

X struct ufs_buffer_head * ubh;
X unsigned block_size, super_block_size;


- unsigned flags, swab;
+ unsigned flags;
X

X uspi = NULL;
X ubh = NULL;
X flags = 0;
- swab = 0;


X
X UFSD(("ENTER\n"))
X

@@ -614,37 +612,22 @@
X /*
X * Check ufs magic number
X */


-#if defined(__LITTLE_ENDIAN) || defined(__BIG_ENDIAN) /* sane bytesex */

- switch (usb3->fs_magic) {
+ switch (__constant_le32_to_cpu(usb3->fs_magic)) {
X case UFS_MAGIC:
- case UFS_MAGIC_LFN:
+ case UFS_MAGIC_LFN:
X case UFS_MAGIC_FEA:
X case UFS_MAGIC_4GB:
- swab = UFS_NATIVE_ENDIAN;
- goto magic_found;
- case UFS_CIGAM:
- case UFS_CIGAM_LFN:
- case UFS_CIGAM_FEA:
- case UFS_CIGAM_4GB:
- swab = UFS_SWABBED_ENDIAN;
+ sb->u.ufs_sb.s_bytesex = BYTESEX_LE;
X goto magic_found;
X }
-#else /* bytesex perversion */
- switch (le32_to_cpup(&usb3->fs_magic)) {
+ switch (__constant_be32_to_cpu(usb3->fs_magic)) {
X case UFS_MAGIC:
X case UFS_MAGIC_LFN:
X case UFS_MAGIC_FEA:
X case UFS_MAGIC_4GB:
- swab = UFS_LITTLE_ENDIAN;
- goto magic_found;
- case UFS_CIGAM:
- case UFS_CIGAM_LFN:
- case UFS_CIGAM_FEA:
- case UFS_CIGAM_4GB:
- swab = UFS_BIG_ENDIAN;
+ sb->u.ufs_sb.s_bytesex = BYTESEX_BE;
X goto magic_found;
X }
-#endif
X
X if ((((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_NEXTSTEP)
X || ((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_NEXTSTEP_CD)
@@ -662,11 +645,11 @@
X /*
X * Check block and fragment sizes
X */
- uspi->s_bsize = SWAB32(usb1->fs_bsize);
- uspi->s_fsize = SWAB32(usb1->fs_fsize);
- uspi->s_sbsize = SWAB32(usb1->fs_sbsize);
- uspi->s_fmask = SWAB32(usb1->fs_fmask);
- uspi->s_fshift = SWAB32(usb1->fs_fshift);
+ uspi->s_bsize = fs32_to_cpu(sb, usb1->fs_bsize);
+ uspi->s_fsize = fs32_to_cpu(sb, usb1->fs_fsize);
+ uspi->s_sbsize = fs32_to_cpu(sb, usb1->fs_sbsize);
+ uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask);
+ uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift);
X
X if (uspi->s_bsize != 4096 && uspi->s_bsize != 8192
X && uspi->s_bsize != 32768) {
@@ -688,7 +671,7 @@
X }
X
X #ifdef UFS_SUPER_DEBUG_MORE
- ufs_print_super_stuff (usb1, usb2, usb3, swab);
+ ufs_print_super_stuff(sb, usb1, usb2, usb3);
X #endif
X
X /*
@@ -699,7 +682,7 @@
X ((flags & UFS_ST_MASK) == UFS_ST_OLD) ||
X (((flags & UFS_ST_MASK) == UFS_ST_SUN ||
X (flags & UFS_ST_MASK) == UFS_ST_SUNx86) &&
- (ufs_get_fs_state(usb1, usb3) == (UFS_FSOK - SWAB32(usb1->fs_time))))) {
+ (ufs_get_fs_state(sb, usb1, usb3) == (UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time))))) {
X switch(usb1->fs_clean) {
X case UFS_FSCLEAN:
X UFSD(("fs is clean\n"))
@@ -732,56 +715,56 @@
X /*
X * Read ufs_super_block into internal data structures
X */
- sb->s_blocksize = SWAB32(usb1->fs_fsize);
- sb->s_blocksize_bits = SWAB32(usb1->fs_fshift);
+ sb->s_blocksize = fs32_to_cpu(sb, usb1->fs_fsize);
+ sb->s_blocksize_bits = fs32_to_cpu(sb, usb1->fs_fshift);
X sb->s_op = &ufs_super_ops;
X sb->dq_op = NULL; /***/
- sb->s_magic = SWAB32(usb3->fs_magic);
+ sb->s_magic = fs32_to_cpu(sb, usb3->fs_magic);
X
- uspi->s_sblkno = SWAB32(usb1->fs_sblkno);
- uspi->s_cblkno = SWAB32(usb1->fs_cblkno);
- uspi->s_iblkno = SWAB32(usb1->fs_iblkno);
- uspi->s_dblkno = SWAB32(usb1->fs_dblkno);
- uspi->s_cgoffset = SWAB32(usb1->fs_cgoffset);
- uspi->s_cgmask = SWAB32(usb1->fs_cgmask);
- uspi->s_size = SWAB32(usb1->fs_size);
- uspi->s_dsize = SWAB32(usb1->fs_dsize);
- uspi->s_ncg = SWAB32(usb1->fs_ncg);
+ uspi->s_sblkno = fs32_to_cpu(sb, usb1->fs_sblkno);
+ uspi->s_cblkno = fs32_to_cpu(sb, usb1->fs_cblkno);
+ uspi->s_iblkno = fs32_to_cpu(sb, usb1->fs_iblkno);
+ uspi->s_dblkno = fs32_to_cpu(sb, usb1->fs_dblkno);
+ uspi->s_cgoffset = fs32_to_cpu(sb, usb1->fs_cgoffset);
+ uspi->s_cgmask = fs32_to_cpu(sb, usb1->fs_cgmask);
+ uspi->s_size = fs32_to_cpu(sb, usb1->fs_size);
+ uspi->s_dsize = fs32_to_cpu(sb, usb1->fs_dsize);
+ uspi->s_ncg = fs32_to_cpu(sb, usb1->fs_ncg);
X /* s_bsize already set */
X /* s_fsize already set */
- uspi->s_fpb = SWAB32(usb1->fs_frag);
- uspi->s_minfree = SWAB32(usb1->fs_minfree);
- uspi->s_bmask = SWAB32(usb1->fs_bmask);
- uspi->s_fmask = SWAB32(usb1->fs_fmask);
- uspi->s_bshift = SWAB32(usb1->fs_bshift);
- uspi->s_fshift = SWAB32(usb1->fs_fshift);
- uspi->s_fpbshift = SWAB32(usb1->fs_fragshift);
- uspi->s_fsbtodb = SWAB32(usb1->fs_fsbtodb);
+ uspi->s_fpb = fs32_to_cpu(sb, usb1->fs_frag);
+ uspi->s_minfree = fs32_to_cpu(sb, usb1->fs_minfree);
+ uspi->s_bmask = fs32_to_cpu(sb, usb1->fs_bmask);
+ uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask);
+ uspi->s_bshift = fs32_to_cpu(sb, usb1->fs_bshift);
+ uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift);
+ uspi->s_fpbshift = fs32_to_cpu(sb, usb1->fs_fragshift);
+ uspi->s_fsbtodb = fs32_to_cpu(sb, usb1->fs_fsbtodb);
X /* s_sbsize already set */
- uspi->s_csmask = SWAB32(usb1->fs_csmask);
- uspi->s_csshift = SWAB32(usb1->fs_csshift);
- uspi->s_nindir = SWAB32(usb1->fs_nindir);
- uspi->s_inopb = SWAB32(usb1->fs_inopb);
- uspi->s_nspf = SWAB32(usb1->fs_nspf);
- uspi->s_npsect = ufs_get_fs_npsect(usb1, usb3);
- uspi->s_interleave = SWAB32(usb1->fs_interleave);
- uspi->s_trackskew = SWAB32(usb1->fs_trackskew);
- uspi->s_csaddr = SWAB32(usb1->fs_csaddr);
- uspi->s_cssize = SWAB32(usb1->fs_cssize);
- uspi->s_cgsize = SWAB32(usb1->fs_cgsize);
- uspi->s_ntrak = SWAB32(usb1->fs_ntrak);
- uspi->s_nsect = SWAB32(usb1->fs_nsect);
- uspi->s_spc = SWAB32(usb1->fs_spc);
- uspi->s_ipg = SWAB32(usb1->fs_ipg);
- uspi->s_fpg = SWAB32(usb1->fs_fpg);
- uspi->s_cpc = SWAB32(usb2->fs_cpc);
- uspi->s_contigsumsize = SWAB32(usb3->fs_u2.fs_44.fs_contigsumsize);
- uspi->s_qbmask = ufs_get_fs_qbmask(usb3);
- uspi->s_qfmask = ufs_get_fs_qfmask(usb3);
- uspi->s_postblformat = SWAB32(usb3->fs_postblformat);
- uspi->s_nrpos = SWAB32(usb3->fs_nrpos);
- uspi->s_postbloff = SWAB32(usb3->fs_postbloff);
- uspi->s_rotbloff = SWAB32(usb3->fs_rotbloff);
+ uspi->s_csmask = fs32_to_cpu(sb, usb1->fs_csmask);
+ uspi->s_csshift = fs32_to_cpu(sb, usb1->fs_csshift);
+ uspi->s_nindir = fs32_to_cpu(sb, usb1->fs_nindir);
+ uspi->s_inopb = fs32_to_cpu(sb, usb1->fs_inopb);
+ uspi->s_nspf = fs32_to_cpu(sb, usb1->fs_nspf);
+ uspi->s_npsect = ufs_get_fs_npsect(sb, usb1, usb3);
+ uspi->s_interleave = fs32_to_cpu(sb, usb1->fs_interleave);
+ uspi->s_trackskew = fs32_to_cpu(sb, usb1->fs_trackskew);
+ uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr);
+ uspi->s_cssize = fs32_to_cpu(sb, usb1->fs_cssize);
+ uspi->s_cgsize = fs32_to_cpu(sb, usb1->fs_cgsize);
+ uspi->s_ntrak = fs32_to_cpu(sb, usb1->fs_ntrak);
+ uspi->s_nsect = fs32_to_cpu(sb, usb1->fs_nsect);
+ uspi->s_spc = fs32_to_cpu(sb, usb1->fs_spc);
+ uspi->s_ipg = fs32_to_cpu(sb, usb1->fs_ipg);
+ uspi->s_fpg = fs32_to_cpu(sb, usb1->fs_fpg);
+ uspi->s_cpc = fs32_to_cpu(sb, usb2->fs_cpc);
+ uspi->s_contigsumsize = fs32_to_cpu(sb, usb3->fs_u2.fs_44.fs_contigsumsize);
+ uspi->s_qbmask = ufs_get_fs_qbmask(sb, usb3);
+ uspi->s_qfmask = ufs_get_fs_qfmask(sb, usb3);
+ uspi->s_postblformat = fs32_to_cpu(sb, usb3->fs_postblformat);
+ uspi->s_nrpos = fs32_to_cpu(sb, usb3->fs_nrpos);
+ uspi->s_postbloff = fs32_to_cpu(sb, usb3->fs_postbloff);
+ uspi->s_rotbloff = fs32_to_cpu(sb, usb3->fs_rotbloff);
X
X /*
X * Compute another frequently used values
@@ -803,11 +786,9 @@
X if ((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) ==
X UFS_MOUNT_UFSTYPE_44BSD)
X uspi->s_maxsymlinklen =
- SWAB32(usb3->fs_u2.fs_44.fs_maxsymlinklen);
+ fs32_to_cpu(sb, usb3->fs_u2.fs_44.fs_maxsymlinklen);
X
X sb->u.ufs_sb.s_flags = flags;
- sb->u.ufs_sb.s_swab = swab;


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

echo 'End of part 104'
echo 'File patch-2.4.15 is continued in part 105'
echo "105" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:30 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part114

#!/bin/sh -x
# this is part 114 of a 115 - part archive


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

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

- * Some apps forget to close sockets, or hang to it a bit too long,
- * so we may stay in this dead state long enough to be noticed...
- * Note : all socket function do check sk->state, so we are safe...
- * Jean II
- */
- if (self->tsap) {
- irttp_close_tsap(self->tsap);
- self->tsap = NULL;
- }
+ /* Close our TSAP.
+ * If we leave it open, IrLMP put it back into the list of
+ * unconnected LSAPs. The problem is that any incoming request
+ * can then be matched to this socket (and it will be, because
+ * it is at the head of the list). This would prevent any
+ * listening socket waiting on the same TSAP to get those
+ * requests. Some apps forget to close sockets, or hang to it
+ * a bit too long, so we may stay in this dead state long
+ * enough to be noticed...
+ * Note : all socket function do check sk->state, so we are
+ * safe...
+ * Jean II
+ */
+ if (self->tsap) {
+ irttp_close_tsap(self->tsap);
+ self->tsap = NULL;
+ }
+ }
X
X /* Note : once we are there, there is not much you want to do
X * with the socket anymore, apart from closing it.
@@ -222,7 +230,8 @@
X self->max_data_size);
X
X memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
- kfree_skb(skb);
+ dev_kfree_skb(skb);
+ // Should be ??? skb_queue_tail(&sk->receive_queue, skb);
X
X /* We are now connected! */
X sk->state = TCP_ESTABLISHED;
@@ -1205,7 +1214,7 @@
X sk->protinfo.irda = NULL;
X
X sock_orphan(sk);
- sock->sk = NULL;
+ sock->sk = NULL;
X
X /* Purge queues (see sock_init_data()) */
X skb_queue_purge(&sk->receive_queue);
diff -u --recursive --new-file v2.4.14/linux/net/irda/ircomm/ircomm_param.c linux/net/irda/ircomm/ircomm_param.c
--- v2.4.14/linux/net/irda/ircomm/ircomm_param.c Tue Mar 21 11:17:28 2000
+++ linux/net/irda/ircomm/ircomm_param.c Fri Nov 9 14:22:17 2001
@@ -182,13 +182,13 @@
X int get)
X {
X struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
- __u8 service_type = param->pv.b; /* We know it's a one byte integer */
+ __u8 service_type = (__u8) param->pv.i;
X
X ASSERT(self != NULL, return -1;);
X ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
X
X if (get) {
- param->pv.b = self->settings.service_type;
+ param->pv.i = self->settings.service_type;


X return 0;
X }
X

@@ -246,9 +246,9 @@
X ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
X
X if (get)
- param->pv.b = IRCOMM_SERIAL;
+ param->pv.i = IRCOMM_SERIAL;
X else {
- self->settings.port_type = param->pv.b;
+ self->settings.port_type = (__u8) param->pv.i;
X
X IRDA_DEBUG(0, __FUNCTION__ "(), port type=%d\n",
X self->settings.port_type);
@@ -317,9 +317,9 @@
X ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
X
X if (get)
- param->pv.b = self->settings.data_format;
+ param->pv.i = self->settings.data_format;
X else
- self->settings.data_format = param->pv.b;
+ self->settings.data_format = (__u8) param->pv.i;


X
X return 0;
X }

@@ -339,11 +339,11 @@
X ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
X
X if (get)
- param->pv.b = self->settings.flow_control;
+ param->pv.i = self->settings.flow_control;
X else
- self->settings.flow_control = param->pv.b;
+ self->settings.flow_control = (__u8) param->pv.i;
X
- IRDA_DEBUG(1, __FUNCTION__ "(), flow control = 0x%02x\n", param->pv.b);
+ IRDA_DEBUG(1, __FUNCTION__ "(), flow control = 0x%02x\n", (__u8) param->pv.i);


X
X return 0;
X }

@@ -362,15 +362,15 @@
X ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
X
X if (get) {
- param->pv.s = self->settings.xonxoff[0];
- param->pv.s |= self->settings.xonxoff[1] << 8;
+ param->pv.i = self->settings.xonxoff[0];
+ param->pv.i |= self->settings.xonxoff[1] << 8;
X } else {
- self->settings.xonxoff[0] = param->pv.s & 0xff;
- self->settings.xonxoff[1] = param->pv.s >> 8;
+ self->settings.xonxoff[0] = (__u16) param->pv.i & 0xff;
+ self->settings.xonxoff[1] = (__u16) param->pv.i >> 8;
X }
X
X IRDA_DEBUG(0, __FUNCTION__ "(), XON/XOFF = 0x%02x,0x%02x\n",
- param->pv.s & 0xff, param->pv.s >> 8);
+ param->pv.i & 0xff, param->pv.i >> 8);


X
X return 0;
X }

@@ -389,15 +389,15 @@
X ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
X
X if (get) {
- param->pv.s = self->settings.enqack[0];
- param->pv.s |= self->settings.enqack[1] << 8;
+ param->pv.i = self->settings.enqack[0];
+ param->pv.i |= self->settings.enqack[1] << 8;
X } else {
- self->settings.enqack[0] = param->pv.s & 0xff;
- self->settings.enqack[1] = param->pv.s >> 8;
+ self->settings.enqack[0] = (__u16) param->pv.i & 0xff;
+ self->settings.enqack[1] = (__u16) param->pv.i >> 8;
X }
X
X IRDA_DEBUG(0, __FUNCTION__ "(), ENQ/ACK = 0x%02x,0x%02x\n",
- param->pv.s & 0xff, param->pv.s >> 8);
+ param->pv.i & 0xff, param->pv.i >> 8);


X
X return 0;
X }

@@ -431,9 +431,9 @@
X ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
X
X if (get)
- param->pv.b = self->settings.dte;
+ param->pv.i = self->settings.dte;
X else {
- dte = param->pv.b;
+ dte = (__u8) param->pv.i;
X
X if (dte & IRCOMM_DELTA_DTR)
X self->settings.dce |= (IRCOMM_DELTA_DSR|
@@ -470,9 +470,9 @@
X struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
X __u8 dce;
X
- IRDA_DEBUG(1, __FUNCTION__ "(), dce = 0x%02x\n", param->pv.b);
+ IRDA_DEBUG(1, __FUNCTION__ "(), dce = 0x%02x\n", (__u8) param->pv.i);
X
- dce = param->pv.b;
+ dce = (__u8) param->pv.i;
X
X ASSERT(self != NULL, return -1;);
X ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
diff -u --recursive --new-file v2.4.14/linux/net/irda/irda_device.c linux/net/irda/irda_device.c
--- v2.4.14/linux/net/irda/irda_device.c Sun Sep 23 11:41:02 2001
+++ linux/net/irda/irda_device.c Mon Nov 12 11:29:57 2001
@@ -10,6 +10,7 @@
X * Modified by: Dag Brattli <da...@cs.uit.no>
X *
X * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 2000-2001 Jean Tourrilhes <j...@hpl.hp.com>
X *

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

X * modify it under the terms of the GNU General Public License as
@@ -65,6 +66,8 @@
X extern int tekram_init(void);
X extern int actisys_init(void);
X extern int girbil_init(void);
+extern int sa1100_irda_init(void);
+extern int ep7211_ir_init(void);
X
X static void __irda_task_delete(struct irda_task *task);
X
@@ -124,6 +127,9 @@
X #ifdef CONFIG_WINBOND_FIR
X w83977af_init();
X #endif
+#ifdef CONFIG_SA1100_FIR
+ sa1100_irda_init();
+#endif
X #ifdef CONFIG_NSC_FIR
X nsc_ircc_init();
X #endif
@@ -151,6 +157,9 @@
X #ifdef CONFIG_OLD_BELKIN
X old_belkin_init();
X #endif
+#ifdef CONFIG_EP7211_IR
+ ep7211_ir_init();
+#endif


X return 0;
X }
X

@@ -181,7 +190,10 @@
X
X if (status) {
X self->media_busy = TRUE;
- irlap_start_mbusy_timer(self);
+ if (status == SMALL)
+ irlap_start_mbusy_timer(self, SMALLBUSY_TIMEOUT);
+ else
+ irlap_start_mbusy_timer(self, MEDIABUSY_TIMEOUT);
X IRDA_DEBUG( 4, "Media busy!\n");
X } else {
X self->media_busy = FALSE;
diff -u --recursive --new-file v2.4.14/linux/net/irda/iriap.c linux/net/irda/iriap.c
--- v2.4.14/linux/net/irda/iriap.c Sun Sep 23 11:41:02 2001
+++ linux/net/irda/iriap.c Fri Nov 9 14:22:17 2001
@@ -11,6 +11,7 @@
X *
X * Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>,

X * All Rights Reserved.

+ * Copyright (c) 2000-2001 Jean Tourrilhes <j...@hpl.hp.com>
X *

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

X * modify it under the terms of the GNU General Public License as
@@ -773,7 +774,7 @@
X {
X struct iriap_cb *self, *new;
X
- IRDA_DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(1, __FUNCTION__ "()\n");
X
X self = (struct iriap_cb *) instance;
X
diff -u --recursive --new-file v2.4.14/linux/net/irda/irlap.c linux/net/irda/irlap.c
--- v2.4.14/linux/net/irda/irlap.c Sun Sep 23 11:41:02 2001
+++ linux/net/irda/irlap.c Fri Nov 9 14:22:17 2001
@@ -10,6 +10,7 @@
X * Modified by: Dag Brattli <da...@cs.uit.no>
X *
X * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 2000-2001 Jean Tourrilhes <j...@hpl.hp.com>
X *

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

X * modify it under the terms of the GNU General Public License as
@@ -502,10 +503,17 @@
X IRDA_DEBUG(4, __FUNCTION__
X "(), discovery only possible in NDM mode\n");
X irlap_discovery_confirm(self, NULL);
+ /* Note : in theory, if we are not in NDM, we could postpone
+ * the discovery like we do for connection request.
+ * In practice, it's not worth it. If the media was busy,
+ * it's likely next time around it won't be busy. If we are
+ * in REPLY state, we will get passive discovery info & event.
+ * Jean II */
X return;
X }
X
- /* Check if last discovery request finished in time */
+ /* Check if last discovery request finished in time, or if
+ * it was aborted due to the media busy flag. */
X if (self->discovery_log != NULL) {
X hashbin_delete(self->discovery_log, (FREE_FUNC) kfree);
X self->discovery_log = NULL;
@@ -555,10 +563,16 @@
X
X /*
X * Check for successful discovery, since we are then allowed to clear
- * the media busy condition (irlap p.94). This should allow us to make
- * connection attempts much easier.
+ * the media busy condition (IrLAP 6.13.4 - p.94). This should allow
+ * us to make connection attempts much faster and easier (i.e. no
+ * collisions).
+ * Setting media busy to false will also generate an event allowing
+ * to process pending events in NDM state machine.
+ * Note : the spec doesn't define what's a successful discovery is.
+ * If we want Ultra to work, it's successful even if there is
+ * nobody discovered - Jean II
X */
- if (discovery_log && HASHBIN_GET_SIZE(discovery_log) > 0)
+ if (discovery_log)
X irda_device_set_media_busy(self->netdev, FALSE);
X
X /* Inform IrLMP */
@@ -580,7 +594,18 @@
X ASSERT(discovery != NULL, return;);
X
X ASSERT(self->notify.instance != NULL, return;);
-
+
+ /* A device is very likely to connect immediately after it performs
+ * a successful discovery. This means that in our case, we are much
+ * more likely to receive a connection request over the medium.
+ * So, we backoff to avoid collisions.
+ * IrLAP spec 6.13.4 suggest 100ms...
+ * Note : this little trick actually make a *BIG* difference. If I set
+ * my Linux box with discovery enabled and one Ultra frame sent every
+ * second, my Palm has no trouble connecting to it every time !
+ * Jean II */
+ irda_device_set_media_busy(self->netdev, SMALL);
+
X irlmp_link_discovery_indication(self->notify.instance, discovery);
X }
X
diff -u --recursive --new-file v2.4.14/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
--- v2.4.14/linux/net/irda/irlap_event.c Tue Oct 9 17:06:53 2001
+++ linux/net/irda/irlap_event.c Fri Nov 9 14:22:17 2001
@@ -12,6 +12,7 @@
X * Copyright (c) 1998-2000 Dag Brattli <d...@brattli.net>,
X * Copyright (c) 1998 Thomas Davis <rat...@radiks.net>


X * All Rights Reserved.

+ * Copyright (c) 2000-2001 Jean Tourrilhes <j...@hpl.hp.com>
X *

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

X * modify it under the terms of the GNU General Public License as
@@ -114,6 +115,7 @@
X "DISCOVERY_TIMER_EXPIRED",
X "WD_TIMER_EXPIRED",
X "BACKOFF_TIMER_EXPIRED",
+ "MEDIA_BUSY_TIMER_EXPIRED",
X };
X
X const char *irlap_state[] = {
@@ -263,15 +265,7 @@
X NULL, NULL);
X }
X break;
- case LAP_NDM:
- /* Check if we should try to connect */
- if ((self->connect_pending) && !self->media_busy) {
- self->connect_pending = FALSE;
-
- ret = (*state[self->state])(self, CONNECT_REQUEST,
- NULL, NULL);
- }
- break;
+/* case LAP_NDM: */
X /* case LAP_CONN: */
X /* case LAP_RESET_WAIT: */
X /* case LAP_RESET_CHECK: */
@@ -305,17 +299,6 @@
X if ((state != LAP_XMIT_P) && (state != LAP_XMIT_S))
X self->bytes_left = self->line_capacity;
X #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
-#ifdef CONFIG_IRDA_ULTRA
- /* Send any pending Ultra frames if any */
- /* The higher layers may have sent a few Ultra frames while we
- * were doing discovery (either query or reply). Those frames
- * have been queued, but were never sent. It is now time to
- * send them...
- * Jean II */
- if ((state == LAP_NDM) && (!skb_queue_empty(&self->txq_ultra)))
- /* Force us to listen 500 ms before sending Ultra */
- irda_device_set_media_busy(self->netdev, TRUE);
-#endif /* CONFIG_IRDA_ULTRA */
X }
X
X /*
@@ -339,6 +322,9 @@
X ASSERT(self->netdev != NULL, return -1;);
X
X if (self->media_busy) {
+ /* Note : this will never happen, because we test
+ * media busy in irlap_connect_request() and
+ * postpone the event... - Jean II */
X IRDA_DEBUG(0, __FUNCTION__
X "(), CONNECT_REQUEST: media busy!\n");
X
@@ -379,6 +365,9 @@
X
X /* This will make IrLMP try again */
X irlap_discovery_confirm(self, NULL);
+ /* Note : the discovery log is not cleaned up here,
+ * it will be done in irlap_discovery_request()
+ * Jean II */


X return 0;
X }
X

@@ -417,8 +406,7 @@
X */
X irlap_start_query_timer(self, QUERY_TIMEOUT*info->S);
X irlap_next_state(self, LAP_REPLY);
- }
- else {
+ } else {
X /* This is the final slot. How is it possible ?
X * This would happen is both discoveries are just slightly
X * offset (if they are in sync, all packets are lost).
@@ -440,6 +428,54 @@
X irlap_discovery_indication(self, info->discovery);
X }
X break;
+ case MEDIA_BUSY_TIMER_EXPIRED:
+ /* A bunch of events may be postponed because the media is
+ * busy (usually immediately after we close a connection),
+ * or while we are doing discovery (state query/reply).
+ * In all those cases, the media busy flag will be cleared
+ * when it's OK for us to process those postponed events.
+ * This event is not mentioned in the state machines in the
+ * IrLAP spec. It's because they didn't consider Ultra and
+ * postponing connection request is optional.
+ * Jean II */
+#ifdef CONFIG_IRDA_ULTRA
+ /* Send any pending Ultra frames if any */
+ if (!skb_queue_empty(&self->txq_ultra)) {
+ /* We don't send the frame, just post an event.
+ * Also, previously this code was in timer.c...
+ * Jean II */
+ ret = (*state[self->state])(self, SEND_UI_FRAME,
+ NULL, NULL);
+ }
+#endif /* CONFIG_IRDA_ULTRA */
+ /* Check if we should try to connect.
+ * This code was previously in irlap_do_event() */
+ if (self->connect_pending) {
+ self->connect_pending = FALSE;
+
+ /* This one *should* not pend in this state, except
+ * if a socket try to connect and immediately
+ * disconnect. - clear - Jean II */
+ if (self->disconnect_pending)
+ irlap_disconnect_indication(self, LAP_DISC_INDICATION);
+ else
+ ret = (*state[self->state])(self,
+ CONNECT_REQUEST,
+ NULL, NULL);
+ self->disconnect_pending = FALSE;
+ }
+ /* Note : one way to test if this code works well (including
+ * media busy and small busy) is to create a user space
+ * application generating an Ultra packet every 3.05 sec (or
+ * 2.95 sec) and to see how it interact with discovery.
+ * It's fairly easy to check that no packet is lost, that the
+ * packets are postponed during discovery and that after
+ * discovery indication you have a 100ms "gap".
+ * As connection request and Ultra are now processed the same
+ * way, this avoid the tedious job of trying IrLAP connection
+ * in all those cases...
+ * Jean II */
+ break;
X #ifdef CONFIG_IRDA_ULTRA
X case SEND_UI_FRAME:
X /* Only allowed to repeat an operation twice */
@@ -735,8 +771,10 @@
X
X break;
X case DISCONNECT_REQUEST:
+ IRDA_DEBUG(0, __FUNCTION__ "(), Disconnect request!\n");
X irlap_send_dm_frame(self);
- irlap_next_state( self, LAP_CONN);
+ irlap_next_state( self, LAP_NDM);
+ irlap_disconnect_indication(self, LAP_DISC_INDICATION);
X break;
X default:
X IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
@@ -1417,13 +1455,12 @@
X irlap_start_final_timer(self, self->final_timeout);
X break;
X case RECV_RD_RSP:
- IRDA_DEBUG(0, __FUNCTION__ "(), RECV_RD_RSP\n");
+ IRDA_DEBUG(1, __FUNCTION__ "(), RECV_RD_RSP\n");
X
- irlap_next_state(self, LAP_PCLOSE);
- irlap_send_disc_frame(self);
X irlap_flush_all_queues(self);
- irlap_start_final_timer(self, self->final_timeout);
- self->retry_count = 0;
+ irlap_next_state(self, LAP_XMIT_P);
+ /* Call back the LAP state machine to do a proper disconnect */
+ irlap_disconnect_request(self);
X break;
X default:
X IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n",
diff -u --recursive --new-file v2.4.14/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c
--- v2.4.14/linux/net/irda/irlap_frame.c Wed Jul 25 17:10:27 2001
+++ linux/net/irda/irlap_frame.c Fri Nov 9 14:22:17 2001
@@ -11,6 +11,7 @@
X *
X * Copyright (c) 1998-2000 Dag Brattli <da...@cs.uit.no>,

X * All Rights Reserved.

+ * Copyright (c) 2000-2001 Jean Tourrilhes <j...@hpl.hp.com>
X *

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

X * modify it under the terms of the GNU General Public License as
@@ -696,7 +697,7 @@
X static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb,
X struct irlap_info *info, int command)
X {
- IRDA_DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
X
X /* Check if this is a command or a response frame */
X if (command)
diff -u --recursive --new-file v2.4.14/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
--- v2.4.14/linux/net/irda/irlmp.c Tue Oct 9 17:06:53 2001
+++ linux/net/irda/irlmp.c Fri Nov 9 14:22:17 2001
@@ -11,6 +11,7 @@
X *
X * Copyright (c) 1998-2000 Dag Brattli <da...@cs.uit.no>,

X * All Rights Reserved.

+ * Copyright (c) 2000-2001 Jean Tourrilhes <j...@hpl.hp.com>
X *

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

X * modify it under the terms of the GNU General Public License as
@@ -75,7 +76,7 @@
X */
X int __init irlmp_init(void)
X {
- IRDA_DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(1, __FUNCTION__ "()\n");
X /* Initialize the irlmp structure. */
X irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
X if (irlmp == NULL)
@@ -170,14 +171,14 @@
X #endif /* CONFIG_IRDA_ULTRA */
X } else
X self->dlsap_sel = LSAP_ANY;
- self->connected = FALSE;
+ /* self->connected = FALSE; -> already NULL via memset() */
X
X init_timer(&self->watchdog_timer);
X
X ASSERT(notify->instance != NULL, return NULL;);
X self->notify = *notify;
X
- irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
+ self->lsap_state = LSAP_DISCONNECTED;
X
X /* Insert into queue of unconnected LSAPs */
X hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self, (int) self,
@@ -237,6 +238,7 @@
X ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
X lsap = hashbin_remove(lap->lsaps, (int) self, NULL);
X }
+ self->lap = NULL;
X /* Check if we found the LSAP! If not then try the unconnected lsaps */
X if (!lsap) {
X lsap = hashbin_remove(irlmp->unconnected_lsaps, (int) self,
@@ -281,7 +283,7 @@
X lap->daddr = DEV_ADDR_ANY;
X lap->lsaps = hashbin_new(HB_GLOBAL);
X
- irlmp_next_lap_state(lap, LAP_STANDBY);
+ lap->lap_state = LAP_STANDBY;
X
X init_timer(&lap->idle_timer);
X
@@ -346,7 +348,7 @@
X "(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n",
X self->slsap_sel, dlsap_sel, saddr, daddr);
X
- if (self->connected)
+ if (test_bit(0, &self->connected))
X return -EISCONN;
X
X /* Client must supply destination device address */


@@ -435,7 +437,7 @@
X

X hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (int) self, NULL);
X
- self->connected = TRUE;
+ set_bit(0, &self->connected); /* TRUE */
X
X /*
X * User supplied qos specifications?
@@ -481,6 +483,8 @@
X self->notify.connect_indication(self->notify.instance, self,
X &self->qos, max_seg_size,
X max_header_size, skb);
+ else
+ dev_kfree_skb(skb);
X }
X
X /*
@@ -495,7 +499,7 @@
X ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
X ASSERT(userdata != NULL, return -1;);
X
- self->connected = TRUE;
+ set_bit(0, &self->connected); /* TRUE */
X
X IRDA_DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n",
X self->slsap_sel, self->dlsap_sel);
@@ -543,7 +547,8 @@
X self->notify.connect_confirm(self->notify.instance, self,
X &self->qos, max_seg_size,
X max_header_size, skb);
- }
+ } else
+ dev_kfree_skb(skb);
X }
X
X /*
@@ -598,16 +603,18 @@
X
X ASSERT(self != NULL, return -1;);
X ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ ASSERT(userdata != NULL, return -1;);
X
- /* Already disconnected? */
- if (!self->connected) {
- WARNING(__FUNCTION__ "(), already disconnected!\n");
+ /* Already disconnected ?
+ * There is a race condition between irlmp_disconnect_indication()
+ * and us that might mess up the hashbins below. This fixes it.
+ * Jean II */
+ if (! test_and_clear_bit(0, &self->connected)) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), already disconnected!\n");
+ dev_kfree_skb(userdata);
X return -1;
X }
X
- ASSERT(userdata != NULL, return -1;);
- ASSERT(self->connected == TRUE, return -1;);
-
X skb_push(userdata, LMP_CONTROL_HEADER);
X
X /*
@@ -634,7 +641,6 @@
X NULL);
X
X /* Reset some values */
- self->connected = FALSE;
X self->dlsap_sel = LSAP_ANY;
X self->lap = NULL;
X
@@ -651,16 +657,23 @@
X {
X struct lsap_cb *lsap;
X
- IRDA_DEBUG(1, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
+ IRDA_DEBUG(1, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
X ASSERT(self != NULL, return;);
X ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
- ASSERT(self->connected == TRUE, return;);
X
X IRDA_DEBUG(3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n",
X self->slsap_sel, self->dlsap_sel);
X
- self->connected = FALSE;
- self->dlsap_sel = LSAP_ANY;
+ /* Already disconnected ?
+ * There is a race condition between irlmp_disconnect_request()
+ * and us that might mess up the hashbins below. This fixes it.
+ * Jean II */
+ if (! test_and_clear_bit(0, &self->connected)) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), already disconnected!\n");
+ if (userdata)
+ dev_kfree_skb(userdata);
+ return;
+ }
X
X #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
X irlmp->cache.valid = FALSE;
@@ -679,6 +692,7 @@
X hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) lsap, (int) lsap,
X NULL);
X
+ self->dlsap_sel = LSAP_ANY;
X self->lap = NULL;
X
X /*
@@ -689,7 +703,8 @@
X self, reason, userdata);
X else {
X IRDA_DEBUG(0, __FUNCTION__ "(), no handler\n");
- dev_kfree_skb(userdata);
+ if (userdata)
+ dev_kfree_skb(userdata);
X }
X }
X
@@ -1401,7 +1416,7 @@
X irlmp_client_t *client;
X __u32 handle;
X
- IRDA_DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(1, __FUNCTION__ "()\n");
X ASSERT(irlmp != NULL, return 0;);
X
X /* Get a unique handle for this client */
@@ -1673,14 +1688,15 @@
X
X len += sprintf(buf+len, "saddr: %#08x, daddr: %#08x, ",
X lap->saddr, lap->daddr);
- len += sprintf(buf+len, "refcount: %d", lap->refcount);
+ len += sprintf(buf+len, "num lsaps: %d",
+ HASHBIN_GET_SIZE(lap->lsaps));
X len += sprintf(buf+len, "\n");
X
- len += sprintf(buf+len, "\nConnected LSAPs:\n");
+ len += sprintf(buf+len, "\n Connected LSAPs:\n");
X self = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
X while (self != NULL) {
X ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
- len += sprintf(buf+len, "lsap state: %s, ",
+ len += sprintf(buf+len, " lsap state: %s, ",
X irlsap_state[ self->lsap_state]);
X len += sprintf(buf+len,
X "slsap_sel: %#02x, dlsap_sel: %#02x, ",
diff -u --recursive --new-file v2.4.14/linux/net/irda/irlmp_event.c linux/net/irda/irlmp_event.c
--- v2.4.14/linux/net/irda/irlmp_event.c Sun Sep 23 11:41:02 2001
+++ linux/net/irda/irlmp_event.c Fri Nov 9 14:22:17 2001
@@ -11,6 +11,7 @@
X *
X * Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>,

X * All Rights Reserved.

+ * Copyright (c) 2000-2001 Jean Tourrilhes <j...@hpl.hp.com>
X *

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

X * modify it under the terms of the GNU General Public License as
@@ -114,6 +115,25 @@
X irlmp_state_setup_pend
X };
X
+static inline void irlmp_next_lap_state(struct lap_cb *self,
+ IRLMP_STATE state)
+{
+ /*
+ IRDA_DEBUG(4, __FUNCTION__ "(), LMP LAP = %s\n", irlmp_state[state]);
+ */
+ self->lap_state = state;
+}
+
+static inline void irlmp_next_lsap_state(struct lsap_cb *self,
+ LSAP_STATE state)
+{
+ /*
+ ASSERT(self != NULL, return;);
+ IRDA_DEBUG(4, __FUNCTION__ "(), LMP LSAP = %s\n", irlsap_state[state]);
+ */
+ self->lsap_state = state;
+}
+
X /* Do connection control events */
X int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event,
X struct sk_buff *skb)
@@ -223,7 +243,6 @@
X IRDA_DEBUG(4, __FUNCTION__ "() LS_CONNECT_REQUEST\n");
X
X irlmp_next_lap_state(self, LAP_U_CONNECT);
- self->refcount++;
X
X /* FIXME: need to set users requested QoS */
X irlap_connect_request(self->irlap, self->daddr, NULL, 0);
@@ -278,12 +297,12 @@
X * the lsaps may already have gone. This avoid getting stuck
X * forever in LAP_ACTIVE state - Jean II */
X if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
+ IRDA_DEBUG(0, __FUNCTION__ "() NO LSAPs !\n");
X irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
X }
X break;
X case LM_LAP_CONNECT_REQUEST:
X /* Already trying to connect */
- self->refcount++;
X break;
X case LM_LAP_CONNECT_CONFIRM:
X /* For all lsap_ce E Associated do LS_Connect_confirm */
@@ -298,12 +317,13 @@
X * the lsaps may already have gone. This avoid getting stuck
X * forever in LAP_ACTIVE state - Jean II */
X if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
+ IRDA_DEBUG(0, __FUNCTION__ "() NO LSAPs !\n");
X irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
X }
X break;
X case LM_LAP_DISCONNECT_INDICATION:
+ IRDA_DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_INDICATION\n");
X irlmp_next_lap_state(self, LAP_STANDBY);
- self->refcount = 0;
X
X /* Send disconnect event to all LSAPs using this link */
X lsap = (struct lsap_cb *) hashbin_get_first( self->lsaps);
@@ -322,9 +342,11 @@
X case LM_LAP_DISCONNECT_REQUEST:
X IRDA_DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
X
- self->refcount--;
- if (self->refcount == 0)
- irlmp_next_lap_state(self, LAP_STANDBY);
+ /* One of the LSAP did timeout or was closed, if it was
+ * the last one, try to get out of here - Jean II */
+ if (HASHBIN_GET_SIZE(self->lsaps) <= 1) {
+ irlap_disconnect_request(self->irlap);


+ }
X break;
X default:

X IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
@@ -352,7 +374,6 @@
X switch (event) {
X case LM_LAP_CONNECT_REQUEST:
X IRDA_DEBUG(4, __FUNCTION__ "(), LS_CONNECT_REQUEST\n");
- self->refcount++;
X
X /*
X * LAP connection allready active, just bounce back! Since we
@@ -379,8 +400,6 @@
X /* Keep state */
X break;
X case LM_LAP_DISCONNECT_REQUEST:
- self->refcount--;
-
X /*
X * Need to find out if we should close IrLAP or not. If there
X * is only one LSAP connection left on this link, that LSAP
@@ -419,7 +438,6 @@
X break;
X case LM_LAP_DISCONNECT_INDICATION:
X irlmp_next_lap_state(self, LAP_STANDBY);
- self->refcount = 0;
X
X /* In some case, at this point our side has already closed
X * all lsaps, and we are waiting for the idle_timer to
@@ -517,6 +535,8 @@
X * If we receive this event while our LAP is closing down,
X * the LM_LAP_CONNECT_REQUEST get lost and we get stuck in
X * CONNECT_PEND state forever.
+ * The other cause of getting stuck down there is if the
+ * higher layer never reply to the CONNECT_INDICATION.
X * Anyway, it make sense to make sure that we always have
X * a backup plan. 1 second is plenty (should be immediate).
X * Jean II */
@@ -577,9 +597,8 @@
X * Jean II */
X IRDA_DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
X
- /* Here, we should probably disconnect proper */
+ /* Disconnect, get out... - Jean II */
X self->dlsap_sel = LSAP_ANY;
- self->conn_skb = NULL;
X irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
X break;
X default:
@@ -612,15 +631,6 @@
X case LM_CONNECT_REQUEST:
X /* Keep state */
X break;
- case LM_CONNECT_INDICATION:
- /* Will happen in some rare cases when the socket get stuck,
- * the other side retries the connect request.
- * We just unstuck the socket - Jean II */
- IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_INDICATION, "
- "LSAP stuck in CONNECT_PEND state...\n");
- /* Keep state */
- irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
- break;
X case LM_CONNECT_RESPONSE:
X IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, "
X "no indication issued yet\n");
@@ -648,6 +658,8 @@
X
X /* Go back to disconnected mode, keep the socket waiting */
X self->dlsap_sel = LSAP_ANY;
+ if(self->conn_skb)
+ dev_kfree_skb(self->conn_skb);
X self->conn_skb = NULL;
X irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
X break;
@@ -856,7 +868,7 @@
X irlmp_next_lsap_state(self, LSAP_SETUP);
X break;
X case LM_WATCHDOG_TIMEOUT:
- IRDA_DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
+ IRDA_DEBUG(0, __FUNCTION__ "() : WATCHDOG_TIMEOUT !\n");
X
X ASSERT(self->lap != NULL, return -1;);
X irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
@@ -881,18 +893,4 @@
X break;
X }
X return ret;
-}
-
-void irlmp_next_lap_state(struct lap_cb *self, IRLMP_STATE state)
-{
- IRDA_DEBUG(4, __FUNCTION__ "(), LMP LAP = %s\n", irlmp_state[state]);
- self->lap_state = state;
-}
-
-void irlmp_next_lsap_state(struct lsap_cb *self, LSAP_STATE state)
-{
- ASSERT(self != NULL, return;);
-
- IRDA_DEBUG(4, __FUNCTION__ "(), LMP LSAP = %s\n", irlsap_state[state]);
- self->lsap_state = state;
X }
diff -u --recursive --new-file v2.4.14/linux/net/irda/irlmp_frame.c linux/net/irda/irlmp_frame.c
--- v2.4.14/linux/net/irda/irlmp_frame.c Sun Sep 23 11:41:02 2001
+++ linux/net/irda/irlmp_frame.c Fri Nov 9 14:22:17 2001
@@ -11,6 +11,7 @@
X *
X * Copyright (c) 1998-1999 Dag Brattli <da...@cs.uit.no>


X * All Rights Reserved.

+ * Copyright (c) 2000-2001 Jean Tourrilhes <j...@hpl.hp.com>
X *

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

X * modify it under the terms of the GNU General Public License as
@@ -34,9 +35,6 @@
X #include <net/irda/irlmp_frame.h>
X #include <net/irda/discovery.h>
X
-#define DISCO_SMALL_DELAY 250 /* Delay for some discoveries in ms */
-struct timer_list disco_delay; /* The timer associated */
-
X static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap,
X __u8 slsap, int status, hashbin_t *);
X
@@ -343,28 +341,6 @@
X }
X
X /*
- * Function irlmp_discovery_timeout (priv)
- *
- * Create a discovery event to the state machine (called after a delay)
- *
- * Note : irlmp_do_lap_event will handle the very rare case where the LAP
- * is destroyed while we were sleeping.
- */
-static void irlmp_discovery_timeout(u_long priv)
-{
- struct lap_cb *self;
-
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
-
- self = (struct lap_cb *) priv;
- ASSERT(self != NULL, return;);
-
- /* Just handle it the same way as a discovery confirm,
- * bypass the LM_LAP state machine (see below) */
- irlmp_discovery_confirm(irlmp->cachelog);
-}
-
-/*
X * Function irlmp_link_discovery_indication (self, log)
X *
X * Device is discovering us
@@ -379,25 +355,16 @@
X * o Make faster discovery, statistically divide time of discovery
X * events by 2 (important for the latency aspect and user feel)
X * o Even is we do active discovery, the other node might not
- * answer our discoveries (ex: Palm).
+ * answer our discoveries (ex: Palm). The Palm will just perform
+ * one active discovery and connect directly to us.
X *
X * However, when both devices discover each other, they might attempt to
X * connect to each other following the discovery event, and it would create
X * collisions on the medium (SNRM battle).
- * The trick here is to defer the event by a little delay to avoid both
- * devices to jump in exactly at the same time...
- *
- * The delay is currently set to 0.25s, which leave enough time to perform
- * a connection and don't interfer with next discovery (the lowest discovery
- * period/timeout that may be set is 1s). The message triggering this
- * event was the last of the discovery, so the medium is now free...
- * Maybe more testing is needed to get the value right...
-
- * One more problem : the other node might do only a single discovery
- * and connect immediately to us, and we would receive only a single
- * discovery indication event, and because of the delay, it will arrive
- * while the LAP is connected. That's another good reason to
- * bypass the LM_LAP state machine ;-)
+ * The "fix" for that is to disable all connection requests in IrLAP
+ * for 100ms after a discovery indication by setting the media_busy flag.
+ * Previously, we used to postpone the event which was quite ugly. Now
+ * that IrLAP takes care of this problem, just pass the event up...
X *
X * Jean II
X */
@@ -409,14 +376,9 @@
X
X irlmp_add_discovery(irlmp->cachelog, discovery);
X
- /* If delay was activated, kill it! */
- if(timer_pending(&disco_delay))
- del_timer(&disco_delay);
- /* Set delay timer to expire in 0.25s. */
- disco_delay.expires = jiffies + (DISCO_SMALL_DELAY * HZ/1000);
- disco_delay.function = irlmp_discovery_timeout;
- disco_delay.data = (unsigned long) self;
- add_timer(&disco_delay);
+ /* Just handle it the same way as a discovery confirm,
+ * bypass the LM_LAP state machine (see below) */
+ irlmp_discovery_confirm(irlmp->cachelog);
X }
X
X /*
@@ -435,10 +397,6 @@
X ASSERT(self->magic == LMP_LAP_MAGIC, return;);
X
X irlmp_add_discovery_log(irlmp->cachelog, log);
-
- /* If discovery delay was activated, kill it! */
- if(timer_pending(&disco_delay))
- del_timer(&disco_delay);
X
X /* Propagate event to various LSAPs registered for it.
X * We bypass the LM_LAP state machine because
diff -u --recursive --new-file v2.4.14/linux/net/irda/irnet/irnet.h linux/net/irda/irnet/irnet.h
--- v2.4.14/linux/net/irda/irnet/irnet.h Sun Sep 23 11:41:02 2001
+++ linux/net/irda/irnet/irnet.h Fri Nov 9 14:22:17 2001
@@ -126,17 +126,17 @@
X * History :
X * -------
X *
- * v1 - 15/5/00 - Jean II
+ * v1 - 15.5.00 - Jean II
X * o Basic IrNET (hook to ppp_generic & IrTTP - incl. multipoint)
X * o control channel on /dev/irnet (set name/address)
X * o event channel on /dev/irnet (for user space daemon)
X *
- * v2 - 5/6/00 - Jean II
+ * v2 - 5.6.00 - Jean II
X * o Enable DROP_NOT_READY to avoid PPP timeouts & other weirdness...
X * o Add DISCONNECT_TO event and rename DISCONNECT_FROM.
X * o Set official device number alloaction on /dev/irnet
X *
- * v3 - 30/8/00 - Jean II
+ * v3 - 30.8.00 - Jean II
X * o Update to latest Linux-IrDA changes :
X * - queue_t => irda_queue_t
X * o Update to ppp-2.4.0 :
@@ -148,17 +148,17 @@
X * another multilink bug (darn !)
X * o Remove LINKNAME_IOCTL cruft
X *
- * v3b - 31/8/00 - Jean II
+ * v3b - 31.8.00 - Jean II
X * o Dump discovery log at event channel startup
X *
- * v4 - 28/9/00 - Jean II
+ * v4 - 28.9.00 - Jean II
X * o Fix interaction between poll/select and dump discovery log
X * o Add IRNET_BLOCKED_LINK event (depend on new IrDA-Linux patch)
X * o Add IRNET_NOANSWER_FROM event (mostly to help support)
X * o Release flow control in disconnect_indication
X * o Block packets while connecting (speed up connections)
X *
- * v5 - 11/01/01 - Jean II
+ * v5 - 11.01.01 - Jean II
X * o Init self->max_header_size, just in case...
X * o Set up ap->chan.hdrlen, to get zero copy on tx side working.
X * o avoid tx->ttp->flow->ppp->tx->... loop, by checking flow state
@@ -169,7 +169,7 @@
X * o Declare hashbin HB_NOLOCK instead of HB_LOCAL to avoid
X * disabling and enabling irq twice
X *
- * v6 - 31/05/01 - Jean II
+ * v6 - 31.05.01 - Jean II
X * o Print source address in Found, Discovery, Expiry & Request events
X * o Print requested source address in /proc/net/irnet
X * o Change control channel input. Allow multiple commands in one line.
@@ -186,12 +186,19 @@
X * o Add ttp_connect flag to prevent rentry on the connect procedure
X * o Test and fixups to eliminate side effects of retries
X *
- * v7 - 22/08/01 - Jean II
+ * v7 - 22.08.01 - Jean II
X * o Cleanup : Change "saddr = 0x0" to "saddr = DEV_ADDR_ANY"
X * o Fix bug in BLOCK_WHEN_CONNECT introduced in v6 : due to the
X * asynchronous IAS query, self->tsap is NULL when PPP send the
X * first packet. This was preventing "connect-delay 0" to work.
X * Change the test in ppp_irnet_send() to self->ttp_connect.
+ *
+ * v8 - 1.11.01 - Jean II
+ * o Tighten the use of self->ttp_connect and self->ttp_open to
+ * prevent various race conditions.
+ * o Avoid leaking discovery log and skb
+ * o Replace "self" with "server" in irnet_connect_indication() to
+ * better detect cut'n'paste error ;-)
X */
X
X /***************************** INCLUDES *****************************/
@@ -204,6 +211,7 @@
X #include <linux/proc_fs.h>
X #include <linux/devfs_fs_kernel.h>
X #include <linux/netdevice.h>
+#include <linux/miscdevice.h>
X #include <linux/poll.h>
X #include <linux/config.h>
X #include <linux/ctype.h> /* isspace() */
diff -u --recursive --new-file v2.4.14/linux/net/irda/irnet/irnet_irda.c linux/net/irda/irnet/irnet_irda.c
--- v2.4.14/linux/net/irda/irnet/irnet_irda.c Tue Oct 9 17:06:53 2001
+++ linux/net/irda/irnet/irnet_irda.c Fri Nov 9 14:22:17 2001
@@ -272,7 +272,7 @@
X err = irnet_open_tsap(self);
X if(err != 0)
X {
- self->ttp_connect = 0;
+ clear_bit(0, &self->ttp_connect);
X DERROR(IRDA_SR_ERROR, "connect aborted!\n");
X return(err);


X }
@@ -283,7 +283,7 @@

X self->max_sdu_size_rx, NULL);
X if(err != 0)
X {
- self->ttp_connect = 0;
+ clear_bit(0, &self->ttp_connect);
X DERROR(IRDA_SR_ERROR, "connect aborted!\n");
X return(err);
X }
@@ -377,7 +377,7 @@
X if(self->discoveries == NULL)
X {
X self->disco_number = -1;
- self->ttp_connect = 0;
+ clear_bit(0, &self->ttp_connect);
X DRETURN(-ENETUNREACH, IRDA_SR_INFO, "No Cachelog...\n");
X }
X DEBUG(IRDA_SR_INFO, "Got the log (0x%X), size is %d\n",
@@ -399,7 +399,7 @@
X kfree(self->discoveries);
X self->discoveries = NULL;
X
- self->ttp_connect = 0;
+ clear_bit(0, &self->ttp_connect);
X DRETURN(-ENETUNREACH, IRDA_SR_INFO, "Cachelog empty...\n");
X }
X
@@ -518,12 +518,12 @@
X
X DENTER(IRDA_SOCK_TRACE, "(self=0x%X)\n", (unsigned int) self);
X
- /* Check if we have opened a local TSAP :
- * If we have already opened a TSAP, it means that either we are already
- * connected or in the process of doing so... */
- if(self->ttp_connect)
+ /* Check if we are already trying to connect.
+ * Because irda_irnet_connect() can be called directly by pppd plus
+ * packet retries in ppp_generic and connect may take time, plus we may
+ * race with irnet_connect_indication(), we need to be careful there... */
+ if(test_and_set_bit(0, &self->ttp_connect))
X DRETURN(-EBUSY, IRDA_SOCK_INFO, "Already connecting...\n");
- self->ttp_connect = 1;
X if((self->iriap != NULL) || (self->tsap != NULL))
X DERROR(IRDA_SOCK_ERROR, "Socket not cleaned up...\n");
X
@@ -579,6 +579,7 @@
X *
X * Destroy irnet instance
X *
+ * Note : this need to be called from a process context.
X */
X void
X irda_irnet_destroy(irnet_socket * self)
@@ -601,6 +602,23 @@
X DASSERT(entry == self, , IRDA_SOCK_ERROR, "Can't remove from hash.\n");
X }
X
+ /* If we were connected, post a message */
+ if(test_bit(0, &self->ttp_open))
+ {
+ /* Note : as the disconnect comes from ppp_generic, the unit number
+ * doesn't exist anymore when we post the event, so we need to pass
+ * NULL as the first arg... */
+ irnet_post_event(NULL, IRNET_DISCONNECT_TO,
+ self->saddr, self->daddr, self->rname);
+ }
+
+ /* Prevent various IrDA callbacks from messing up things
+ * Need to be first */
+ clear_bit(0, &self->ttp_connect);
+
+ /* Prevent higher layer from accessing IrTTP */
+ clear_bit(0, &self->ttp_open);
+
X /* Unregister with IrLMP */
X irlmp_unregister_client(self->ckey);
X
@@ -611,19 +629,14 @@
X self->iriap = NULL;
X }
X
- /* If we were connected, post a message */
- if(self->ttp_open)
+ /* Cleanup eventual discoveries from connection attempt */
+ if(self->discoveries != NULL)
X {
- /* Note : as the disconnect comes from ppp_generic, the unit number
- * doesn't exist anymore when we post the event, so we need to pass
- * NULL as the first arg... */
- irnet_post_event(NULL, IRNET_DISCONNECT_TO,
- self->saddr, self->daddr, self->rname);
+ /* Cleanup our copy of the discovery log */
+ kfree(self->discoveries);
+ self->discoveries = NULL;
X }
X
- /* Prevent higher layer from accessing IrTTP */
- self->ttp_open = 0;
-
X /* Close our IrTTP connection */
X if(self->tsap)
X {
@@ -761,7 +774,7 @@
X while(new !=(irnet_socket *) NULL)
X {
X /* Is it available ? */
- if(!(new->ttp_open) && (new->rdaddr == DEV_ADDR_ANY) &&
+ if(!(test_bit(0, &new->ttp_open)) && (new->rdaddr == DEV_ADDR_ANY) &&
X (new->rname[0] == '\0') && (new->ppp_open))
X {
X /* Yes !!! Get it.. */
@@ -788,17 +801,17 @@
X *
X */
X static inline int
-irnet_connect_socket(irnet_socket * self,
+irnet_connect_socket(irnet_socket * server,
X irnet_socket * new,
X struct qos_info * qos,
X __u32 max_sdu_size,
X __u8 max_header_size)
X {
- DENTER(IRDA_SERV_TRACE, "(self=0x%X, new=0x%X)\n",
- (unsigned int) self, (unsigned int) new);
+ DENTER(IRDA_SERV_TRACE, "(server=0x%X, new=0x%X)\n",
+ (unsigned int) server, (unsigned int) new);
X
X /* Now attach up the new socket */
- new->tsap = irttp_dup(self->tsap, new);
+ new->tsap = irttp_dup(server->tsap, new);
X DABORT(new->tsap == NULL, -1, IRDA_SERV_ERROR, "dup failed!\n");
X
X /* Set up all the relevant parameters on the new socket */
@@ -817,17 +830,32 @@
X #endif /* STREAM_COMPAT */
X
X /* Clean up the original one to keep it in listen state */
- self->tsap->dtsap_sel = self->tsap->lsap->dlsap_sel = LSAP_ANY;
- self->tsap->lsap->lsap_state = LSAP_DISCONNECTED;
+ server->tsap->dtsap_sel = server->tsap->lsap->dlsap_sel = LSAP_ANY;
+ server->tsap->lsap->lsap_state = LSAP_DISCONNECTED;
X
X /* Send a connection response on the new socket */
X irttp_connect_response(new->tsap, new->max_sdu_size_rx, NULL);
X
X /* Allow PPP to send its junk over the new socket... */
- new->ttp_open = 1;
- new->ttp_connect = 0;
+ set_bit(0, &new->ttp_open);
+
+ /* Not connecting anymore, and clean up last possible remains
+ * of connection attempts on the socket */
+ clear_bit(0, &new->ttp_connect);
+ if(new->iriap)
+ {
+ iriap_close(new->iriap);
+ new->iriap = NULL;
+ }
+ if(new->discoveries != NULL)
+ {
+ kfree(new->discoveries);
+ new->discoveries = NULL;
+ }
+
X #ifdef CONNECT_INDIC_KICK
- /* As currently we don't packets in ppp_irnet_send(), this is not needed...
+ /* As currently we don't block packets in ppp_irnet_send() while passive,
+ * this is not really needed...
X * Also, not doing it give IrDA a chance to finish the setup properly
X * before beeing swamped with packets... */
X ppp_output_wakeup(&new->chan);
@@ -835,7 +863,7 @@
X
X /* Notify the control channel */
X irnet_post_event(new, IRNET_CONNECT_FROM,
- new->saddr, new->daddr, self->rname);
+ new->saddr, new->daddr, server->rname);
X
X DEXIT(IRDA_SERV_TRACE, "\n");
X return 0;
@@ -1053,12 +1081,33 @@
X struct sk_buff *skb)
X {
X irnet_socket * self = (irnet_socket *) instance;
+ int test = 0;
X
X DENTER(IRDA_TCB_TRACE, "(self=0x%X)\n", (unsigned int) self);
X DASSERT(self != NULL, , IRDA_CB_ERROR, "Self is NULL !!!\n");


X
+ /* Don't care about it, but let's not leak it */
+ if(skb)
+ dev_kfree_skb(skb);
+

+ /* Prevent higher layer from accessing IrTTP */
+ test = test_and_clear_bit(0, &self->ttp_open);
+ /* Not connecting anymore...
+ * (note : TSAP is open, so IAP callbacks are no longer pending...) */
+ test |= test_and_clear_bit(0, &self->ttp_connect);
+
+ /* If both self->ttp_open and self->ttp_connect are NULL, it mean that we
+ * have a race condition with irda_irnet_destroy() or
+ * irnet_connect_indication(), so don't mess up tsap...
+ */
+ if(!test)
+ {
+ DERROR(IRDA_CB_ERROR, "Race condition detected...\n");
+ return;
+ }
+
X /* If we were active, notify the control channel */
- if(self->ttp_open)
+ if(test_bit(0, &self->ttp_open))
X irnet_post_event(self, IRNET_DISCONNECT_FROM,
X self->saddr, self->daddr, self->rname);
X else
@@ -1067,15 +1116,10 @@
X irnet_post_event(self, IRNET_NOANSWER_FROM,
X self->saddr, self->daddr, self->rname);
X
- /* Prevent higher layer from accessing IrTTP */
- self->ttp_open = 0;
- self->ttp_connect = 0;
-
- /* Close our IrTTP connection */
+ /* Close our IrTTP connection, cleanup tsap */
X if((self->tsap) && (self != &irnet_server.s))
X {
X DEBUG(IRDA_CB_INFO, "Closing our TTP connection.\n");
- irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
X irttp_close_tsap(self->tsap);
X self->tsap = NULL;
X
@@ -1114,6 +1158,13 @@
X
X DENTER(IRDA_TCB_TRACE, "(self=0x%X)\n", (unsigned int) self);
X
+ /* Check if socket is closing down (via irda_irnet_destroy()) */
+ if(! test_bit(0, &self->ttp_connect))
+ {
+ DERROR(IRDA_CB_ERROR, "Socket no longer connecting. Ouch !\n");
+ return;
+ }
+
X /* How much header space do we need to reserve */
X self->max_header_size = max_header_size;
X
@@ -1129,8 +1180,8 @@
X self->saddr = irttp_get_saddr(self->tsap);
X
X /* Allow higher layer to access IrTTP */
- self->ttp_connect = 0;
- self->ttp_open = 1;
+ set_bit(0, &self->ttp_open);
+ clear_bit(0, &self->ttp_connect); /* Not racy, IrDA traffic is serial */
X /* Give a kick in the ass of ppp_generic so that he sends us some data */
X ppp_output_wakeup(&self->chan);
X
@@ -1251,56 +1302,76 @@
X __u8 max_header_size,
X struct sk_buff *skb)
X {
- irnet_socket * self = &irnet_server.s;
+ irnet_socket * server = &irnet_server.s;
X irnet_socket * new = (irnet_socket *) NULL;
X
- DENTER(IRDA_TCB_TRACE, "(self=0x%X)\n", (unsigned int) self);
+ DENTER(IRDA_TCB_TRACE, "(server=0x%X)\n", (unsigned int) server);
X DASSERT(instance == &irnet_server, , IRDA_CB_ERROR,
X "Invalid instance (0x%X) !!!\n", (unsigned int) instance);
X DASSERT(sap == irnet_server.s.tsap, , IRDA_CB_ERROR, "Invalid sap !!!\n");
X
X /* Try to find the most appropriate IrNET socket */
- new = irnet_find_socket(self);
+ new = irnet_find_socket(server);
X
X /* After all this hard work, do we have an socket ? */
X if(new == (irnet_socket *) NULL)
X {
X DEXIT(IRDA_CB_INFO, ": No socket waiting for this connection.\n");
- irnet_disconnect_server(self, skb);
+ irnet_disconnect_server(server, skb);
X return;
X }
X
X /* Is the socket already busy ? */
- if(new->ttp_open)
+ if(test_bit(0, &new->ttp_open))
X {
X DEXIT(IRDA_CB_INFO, ": Socket already connected.\n");
- irnet_disconnect_server(self, skb);
+ irnet_disconnect_server(server, skb);
X return;
X }
X
- /* Socket connecting */
- if(new->tsap != NULL)
- {
- /* The socket has sent a IrTTP connection request and is waiting for
- * a connection response (that may never come).
- * Now, the pain is that the socket has open a tsap and is waiting on it,
- * while the other end is trying to connect to it on another tsap.
- * Argh ! We will deal with that later...
+ /* Socket connecting ?
+ * Clear up flag : prevent irnet_disconnect_indication() to mess up tsap */
+ if(test_and_clear_bit(0, &new->ttp_connect))
+ {
+ /* The socket is trying to connect to the other end and may have sent
+ * a IrTTP connection request and is waiting for a connection response
+ * (that may never come).
+ * Now, the pain is that the socket may have opened a tsap and is
+ * waiting on it, while the other end is trying to connect to it on
+ * another tsap.
X */
X DERROR(IRDA_CB_ERROR, "Socket already connecting. Ouch !\n");
X #ifdef ALLOW_SIMULT_CONNECT
- /* Close the connection the new socket was attempting.
- * WARNING : This need more testing ! */
- irttp_close_tsap(new->tsap);
+ /* Cleanup the TSAP if necessary - IrIAP will be cleaned up later */
+ if(new->tsap != NULL)
+ {
+ /* Close the connection the new socket was attempting.
+ * This seems to be safe... */
+ irttp_close_tsap(new->tsap);
+ new->tsap = NULL;
+ }
X /* Note : no return, fall through... */
X #else /* ALLOW_SIMULT_CONNECT */
- irnet_disconnect_server(self, skb);
+ irnet_disconnect_server(server, skb);
X return;
X #endif /* ALLOW_SIMULT_CONNECT */
X }
+ else
+ /* If socket is not connecting or connected, tsap should be NULL */
+ if(new->tsap != NULL)
+ {
+ /* If we are here, we are also in irnet_disconnect_indication(),
+ * and it's a nice race condition... On the other hand, we can't be
+ * in irda_irnet_destroy() otherwise we would not have found the
+ * socket in the hashbin. */
+ /* Better get out of here, otherwise we will mess up tsaps ! */
+ DERROR(IRDA_CB_ERROR, "Race condition detected, abort connect...\n");
+ irnet_disconnect_server(server, skb);
+ return;
+ }
X
X /* So : at this point, we have a socket, and it is idle. Good ! */
- irnet_connect_socket(self, new, qos, max_sdu_size, max_header_size);
+ irnet_connect_socket(server, new, qos, max_sdu_size, max_header_size);
X
X /* Check size of received packet */
X if(skb->len > 0)
@@ -1349,24 +1420,25 @@
X DENTER(IRDA_OCB_TRACE, "(self=0x%X)\n", (unsigned int) self);
X DASSERT(self != NULL, , IRDA_OCB_ERROR, "Self is NULL !!!\n");
X
- /* We probably don't need to make any more queries */
- iriap_close(self->iriap);
- self->iriap = NULL;
-
- /* Check if already connected (via irnet_connect_socket()) */
- if(self->ttp_open)
+ /* Check if already connected (via irnet_connect_socket())
+ * or socket is closing down (via irda_irnet_destroy()) */
+ if(! test_bit(0, &self->ttp_connect))
X {
- DERROR(IRDA_OCB_ERROR, "Socket already connected. Ouch !\n");
+ DERROR(IRDA_OCB_ERROR, "Socket no longer connecting. Ouch !\n");
X return;
X }
X
+ /* We probably don't need to make any more queries */
+ iriap_close(self->iriap);
+ self->iriap = NULL;
+
X /* Post process the IAS reply */
X self->dtsap_sel = irnet_ias_to_tsap(self, result, value);
X
X /* If error, just go out */
X if(self->errno)
X {
- self->ttp_connect = 0;
+ clear_bit(0, &self->ttp_connect);
X DERROR(IRDA_OCB_ERROR, "IAS connect failed ! (0x%X)\n", self->errno);
X return;
X }
@@ -1412,6 +1484,14 @@
X DENTER(IRDA_OCB_TRACE, "(self=0x%X)\n", (unsigned int) self);
X DASSERT(self != NULL, , IRDA_OCB_ERROR, "Self is NULL !!!\n");
X
+ /* Check if already connected (via irnet_connect_socket())
+ * or socket is closing down (via irda_irnet_destroy()) */
+ if(! test_bit(0, &self->ttp_connect))
+ {
+ DERROR(IRDA_OCB_ERROR, "Socket no longer connecting. Ouch !\n");
+ return;
+ }
+
X /* Post process the IAS reply */
X dtsap_sel = irnet_ias_to_tsap(self, result, value);
X
@@ -1468,15 +1548,8 @@
X if(self->daddr == DEV_ADDR_ANY)
X {
X self->daddr = DEV_ADDR_ANY;
- self->ttp_connect = 0;
+ clear_bit(0, &self->ttp_connect);
X DEXIT(IRDA_OCB_TRACE, ": cannot discover IrNET in any device !!!\n");
- return;
- }
-
- /* Check if already connected (via irnet_connect_socket()) */
- if(self->ttp_open)
- {
- DERROR(IRDA_OCB_ERROR, "Socket already connected. Ouch !\n");
X return;
X }
X
diff -u --recursive --new-file v2.4.14/linux/net/irda/irnet/irnet_ppp.c linux/net/irda/irnet/irnet_ppp.c
--- v2.4.14/linux/net/irda/irnet/irnet_ppp.c Tue Oct 9 17:06:53 2001
+++ linux/net/irda/irnet/irnet_ppp.c Fri Nov 9 14:22:17 2001
@@ -850,7 +850,7 @@
X DASSERT(self != NULL, 0, PPP_ERROR, "Self is NULL !!!\n");
X
X /* Check if we are connected */
- if(self->ttp_open == 0)
+ if(!(test_bit(0, &self->ttp_open)))
X {
X #ifdef CONNECT_IN_SEND
X /* Let's try to connect one more time... */
@@ -884,7 +884,7 @@
X */
X #ifdef BLOCK_WHEN_CONNECT
X /* If we are attempting to connect */
- if(self->ttp_connect)
+ if(test_bit(0, &self->ttp_connect))
X {
X /* Blocking packet, ppp_generic will retry later */
X return 0;
diff -u --recursive --new-file v2.4.14/linux/net/irda/irsyms.c linux/net/irda/irsyms.c
--- v2.4.14/linux/net/irda/irsyms.c Wed Jul 25 17:10:27 2001
+++ linux/net/irda/irsyms.c Fri Nov 9 14:22:17 2001
@@ -10,6 +10,7 @@
X * Modified by: Dag Brattli <da...@cs.uit.no>
X *
X * Copyright (c) 1997, 1999-2000 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 2000-2001 Jean Tourrilhes <j...@hpl.hp.com>
X *

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

X * modify it under the terms of the GNU General Public License as
@@ -79,7 +80,6 @@
X EXPORT_SYMBOL(irda_debug);
X #endif
X EXPORT_SYMBOL(irda_notify_init);
-EXPORT_SYMBOL(irda_lock);
X #ifdef CONFIG_PROC_FS
X EXPORT_SYMBOL(proc_irda);
X #endif
@@ -217,21 +217,6 @@
X
X /* Remove middle layer */
X irlmp_cleanup();
-}
-
-/*
- * Function irda_unlock (lock)
- *
- * Unlock variable. Returns false if lock is already unlocked
- *
- */
-inline int irda_unlock(int *lock)
-{
- if (!test_and_clear_bit(0, (void *) lock)) {
- printk("Trying to unlock already unlocked variable!\n");
- return FALSE;
- }
- return TRUE;
X }
X
X /*
diff -u --recursive --new-file v2.4.14/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.4.14/linux/net/irda/irttp.c Wed Jul 25 17:10:27 2001
+++ linux/net/irda/irttp.c Fri Nov 9 14:22:17 2001
@@ -11,6 +11,7 @@
X *
X * Copyright (c) 1998-2000 Dag Brattli <da...@cs.uit.no>,

X * All Rights Reserved.

+ * Copyright (c) 2000-2001 Jean Tourrilhes <j...@hpl.hp.com>
X *

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

X * modify it under the terms of the GNU General Public License as
@@ -223,6 +224,11 @@
X
X del_timer(&self->todo_timer);
X
+ /* This one won't be cleaned up if we are diconnect_pend + close_pend
+ * and we receive a disconnect_indication */
+ if (self->disconnect_skb)
+ dev_kfree_skb(self->disconnect_skb);
+
X self->connected = FALSE;
X self->magic = ~TTP_TSAP_MAGIC;
X
@@ -235,6 +241,9 @@
X * Remove TSAP from list of all TSAPs and then deallocate all resources
X * associated with this TSAP
X *
+ * Note : because we *free* the tsap structure, it is the responsability
+ * of the caller to make sure we are called only once and to deal with
+ * possible race conditions. - Jean II
X */
X int irttp_close_tsap(struct tsap_cb *self)
X {
@@ -248,8 +257,8 @@
X /* Make sure tsap has been disconnected */
X if (self->connected) {
X /* Check if disconnect is not pending */
- if (!self->disconnect_pend) {
- IRDA_DEBUG(0, __FUNCTION__ "(), TSAP still connected!\n");
+ if (!test_bit(0, &self->disconnect_pend)) {
+ WARNING(__FUNCTION__ "(), TSAP still connected!\n");
X irttp_disconnect_request(self, NULL, P_NORMAL);
X }
X self->close_pend = TRUE;
@@ -407,6 +416,7 @@
X unsigned long flags;
X int n;
X
+ /* Get exclusive access to the tx queue, otherwise don't touch it */
X if (irda_lock(&self->tx_queue_lock) == FALSE)
X return;
X
@@ -473,27 +483,17 @@
X * close the socket, we are dead !
X * Jean II */
X if (skb->sk != NULL) {
- struct sk_buff *tx_skb;
-
X /* IrSOCK application, IrOBEX, ... */
X IRDA_DEBUG(4, __FUNCTION__ "() : Detaching SKB from socket.\n");
- /* Note : still looking for a more efficient way
- * to do that - Jean II */
X
- /* Get another skb on the same buffer, but without
- * a reference to the socket (skb->sk = NULL) */
- tx_skb = skb_clone(skb, GFP_ATOMIC);
- if (tx_skb != NULL) {
- /* Release the skb associated with the
- * socket, and use the new skb insted */
- kfree_skb(skb);
- skb = tx_skb;
- }
+ /* That's the right way to do it - Jean II */
+ skb_orphan(skb);
X } else {
X /* IrCOMM over IrTTP, IrLAN, ... */
X IRDA_DEBUG(4, __FUNCTION__ "() : Got SKB not attached to a socket.\n");
X }
X
+ /* Pass the skb to IrLMP - done */
X irlmp_data_request(self->lsap, skb);
X self->stats.tx_packets++;
X
@@ -1105,18 +1105,23 @@
X /* Already disconnected? */
X if (!self->connected) {
X IRDA_DEBUG(4, __FUNCTION__ "(), already disconnected!\n");
+ if (userdata)
+ dev_kfree_skb(userdata);
X return -1;
X }
X
- /* Disconnect already pending? */
- if (self->disconnect_pend) {
- IRDA_DEBUG(1, __FUNCTION__ "(), disconnect already pending\n");
- if (userdata) {
+ /* Disconnect already pending ?
+ * We need to use an atomic operation to prevent reentry. This
+ * function may be called from various context, like user, timer
+ * for following a disconnect_indication() (i.e. net_bh).
+ * Jean II */
+ if(test_and_set_bit(0, &self->disconnect_pend)) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), disconnect already pending\n");


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

echo 'End of part 114'
echo 'File patch-2.4.15 is continued in part 115'
echo "115" > _shar_seq_.tmp
exit 0

Thomas Kobienia

unread,
Nov 24, 2001, 4:00:16 AM11/24/01
to
Archive-name: v2.4/patch-2.4.15/part100

#!/bin/sh -x
# this is part 100 of a 115 - part archive


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

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

+ int n = atomic_read(&nr_journal_heads);
+ if (n)
+ printk(KERN_EMERG "JBD: leaked %d journal_heads!\n", n);
+#endif
+ remove_jbd_proc_entry();
+ journal_destroy_caches();


+}
+
+MODULE_LICENSE("GPL");

+module_init(journal_init);
+module_exit(journal_exit);
+
diff -u --recursive --new-file v2.4.14/linux/fs/jbd/recovery.c linux/fs/jbd/recovery.c
--- v2.4.14/linux/fs/jbd/recovery.c Wed Dec 31 16:00:00 1969
+++ linux/fs/jbd/recovery.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,586 @@
+/*
+ * linux/fs/recovery.c
+ *
+ * Written by Stephen C. Tweedie <s...@redhat.com>, 1999
+ *
+ * Copyright 1999-2000 Red Hat Software --- All Rights Reserved


+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *

+ * Journal recovery routines for the generic filesystem journaling code;


+ * part of the ext2fs journaling system.
+ */
+

+#ifndef __KERNEL__
+#include "jfs_user.h"
+#else


+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/jbd.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/locks.h>

+#endif
+
+/*
+ * Maintain information about the progress of the recovery job, so that
+ * the different passes can carry information between them.
+ */
+struct recovery_info
+{
+ tid_t start_transaction;
+ tid_t end_transaction;
+
+ int nr_replays;
+ int nr_revokes;
+ int nr_revoke_hits;
+};
+
+enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
+static int do_one_pass(journal_t *journal,
+ struct recovery_info *info, enum passtype pass);
+static int scan_revoke_records(journal_t *, struct buffer_head *,
+ tid_t, struct recovery_info *);
+
+#ifdef __KERNEL__
+
+/* Release readahead buffers after use */
+void journal_brelse_array(struct buffer_head *b[], int n)
+{
+ while (--n >= 0)
+ brelse (b[n]);
+}
+
+
+/*
+ * When reading from the journal, we are going through the block device
+ * layer directly and so there is no readahead being done for us. We
+ * need to implement any readahead ourselves if we want it to happen at
+ * all. Recovery is basically one long sequential read, so make sure we
+ * do the IO in reasonably large chunks.
+ *
+ * This is not so critical that we need to be enormously clever about
+ * the readahead size, though. 128K is a purely arbitrary, good-enough
+ * fixed value.
+ */
+
+#define MAXBUF 8
+static int do_readahead(journal_t *journal, unsigned int start)
+{
+ int err;
+ unsigned int max, nbufs, next, blocknr;


+ struct buffer_head *bh;
+

+ struct buffer_head * bufs[MAXBUF];
+
+ /* Do up to 128K of readahead */
+ max = start + (128 * 1024 / journal->j_blocksize);
+ if (max > journal->j_maxlen)
+ max = journal->j_maxlen;
+
+ /* Do the readahead itself. We'll submit MAXBUF buffer_heads at
+ * a time to the block device IO layer. */
+
+ nbufs = 0;
+
+ for (next = start; next < max; next++) {
+ blocknr = journal_bmap(journal, next);
+
+ if (!blocknr) {
+ printk (KERN_ERR "JBD: bad block at offset %u\n",
+ next);
+ err = -EIO;
+ goto failed;
+ }


+
+ bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);

+ if (!bh) {
+ err = -ENOMEM;
+ goto failed;
+ }
+
+ if (!buffer_uptodate(bh) && !buffer_locked(bh)) {
+ bufs[nbufs++] = bh;
+ if (nbufs == MAXBUF) {
+ ll_rw_block(READ, nbufs, bufs);
+ journal_brelse_array(bufs, nbufs);
+ nbufs = 0;
+ }
+ } else
+ brelse(bh);
+ }
+
+ if (nbufs)
+ ll_rw_block(READ, nbufs, bufs);
+ err = 0;
+
+failed:
+ if (nbufs)
+ journal_brelse_array(bufs, nbufs);


+ return err;
+}
+

+#endif /* __KERNEL__ */
+
+
+/*
+ * Read a block from the journal
+ */
+
+static int jread(struct buffer_head **bhp, journal_t *journal,
+ unsigned int offset)
+{
+ unsigned int blocknr;


+ struct buffer_head *bh;
+

+ *bhp = NULL;
+
+ J_ASSERT (offset < journal->j_maxlen);
+
+ blocknr = journal_bmap(journal, offset);
+
+ if (!blocknr) {
+ printk (KERN_ERR "JBD: bad block at offset %u\n",
+ offset);


+ return -EIO;
+ }
+

+ bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);

+ if (!bh)
+ return -ENOMEM;
+
+ if (!buffer_uptodate(bh)) {
+ /* If this is a brand new buffer, start readahead.
+ Otherwise, we assume we are already reading it. */
+ if (!buffer_req(bh))
+ do_readahead(journal, offset);
+ wait_on_buffer(bh);
+ }
+
+ if (!buffer_uptodate(bh)) {
+ printk (KERN_ERR "JBD: Failed to read block at offset %u\n",
+ offset);
+ brelse(bh);


+ return -EIO;
+ }
+

+ *bhp = bh;


+ return 0;
+}
+
+
+/*

+ * Count the number of in-use tags in a journal descriptor block.
+ */
+
+static int count_tags(struct buffer_head *bh, int size)
+{
+ char * tagp;
+ journal_block_tag_t * tag;


+ int nr = 0;

+
+ tagp = &bh->b_data[sizeof(journal_header_t)];
+

+ while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {


+ tag = (journal_block_tag_t *) tagp;
+

+ nr++;
+ tagp += sizeof(journal_block_tag_t);
+ if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))


+ tagp += 16;
+

+ if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
+ break;
+ }
+
+ return nr;
+}
+
+
+/* Make sure we wrap around the log correctly! */
+#define wrap(journal, var) \
+do { \
+ if (var >= (journal)->j_last) \
+ var -= ((journal)->j_last - (journal)->j_first); \
+} while (0)
+
+/*
+ * journal_recover
+ *
+ * The primary function for recovering the log contents when mounting a
+ * journaled device.
+ *
+ * Recovery is done in three passes. In the first pass, we look for the
+ * end of the log. In the second, we assemble the list of revoke
+ * blocks. In the third and final pass, we replay any un-revoked blocks
+ * in the log.
+ */
+
+int journal_recover(journal_t *journal)


+{
+ int err;
+ journal_superblock_t * sb;
+

+ struct recovery_info info;


+
+ memset(&info, 0, sizeof(info));

+ sb = journal->j_superblock;
+
+ /*

+ * The journal superblock's s_start field (the current log head)
+ * is always zero if, and only if, the journal was cleanly
+ * unmounted.
+ */
+
+ if (!sb->s_start) {
+ jbd_debug(1, "No recovery required, last transaction %d\n",
+ ntohl(sb->s_sequence));
+ journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;


+ return 0;
+ }
+
+

+ err = do_one_pass(journal, &info, PASS_SCAN);
+ if (!err)
+ err = do_one_pass(journal, &info, PASS_REVOKE);
+ if (!err)
+ err = do_one_pass(journal, &info, PASS_REPLAY);
+
+ jbd_debug(0, "JBD: recovery, exit status %d, "
+ "recovered transactions %u to %u\n",
+ err, info.start_transaction, info.end_transaction);
+ jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n",
+ info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
+
+ /* Restart the log at the next transaction ID, thus invalidating
+ * any existing commit records in the log. */
+ journal->j_transaction_sequence = ++info.end_transaction;
+
+ journal_clear_revoke(journal);
+ fsync_no_super(journal->j_fs_dev);


+ return err;
+}
+
+/*

+ * journal_skip_recovery
+ *
+ * Locate any valid recovery information from the journal and set up the
+ * journal structures in memory to ignore it (presumably because the
+ * caller has evidence that it is out of date).
+ *
+ * We perform one pass over the journal to allow us to tell the user how
+ * much recovery information is being erased, and to let us initialise
+ * the journal transaction sequence numbers to the next unused ID.
+ */
+
+int journal_skip_recovery(journal_t *journal)


+{
+ int err;
+ journal_superblock_t * sb;
+

+ struct recovery_info info;
+
+ memset (&info, 0, sizeof(info));


+ sb = journal->j_superblock;
+

+ err = do_one_pass(journal, &info, PASS_SCAN);
+
+ if (err) {
+ printk(KERN_ERR "JBD: error %d scanning journal\n", err);
+ ++journal->j_transaction_sequence;
+ } else {
+#ifdef CONFIG_JBD_DEBUG
+ int dropped = info.end_transaction - ntohl(sb->s_sequence);
+#endif
+
+ jbd_debug(0,
+ "JBD: ignoring %d transaction%s from the journal.\n",
+ dropped, (dropped == 1) ? "" : "s");
+ journal->j_transaction_sequence = ++info.end_transaction;
+ }
+


+ journal->j_tail = 0;
+

+ return err;
+}
+

+static int do_one_pass(journal_t *journal,
+ struct recovery_info *info, enum passtype pass)
+{
+
+ unsigned int first_commit_ID, next_commit_ID;
+ unsigned long next_log_block;
+ int err, success = 0;
+ journal_superblock_t * sb;
+ journal_header_t * tmp;


+ struct buffer_head * bh;

+ unsigned int sequence;
+ int blocktype;
+
+ /* Precompute the maximum metadata descriptors in a descriptor block */
+ int MAX_BLOCKS_PER_DESC;
+ MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
+ / sizeof(journal_block_tag_t));
+
+ /*
+ * First thing is to establish what we expect to find in the log
+ * (in terms of transaction IDs), and where (in terms of log
+ * block offsets): query the superblock.
+ */


+
+ sb = journal->j_superblock;

+ next_commit_ID = ntohl(sb->s_sequence);
+ next_log_block = ntohl(sb->s_start);
+
+ first_commit_ID = next_commit_ID;
+ if (pass == PASS_SCAN)
+ info->start_transaction = first_commit_ID;
+
+ jbd_debug(1, "Starting recovery pass %d\n", pass);
+
+ /*
+ * Now we walk through the log, transaction by transaction,
+ * making sure that each transaction has a commit block in the
+ * expected place. Each complete transaction gets replayed back
+ * into the main filesystem.
+ */
+
+ while (1) {
+ int flags;
+ char * tagp;
+ journal_block_tag_t * tag;
+ struct buffer_head * obh;
+ struct buffer_head * nbh;
+
+ /* If we already know where to stop the log traversal,
+ * check right now that we haven't gone past the end of
+ * the log. */
+
+ if (pass != PASS_SCAN)
+ if (tid_geq(next_commit_ID, info->end_transaction))
+ break;
+
+ jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
+ next_commit_ID, next_log_block, journal->j_last);
+
+ /* Skip over each chunk of the transaction looking
+ * either the next descriptor block or the final commit
+ * record. */
+
+ jbd_debug(3, "JBD: checking block %ld\n", next_log_block);
+ err = jread(&bh, journal, next_log_block);
+ if (err)
+ goto failed;
+
+ next_log_block++;
+ wrap(journal, next_log_block);
+
+ /* What kind of buffer is it?
+ *
+ * If it is a descriptor block, check that it has the
+ * expected sequence number. Otherwise, we're all done
+ * here. */
+
+ tmp = (journal_header_t *)bh->b_data;
+
+ if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
+ brelse(bh);
+ break;
+ }
+
+ blocktype = ntohl(tmp->h_blocktype);
+ sequence = ntohl(tmp->h_sequence);
+ jbd_debug(3, "Found magic %d, sequence %d\n",
+ blocktype, sequence);
+
+ if (sequence != next_commit_ID) {


+ brelse(bh);
+ break;
+ }

+
+ /* OK, we have a valid descriptor block which matches
+ * all of the sequence number checks. What are we going
+ * to do with it? That depends on the pass... */
+
+ switch(blocktype) {
+ case JFS_DESCRIPTOR_BLOCK:
+ /* If it is a valid descriptor block, replay it
+ * in pass REPLAY; otherwise, just skip over the
+ * blocks it describes. */
+ if (pass != PASS_REPLAY) {
+ next_log_block +=
+ count_tags(bh, journal->j_blocksize);
+ wrap(journal, next_log_block);
+ brelse(bh);
+ continue;
+ }
+
+ /* A descriptor block: we can now write all of
+ * the data blocks. Yay, useful work is finally
+ * getting done here! */


+
+ tagp = &bh->b_data[sizeof(journal_header_t)];

+ while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
+ <= journal->j_blocksize) {
+ unsigned long io_block;
+
+ tag = (journal_block_tag_t *) tagp;
+ flags = ntohl(tag->t_flags);
+
+ io_block = next_log_block++;
+ wrap(journal, next_log_block);
+ err = jread(&obh, journal, io_block);
+ if (err) {
+ /* Recover what we can, but
+ * report failure at the end. */
+ success = err;
+ printk (KERN_ERR
+ "JBD: IO error %d recovering "
+ "block %ld in log\n",
+ err, io_block);
+ } else {


+ unsigned long blocknr;
+

+ J_ASSERT(obh != NULL);
+ blocknr = ntohl(tag->t_blocknr);
+
+ /* If the block has been
+ * revoked, then we're all done
+ * here. */
+ if (journal_test_revoke
+ (journal, blocknr,
+ next_commit_ID)) {
+ brelse(obh);
+ ++info->nr_revoke_hits;
+ goto skip_write;
+ }
+
+ /* Find a buffer for the new
+ * data being restored */
+ nbh = getblk(journal->j_fs_dev, blocknr,
+ journal->j_blocksize);
+ if (nbh == NULL) {
+ printk(KERN_ERR
+ "JBD: Out of memory "
+ "during recovery.\n");
+ err = -ENOMEM;
+ brelse(bh);
+ brelse(obh);
+ goto failed;
+ }
+
+ memcpy(nbh->b_data, obh->b_data,
+ journal->j_blocksize);
+ if (flags & JFS_FLAG_ESCAPE) {
+ *((unsigned int *)bh->b_data) =
+ htonl(JFS_MAGIC_NUMBER);
+ }
+
+ BUFFER_TRACE(nbh, "marking dirty");
+ mark_buffer_dirty(nbh);
+ BUFFER_TRACE(nbh, "marking uptodate");
+ mark_buffer_uptodate(nbh, 1);
+ ++info->nr_replays;
+ /* ll_rw_block(WRITE, 1, &nbh); */
+ brelse(obh);
+ brelse(nbh);
+ }
+
+ skip_write:
+ tagp += sizeof(journal_block_tag_t);
+ if (!(flags & JFS_FLAG_SAME_UUID))


+ tagp += 16;
+

+ if (flags & JFS_FLAG_LAST_TAG)
+ break;
+ }
+
+ brelse(bh);
+ continue;
+
+ case JFS_COMMIT_BLOCK:
+ /* Found an expected commit block: not much to
+ * do other than move on to the next sequence
+ * number. */
+ brelse(bh);
+ next_commit_ID++;
+ continue;
+
+ case JFS_REVOKE_BLOCK:
+ /* If we aren't in the REVOKE pass, then we can
+ * just skip over this block. */
+ if (pass != PASS_REVOKE) {
+ brelse(bh);
+ continue;
+ }
+
+ err = scan_revoke_records(journal, bh,
+ next_commit_ID, info);
+ brelse(bh);
+ if (err)
+ goto failed;
+ continue;
+
+ default:
+ jbd_debug(3, "Unrecognised magic %d, end of scan.\n",
+ blocktype);
+ goto done;
+ }
+ }
+
+ done:
+ /*
+ * We broke out of the log scan loop: either we came to the
+ * known end of the log or we found an unexpected block in the
+ * log. If the latter happened, then we know that the "current"
+ * transaction marks the end of the valid log.
+ */
+
+ if (pass == PASS_SCAN)
+ info->end_transaction = next_commit_ID;
+ else {
+ /* It's really bad news if different passes end up at
+ * different places (but possible due to IO errors). */
+ if (info->end_transaction != next_commit_ID) {
+ printk (KERN_ERR "JBD: recovery pass %d ended at "
+ "transaction %u, expected %u\n",
+ pass, next_commit_ID, info->end_transaction);
+ if (!success)
+ success = -EIO;
+ }
+ }
+
+ return success;
+
+ failed:


+ return err;
+}
+

+
+/* Scan a revoke record, marking all blocks mentioned as revoked. */
+
+static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
+ tid_t sequence, struct recovery_info *info)
+{
+ journal_revoke_header_t *header;
+ int offset, max;
+
+ header = (journal_revoke_header_t *) bh->b_data;
+ offset = sizeof(journal_revoke_header_t);
+ max = ntohl(header->r_count);
+
+ while (offset < max) {
+ unsigned long blocknr;
+ int err;
+
+ blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
+ offset += 4;
+ err = journal_set_revoke(journal, blocknr, sequence);


+ if (err)
+ return err;

+ ++info->nr_revokes;


+ }
+ return 0;
+}

diff -u --recursive --new-file v2.4.14/linux/fs/jbd/revoke.c linux/fs/jbd/revoke.c
--- v2.4.14/linux/fs/jbd/revoke.c Wed Dec 31 16:00:00 1969
+++ linux/fs/jbd/revoke.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,631 @@
+/*
+ * linux/fs/revoke.c
+ *
+ * Written by Stephen C. Tweedie <s...@redhat.com>, 2000
+ *
+ * Copyright 2000 Red Hat corp --- All Rights Reserved


+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *

+ * Journal revoke routines for the generic filesystem journaling code;
+ * part of the ext2fs journaling system.
+ *
+ * Revoke is the mechanism used to prevent old log records for deleted
+ * metadata from being replayed on top of newer data using the same
+ * blocks. The revoke mechanism is used in two separate places:
+ *
+ * + Commit: during commit we write the entire list of the current
+ * transaction's revoked blocks to the journal
+ *
+ * + Recovery: during recovery we record the transaction ID of all
+ * revoked blocks. If there are multiple revoke records in the log
+ * for a single block, only the last one counts, and if there is a log
+ * entry for a block beyond the last revoke, then that log entry still
+ * gets replayed.
+ *
+ * We can get interactions between revokes and new log data within a
+ * single transaction:
+ *
+ * Block is revoked and then journaled:
+ * The desired end result is the journaling of the new block, so we
+ * cancel the revoke before the transaction commits.
+ *
+ * Block is journaled and then revoked:
+ * The revoke must take precedence over the write of the block, so we
+ * need either to cancel the journal entry or to write the revoke
+ * later in the log than the log block. In this case, we choose the
+ * latter: journaling a block cancels any revoke record for that block
+ * in the current transaction, so any revoke for that block in the
+ * transaction must have happened after the block was journaled and so
+ * the revoke must take precedence.
+ *
+ * Block is revoked and then written as data:
+ * The data write is allowed to succeed, but the revoke is _not_
+ * cancelled. We still need to prevent old log records from
+ * overwriting the new data. We don't even need to clear the revoke
+ * bit here.
+ *
+ * Revoke information on buffers is a tri-state value:
+ *
+ * RevokeValid clear: no cached revoke status, need to look it up
+ * RevokeValid set, Revoked clear:
+ * buffer has not been revoked, and cancel_revoke
+ * need do nothing.
+ * RevokeValid set, Revoked set:
+ * buffer has been revoked.
+ */
+
+#ifndef __KERNEL__
+#include "jfs_user.h"
+#else


+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/jbd.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/locks.h>

+#include <linux/list.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#endif
+
+static kmem_cache_t *revoke_record_cache;
+static kmem_cache_t *revoke_table_cache;
+
+/* Each revoke record represents one single revoked block. During
+ journal replay, this involves recording the transaction ID of the
+ last transaction to revoke this block. */
+
+struct jbd_revoke_record_s
+{
+ struct list_head hash;
+ tid_t sequence; /* Used for recovery only */


+ unsigned long blocknr;
+};
+

+
+/* The revoke table is just a simple hash table of revoke records. */
+struct jbd_revoke_table_s
+{
+ /* It is conceivable that we might want a larger hash table
+ * for recovery. Must be a power of two. */
+ int hash_size;
+ int hash_shift;
+ struct list_head *hash_table;
+};
+
+
+#ifdef __KERNEL__
+static void write_one_revoke_record(journal_t *, transaction_t *,
+ struct journal_head **, int *,
+ struct jbd_revoke_record_s *);
+static void flush_descriptor(journal_t *, struct journal_head *, int);
+#endif
+
+/* Utility functions to maintain the revoke table */
+
+/* Borrowed from buffer.c: this is a tried and tested block hash function */
+static inline int hash(journal_t *journal, unsigned long block)
+{
+ struct jbd_revoke_table_s *table = journal->j_revoke;
+ int hash_shift = table->hash_shift;
+
+ return ((block << (hash_shift - 6)) ^
+ (block >> 13) ^
+ (block << (hash_shift - 12))) & (table->hash_size - 1);
+}
+
+int insert_revoke_hash(journal_t *journal, unsigned long blocknr, tid_t seq)
+{
+ struct list_head *hash_list;
+ struct jbd_revoke_record_s *record;
+
+repeat:
+ record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
+ if (!record)
+ goto oom;
+
+ record->sequence = seq;
+ record->blocknr = blocknr;
+ hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
+ list_add(&record->hash, hash_list);
+ return 0;
+
+oom:
+ if (!journal_oom_retry)
+ return -ENOMEM;
+ jbd_debug(1, "ENOMEM in " __FUNCTION__ ", retrying.\n");


+ current->policy |= SCHED_YIELD;
+ schedule();

+ goto repeat;
+}
+
+/* Find a revoke record in the journal's hash table. */
+
+static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
+ unsigned long blocknr)
+{
+ struct list_head *hash_list;
+ struct jbd_revoke_record_s *record;
+
+ hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
+
+ record = (struct jbd_revoke_record_s *) hash_list->next;
+ while (&(record->hash) != hash_list) {
+ if (record->blocknr == blocknr)
+ return record;
+ record = (struct jbd_revoke_record_s *) record->hash.next;
+ }


+ return NULL;
+}
+

+int __init journal_init_revoke_caches(void)
+{
+ revoke_record_cache = kmem_cache_create("revoke_record",
+ sizeof(struct jbd_revoke_record_s),
+ 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (revoke_record_cache == 0)
+ return -ENOMEM;
+
+ revoke_table_cache = kmem_cache_create("revoke_table",
+ sizeof(struct jbd_revoke_table_s),
+ 0, 0, NULL, NULL);
+ if (revoke_table_cache == 0) {
+ kmem_cache_destroy(revoke_record_cache);
+ revoke_record_cache = NULL;
+ return -ENOMEM;


+ }
+ return 0;
+}
+

+void journal_destroy_revoke_caches(void)
+{
+ kmem_cache_destroy(revoke_record_cache);
+ revoke_record_cache = 0;
+ kmem_cache_destroy(revoke_table_cache);
+ revoke_table_cache = 0;
+}
+
+/* Initialise the revoke table for a given journal to a given size. */
+
+int journal_init_revoke(journal_t *journal, int hash_size)
+{
+ int shift, tmp;
+
+ J_ASSERT (journal->j_revoke == NULL);
+
+ journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
+ if (!journal->j_revoke)
+ return -ENOMEM;
+
+ /* Check that the hash_size is a power of two */
+ J_ASSERT ((hash_size & (hash_size-1)) == 0);
+
+ journal->j_revoke->hash_size = hash_size;
+
+ shift = 0;
+ tmp = hash_size;
+ while((tmp >>= 1UL) != 0UL)
+ shift++;
+ journal->j_revoke->hash_shift = shift;
+
+ journal->j_revoke->hash_table =
+ kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
+ if (!journal->j_revoke->hash_table) {
+ kmem_cache_free(revoke_table_cache, journal->j_revoke);
+ journal->j_revoke = NULL;


+ return -ENOMEM;
+ }
+

+ for (tmp = 0; tmp < hash_size; tmp++)
+ INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);


+
+ return 0;
+}
+

+/* Destoy a journal's revoke table. The table must already be empty! */
+
+void journal_destroy_revoke(journal_t *journal)
+{
+ struct jbd_revoke_table_s *table;
+ struct list_head *hash_list;
+ int i;
+
+ table = journal->j_revoke;
+ if (!table)
+ return;
+
+ for (i=0; i<table->hash_size; i++) {
+ hash_list = &table->hash_table[i];
+ J_ASSERT (list_empty(hash_list));
+ }
+
+ kfree(table->hash_table);
+ kmem_cache_free(revoke_table_cache, table);
+ journal->j_revoke = NULL;
+}
+
+
+#ifdef __KERNEL__
+
+/*
+ * journal_revoke: revoke a given buffer_head from the journal. This
+ * prevents the block from being replayed during recovery if we take a
+ * crash after this current transaction commits. Any subsequent
+ * metadata writes of the buffer in this transaction cancel the
+ * revoke.
+ *
+ * Note that this call may block --- it is up to the caller to make
+ * sure that there are no further calls to journal_write_metadata
+ * before the revoke is complete. In ext3, this implies calling the
+ * revoke before clearing the block bitmap when we are deleting
+ * metadata.
+ *
+ * Revoke performs a journal_forget on any buffer_head passed in as a
+ * parameter, but does _not_ forget the buffer_head if the bh was only
+ * found implicitly.
+ *
+ * bh_in may not be a journalled buffer - it may have come off
+ * the hash tables without an attached journal_head.
+ *
+ * If bh_in is non-zero, journal_revoke() will decrement its b_count
+ * by one.
+ */
+
+int journal_revoke(handle_t *handle, unsigned long blocknr,
+ struct buffer_head *bh_in)
+{
+ struct buffer_head *bh = NULL;
+ journal_t *journal;
+ kdev_t dev;
+ int err;
+
+ if (bh_in)
+ BUFFER_TRACE(bh_in, "enter");
+
+ journal = handle->h_transaction->t_journal;
+ if (!journal_set_features(journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)){
+ J_ASSERT (!"Cannot set revoke feature!");


+ return -EINVAL;
+ }
+

+ dev = journal->j_fs_dev;
+ bh = bh_in;
+
+ if (!bh) {
+ bh = get_hash_table(dev, blocknr, journal->j_blocksize);
+ if (bh)
+ BUFFER_TRACE(bh, "found on hash");
+ }
+#ifdef JBD_EXPENSIVE_CHECKING
+ else {
+ struct buffer_head *bh2;
+
+ /* If there is a different buffer_head lying around in
+ * memory anywhere... */
+ bh2 = get_hash_table(dev, blocknr, journal->j_blocksize);
+ if (bh2) {
+ /* ... and it has RevokeValid status... */
+ if ((bh2 != bh) &&
+ test_bit(BH_RevokeValid, &bh2->b_state))
+ /* ...then it better be revoked too,
+ * since it's illegal to create a revoke
+ * record against a buffer_head which is
+ * not marked revoked --- that would
+ * risk missing a subsequent revoke
+ * cancel. */
+ J_ASSERT_BH(bh2, test_bit(BH_Revoked, &
+ bh2->b_state));
+ __brelse(bh2);
+ }
+ }
+#endif
+
+ /* We really ought not ever to revoke twice in a row without
+ first having the revoke cancelled: it's illegal to free a
+ block twice without allocating it in between! */
+ if (bh) {
+ J_ASSERT_BH(bh, !test_bit(BH_Revoked, &bh->b_state));
+ set_bit(BH_Revoked, &bh->b_state);
+ set_bit(BH_RevokeValid, &bh->b_state);
+ if (bh_in) {
+ BUFFER_TRACE(bh_in, "call journal_forget");
+ journal_forget(handle, bh_in);
+ } else {
+ BUFFER_TRACE(bh, "call brelse");


+ __brelse(bh);
+ }
+ }
+

+ lock_journal(journal);
+ jbd_debug(2, "insert revoke for block %lu, bh_in=%p\n", blocknr, bh_in);
+ err = insert_revoke_hash(journal, blocknr,
+ handle->h_transaction->t_tid);
+ unlock_journal(journal);
+ BUFFER_TRACE(bh_in, "exit");


+ return err;
+}
+
+/*

+ * Cancel an outstanding revoke. For use only internally by the
+ * journaling code (called from journal_get_write_access).
+ *
+ * We trust the BH_Revoked bit on the buffer if the buffer is already
+ * being journaled: if there is no revoke pending on the buffer, then we
+ * don't do anything here.
+ *
+ * This would break if it were possible for a buffer to be revoked and
+ * discarded, and then reallocated within the same transaction. In such
+ * a case we would have lost the revoked bit, but when we arrived here
+ * the second time we would still have a pending revoke to cancel. So,
+ * do not trust the Revoked bit on buffers unless RevokeValid is also
+ * set.
+ *
+ * The caller must have the journal locked.
+ */
+int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
+{
+ struct jbd_revoke_record_s *record;


+ journal_t *journal = handle->h_transaction->t_journal;

+ int need_cancel;
+ int did_revoke = 0; /* akpm: debug */


+ struct buffer_head *bh = jh2bh(jh);
+

+ jbd_debug(4, "journal_head %p, cancelling revoke\n", jh);
+
+ /* Is the existing Revoke bit valid? If so, we trust it, and
+ * only perform the full cancel if the revoke bit is set. If
+ * not, we can't trust the revoke bit, and we need to do the
+ * full search for a revoke record. */
+ if (test_and_set_bit(BH_RevokeValid, &bh->b_state))
+ need_cancel = (test_and_clear_bit(BH_Revoked, &bh->b_state));
+ else {
+ need_cancel = 1;
+ clear_bit(BH_Revoked, &bh->b_state);
+ }
+
+ if (need_cancel) {
+ record = find_revoke_record(journal, bh->b_blocknr);
+ if (record) {
+ jbd_debug(4, "cancelled existing revoke on "
+ "blocknr %lu\n", bh->b_blocknr);
+ list_del(&record->hash);
+ kmem_cache_free(revoke_record_cache, record);
+ did_revoke = 1;
+ }
+ }
+
+#ifdef JBD_EXPENSIVE_CHECKING
+ /* There better not be one left behind by now! */
+ record = find_revoke_record(journal, bh->b_blocknr);
+ J_ASSERT_JH(jh, record == NULL);
+#endif
+
+ /* Finally, have we just cleared revoke on an unhashed
+ * buffer_head? If so, we'd better make sure we clear the
+ * revoked status on any hashed alias too, otherwise the revoke
+ * state machine will get very upset later on. */
+ if (need_cancel && !bh->b_pprev) {
+ struct buffer_head *bh2;
+ bh2 = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size);
+ if (bh2) {
+ clear_bit(BH_Revoked, &bh2->b_state);
+ __brelse(bh2);
+ }
+ }
+
+ return did_revoke;
+}
+
+
+/*
+ * Write revoke records to the journal for all entries in the current
+ * revoke hash, deleting the entries as we go.
+ *
+ * Called with the journal lock held.
+ */
+
+void journal_write_revoke_records(journal_t *journal,
+ transaction_t *transaction)
+{
+ struct journal_head *descriptor;
+ struct jbd_revoke_record_s *record;
+ struct jbd_revoke_table_s *revoke;
+ struct list_head *hash_list;
+ int i, offset, count;
+
+ descriptor = NULL;
+ offset = 0;
+ count = 0;
+ revoke = journal->j_revoke;
+
+ for (i = 0; i < revoke->hash_size; i++) {
+ hash_list = &revoke->hash_table[i];
+
+ while (!list_empty(hash_list)) {
+ record = (struct jbd_revoke_record_s *)
+ hash_list->next;
+ write_one_revoke_record(journal, transaction,
+ &descriptor, &offset,
+ record);
+ count++;
+ list_del(&record->hash);
+ kmem_cache_free(revoke_record_cache, record);
+ }
+ }
+ if (descriptor)
+ flush_descriptor(journal, descriptor, offset);
+ jbd_debug(1, "Wrote %d revoke records\n", count);
+}
+
+/*
+ * Write out one revoke record. We need to create a new descriptor
+ * block if the old one is full or if we have not already created one.
+ */
+
+static void write_one_revoke_record(journal_t *journal,
+ transaction_t *transaction,
+ struct journal_head **descriptorp,
+ int *offsetp,
+ struct jbd_revoke_record_s *record)
+{
+ struct journal_head *descriptor;
+ int offset;
+ journal_header_t *header;
+
+ /* If we are already aborting, this all becomes a noop. We
+ still need to go round the loop in
+ journal_write_revoke_records in order to free all of the
+ revoke records: only the IO to the journal is omitted. */
+ if (is_journal_aborted(journal))
+ return;
+
+ descriptor = *descriptorp;
+ offset = *offsetp;
+
+ /* Make sure we have a descriptor with space left for the record */
+ if (descriptor) {
+ if (offset == journal->j_blocksize) {
+ flush_descriptor(journal, descriptor, offset);
+ descriptor = NULL;
+ }
+ }
+
+ if (!descriptor) {
+ descriptor = journal_get_descriptor_buffer(journal);
+ header = (journal_header_t *) &jh2bh(descriptor)->b_data[0];


+ header->h_magic = htonl(JFS_MAGIC_NUMBER);

+ header->h_blocktype = htonl(JFS_REVOKE_BLOCK);
+ header->h_sequence = htonl(transaction->t_tid);
+
+ /* Record it so that we can wait for IO completion later */
+ JBUFFER_TRACE(descriptor, "file as BJ_LogCtl");
+ journal_file_buffer(descriptor, transaction, BJ_LogCtl);
+
+ offset = sizeof(journal_revoke_header_t);
+ *descriptorp = descriptor;
+ }
+
+ * ((unsigned int *)(&jh2bh(descriptor)->b_data[offset])) =
+ htonl(record->blocknr);
+ offset += 4;
+ *offsetp = offset;
+}
+
+/*
+ * Flush a revoke descriptor out to the journal. If we are aborting,
+ * this is a noop; otherwise we are generating a buffer which needs to
+ * be waited for during commit, so it has to go onto the appropriate
+ * journal buffer list.
+ */
+
+static void flush_descriptor(journal_t *journal,
+ struct journal_head *descriptor,
+ int offset)
+{
+ journal_revoke_header_t *header;
+
+ if (is_journal_aborted(journal)) {
+ JBUFFER_TRACE(descriptor, "brelse");
+ __brelse(jh2bh(descriptor));
+ return;
+ }
+
+ header = (journal_revoke_header_t *) jh2bh(descriptor)->b_data;
+ header->r_count = htonl(offset);
+ set_bit(BH_JWrite, &jh2bh(descriptor)->b_state);


+ {
+ struct buffer_head *bh = jh2bh(descriptor);

+ BUFFER_TRACE(bh, "write");


+ ll_rw_block (WRITE, 1, &bh);
+ }

+}
+
+#endif
+
+/*
+ * Revoke support for recovery.
+ *
+ * Recovery needs to be able to:
+ *
+ * record all revoke records, including the tid of the latest instance
+ * of each revoke in the journal
+ *
+ * check whether a given block in a given transaction should be replayed
+ * (ie. has not been revoked by a revoke record in that or a subsequent
+ * transaction)
+ *
+ * empty the revoke table after recovery.
+ */
+
+/*
+ * First, setting revoke records. We create a new revoke record for
+ * every block ever revoked in the log as we scan it for recovery, and
+ * we update the existing records if we find multiple revokes for a
+ * single block.
+ */
+
+int journal_set_revoke(journal_t *journal,
+ unsigned long blocknr,
+ tid_t sequence)
+{
+ struct jbd_revoke_record_s *record;
+
+ record = find_revoke_record(journal, blocknr);
+ if (record) {
+ /* If we have multiple occurences, only record the
+ * latest sequence number in the hashed record */
+ if (tid_gt(sequence, record->sequence))
+ record->sequence = sequence;
+ return 0;
+ }
+ return insert_revoke_hash(journal, blocknr, sequence);
+}
+
+/*
+ * Test revoke records. For a given block referenced in the log, has
+ * that block been revoked? A revoke record with a given transaction
+ * sequence number revokes all blocks in that transaction and earlier
+ * ones, but later transactions still need replayed.
+ */
+
+int journal_test_revoke(journal_t *journal,
+ unsigned long blocknr,
+ tid_t sequence)
+{
+ struct jbd_revoke_record_s *record;
+
+ record = find_revoke_record(journal, blocknr);
+ if (!record)
+ return 0;
+ if (tid_gt(sequence, record->sequence))
+ return 0;


+ return 1;
+}
+

+/*
+ * Finally, once recovery is over, we need to clear the revoke table so
+ * that it can be reused by the running filesystem.
+ */
+
+void journal_clear_revoke(journal_t *journal)
+{
+ int i;
+ struct list_head *hash_list;
+ struct jbd_revoke_record_s *record;
+ struct jbd_revoke_table_s *revoke;
+
+ revoke = journal->j_revoke;
+
+ for (i = 0; i < revoke->hash_size; i++) {
+ hash_list = &revoke->hash_table[i];
+ while (!list_empty(hash_list)) {
+ record = (struct jbd_revoke_record_s*) hash_list->next;
+ list_del(&record->hash);
+ kmem_cache_free(revoke_record_cache, record);
+ }
+ }
+}
+
diff -u --recursive --new-file v2.4.14/linux/fs/jbd/transaction.c linux/fs/jbd/transaction.c
--- v2.4.14/linux/fs/jbd/transaction.c Wed Dec 31 16:00:00 1969
+++ linux/fs/jbd/transaction.c Fri Nov 9 14:25:04 2001
@@ -0,0 +1,2070 @@
+/*
+ * linux/fs/transaction.c


+ *
+ * Written by Stephen C. Tweedie <s...@redhat.com>, 1998
+ *
+ * Copyright 1998 Red Hat corp --- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *

+ * Generic filesystem transaction handling code; part of the ext2fs


+ * journaling system.
+ *

+ * This file manages transactions (compound commits managed by the
+ * journaling code) and handles (individual atomic operations by the
+ * filesystem).
+ */
+


+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/jbd.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/locks.h>

+#include <linux/timer.h>
+#include <linux/smp_lock.h>
+#include <linux/mm.h>


+
+extern spinlock_t journal_datalist_lock;
+
+/*

+ * get_transaction: obtain a new transaction_t object.
+ *
+ * Simply allocate and initialise a new transaction. Create it in
+ * RUNNING state and add it to the current journal (which should not
+ * have an existing running transaction: we only make a new transaction
+ * once we have started to commit the old one).
+ *
+ * Preconditions:
+ * The journal MUST be locked. We don't perform atomic mallocs on the
+ * new transaction and we can't block without protecting against other
+ * processes trying to touch the journal while it is in transition.
+ */
+
+static transaction_t * get_transaction (journal_t * journal, int is_try)
+{


+ transaction_t * transaction;
+

+ transaction = jbd_kmalloc (sizeof (transaction_t), GFP_NOFS);
+ if (!transaction)
+ return NULL;
+
+ memset (transaction, 0, sizeof (transaction_t));
+
+ transaction->t_journal = journal;
+ transaction->t_state = T_RUNNING;
+ transaction->t_tid = journal->j_transaction_sequence++;
+ transaction->t_expires = jiffies + journal->j_commit_interval;
+
+ /* Set up the commit timer for the new transaction. */
+ J_ASSERT (!journal->j_commit_timer_active);
+ journal->j_commit_timer_active = 1;
+ journal->j_commit_timer->expires = transaction->t_expires;
+ add_timer(journal->j_commit_timer);
+
+ J_ASSERT (journal->j_running_transaction == NULL);
+ journal->j_running_transaction = transaction;
+
+ return transaction;
+}
+
+/*
+ * Handle management.
+ *
+ * A handle_t is an object which represents a single atomic update to a
+ * filesystem, and which tracks all of the modifications which form part
+ * of that one update.
+ */
+
+/*
+ * start_this_handle: Given a handle, deal with any locking or stalling
+ * needed to make sure that there is enough journal space for the handle
+ * to begin. Attach the handle to a transaction and set up the
+ * transaction's buffer credits.
+ */
+
+static int start_this_handle(journal_t *journal, handle_t *handle)
+{
+ transaction_t *transaction;
+ int needed;
+ int nblocks = handle->h_buffer_credits;
+
+ jbd_debug(3, "New handle %p going live.\n", handle);
+
+repeat:
+
+ lock_journal(journal);
+
+ if (is_journal_aborted(journal) ||
+ (journal->j_errno != 0 && !(journal->j_flags & JFS_ACK_ERR))) {
+ unlock_journal(journal);


+ return -EROFS;
+ }
+

+ /* Wait on the journal's transaction barrier if necessary */
+ if (journal->j_barrier_count) {
+ unlock_journal(journal);
+ sleep_on(&journal->j_wait_transaction_locked);


+ goto repeat;
+ }
+

+repeat_locked:
+ if (!journal->j_running_transaction)
+ get_transaction(journal, 0);
+ /* @@@ Error? */
+ J_ASSERT(journal->j_running_transaction);
+

+ transaction = journal->j_running_transaction;
+

+ /* If the current transaction is locked down for commit, wait
+ * for the lock to be released. */
+
+ if (transaction->t_state == T_LOCKED) {
+ unlock_journal(journal);
+ jbd_debug(3, "Handle %p stalling...\n", handle);
+ sleep_on(&journal->j_wait_transaction_locked);
+ goto repeat;
+ }
+
+ /* If there is not enough space left in the log to write all
+ * potential buffers requested by this operation, we need to
+ * stall pending a log checkpoint to free some more log
+ * space. */
+
+ needed = transaction->t_outstanding_credits + nblocks;
+
+ if (needed > journal->j_max_transaction_buffers) {
+ /* If the current transaction is already too large, then
+ * start to commit it: we can then go back and attach
+ * this handle to a new transaction. */
+
+ jbd_debug(2, "Handle %p starting new commit...\n", handle);


+ log_start_commit(journal, transaction);
+ unlock_journal(journal);

+ sleep_on(&journal->j_wait_transaction_locked);
+ lock_journal(journal);
+ goto repeat_locked;
+ }
+
+ /*
+ * The commit code assumes that it can get enough log space
+ * without forcing a checkpoint. This is *critical* for
+ * correctness: a checkpoint of a buffer which is also
+ * associated with a committing transaction creates a deadlock,
+ * so commit simply cannot force through checkpoints.
+ *
+ * We must therefore ensure the necessary space in the journal
+ * *before* starting to dirty potentially checkpointed buffers
+ * in the new transaction.
+ *
+ * The worst part is, any transaction currently committing can
+ * reduce the free space arbitrarily. Be careful to account for
+ * those buffers when checkpointing.
+ */
+
+ /*
+ * @@@ AKPM: This seems rather over-defensive. We're giving commit
+ * a _lot_ of headroom: 1/4 of the journal plus the size of
+ * the committing transaction. Really, we only need to give it
+ * committing_transaction->t_outstanding_credits plus "enough" for
+ * the log control blocks.
+ * Also, this test is inconsitent with the matching one in
+ * journal_extend().
+ */
+ needed = journal->j_max_transaction_buffers;
+ if (journal->j_committing_transaction)
+ needed += journal->j_committing_transaction->
+ t_outstanding_credits;
+
+ if (log_space_left(journal) < needed) {
+ jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle);
+ log_wait_for_space(journal, needed);
+ goto repeat_locked;
+ }
+
+ /* OK, account for the buffers that this operation expects to
+ * use and add the handle to the running transaction. */
+
+ handle->h_transaction = transaction;
+ transaction->t_outstanding_credits += nblocks;
+ transaction->t_updates++;
+ transaction->t_handle_count++;
+ jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n",
+ handle, nblocks, transaction->t_outstanding_credits,
+ log_space_left(journal));
+
+ unlock_journal(journal);
+

+ return 0;
+}
+
+/*

+ * Obtain a new handle.
+ *
+ * We make sure that the transaction can guarantee at least nblocks of
+ * modified buffers in the log. We block until the log can guarantee
+ * that much space.
+ *
+ * This function is visible to journal users (like ext2fs), so is not
+ * called with the journal already locked.
+ *
+ * Return a pointer to a newly allocated handle, or NULL on failure
+ */
+
+handle_t *journal_start(journal_t *journal, int nblocks)
+{
+ handle_t *handle = journal_current_handle();
+ int err;
+
+ if (!journal)
+ return ERR_PTR(-EROFS);
+
+ if (handle) {
+ J_ASSERT(handle->h_transaction->t_journal == journal);
+ handle->h_ref++;
+ return handle;
+ }
+
+ handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
+ if (!handle)
+ return ERR_PTR(-ENOMEM);
+ memset (handle, 0, sizeof (handle_t));
+
+ handle->h_buffer_credits = nblocks;
+ handle->h_ref = 1;
+ current->journal_info = handle;
+
+ err = start_this_handle(journal, handle);
+ if (err < 0) {
+ kfree(handle);


+ current->journal_info = NULL;

+ return ERR_PTR(err);
+ }
+
+ return handle;
+}
+
+/*
+ * Return zero on success
+ */
+static int try_start_this_handle(journal_t *journal, handle_t *handle)
+{
+ transaction_t *transaction;
+ int needed;
+ int nblocks = handle->h_buffer_credits;


+ int ret = 0;
+

+ jbd_debug(3, "New handle %p maybe going live.\n", handle);
+
+ lock_journal(journal);
+
+ if (is_journal_aborted(journal) ||
+ (journal->j_errno != 0 && !(journal->j_flags & JFS_ACK_ERR))) {
+ ret = -EROFS;
+ goto fail_unlock;
+ }
+
+ if (journal->j_barrier_count)
+ goto fail_unlock;
+
+ if (!journal->j_running_transaction && get_transaction(journal, 1) == 0)
+ goto fail_unlock;
+

+ transaction = journal->j_running_transaction;

+ if (transaction->t_state == T_LOCKED)
+ goto fail_unlock;
+
+ needed = transaction->t_outstanding_credits + nblocks;
+ /* We could run log_start_commit here */
+ if (needed > journal->j_max_transaction_buffers)
+ goto fail_unlock;
+
+ needed = journal->j_max_transaction_buffers;
+ if (journal->j_committing_transaction)
+ needed += journal->j_committing_transaction->
+ t_outstanding_credits;
+
+ if (log_space_left(journal) < needed)
+ goto fail_unlock;
+
+ handle->h_transaction = transaction;
+ transaction->t_outstanding_credits += nblocks;
+ transaction->t_updates++;
+ jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n",
+ handle, nblocks, transaction->t_outstanding_credits,
+ log_space_left(journal));


+ unlock_journal(journal);
+ return 0;
+

+fail_unlock:
+ unlock_journal(journal);
+ if (ret >= 0)
+ ret = -1;


+ return ret;
+}
+
+/*

+ * Try to start a handle, but non-blockingly. If we weren't able
+ * to, return an ERR_PTR value.
+ */
+handle_t *journal_try_start(journal_t *journal, int nblocks)
+{
+ handle_t *handle = journal_current_handle();
+ int err;
+
+ if (!journal)
+ return ERR_PTR(-EROFS);
+
+ if (handle) {


+ jbd_debug(4, "h_ref %d -> %d\n",

+ handle->h_ref,
+ handle->h_ref + 1);
+ J_ASSERT(handle->h_transaction->t_journal == journal);
+ if (is_handle_aborted(handle))
+ return ERR_PTR(-EIO);
+ handle->h_ref++;
+ return handle;
+ } else {
+ jbd_debug(4, "no current transaction\n");
+ }
+
+ if (is_journal_aborted(journal))
+ return ERR_PTR(-EIO);
+
+ handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
+ if (!handle)
+ return ERR_PTR(-ENOMEM);
+ memset (handle, 0, sizeof (handle_t));
+
+ handle->h_buffer_credits = nblocks;
+ handle->h_ref = 1;
+ current->journal_info = handle;
+
+ err = try_start_this_handle(journal, handle);
+ if (err < 0) {
+ kfree(handle);


+ current->journal_info = NULL;

+ return ERR_PTR(err);
+ }
+
+ return handle;
+}
+
+/*
+ * journal_extend: extend buffer credits.
+ *
+ * Some transactions, such as large extends and truncates, can be done
+ * atomically all at once or in several stages. The operation requests
+ * a credit for a number of buffer modications in advance, but can
+ * extend its credit if it needs more.
+ *
+ * journal_extend tries to give the running handle more buffer credits.
+ * It does not guarantee that allocation: this is a best-effort only.
+ * The calling process MUST be able to deal cleanly with a failure to
+ * extend here.
+ *
+ * Return 0 on success, non-zero on failure.
+ *
+ * return code < 0 implies an error
+ * return code > 0 implies normal transaction-full status.
+ */
+
+int journal_extend (handle_t *handle, int nblocks)
+{


+ transaction_t *transaction = handle->h_transaction;
+ journal_t *journal = transaction->t_journal;

+ int result;
+ int wanted;
+
+ lock_journal (journal);
+
+ result = -EIO;
+ if (is_handle_aborted(handle))
+ goto error_out;
+
+ result = 1;
+
+ /* Don't extend a locked-down transaction! */
+ if (handle->h_transaction->t_state != T_RUNNING) {
+ jbd_debug(3, "denied handle %p %d blocks: "
+ "transaction not running\n", handle, nblocks);


+ goto error_out;
+ }
+

+ wanted = transaction->t_outstanding_credits + nblocks;
+
+ if (wanted > journal->j_max_transaction_buffers) {
+ jbd_debug(3, "denied handle %p %d blocks: "
+ "transaction too large\n", handle, nblocks);


+ goto error_out;
+ }
+

+ if (wanted > log_space_left(journal)) {
+ jbd_debug(3, "denied handle %p %d blocks: "
+ "insufficient log space\n", handle, nblocks);


+ goto error_out;
+ }
+

+ handle->h_buffer_credits += nblocks;
+ transaction->t_outstanding_credits += nblocks;
+ result = 0;
+
+ jbd_debug(3, "extended handle %p by %d\n", handle, nblocks);
+
+error_out:
+ unlock_journal (journal);
+ return result;
+}
+
+
+/*
+ * journal_restart: restart a handle for a multi-transaction filesystem
+ * operation.
+ *
+ * If the journal_extend() call above fails to grant new buffer credits
+ * to a running handle, a call to journal_restart will commit the
+ * handle's transaction so far and reattach the handle to a new
+ * transaction capabable of guaranteeing the requested number of
+ * credits.
+ */
+
+int journal_restart(handle_t *handle, int nblocks)
+{


+ transaction_t *transaction = handle->h_transaction;
+ journal_t *journal = transaction->t_journal;

+ int ret;
+
+ /* If we've had an abort of any type, don't even think about
+ * actually doing the restart! */
+ if (is_handle_aborted(handle))
+ return 0;
+
+ /* First unlink the handle from its current transaction, and
+ * start the commit on that. */


+
+ J_ASSERT (transaction->t_updates > 0);
+ J_ASSERT (journal_current_handle() == handle);
+

+ transaction->t_outstanding_credits -= handle->h_buffer_credits;
+ transaction->t_updates--;
+
+ if (!transaction->t_updates)
+ wake_up(&journal->j_wait_updates);
+

+ jbd_debug(2, "restarting handle %p\n", handle);
+ log_start_commit(journal, transaction);
+
+ handle->h_buffer_credits = nblocks;
+ ret = start_this_handle(journal, handle);


+ return ret;
+}
+
+

+/*
+ * Barrier operation: establish a transaction barrier.
+ *
+ * This locks out any further updates from being started, and blocks
+ * until all existing updates have completed, returning only once the
+ * journal is in a quiescent state with no updates running.
+ *
+ * The journal lock should not be held on entry.
+ */
+
+void journal_lock_updates (journal_t *journal)
+{
+ lock_journal(journal);
+ ++journal->j_barrier_count;
+
+ /* Wait until there are no running updates */
+ while (1) {
+ transaction_t *transaction = journal->j_running_transaction;
+ if (!transaction)
+ break;
+ if (!transaction->t_updates)
+ break;
+

+ unlock_journal(journal);
+ sleep_on(&journal->j_wait_updates);
+ lock_journal(journal);

+ }
+
+ unlock_journal(journal);
+

+ /* We have now established a barrier against other normal
+ * updates, but we also need to barrier against other
+ * journal_lock_updates() calls to make sure that we serialise
+ * special journal-locked operations too. */
+ down(&journal->j_barrier);
+}
+
+/*
+ * Release a transaction barrier obtained with journal_lock_updates().
+ *
+ * Should be called without the journal lock held.
+ */
+
+void journal_unlock_updates (journal_t *journal)
+{
+ lock_journal(journal);
+
+ J_ASSERT (journal->j_barrier_count != 0);
+
+ up(&journal->j_barrier);
+ --journal->j_barrier_count;
+ wake_up(&journal->j_wait_transaction_locked);
+ unlock_journal(journal);
+}
+
+/*
+ * journal_get_write_access: notify intent to modify a buffer for metadata
+ * (not data) update.
+ *
+ * If the buffer is already part of the current transaction, then there
+ * is nothing we need to do. If it is already part of a prior
+ * transaction which we are still committing to disk, then we need to
+ * make sure that we do not overwrite the old copy: we do copy-out to
+ * preserve the copy going to disk. We also account the buffer against
+ * the handle's metadata buffer credits (unless the buffer is already
+ * part of the transaction, that is).
+ *
+ * Returns an error code or 0 on success.
+ *
+ * In full data journalling mode the buffer may be of type BJ_AsyncData,
+ * because we're write()ing a buffer which is also part of a shared mapping.


+ */
+
+static int

+do_get_write_access(handle_t *handle, struct journal_head *jh, int force_copy)

+{
+ transaction_t *transaction = handle->h_transaction;
+ journal_t *journal = transaction->t_journal;

+ int error;
+ char *frozen_buffer = NULL;
+ int need_copy = 0;
+
+ jbd_debug(5, "buffer_head %p, force_copy %d\n", jh, force_copy);


+
+ JBUFFER_TRACE(jh, "entry");

+repeat:
+ /* @@@ Need to check for errors here at some point. */
+
+ /*
+ * AKPM: neither bdflush nor kupdate run with the BKL. There's
+ * nothing we can do to prevent them from starting writeout of a
+ * BUF_DIRTY buffer at any time. And checkpointing buffers are on
+ * BUF_DIRTY. So. We no longer assert that the buffer is unlocked.
+ *
+ * However. It is very wrong for us to allow ext3 to start directly
+ * altering the ->b_data of buffers which may at that very time be
+ * undergoing writeout to the client filesystem. This can leave
+ * the filesystem in an inconsistent, transient state if we crash.
+ * So what we do is to steal the buffer if it is in checkpoint
+ * mode and dirty. The journal lock will keep out checkpoint-mode
+ * state transitions within journal_remove_checkpoint() and the buffer
+ * is locked to keep bdflush/kupdate/whoever away from it as well.
+ *
+ * AKPM: we have replaced all the lock_journal_bh_wait() stuff with a
+ * simple lock_journal(). This code here will care for locked buffers.
+ */
+ /*
+ * The buffer_locked() || buffer_dirty() tests here are simply an
+ * optimisation tweak. If anyone else in the system decides to
+ * lock this buffer later on, we'll blow up. There doesn't seem
+ * to be a good reason why they should do this.
+ */
+ if (jh->b_cp_transaction &&
+ (buffer_locked(jh2bh(jh)) || buffer_dirty(jh2bh(jh)))) {
+ unlock_journal(journal);
+ lock_buffer(jh2bh(jh));
+ spin_lock(&journal_datalist_lock);
+ if (jh->b_cp_transaction && buffer_dirty(jh2bh(jh))) {
+ /* OK, we need to steal it */
+ JBUFFER_TRACE(jh, "stealing from checkpoint mode");


+ J_ASSERT_JH(jh, jh->b_next_transaction == NULL);

+ J_ASSERT_JH(jh, jh->b_frozen_data == NULL);
+
+ J_ASSERT(handle->h_buffer_credits > 0);
+ handle->h_buffer_credits--;
+
+ /* This will clear BH_Dirty and set BH_JBDDirty. */


+ JBUFFER_TRACE(jh, "file as BJ_Reserved");
+ __journal_file_buffer(jh, transaction, BJ_Reserved);
+

+ /* And pull it off BUF_DIRTY, onto BUF_CLEAN */
+ refile_buffer(jh2bh(jh));
+
+ /*
+ * The buffer is now hidden from bdflush. It is
+ * metadata against the current transaction.
+ */
+ JBUFFER_TRACE(jh, "steal from cp mode is complete");
+ }
+ spin_unlock(&journal_datalist_lock);
+ unlock_buffer(jh2bh(jh));
+ lock_journal(journal);
+ }
+
+ J_ASSERT_JH(jh, !buffer_locked(jh2bh(jh)));
+
+ error = -EROFS;
+ if (is_handle_aborted(handle))
+ goto out_unlocked;


+ error = 0;
+

+ spin_lock(&journal_datalist_lock);
+
+ /* The buffer is already part of this transaction if
+ * b_transaction or b_next_transaction points to it. */
+
+ if (jh->b_transaction == transaction ||
+ jh->b_next_transaction == transaction)
+ goto done_locked;
+
+ /* If there is already a copy-out version of this buffer, then
+ * we don't need to make another one. */
+
+ if (jh->b_frozen_data) {
+ JBUFFER_TRACE(jh, "has frozen data");


+ J_ASSERT_JH(jh, jh->b_next_transaction == NULL);

+ jh->b_next_transaction = transaction;
+

+ J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
+ handle->h_buffer_credits--;

+ goto done_locked;
+ }
+

+ /* Is there data here we need to preserve? */
+
+ if (jh->b_transaction && jh->b_transaction != transaction) {
+ JBUFFER_TRACE(jh, "owned by older transaction");


+ J_ASSERT_JH(jh, jh->b_next_transaction == NULL);

+ J_ASSERT_JH(jh, jh->b_transaction ==
+ journal->j_committing_transaction);
+

+ /* There is one case we have to be very careful about.
+ * If the committing transaction is currently writing
+ * this buffer out to disk and has NOT made a copy-out,
+ * then we cannot modify the buffer contents at all
+ * right now. The essence of copy-out is that it is the
+ * extra copy, not the primary copy, which gets
+ * journaled. If the primary copy is already going to
+ * disk then we cannot do copy-out here. */
+
+ if (jh->b_jlist == BJ_Shadow) {
+ JBUFFER_TRACE(jh, "on shadow: sleep");
+ spin_unlock(&journal_datalist_lock);
+ unlock_journal(journal);
+ /* commit wakes up all shadow buffers after IO */
+ sleep_on(&jh2bh(jh)->b_wait);
+ lock_journal(journal);
+ goto repeat;
+ }
+
+ /* Only do the copy if the currently-owning transaction
+ * still needs it. If it is on the Forget list, the
+ * committing transaction is past that stage. The
+ * buffer had better remain locked during the kmalloc,
+ * but that should be true --- we hold the journal lock
+ * still and the buffer is already on the BUF_JOURNAL
+ * list so won't be flushed.
+ *
+ * Subtle point, though: if this is a get_undo_access,
+ * then we will be relying on the frozen_data to contain
+ * the new value of the committed_data record after the
+ * transaction, so we HAVE to force the frozen_data copy
+ * in that case. */
+
+ if (jh->b_jlist != BJ_Forget || force_copy) {
+ JBUFFER_TRACE(jh, "generate frozen data");
+ if (!frozen_buffer) {
+ JBUFFER_TRACE(jh, "allocate memory for buffer");
+ spin_unlock(&journal_datalist_lock);
+ unlock_journal(journal);
+ frozen_buffer = jbd_kmalloc(jh2bh(jh)->b_size,
+ GFP_NOFS);
+ lock_journal(journal);
+ if (!frozen_buffer) {
+ printk(KERN_EMERG __FUNCTION__
+ "OOM for frozen_buffer\n");
+ JBUFFER_TRACE(jh, "oom!");
+ error = -ENOMEM;
+ spin_lock(&journal_datalist_lock);
+ goto done_locked;
+ }
+ goto repeat;
+ }
+
+ jh->b_frozen_data = frozen_buffer;
+ frozen_buffer = NULL;
+ need_copy = 1;
+ }


+ jh->b_next_transaction = transaction;
+ }
+

+ J_ASSERT(handle->h_buffer_credits > 0);
+ handle->h_buffer_credits--;
+
+ /* Finally, if the buffer is not journaled right now, we need to
+ * make sure it doesn't get written to disk before the caller
+ * actually commits the new data. */
+
+ if (!jh->b_transaction) {
+ JBUFFER_TRACE(jh, "no transaction");
+ J_ASSERT_JH(jh, !jh->b_next_transaction);


+ jh->b_transaction = transaction;
+ JBUFFER_TRACE(jh, "file as BJ_Reserved");
+ __journal_file_buffer(jh, transaction, BJ_Reserved);
+ }

+
+done_locked:
+ spin_unlock(&journal_datalist_lock);
+ if (need_copy) {
+ struct page *page;
+ int offset;
+ char *source;
+
+ J_ASSERT_JH(jh, buffer_uptodate(jh2bh(jh)));
+ page = jh2bh(jh)->b_page;
+ offset = ((unsigned long) jh2bh(jh)->b_data) & ~PAGE_MASK;
+ source = kmap(page);
+ memcpy(jh->b_frozen_data, source+offset, jh2bh(jh)->b_size);
+ kunmap(page);
+ }
+
+
+ /* If we are about to journal a buffer, then any revoke pending
+ on it is no longer valid. */
+ journal_cancel_revoke(handle, jh);
+
+out_unlocked:
+ if (frozen_buffer)
+ kfree(frozen_buffer);


+
+ JBUFFER_TRACE(jh, "exit");

+ return error;
+}
+

+int journal_get_write_access (handle_t *handle, struct buffer_head *bh)
+{


+ transaction_t *transaction = handle->h_transaction;
+ journal_t *journal = transaction->t_journal;

+ struct journal_head *jh = journal_add_journal_head(bh);
+ int rc;
+
+ /* We do not want to get caught playing with fields which the
+ * log thread also manipulates. Make sure that the buffer
+ * completes any outstanding IO before proceeding. */
+ lock_journal(journal);
+ rc = do_get_write_access(handle, jh, 0);
+ journal_unlock_journal_head(jh);
+ unlock_journal(journal);
+ return rc;
+}
+
+
+/*
+ * When the user wants to journal a newly created buffer_head
+ * (ie. getblk() returned a new buffer and we are going to populate it


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

echo 'End of part 100'
echo 'File patch-2.4.15 is continued in part 101'
echo "101" > _shar_seq_.tmp
exit 0

It is loading more messages.
0 new messages